Solving the git Merge nightmare

I recently started using git at my new job. I have very little experience with git. And Obviously I made mistake. This it was big mistake. I just took down out beta site :) . More over I created new branches from the corrupted master branch. My other colleague also use that branch. In the morning I got email from CTO that beta site is not working and I added some code on some program that I should not touch. BTW my CTO is awesome who fixed the whole mess and was cool about it.

Let me tell you what I did. After working on a branch. I switched to main branch and I forget that I was on main branch. So I changed some files. Then I pull the code form my forked repo.

git pull upstream master

then git told me that there were some conflicts. I never resolved any conflict before – so it was quite daunting experience. Long story short – I messed up and kept “<<<<<<<:", "=======", "HEAD" & ">>>>>>>” in js file, css file and in some perl program. Then I merge the branch i worked in master branch. See what I did.

So my CTO sat down with me – basically he did everything. First he reset to last commit which was just before my virus merge.
First he went to the main branch and reset the head. Then he pick the commits that was committed after my virus commit. In this way the branch was clear of my bug

git reset --hard commithash
git cherry-pick commithash

13. May 2013 by Zakir Hyder
Categories: git | Tags: , , | Comments

Things I Learn While Working with Mojolicious

If you are using DBIx::Class then it will be great if you can see the SQL statements.

DBIC_TRACE=1 morbo ./script/awsomeapp 

Use Data::Dumper print out variables

use Data::Dumper; 
print Dumper($variable);

in a template you can use

[% h.dumper(variable) %]

Locale::Maketext supports quantification so we can always get the correct sentence:

[% c.l('You have [quant,_1,unpublished ad,unpublished ads]. If you would like to publish the [numerate,_1,ad,ads], please check under "Ads" below.', new_items_count)%]

See here for other commands: https://metacpan.org/module/Locale::Maketext#Utility-Methods (although quant and numerate is the most useful ones).

Another little tip for starting the dev server:

 
morbo ./script/awsomeapp -w ..

That will make it reload when you change files in the other modules

To get absolute url

 
my $self = shift;
$self->url_for("/")->to_abs;

Set page title from controller

$self->title("Jambur");

in template

<title>[% h.title || 'CellBazaar &ndash; Market In Your Pocket' %]</title>

28. April 2013 by Zakir Hyder
Categories: Mojolicious, Perl | Tags: , , , | Comments

Test Your Website’s Features In Firefox, Safari And Chrome Using Rspec and Capybara With Selenium.

First setup you mac as mentioned in Check Your Web-App’s Functionality Using Rspec, Cucumber And Capybara With Selenium. As of writing this post you can use firefox version 19 and chrome version 26 with selenium-webdriver (2.31.0). I hope you installed Homebrew. It really simplifies things. Selenium include FirefoxDriver and you do not have have to add any code for this. All you need is just install Firefox.

For Chrome, you have to install ChromeDriver.

brew install chromedriver

Now add the following code in spec_helper.rb to run tests on Chrome

Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(app, :browser =&amp;gt; :chrome)
end

Installing SafariDriver is not so simple as ChromeDriver. We have to build the SafariDriver ourself. We have to install Google Go.

brew install go

Now you have to sign up for Apple’s (free) Safari Developer Program and generate a signed certificate for the extension from here https://developer.apple.com/certificates/index.action. Download the certificate and click it, then it will be added to keychain.

Now download the Selenium source Binaries.

cd ~/Downloads/
git clone https://code.google.com/p/selenium/

It will download all the selenium code which is about 1.2 GB. After that just goto the folder and compile with go.

cd selenium/
./go safari

It will create safari extention which we will use. It is better to copy the SafariDriver.safariextension folder to you Document folder. You can find SafariDriver.safariextension folder in ~/Downloads/build/javascript/safari-driver/

Now we need to enable the Develop menu (Preferences > Advanced > Show Develop menu in menu bar).

Open the Extension Builder (Develop > Show Extension Builder)

Click the add extension

Locate the SafariDriver.safariextension and select.

Now add the following code in spec_helper.rb to run test on Safari

Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(app, :browser =&amp;gt; :safari)
end

