Rspec and Capybara uninitialized constant - ruby

I am using Rspec 3.2 and Capybara 2.4 in a non RoR project. I am trying to test with feature mode provided by Capybara gem.
$ cat .rspec
--color
--require spec_helper
$ cat spec/features/test_spec.rb
feature 'login' do
username ="rspec#{Time.now.to_i}"
valid_email = "#{username}#gmail.com"
scenario 'with valid email' do
sign_up_with valid_email, 'pwd', 'pwd', username
expect(page).to have_content('LOGOUT')
end
end
$ cat spec/support/session_helper.rb
module SessionHelper
def sign_up_with(email, password, confirm_password, username)
visit '/signup'
fill_in 'email', with: email
fill_in 'password', with: password
fill_in 'passconf', with: confirm_password
fill_in 'username', with: username
click_button 'submit'
end
end
$ cat spec/spec_helper.rb
require 'capybara/rspec'
Capybara.default_driver = :selenium
RSpec.configure do |config|
...
config.include SessionHelper, type: :feature
...
end
This is a non RoR project, when I run the test I have this error:
$ rspec
spec/spec_helper.rb:26:in `block in <top (required)>': uninitialized constant SessionHelper (NameError)
In online documentation there are many examples, I have structured my files like the examples but it not works.

The way I handle this in all of my projects is like this:
Require all the support files:
In spec_helper.rb
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
And then your spec/support/session_helper.rb should look like this:
module SessionHelper
def sign_up_with(email, password, confirm_password, username)
visit '/signup'
fill_in 'email', with: email
fill_in 'password', with: password
fill_in 'passconf', with: confirm_password
fill_in 'username', with: username
click_button 'submit'
end
end
RSpec.configure do |config|
# Remove the equivalent line from spec_helper.rb
config.include(SessionHelper)
end

Related

Getting Frozen Error-Can't modify frozen string

Getting frozen error while running below mentioned cod. Also find the helpers files. Below is the main file:
require 'spec_helper.rb'
require 'rspec_capybara_assignment_helper.rb'
describe 'Open the automationpractices site' , :type => :request do
it 'Test: Page Content', :page do
visit "http://automationpractice.com/index.php"
expect(page).to have_xpath(".//img[contains(#src,'automationpractice.com/img/logo')]")
expect(page).to have_xpath(".//input[#id='search_query_top']")
expect(page).to have_link("Contact us")
expect(page).to have_link("Sign in")
within('div#block_top_menu') do
expect(page).to have_link("Women")
expect(page).to have_link("Dresses")
expect(page).to have_link("T-shirts")
end
within('div#center_column') do
expect(page).to have_link("Popular")
expect(page).to have_link("Best Sellers")
end
expect(page).to have_content("Automation Practice Website")
end
end
Spec_Helper file:-spec_helper.rb
require 'rspec'
require 'capybara/rspec'
require 'capybara/dsl'
require "selenium-webdriver"
require "capybara"
require 'capybara/rspec/matchers'
RSpec.configure do |config|
config.include Capybara::DSL , :type => :request # to include capybara DSL methods
config.include Capybara::RSpecMatchers,:type => :request # to include Rspec matchers available.
end
Capybara.configure do |config|
config.run_server = false
config.default_driver = :selenium # which driver to use (selenium / chrome /internet explorer)
config.default_selector = :css #(by default css selector) # if user want to use xpath, he has to write find(:xpath, <xpath>).click
config.app_host = "http://automationpractice.com/index.php" # host app
config.default_max_wait_time = 5 # wait for 4 seconds.
config.app_host = #url
config.ignore_hidden_elements = true # will ignore hidden elements on page.
config.match =:prefer_exact # check for exact match.
end
Rspec Capybara Assignmnet Helper File:
rspec_capybara_assignment_helper.rb
def click_on(value)
find(value).click
end
def link_click(value)
click_link(value)
end
def button_click(value)
click_button(value)
end
def login_application
link_click('Sign in')
fill_in('email', :with => 'test.test#testing.com')
fill_in('passwd', :with => 'testtest')
button_click('SubmitLogin')
end
def sign_out
link_click('Sign out')
end
def search_product(value)
fill_in('search_query_top', :with => value)
button_click('Search')
sleep(2)
end
def add_product(value)
page.find(:css,'.product-image-container').hover
sleep(2)
first("a", :text => "More").click
sleep(4)
fill_in('quantity_wanted', :with => '2', visible: false)
select('M', :from => 'group_1')
find('button.exclusive').click
sleep(2)
first("span", :text => "Continue shopping", wait: 3).click
sleep(2)
end
def check_locator(value)
expect(page).to have_selector(value)
end
Error as below:
Open the automationpractices site
Test: Page Content (FAILED - 1)
Failures:
Open the automationpractices site Test: Page Content
Failure/Error: visit "http://automationpractice.com/index.php"
FrozenError:
can't modify frozen String
./spec/tests/rspec_capybara_assignment.rb:6:in `block (2 levels) in <top (required)>'
Finished in 0.7789 seconds (files took 3.61 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/tests/rspec_capybara_assignment.rb:5 # Open the automationpractices site Test: Page Content
This appears to be related to selenium-webdriver, not capybara itself.
There's an issue about this at https://github.com/SeleniumHQ/selenium/issues/7365
To fix, specify in your gemfile that you want 3.142.4 as a minimum: gem 'selenium-webdriver', '~> 3.142.4'
And then run bundle update selenium-webdriver
That should get this specific issue resolved.

Why am I getting FactoryGirl wrong number of arguments error?

Having strange behavior from FactoryGirl in non-rails app. getting wrong number of arguments error...don't know why.
gideon#thefonso ~/Sites/testing (master)$ rspec spec
/Users/gideon/.rvm/gems/ruby-1.9.3-p194/gems/factory_girl-4.1.0/lib/factory_girl/syntax/default.rb:6:in `define': wrong number of arguments (1 for 0) (ArgumentError)
from /Users/gideon/Sites/testing/spec/factories.rb:1:in `<top (required)>'
Here are the files involved...
login_user_spec.rb
require_relative '../spec_helper'
require_relative '../lib/login_user'
describe "Existing User Log in Scenario", :type => :request do
before :all do
#user = FactoryGirl(:user)
end
xit "should allow user to select login from top nav" do
visit "/"
within("#main-header")do
click_link 'Log In'
end
page.should have_content('Log in to your account')
end
it "and fill in login form" do
visit "/login"
within("#login-form")do
fill_in 'user-email', :with => #user.email
fill_in 'user-password', :with => #user.password
end
#FIXME - the design crew will make this go away
within("#login-form") do
click_link '#login-link' #this gives false failing test...geek query...why?
end
page.should have_content('Manage courses')
end
end
Factories.rb
FactoryGirl.define :user do |u|
u.email "joe#website.com"
u.password "joe009"
end
user.rb
class User
attr_accessor :email, :password
end
spec_helper.rb
require 'rubygems'
require 'bundler/setup'
require 'capybara'
require 'rspec'
require 'capybara/rspec'
require 'json'
require 'capybara/dsl'
# Capybara configuration
Capybara.default_driver = :selenium
Capybara.app_host = "http://www.website.com"
require 'factory_girl'
# give me ma stuff
FactoryGirl.find_definitions
require "rspec/expectations"
include Capybara::DSL
include RSpec::Matchers
ANSWER: :user is a reserved word..changed it to :stuff...works fine now.
Try to use new syntax from readme
FactoryGirl.define do
factory :user do
email "joe#website.com"
password "joe009"
end
end
If this is a non-rails app you will have to create a Userclass first. I'm not sure if you have to have instance vars with name, password and email but you definitely will have to have that class defined somewhere.
See the Getting Started file on Github for more on that.
Try this
FactoryGirl.define do
factory :user do |u|
u.email "joe#website.com"
u.password "joe009"
end
end

How can I switch between two frames with Capybara

I am trying do something inside 2 frames but error raises everytime when I try to switch between frames.
For example:
# encoding: utf-8
require "capybara/dsl"
Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'https://hb.posted.co.rs/posted'
class Account
include Capybara::DSL
def check_balance
visit('/')
page.driver.browser.switch_to.frame 'main'
fill_in 'korisnik', :with => 'foo'
fill_in 'lozinka', :with => 'bar'
click_button 'Potvrda unosa'
page.driver.browser.switch_to.frame 'header'
click_on 'Stanje'
end
end
account = Account.new
account.check_balance
Error is:
[remote server]
file:///tmp/webdriver-profile20120810-9163-xy6dtm/extensions/fxdriver#googlecode.com/components/driver_component.js:6638:in
`unknown': Unable to locate frame: main
(Selenium::WebDriver::Error::NoSuchFrameError)
What is the problem? Maybe I am doing something wrong here?
If I change order of switching frames so try first to switch to 'header' then switch to 'main' frame then same error raises except that it says that this time there is no 'main' frame:
# encoding: utf-8
require "capybara/dsl"
Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'https://hb.posted.co.rs/posted'
class Account
include Capybara::DSL
def check_balance
visit('/')
page.driver.browser.switch_to.frame 'header'
click_on 'Stanje'
page.driver.browser.switch_to.frame 'main'
fill_in 'korisnik', :with => 'foo'
fill_in 'lozinka', :with => 'bar'
click_button 'Potvrda unosa'
end
end
account = Account.new
account.check_balance
Error:
[remote server]
file:///tmp/webdriver-profile20120810-9247-w3o5hj/extensions/fxdriver#googlecode.com/components/driver_component.js:6638:in
`unknown': Unable to locate frame: main
(Selenium::WebDriver::Error::NoSuchFrameError)
Problem
The problem is that when you do page.driver.browser.switch_to.frame, it switches the page's context to the frame. All actions against the page are now actually against the frame. So when you are switching frames the second time, you are actually saying find the 'header' frame inside the 'main' frame (rather than, what I assume you want, the 'header' frame inside the main page).
Solution - Capybara within_frame (recommended):
When working inside a frame, you should use Capybara's within_frame method. You would want to do:
def check_balance
visit('/')
within_frame('main'){
fill_in 'korisnik', :with => 'foo'
fill_in 'lozinka', :with => 'bar'
click_button 'Potvrda unosa'
}
within_frame('header'){
click_on 'Stanje'
}
end
Solution - Selenium switch_to:
If you want to do the frame management yourself (ie not use Capybara's built-in method), you can switch the page's context back to the browser and then to the second frame. This would look like the following. Though I would suggest using the built-in Capybara method.
def check_balance
visit('/')
page.driver.browser.switch_to.frame 'header'
click_on 'Stanje'
#Switch page context back to the main browser
page.driver.browser.switch_to.default_content
page.driver.browser.switch_to.frame 'main'
fill_in 'korisnik', :with => 'foo'
fill_in 'lozinka', :with => 'bar'
click_button 'Potvrda unosa'
end
I've found solution. within_frame works as expected:
# encoding: utf-8
require "capybara/dsl"
Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'https://hb.posted.co.rs/posted'
class Account
include Capybara::DSL
def check_balance
visit('/')
within_frame 'main' do
fill_in 'korisnik', :with => 'foo'
fill_in 'lozinka', :with => 'bar'
click_button 'Potvrda unosa'
end
within_frame 'header' do
click_on 'Stanje'
end
end
end
account = Account.new
account.check_balance
I've found source code for within_frame in file https://github.com/jnicklas/capybara/blob/master/lib/capybara/selenium/driver.rb. starting from line 81.
EDIT:
While I wrote this answer, #JustinKo answered question, so both answers are correct but +1 and accepted answer for him.

Acceptance testing of sinatra app using webrat fails

I am trying to test a ruby authentication app using minitest and webrat but get errors.
Tests like visit '/' fail with an error Status 200 expected but was 404.
Tests containing code like fill_in :email, :with => "first#company.com" fail with error Could not find field: :email.
I read several sinatra, testing and webrat documents and forums. Some of them were old and suggested stuff like Sinatra::Default, but github.com/brynary/webrat/wiki/sinatra, Building a Sinatra App Driven By Webrat Tests and Learning From the Masters: Sinatra Internals are new, yet they still fail.
Basically, I didn't like sentence-like syntax of rspec, cucumber etc but do want to do behaviour driven development. I really like the minitest syntax, both tests and output and that is why I choose webrat for BDD. If I'm wrong about expecting webrat to fulfill acceptance testing requirements, please simply tell me that I should use this framework or that one.
Apart from that, the first parts of the main file and test file are below. I hope someone can explain me, what I am missing?
test_file
require "test/unit"
require "minitest/autorun"
require "rack/test"
require 'webrat'
require_relative "../lib/kimsin.rb"
Webrat.configure do |config|
config.mode = :rack
end
ENV["RACK_ENV"] = "test"
class KimsinTests < Test::Unit::TestCase
include Rack::Test::Methods
include Webrat::Methods
include Webrat::Matchers
def app
Sinatra::Application.new
end
def test_create_user
visit "/user/new"
fill_in :username, :with => "first#company.com"
fill_in :password, :with => "abC123?*"
fill_in :confirm_password, :with => "abC123?*"
click_link "Register"
assert 201, last_response.status, "Status 201 expected but was #{last_response.status}.\n#{error}"
assert_contain /Logged in as first#company.com./, "No user created"
assert_contain /Logout/, "Logout link not present"
end
main_file
require "sinatra"
require "erb"
require_relative "../lib/kimsin/version"
require_relative "../lib/kimsin/user"
class Kimsin < Sinatra::Application
use Rack::Session::Pool, :expire_after => 2592000
set :session_secret, BCrypt::Engine.generate_salt
configure :development do
DataMapper.auto_migrate!
end
get "/" do
if session[:user_id]
user = User.get session[:user_id]
email = user.email
erb :index, :locals => { :email => email }
else
email = nil
erb :index, :locals => { :email => email }
end
end
Using Sinatra with Webrat should work fine. I think that the errors that you are seeing are caused by the following method (around line 18 in your test file):
def app
Sinatra::Application.new
end
This is setting up the Sinatra::Application base class to run your tests against when you really need to set up your own subclass Kimsin (because you are creating a modular style Sinatra app), i.e.
def app
Kimsin.new
end
The 404 errors and missing fields are happening because Sinatra::Application doesn't define any of the routes you are testing.
You might also like to take a look at Capybara if you are looking for similar alternatives to Webrat.

Capybara testing of sinatra app fails

I am trying to test a sinatra app using minitest and capybara but get several errors on all tests using capybara features like fill_in or visit.
test_index gives:
undefined local variable or method `app' for #
test_create_user gives:
Invalid expression: .////form[#id = 'register']
test_same_email gives:
Unable to find css "#register"
test_login gives:
cannot fill in, no text field, text area or password field with id,
name, or label 'email' found
Any suggestions on what may be wrong?
test.rb
require "test/unit"
require "minitest/autorun"
require "capybara"
require "capybara/dsl"
require "rack/test"
require_relative "../lib/kimsin.rb"
ENV["RACK_ENV"] = "test"
class KimsinTests < Test::Unit::TestCase
include Rack::Test::Methods
include Capybara::DSL
Capybara.app = Sinatra::Application
def test_index
visit "/"
assert stuff..
end
def test_create_user
visit "/user/new"
within "//form#register" do
fill_in :username, :with => "first#company.com"
fill_in :password, :with => "abC123?*"
fill_in :confirm_password, :with => "abC123?*"
click_link "Register"
end
assert stuff..
end
end
I'm using cygwin 1.7.15-1 on windows 7, rvm -v 1.14.1 (stable) and ruby -v 1.9.2p320.
----UPDATE----
Finally I got the tests work by incorporating Steve's suggestions:
within "form#register" do
fill_in "email", :with => "first#company.com"
click_button "Register"
and asserting the response by using capybara_minitest_spec:
page.must_have_content "Password"
page.must_have_button "Register"
I just answered a more recent question you posted about Sintra with Webrat.
Acceptance testing of sinatra app using webrat fails
I think the problem here is the same. Try replacing:
Capybara.app = Sinatra::Application
with:
Capybara.app = Kimsin
Personally I would choose Capybara over Webrat.

Resources