Using Cucumber with a Static database - ruby-on-rails

I am trying to run Cucumber tests against a database that is already populated with data. It's basically a copy of our production database.
For some reason I have some tests failing which seemingly is coming from the fact that it can't find the data. Any idea on how to make this work and why it wouldn't like "pre-seeded" databases?
Our data is far too complex to try to recreate via factories/fixtures. There's just no way.
Here's an example:
Scenario: a tech logs in
Given I am on the login page
And user with id 2328 exists
When I login as "user" with password "password"
Then I should be on the dashboard page
And I should see "Logged in as: USER"
The step:
Given /^user with id (\d+) exists$/ do |id|
Employee.exists? id
end
When /^I login as "([^\"]*)" with password "([^\"]*)"$/ do |username, password|
visit login_url
fill_in "username", with: username
fill_in "pwd", with: password
click_button "Login"
end
Maybe its my steps and has nothing to do with the database, but I can't understand why it doesn't fail on the And user with id 2328 exists step when I give it a bad number.
I have seen this but it doesn't seem to affect the flow.
Lastly, here is the actual login method (believe me, I know how awful this login check is, simply checking we have permissions to the database):
def login
if request.post?
# get database config for env
configs = ActiveRecord::Base.configurations[Rails.env]
begin
# attempt to connect to the db
plsql = plsql_connect(params[:username], params[:pwd])
# if no exception, get the employee ID and location
session[:employee_id] = plsql.hes.installer_web_pkg.get_employee_pk.to_i
session[:employee_location] = plsql.hes.installer_web_pkg.fn_get_truck_location(session[:employee_id]).to_i
# logout
plsql.logoff
# dashboard time!
redirect_to dashboard_url(session[:employee_id].to_i)
rescue Exception => err
# could not connect, fail!!
flash.now[:notice] = "Username/password not valid (or locked out of account). Try again or contact the HelpDesk."
render :action => "login"
end
end
end
Every time I run, I get:
expected: "/dashboard",
got: "/login" (using ==) (RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/web_steps.rb:198:in `/^(?:|I )should be on (.+)$/'
features/tech_queue.feature:11:in `Then I should be on the dashboard page'

Related

how to specify page object when rails spec test?

Now, I try to test login and page transition using rails spec.
to check session change via login, test needs "rack_session_access/capybara" library.
I check the session of login user is nil before login.
after the user logged in, I check the session of login user exists by searching session from user id. but, if I write this code(#2), the test doesn't work.(the error occurred at #3. error says can't find out Logout link).
If I comment out this checking session code(#2), the test works well.
Does anybody tell me why??
require 'rails_helper'
require "rack_session_access/capybara"
feature "session_test" do
background do
User.create(name: 'test_user', email: 'user#example.com', password: 'user', password_confirmation: 'user')
end
scenario "Login_and_Logout" do
key = User.find_by(email: 'user#example.com').id
# the session of login user should be empty
expect(page.get_rack_session["user_id"]).to eq nil
visit '/sessions/new'
within("form") do
fill_in 'session_email', with: 'user#example.com'
fill_in 'session_password', with: 'user'
end
# 1 user login
click_button 'Login'
# 2 the session should have user_id value.
expect(page.get_rack_session["user_id"]).to eq key
# 3 user logout
find('body > header > div > nav > ul > li:nth-child(4) > a').click
# 4 check transition
expect(page).to have_content 'This is the home page'
# 5 the session should be empty again
session = page
expect(page.get_rack_session["user_id"]).to eq nil
end
end

Capybara loses cookies between requests

I have the follow test:
def login_user(email, password)
visit new_user_session_path
fill_in 'E-mail', with: email
fill_in 'Password', with: password
click_button 'go'
end
scenario 'some test' do
order = Fabricate(:order_one, company: user.company)
visit "http://127.0.0.1:49645/orders/#{order.id}" # change to visit "/orders/#{order.id}"
login_user(user.email, user.password)
#assert
end
Whats happen is that in first step (visit...) the user is not logged, so I set some informations using cookie. But, when login_user is executed, this cookie is empty.
Usigin selenium-webdriver
Any idea here ?
Thanks in advance
When using a JS capable driver #visit is not guaranteed to have finished loading the page when it returns. Since the cookie is not set in the browser until the response is processed, your login_user is actually telling the browser to stop processing it's current visit and visit somewhere else which stops the cookie from ever being set in the browser. After the first visit you need to wait for something visible on the page to be sure the cookies are correctly set.
scenario 'some test' do
order = Fabricate(:order_one, company: user.company)
visit "http://127.0.0.1:49645/orders/#{order.id}"
expect(page).to have_content('you are not logged in') #or whatever shows on the page visited
login_user(user.email, user.password)
#assert
end

Capybara test fails when run but running the same steps manually is successful

So I'm trying to write some integration tests for this app I'm working on and one of the tests I have written when run follows through the steps and lands on the error page, while performing the exact same steps manually lands on the correct page. Here is the test:
describe 'sign up page' do
it 'signs a user up when valid information is entered and displays success message' do
sign_up_with('John Doe', 'user11#gmail.com', 'a8wsk389nd9w02kdncui20dkc')
current_path.should == root_path
page.should have_content('Email sent with password set instructions')
end
...
def sign_up_with(name, email, registration)
visit('/signup')
fill_in 'Full Name', with: name
fill_in 'Email Address', with: email
fill_in 'Email Address Confirmation', with: email
fill_in 'Registration Code', with: registration
click_button('Create Java user')
end
end
When I run this test it doesn't throw any errors at me, but the route goes to /java_users which is where the page goes if it fails, instead of / like it is supposed to. If I perform these same steps manually with the same data, it works perfectly. I honestly have no idea what is going wrong or what I have done wrong. I'm really new to Capybara (and RoR for that matter) so it could be something really simple. The only thing I can thing of is that because ActionMailer is called to send an email that's throwing it off somehow. Any help would be appreciated.
Updates:
Although I don't receive any errors when running the test (other than the test failing), I installed the launchy gem and tried save_and_open_page. It took me to a page with a wall of text. Here is a snippet:
ArgumentError at /java_users ============================ > Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true app/views/support_mailer/password_set.text.erb, line 3 ------------------------------------------------------ ``` ruby 1 In order to set your password, please click the URL below. 2 > 3 <%= password_set_url(#user.password_reset_token) %> 4 5 If you did not purchase a *******, just ignore this email.``` App backtrace ------------- - app/views/support_mailer/password_set.text.erb:3:in `_app_views_support_mailer_password_set_text_erb___10448386_70208856' - app/mailers/support_mailer.rb:250:in `password_set' - app/models/user.rb:65:in `send_password_set' - app/controllers/java_users_controller.rb:60:in `create' - spec/features/sign_up_spec.rb:28:in `sign_up_with' - spec/features/sign_up_spec.rb:5:in `block (2 levels) in...
Also here is the create function in the controller:
def create
#java_user = JavaUser.new(user_params)
registration = RegistrationCode.find_by_code(params[:registration_code])
email = params[:java_user][:email]
email_confirmation = params[:email_confirmation]
user = User.find_by_email(email)
if validateInput(registration, email, email_confirmation, user)
#java_user.rails_uuid = user.id
if #java_user.save
registration.user_id = #java_user.id
registration.save
if user
user.send_password_set
redirect_to root_url, notice: "Email sent with password reset instructions"
else
render :new
end
else
render :new
end
else
render :new
end
end
I seem to have solved it. I was missing the following in my test.rb file in /config/environments
config.action_mailer.default_url_options = { :host => "localhost:3000" }
I had it in development.rb, but not in test.rb.

Cant sign in user in Rspec test ( devise gem )

I cant find solution for my problem: cant login user in rspec test.
I tried this code, following by this link - https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs
require 'spec_helper'
require 'factory_girl_rails'
describe "ololo" do
it "blocks unauthenticated access" do
user = User.create(email: "lol#mail.com", password: "123456")
request.env['warden'].stub(:authenticate!).
and_throw(:warden, {:scope => :user})
visit "/tasks"
page.should have_content("Signed in successfully.")
end
end
/error/
Failure/Error: page.should have_content("Signed in successfully.")
expected there to be text "Signed in successfully." in "Task App Home Login You need to sign in or sign up before continuing. Sign in Email Password Remember me Sign upForgot
your password? Task App by Denys Medynskyi"
also tried this link - http://codingdaily.wordpress.com/2011/09/13/rails-devise-and-rspec/.
Devise wiki tutorial is also not working for me.
Please, I'm stuck hardly. Help me anyone.
Without seeing your error message, I guest one possible reason is you created hard record of User to test db. You may have run this test once, so in second time this creation fails because record with same email exists.
You've required FactoryGirl. Why don't you use FactoryGirl to create the fixture data?
In spec/factories/user.rb
FactoryGirl.define do
factory :user do
email: "lol#mail.com"
password "123"
end
end
In your test, write
FactoryGirl.create(:user)
Add
Comparing with the tut you lack two steps:
You need to use FactoryGirl to replace the hard created record, as writing above.
You need to execute the sign_in step before visit the private page.
Maybe you would be good with #2 only if you cleared the db after tests. Anyway factory data is recommended over hard data.

cucumber speed, performance tuning

I have profiled my feature files. I have found out that my login step takes the most time.
Given /^I am logged in as "(.+)"$/ do |login|
visit path_to('the home page')
fill_in "login", :with => login
fill_in "password", :with => 'foobar'
click_button "loginButton"
end
It takes over 5 seconds on my development box.
I want to make another step with login functionality, but without filling out the form, simply set the session, and used it in my other tests as background scenario.
Given /^I am logged in as "(.+)" through session$/ do |login|
user= User.find_by_login(login)
end
The above step finds the user, but how I can make it stores the session, and redirects me ?
you could just avoid authenticating in the other steps, probably not what a die hard cucumber dev would say. But if you have the authentication workflow tested elsewhere, then I dont see the harm. I didn't try this, but I think the variable scope should be right.
Given /^I am logged in as "(.+)" through session$/ do |login|
#user= User.find_by_login(login)
#open the class and spike
class ApplicationController < ActionController::Base
def current_user
#user
end
end
end

Resources