Cucumber/Capybara test fails when it should pass - ruby-on-rails

When I manually run the website, it doesn't show Incorrect account ID, please try again and logs in perfectly fine but when I try the same thing with Cucumber/Capybara tests, it fails for some reason. I even outputted the value it is enterring in the form and it seems to be the same id. Please help!
login.feature file
Feature:A user should be able to login
To fill in all the credentials and then go to the landing page of the website
Scenario:Fill the credentials and click login
Given I am on the login page of the website
When I enter my credentials and click the login button
Then I should be directed to the landing page of the website
my_steps.rb file
Given(/^I am on the login page of the website$/) do
visit root_path
end
When(/^I enter my credentials and click the login button$/) do
within("div.row") do
fill_in 'Account', with: 'a1757552'
fill_in 'Password', with: 'adelaideuni'
end
click_button 'Login'
end
Then(/^I should be directed to the landing page of the website$/) do
expect(page).to have_content 'IELTS'
end
Terminal output: (Printing the account id after ggg_d:)
Scenario: Fill the credentials and click login # features/login.feature:5
Given I am on the login page of the website # features/step_definitions/my_steps1.rb:1
When I enter my credentials and click the login button # features/step_definitions/my_steps1.rb:5
Then I should be directed to the landing page of the website # features/step_definitions/my_steps1.rb:13
expected to find text "IELTS" in "Course Advice Assistant\nHelping you choose courses!\nIncorrect account ID, please try again\nAccount\nPassword\nggg_d: a1757552" (RSpec::Expect
ations::ExpectationNotMetError)
./features/step_definitions/my_steps1.rb:14:in `/^I should be directed to the landing page of the website$/'
features/login.feature:8:in `I should be directed to the landing page of the website'
Failing Scenarios:
cucumber features/login.feature:5 # Scenario: Fill the credentials and click login
1 scenario (1 failed)
3 steps (1 failed, 2 passed)

Related

Error going to the correct page in cucumber test on RoR