27. March 2013 by Zakir Hyder
Categories: Black-box Testing, Capybara, Ruby, Selenium | Tags: , , , , , , , , , , , | Comments

Things I Learned While Working With Capybara

I have been testing a website with help of Rspec, Cucumber and Capybara with Selenium. Mainly I am using Capybara for selecting and filling up textfields. It is very easy finding any element with Capybara’s find because it looks for name/id/label text for matching element. Check Check Your Web-App’s Functionality Using Rspec, Cucumber And Capybara With Selenium. In perfect world, it is more than enough. But we dont live in perfect world – we live in a world where multiple elements have same id/name or an element without any name/id. How do we find those elements? Fortunately Capybara allows selecting element using XPath. Xpath makes it easy to find any element which does not have id and or name. I will be updating this post as I learn more and more. Now lets checkout some scenario

Click the first button of two button with same Id. all() returns multiple element if found and we can access it like [0]/[1] etc. Capybara allows chaining so we can add click at the end. We can use first() but it is nice know there is option to get element by [].

all(:xpath, '//button[@id="btn"]')[0].click

Find a button which does not have any attribute except value.

find(:xpath, '//button[contains(text(), "Click Me")]').click 

Select a option from select-box. We can use select() but our select-bix does not have id/name.

find(:xpath, '//option[contains(text(), "Apple")]', 'Apple').select_option

Chaining set with find() to set values for input fields

find(:xpath, '//input[@id="password"]').set(new_password)

Find a button using class attribute

first(:xpath, '//button[@class="btn"]').click

Upload image using send_keys. In this case file field is not as it normally is.

<input type="file" multiple="multiple" accept="image/jpeg,image/gif,image/png" style="font-size: 999px; position: absolute; width: 100%; height: 100%;">

page.driver.browser.all(:xpath, '//input[@accept="image/jpeg,image/gif,image/png"]')[0].send_keys(Dir.getwd + 'img.jpg')

Increase default_wait_time when you are working with asynchronous ajax which is 2 secs by default. If your internet speed it good then you do not need to change it but if you have bad internet then I will suggest you to increase it. I add this line in spec_helper.rb

Capybara.configure do |config|
  config.default_wait_time = 7
end

When you want to test subdomains then use visit. What I do is create new helpers like mobile_customer_service_helpers.rb and use a class variable.

module Features
  module MobileCustomerServiceHelpers
    @@mobile_subdomain = 'http://m.site.com'
    def mobile_fill_up_customer_service(url = '/', name, email)
      visit @@mobile_subdomain + url
      fill_in 'name', with: name
      fill_in 'email', with: email
      click_button 'Send'
    end
  end
end

We can actually loop through page.should.

scenario 'Looping through all the prices' do
    CSV.foreach("prices.csv") do |row|
	fill_in 'price', with: row
	page.should have_css(".text-error", :text => "Please write a price for your ad")
    end  
end

15. March 2013 by Zakir Hyder
Categories: Black-box Testing, Capybara, Selenium | Tags: , , , , , , , , , , , | Comments

Check Your Web-App’s Functionality Using Rspec, Cucumber And Capybara With Selenium

Sometime it is not possible or even feasible too check each functionality of your website/web-app. Or you added a new feature in you site/app – now you want check that if the new functionality breaks old one’s. Now you can go through all the features by yourself or you can automate it. As I am a lazy programmer – I always go for less work. To automate I find Rspec + Cucumber + Capybara With Selenium. I am not a Ruby programmer. So when I start implementing my tests, it was a bit hard for me to figure out how to it. In this post you will see how easliy you can test you app even if you are not a ruby programmer. But you do need to know basic ruby. Here is link to learn basic ruby http://www.tutorialspoint.com/ruby/index.htm.

First install ruby and rvm . Then we need to install http://gembundler.com. Now create a folder named “test”. Create Gemfile. Then add the following codes.

mkdir test
cd test
nano Gemfile

source "https://rubygems.org"
gem "rack", "~>1.1"
gem "rspec", :require => "spec"
gem "capybara"

Now run bundle common. It will install all the necessary gems.

bundle

Now create spec, spec->features and spec->support folders. Create a ruby file named spec_helper.rb.

spec_helper.rb file will hold all the necessary gems and configs.

