Outline

When before syntax is called in Rspec. ?

Example

describe "before spec example" do

  before(:all) do
    # do somthing all(1)
  end

  before(:each) do
    # do somthing each(1)
  end

  it "" doa
    # execute : before all(1)
    # execute : before each(1)
  end

  context "" do

    before(:all) do
	  # do somthing all(2)
    end

    before(:each) do
      # do somthing each(2)
    end

    it "" do
      # execute : before all(2)
      # execute : before each(1)
      # execute : before each(2)
    end
    context "" do
      it "" do
        # execute : before each(1)
        # execute : before each(2)
      end
    end

  end

end

method

fill with value in input

fill_in("name value", with: "value")

click button

click_button("submit")

find element

find("#selector")

select select tag option

select("japan", :from => "country")

access page

visit("/page/path")

change host

Capybara.app_host = "http://example.com"

matchers

expect(page).to have_title("page title")
expect(page).to have_link("link text", :href => "/path")
expect(page).to have_content("content text")
expect(form).to have_selector(:css, "[name='email']", visible: true)

Outline

Do you have experience Capybara (feature test tool in gem not animal) dose not reload the page when you access same url more than once. Try to use page.reset!

Solution

escribe "test" do

  it "the page title is user name" do
    user = Fabricate.create(:user)
    visit "/"
    expect(page).to have_title(user.name)

    user.update_attributes(name: "hoge")
    page.reset! # try to reset
    visit "/"
    expect(page).to have_title("hoge") # will success
  end

end

Outline

For example, You make SAP(single page application) using angularjs then the application change path from /login to /profile. If application change path after ajax request how to wait path changing.

Solution

You need include this helper.

module WaitHelper

  def wait_url(url)
    start = Time.now.tv_sec
    until is_not_over_limit(url, Capybara.default_wait_time, start); end
  end

  private
    def is_not_over_limit(url, limit_sec, start)
      matched = current_path === url
      if (Time.now.tv_sec - start) >= limit_sec then
        raise Exception.new("WaitHelperError: wait timeout")
      end
      matched
    end

end

then You can use like this.

describe "form submit" do

  context "input values are valid" do
    it "send data to server using ajax then path is changed" do
      visit "/login"      

      fill_in("email", with: "test@example.com")
      fill_in("password", with: "aaaaaa")
      click_button("login") # send ajax request    

      wait_url("/profile")
      expect(page).to have_title("profile page")
    end
  end

end

Outline

You can not get $routeparams.key in $routeProvider resolve section.

Example

angular.module('app')
    .config(Router);

  Router.$inject = ['$routeProvider'];

  function Router($routeProvider) {
    $routeProvider
      .when('/path/:iuserId',
          {
            templateUrl: '/templates/path.html',
            controller: 'PathController',
            resolve: {
              user: ['$routeParams', 'PathResource', function($routeParams, PathResource) {
                var id = $routeParams.userId; // you can not get parameter from $routeProvider
                return PathResource.get(id);.
              }]
            }
          });

Reason

In $routeScope.$locationChangeSuccess event, execute resolve section to get data before Rouing then $routeParams are updated.

Solution

angular.module('app')
    .config(Router);

  Router.$inject = ['$routeProvider'];

  function Router($routeProvider) {
    $routeProvider
      .when('/path/:iuserId',
          {
            templateUrl: '/templates/path.html',
            controller: 'PathController',
            resolve: {
              user: ['$route', 'PathResource', function($route, PathResource) {
                var id = $route.current.params.id; // you can get parameter from $route.current
                return PathResource.get(id);.
              }]
            }
          });

$route.current is updated in $routeScope.$locationChangeStart event which is fired before execute resolve section ($routeScope.$locationChangeSuccess)