I have a RoR page with some cucumber tests. The page appears to work.
The link that the human takes to get to the page is:
= link_to "Override Password", edit_admin_client_password_path(#client), :class => "button"
The cucumber step that I believe is SUPPOSED to go there appears to be giving me empty HTML...
Given /^I navigate to the Clients Password Page for "(.*?)"$/ do |client_email|
#current_client = Client.find_by(email: client_email)
visit edit_admin_client_password_path(#current_client)
puts edit_admin_client_password_path(#current_client)
puts Capybara.current_session.html
end
This gives me:
/admin/client_passwords/1/edit
<html><head></head><body></body></html>
I believe that the user is user 1, because it's being generated by the test. I've checked before and user 1 appears to have the correct email, etc..
When, at the web page, I go to http://localhost:3000/admin/client_passwords/6203/edit it goes to the correct place, which I assume is the correct thing.
So, why is this giving me an empty HTML?
ETA: the visit IS changing the page. Before the visit, the html is the home page...
ETA 2: After comments by #thomas-walpole, It appears that I am logging in, I'm using the controller correctly, and I'm trying to produce the view correctly.
HOWEVER: When I add -puts "foobie" to the view haml.html file, I have:
- puts "foobie"
- password = Curl::Easy.perform("http://www.dinopass.com/password/simple").body_str
- puts "bletch"
I get "foobie" but not "bletch".
I'm using curb. Is there a thing that CURL won't work in cucumber testing?
ETA 3:
I've edited the - password = line:
- password = #client.id != 1 ? Curl::Easy.perform("http://www.dinopass.com/password/simple").body_str : 'Password1'
On the assumption that userID 1 doesn't actually exist in the real system.... There's probably a better way of doing that test...

Capybara test case for Login page authentication

I have capybara test case below.
it "Testing login page with valid data" do
fill_in 'email', with: 'kiran#gmail.com'
expect(page).to have_selector("input[value='kiran#gmail.com']")#Checking values are inserted in email field
fill_in 'password', with: 'Kiran.6565'
expect(page).to have_selector("input[value='Kiran.6565']")#Checking values are inserted in password field
click_button('submit')
expect(current_path).to eql(patient_detail_path(4))
end
I am checking Login page once the email and password fields are matches it should redirect to patient_details_path with id field value. In above code i specified email and password is working fine for manual login, but problem is in test case. Expected result: it should redirect to another page(patient_details_path) but it redirecting to home page(/) again.
Failures:
1) Login Page Interface Test login page with valid data
Failure/Error: expect(current_path).to eql(patient_detail_path(4))
expected: "/patient_details/4"
got: "/"
(compared using eql?)
# ./spec/views/login_spec.rb:41:in `block (2 levels) in <top (required)>'
Finished in 1.08 seconds (files took 2.13 seconds to load)
14 examples, 1 failure
I tried different solution's from stackoverflow but nothing work for me. Below are the different solution's tried.
#expect(current_path).to eql(patient_detail_path(4))
#expect(page).to have_current_path(patient_detail_path(4))
If email and password mismatch it will throw an error and redirect to login page again. In my scenario it was throwing an error even if email and password are valid . If i add below code in my test case it will work pass the test case.
#expect(page).to have_content "Invalid username/password combination"
Any one please help me i am new to ruby on rails and capybara.
I'm guessing the test you're trying to write should be written something like
before :each do
#user = # Create the required user with whatever method you're using
#patient = # Create the required patient with whatever method you're using
end
it "Logs in with valid data" do
visit(patient_detail_path(#patient)) # gets redirected to the login path
fill_in 'email', with: 'kiran#gmail.com'
fill_in 'password', with: 'Kiran.6565'
click_button('submit')
expect(page).to have_current_path(patient_detail_path(#patient))
end
That's a general guess and might not be 100% correct (tough to guess exactly what you're trying to do with half the test missing - the before block - from your question) but the general parts should be there. Since yours isn't logging in I'm guessing you're not actually creating a valid user with the given email and password, or you don't have a patient created with an id of 4 (you really shouldn't be relying on testing specific id numbers in feature tests though).
Additionally, you should always use the have_current_path matcher when checking for a given path/url since it will prevent test flakiness and since it's not a view test it shouldn't be in spec/views/login_spec.rb, more appropriate would be spec/features/login_spec.rb.
It seems to me that the driver is capturing the URL before Rails has a chance to update the URL to reflect the new page.
Asserting on URL is hard after performing a navigation change as a race condition might appear. I would suggest:
Assert on some other piece of info that could verify the user successfully logged in.
Assert using the wait option.
expect(page).to have_current_path(patient_detail_path(#patient), wait: 3)

Testing Rails Shopify App with Capybara & Cucumber (upgrading Shopify plan in test causes authentication error)

I have a Shopify Rails app and I am trying to test some of the functionality of my "pro" plan, but having trouble updating the test shop plan. I can login no problem, but when I try to update my shops plan via capybara, I get redirected to the login page.
I've done some troubleshooting, but I really have no idea where this issue is stemming from because it works fine when I try it manually in my browser. Maybe database_cleaner or caching issue?
Here's my cucumber steps (basically just login to the app, choose a plan):
Background:
Given I am a logged in user
When I am on the pro plan
Capybara:
When "I am a logged in user" do
step "I visit the login page"
step "I supply my shopify url"
step "I get taken to the app index page"
end
When /^I am on the (.+) plan$/ do |plan|
click_link_or_button "Settings & Notifications"
click_link_or_button "edit plan"
choose("shop_plan_#{plan}")
click_link_or_button "Update Plan"
click_link_or_button "Approve charge"
end
The driver successfully authenticates into the app, visits the edit plan page, visits the Shopify "approve charge" authorization page. But after clicking "approve charge", the browser is redirected to the login page instead of the action I am expecting.
When I try this manually in my own browser, I am redirected to the correct page.
Here's the actual controller action when a user updates their plan:
Step 1. User selects plan from settings page - posts to this action, which will redirect user to a page with embedded JS which redirects user to a Shopify authentication page (has to be done this way to escape the embedded app iframe).
def update_plan_step_1
#plan = shop_params[:plan]
redirect_url = current_shop.confirm_plan(#plan)
gon.authorization_url = redirect_url
render :redirect_to_shopify_auth
end
And here is the confirm_plan method. Basically this creates a new Shopify Charge object - Shopify is going to respond with a unique expiring URL for the user to confirm the charge. We need to provide the price, name, and return_url for Shopify to redirect the user after they approve the charge:
def confirm_plan(shopify_plan)
price = Plan.cost(shopify_plan)
name = shopify_plan + "Plan"
return_url = update_plan_step_2_url(:host => Figaro.env.root_uri)
response = ShopifyAPI::RecurringApplicationCharge.create({
:name => name,
:price => price,
:return_url => return_url,
:test=> !Rails.env.production?
})
response.confirmation_url
end
When I pry into this, I can see the return_url is set to the proper location: http://localhost:23456/shop/plans/update_plan_step_2 (shops#update_plan_step_2).
After user approves the charge on Shopify authentication page, they are supposed to be redirected to this action:
def update_plan_step_2
#some code to update our shop record
end
But when I pry into this action, I can see that it's not even being called in the Test, so I know the issue is happening before this.
To summarize, it looks like everything is working until the user is supposed to be redirected to http://localhost:23456/shop/plans/update_plan_step_2. Instead, they are redirected to the authentication page.
Why would this happen in the test, but not when I try doing it manually? Any ideas on where the issue lies?
Logs:
Started GET "/shop/plans/update_plan_step_2?charge_id=12345" for 127.0.0.1 at 2015-10-30 11:09:58 -0700
Processing by ShopsController#update_plan_step_2 as HTML
Parameters: {"charge_id"=>"12345"}
Redirected to http://localhost:23456/login
So we can see user is being redirected to authenticate. Why would this be happening only in test? Could it be a caching issue where the shop session is not being stored in the test? And the session is destroyed when the user is taken off the app to the Shopify authentication page?
EDIT: I know exactly where it's being redirected (in an before action in the controller)
def shopify_session
if shop_session
begin
ShopifyAPI::Base.activate_session(shop_session)
yield
ensure
ShopifyAPI::Base.clear_session
end
else
redirect_to_login ## REDIRECTED HERE
end
end
Which means after user authenticates via Shopify, the shopify_session no longer exists.
Capybara.default_host defaults to 127.0.0.1 which means that all access to your app occurs over http://127.0.0.1/some/path by default when visiting paths in your app with Capybara. When your app redirects to http://localhost/some/path the session cookies stored for the hostname 127.0.0.1 are not valid for hostname localhost so the app redirects to login. Either change your return_url to use a hostname of 127.0.0.1 or change Capybara.default_host to 'localhost' (using 'localhost' for default_host has a few small gotchas when using selenium though, so better to change the return_url)

How do I avoid ambiguous step definitions in Cucumber?

I'm running into ambiguous step definition errors. The following scenarios live in different feature files, and have one identical step: Then I should see my profile page. How do I avoid this from happening?
# authentication.feature
Scenario: Successful sign in
Given I visit the sign in page
When I submit valid sign in information
Then I should see my profile page
# signing_up.feature
Scenario: Successful sign up
Given I visit the sign up page
When I submit valid information
Then I should see my profile page
# authentication_steps.rb
...
Then /^I should see my profile page$/ do
page.current_path.should == user_path(#user)
end
# signing_up.feature
...
Then /^I should see my profile page$/ do
page.current_path.should == user_path(#user)
end
I'm running into this problem with error messages too:
Scenario: Unsuccessful sign up
...
Then I should see an error message
Scenario: Unsuccessful login
...
Then I should see an error message
Why not stay only with the one in authentication_steps.rb ? I think you can use all steps in any feature file

Log in test failing with Devise and Cucumber

I'm using Devise for user Authentication and have the following failing Cucumber scenario:
Scenario: Log in to the system
Given a user called "test" with a password of "secret"
And I am not logged in # Just visits /users/sign_out
When I go to the log in page
And I fill in "user_username" with "test"
And I fill in "user_password" with "secret"
And I press "Sign in"
Then I should see "Signed in successfully."
If I stick a "Then show me the page" at the end I'm shown a page with a blank log in form.
The following (very similar) test works:
Scenario: Fail to log in with invalid credentials
Given a user called "test" with a password of "secret"
And I am not logged in
When I go to the log in page
And I fill in "user_username" with "test"
And I fill in "user_password" with "invalid password"
And I press "Sign in"
Then I should see "Invalid email or password."
... so I'm assuming that the log in does a redirect after a successful validation that Cucumber isn't following (FWIW the log in all works when I do it manually in the browser)... can anyone tell me how to get the test to pass?
Thanks,
Ash
EDIT: It's the last step that is failing with an "expected #has_content?("Signed in successfully.") to return true, got false" error (...ahem... should have mentioned that before!)
is the id field user_username or is it user_email or something?
Also what does When I go to the log in page look like? you sure you go there?
Fixed it! I've just loaded my server with the test environment and reproduced the problem.
I'm using ldap_authenticatable with config.ldap_create_user = true. On the first log in the user account is created if it doesn't exist (which it doesn't in the freshly wiped test db), however this is then redirecting back to the log in page rather than following the root route. Subsequent log ins perform the expected behaviour. So the following test passes:
Scenario: Log in to the system
Given a user called "test" with a password of "secret"
And I am not logged in
When I go to the log in page
And I fill in "user_username" with "test"
And I fill in "user_password" with "secret"
And I press "Sign in"
And I fill in "user_username" with "test"
And I fill in "user_password" with "secret"
And I press "Sign in"
Then I should see "Signed in successfully."
Many thanks to pjammer for the rubber ducking!

Resources