require "rubygems"
require "bundler/setup"
require 'rspec' 
require 'capybara'
require "capybara/rspec"
require "support/features/session_helpers"
require 'capybara/dsl'

Capybara.default_driver = :selenium
Capybara.app_host = 'http://www.your-site.com'

RSpec.configure do |config|
  config.include Features::SessionHelpers, type: :feature
end 

Here we make selenium our default driver and set our websites main url. In RSpec configuration we include session so that we can login to in site.

For this post we will just check user sign up and login. Create another folder in spec->support->features. In this folder we will add functions that can be used our test. Lest create a ruby file named session_helpers.rb. We will add a function named sign_up_with and sign_in_with.

module Features
  module SessionHelpers
    def sign_up_with(name, email, password, confirm_password)
      visit '/users/new'
      fill_in 'name', with: name
      fill_in 'email', with: email
      fill_in 'password', with: password
      fill_in 'confirm_password', with: confirm_password
      click_button 'Register'
    end

    def sign_in_with(email, password)
      visit '/login'
      fill_in 'login', with: email
      fill_in 'password', with: password
      click_button 'Submit'
    end
  end
end

visit is method to navigate to other pages.fill_in finds the element and fills with values. click_button clicks button.

Now create a ruby file signup_spec.rb where I will write two test – wrong email address and with all correct values. We have to add “_spec” every ruby file. Rspec will look for all files with “_spec” in filename.

require 'spec_helper'

feature 'Signup' do
  valid_email = 'hhhhbk+' + Time.now.to_f.to_s + '@gmail.com'

  scenario 'with invalid email' do
    sign_up_with 'me me', 'invalid_email', '123456', '123456'
    expect(page).to have_content('Please enter a valid email address')
  end

  scenario 'with all valid info' do
    sign_up_with 'me me', valid_email, '01919046260', '123456', '123456'
    expect(page).to have_content('Check your email to verify your email address')
  end
end

For learn about scenario https://github.com/cucumber/cucumber/wiki/Scenario-Outlines and for feature https://groups.google.com/forum/?fromgroups=#!topic/cukes/HVZogRjk4yE.

To run test just type rspec on command prompt and it will run all the test show you if the test are ok or not.

rspec

Now you can add more test for your app. Happy Testing.

07. March 2013 by Zakir Hyder
Categories: Black-box Testing, Capybara, Cucumber, Rspec, Ruby, Selenium | Tags: , , , , , | Comments

Setup Homebrew, Perlbrew, Ruby, RVM, Perl, cpanm, nginx in Mountain Lion

This is a quick tutorial or run down to setup Homebrew, Perlbrew, Ruby, RVM, Perl, cpanm on Mountain Lion. All the softwares/programs/packages mentioned are very popular. I don’t think I have to give any description on these. I recently installed theses and it took quite effort to make all these up and running.

The first hiccup or glitch is to download the Command Line Tools for mac os. You have to be Apple developer to access this. This will install all necessary programs like make, linker, git etc.

We will then install Homebrew.

ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)"

Then I would suggest checking the installation using this

brew doctor

At this point everything should be fine. Next I would suggest installing GCC 4.2 because Mountain Lion doesn’t come with it by default.

brew tap homebrew/dupes
brew install apple-gcc42
sudo ln -s /usr/local/bin/gcc-4.2 /usr/bin/gcc-4.2

Then will install RVM and update ruby

curl -L https://get.rvm.io | bash -s stable --ruby

Now wer will install Perlbrew. Its much easier than installing it your self.

curl -kL http://install.perlbrew.pl | bash

Make sure you enter next line after install

source ~/perl5/perlbrew/etc/bashrc

Now we can install Perl

perlbrew install perl-5.16.0
perlbrew switch perl-5.16.0

Now we can install cpanm and others

perlbrew install-patchperl
perlbrew  install-cpanm
perlbrew install-ack

INSTALL local::lib

user@host:~$ cpan
cpan[1]> look local::lib
user@host:~/.cpan/build/local-lib-1...$ perl Makefile.PL --bootstrap=~/perl5
user@host:~/.cpan/build/local-lib-1...$ make && make test && make install
user@host:~/.cpan/build/local-lib-1...$ exit
cpan[2]> exit
echo 'eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)' >>~/.bashrc
. ~/.bashrc

