Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing javascript on subdomain with capybara, phantomjs and rails

Solution

This worked. The main essence is that I have to set the Capybara.server_port and Capybara.app_host and sign in manually in the sign in form. Capybara.app_host cannot be set with a dynamic subdomain unless its declared in a variable. All urls has to be hard coded.

require 'spec_helper'

feature 'customer' do

    let(:user)        {FactoryGirl.create(:user)}
    let(:firm)        {user.firm} 
    let(:customers)   {"http://#{firm.subdomain}.lvh.me:31234/customers"} 
    let(:root_url)    {"http://#{firm.subdomain}.lvh.me:31234/"}
    before(:all) do 
      Capybara.server_port = 31234 
      sub = firm.subdomain
      Capybara.app_host = root_url 
    end
   def sign_in_on_js
    visit root_url
    fill_in "Email", :with => user.email
    fill_in "Password", :with => "password"
    click_button "Sign in"
    page.should have_content("Signed in successfully.") 
   end

  scenario "make new", js: true do
    sign_in_on_js
    visit customers
    page.should have_content("Add new customer")       
    find("#dialog_customer").click
    page.should have_content("Create new customer") 
  end 
end

Original question I am making a multitenant app in rails. There is going to be a lot of javascript. But, I cant get the testing to work.

When not running :js = true every thing works. The problem arises in specs like this one

 let(:customers)  {"http://#{firm.subdomain}.lvh.me:3003/customers"} 
 scenario "Statistics select", :js => true do 
   visit customers
   page.should have_content("Add new customer")
 end

The poltergeist web driver for capybara cannot find the url and returns a blank page

Failure/Error: page.should have_content("Add new customer")
       expected there to be text "Add new customer" in ""

I have this in my spec_helper.rb

require 'capybara/rspec'
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, :debug => true)
end

Poltergeist and phantomjs try to deliver. I get this output

{"name"=>"set_debug", "args"=>[true]}
{"response"=>true}
{"name"=>"visit", "args"=>["http://subdomain2.lvh.me:3003/statistics"]}
poltergeist [1362522132943] state default -> loading
{"response"=>{"status"=>"fail"}}

Do I need to have a server running during testing to make this work?

I've tried selenium and capybara-webkit, but phantomjs has gotten closest to success.

I have also tried to change the hosts file in different ways( maybe not correct )

Any tips on setup are welcome!

Update

Starting to get desperate. I now start the rails server

rails s -e test -p 3001

and then run my tests.

Now I get redirected to the sign in page. I have this in the specs

before(:each) do
  login_as(user, :scope => :user) 
end

How can I sign in the test user on the rails test server without going trough the sign in process manually for every spec

like image 267
Andreas Lyngstad Avatar asked Mar 05 '13 22:03

Andreas Lyngstad


1 Answers

Capybara already starts a server for you, to quote the docs:

Some Capybara drivers need to run against an actual HTTP server. Capybara takes care of this and starts one for you in the same process as your test, but on another thread. Selenium is one of those drivers, whereas RackTest is not.

Within your test you can use the visit method with a relative url, for example:

visit("/statistics")

Capybara will direct this request to the server it just started for this test.

When your want to use an absolute url within your test, you can, but you should also specify the port the server is running on. This port is being randomly chosen during the test. Some drivers have a method available to retrieve the port number.

For example when you use the Capybara-Webkit driver:

Capybara.current_session.driver.server_port

To visit an absolute url you can then use:

port_number = Capybara.current_session.driver.server_port
visit("http://127.0.0.1:#{port_number}/statistics")

Within the test specs probably a method login_as won't work. You have to log in with a few simple steps. For example:

before(:each) do
  visit "/login"
  fill_in "Email", :with => "[email protected]"
  fill_in "Password", :with => "secret"
  click_button "Login"
end

To test multiple subdomains you can set the Capybara.app_host. Take a look at this question for a detailed explanation.

UPDATE

Capybara 2 includes a nice feature called always_include_port which will automatically add the port number the server is running on.

Capybara.always_include_port = true

So instead of

visit("http://127.0.0.1:#{port_number}/statistics")

you can now use

visit("/statistics")

and it will automatically connect to http://127.0.0.1:#{port_number}/statistics.

If you want to test multiple subdomains with Capybara.app_host, you could use a domain name which always resolves to 127.0.0.1 for example lvh.me.

For example, if you specify Capybara.app_host = "http://example.lvh.me" it will run the tests using the example subdomain.

like image 169
hjblok Avatar answered Oct 23 '22 21:10

hjblok