Install INSTALL module

cpan Module::Install

Install ELASTICSEARCH

brew install elasticsearch

To have launchd start elasticsearch at login:

ln -sfv /usr/local/opt/elasticsearch/*.plist ~/Library/LaunchAgents

Then to load elasticsearch now:

launchctl load ~/Library/LaunchAgents/homebrew.mxcl.elasticsearch.plist

Or, if you don’t want/need launchctl, you can just run:

elasticsearch -f -D es.config=/usr/local/opt/elasticsearch/config/elasticsearch.yml

you can also add jpg+png support like this

brew install libjpeg
cpanm Imager::File::JPEG

brew install libpng
cpanm Imager::File::PNG

to install PostgreSQL database driver for the DBI module

cpanm DBD::Pg

if face Installing Exporter::Declare failed kind of problem just use

cpanm --installdeps . --prompt
You can s)kip, r)etry, f)orce install, e)xamine build log, or l)ook ? [s] f

to install niginx run the following command

brew install nginx

If you see this “add /usr/local/sbin to path basbrc” and “/usr/bin occurs before /usr/local/bin” then you can add this export PATH=/usr/local/bin:/usr/local/sbin:~/bin:$PATH

nano ~/.bash_profile
export PATH=/usr/local/bin:/usr/local/sbin:~/bin:$PATH

Add the same line to .bashrc and ctrl+x -> y -> return

source ~/.bashrc
nano ~/.bash_profile
export PATH=/usr/local/bin:/usr/local/sbin:~/bin:$PATH

then ctrl+x -> y -> return

19. February 2013 by Zakir Hyder
Categories: Apple, Perl | Tags: , , , , , , , | Comments

How-To Handle expired access tokens for Facebook App

Since Facebook removed offline_access – manageing access tokens has been quite difficult. I have developed a web app http://www.cybernetikz.com/social-background/ for Facebook pages and twitter accounts. While devloping the app i have face the expired access tokens problem. I will discuss how you can solve some of the problem.

There 3 reasons that can make the access token in valid

  • 1. The token expires after expires time (2 hours is the default).
  • 2. The user changes her password which invalidates the access token.
  • 3. The user de-authorizes your app.

The first problem is unavoidable. But we can extend the access token’s expire time to 60 days. After we extend the expire time – all the page access tokens will have unlimited expire time – it means the page access token will not expire unless 2 and 3 happens. You can get more details here https://developers.facebook.com/docs/howtos/login/login-as-page/. So download the latest PHP SDK from github

$facebook = new Facebook(array(
  'appId'  => Configure::read("facebook_app_settings.app_id"),
  'secret' => Configure::read("facebook_app_settings.app_secret"),
));		
$loginUrl = $facebook->getLoginUrl(array(
	'scope'	 => 'manage_pages'),
	''
);
$uid = $facebook->getUser();
if ($uid) {
	try {
		$user_profile = $facebook->api('/me');
		$facebook->setExtendedAccessToken(); // Set access token to 60 days
	} catch (FacebookApiException $e) {
                $uid = false;
		echo $e->getMessage();
	}
}
if ($uid) {
       try {
	    $temp = $facebook->api('/me/accounts?limit=100');
	} catch (FacebookApiException $e) {
	    echo $e->getMessage();
	}
}

Now we can check the access token validity by setAccessToken function

$facebook->setAccessToken($access_token_page_or_user);	
try {
	$user_profile = $facebook->api('/me');						
} catch (FacebookApiException $e) {
	pr($e->getMessage());
}

Now the problem is what to do when the 60 days is over or number 2/3 happens. There actually noting to do but then the user to login urlwhich you can get by calling getLoginUrl() function. You can refreshing Long-lived User Access Tokens bt Facebook does not guarantee this. So sendin user to login url is the best ways. If the user already logged in to Facebook and did not removed your app then user will not see any thing Facebook will just redirect them to you app.

23. January 2013 by Zakir Hyder
Categories: Facebook, Graph Api, PHP | Tags: , , , | Comments

← Older posts