Login using headers in cucumber - ruby

I'm new at cucumber and capybara so maybe this is easy.
I'm using headers to check if a user is logged in or not and i'm having a problem when doing cucumber testing.
I use Capybara and Cucumber and a "add headers hack": http://aflatter.de/2010/06/testing-headers-and-ssl-with-cucumber-and-capybara/
The problem I have is that it only sets the header once in each feature story. So if I have a story that goes trough more than one step the header is gone and the user is no longer logged in.
An example story:
Given I am logged in as a superuser
And I have a database "23456789" that is not active
And I am on the home page
When I follow the "Delete" link for "23456789.sqlite"
Then I should see "Deleted the database"
In this story the "When I follow the "Delete" link for "23456789.sqlite" line will not work since the user is no longer logged in!
Have thought about using session or the before/after in cucumber.
Does someone have a clue on how to fix this?

You can achieve this by passing the username in an environment variable:
When /^I am logged in as a superuser$/ do
ENV['RAILS_TEST_CURRENT_USER'] = 'admin'
end
application_controller.rb:
before_filter :stub_current_user
def stub_current_user
if Rails.env == 'cucumber' || Rails.env == 'test'
if username = ENV['RAILS_TEST_CURRENT_USER']
#current_user = User.find_by_username(username)
end
end
end

Related

How to visit link in email opened with letter_opener gem

I am working on some QA automation using Cucumber and Capybara and have a step:
When(/^I follow the reset password link in the email$/) do
last_email = ActionMailer::Base.deliveries.last
password_reset_url = last_email.body.match(/http.*\/users\/password\/edit.*$/)
visit password_reset_url
end
The step fails with:
undefined method `body' for nil:NilClass (NoMethodError)
Additionally, dropping binding.pry after the first line results in nil for last_email which is weird.
Does anyone have advice or thoughts on why that may be happening here?
If you're using letter_opener then emails aren't going to ActionMailer deliveries and are being opened in a browser not controlled by Capybara. If you want to work with emails in capybara you should probably be looking at the capybara-email gem rather than letter_opener. Letter_opener is aimed more at the dev environment rather than test
Tom Walpole's answer is absolutely correct in content and pointing you in the direction of the capybara-email gem.
Here's a potential example of how you could change your code sample, assuming that you have another Cucumber step that has clicked a button/link to send reset password instructions:
When(/^I follow the reset password link in the email (.*)$/) do |email|
# finds the last email sent to the passed in email address.
# This also sets the `current_email` object, which you can think
# of as similar to Capybara's `page` object, but for an email.
open_email(email)
# Assuming the email link to change your password is called
# 'Change my password', you can just click it, just as you would
# on a Capybara `page`.
current_email.click_link 'Change my password'
end
After clicking the link, you will be taken to whatever page where you can continue on to fill_in 'New password', with: 'foobar' etc, which I'm assuming you've got covered in another Cucumber step.

Mechanize suddenly can't login anymore

I have been trying to login to my airbnb account to scrape all my reservations. I was able to login and get the status of the reservation to appear with the following code but all of a sudden, it seems like I have been blocked out of Airbnb. The script would usually return all of the reservations' status nicely lined up and after calling the script for about 6 hours straight trying to figure out how to get this to work I suddenly couldn't get it to return the /my_reservations page anymore.
When I called
puts page.body
it kept returning the /log_in page
I can still access my account manually through the browser though. Does anyone know anything about this? Any advice is greatly appreciated.
require 'mechanize'
require 'nokogiri'
agent = Mechanize.new {|a| a.user_agent_alias = "Mac Firefox"} page = agent.get('http://www.airbnb.com/my_reservations')
form = agent.page.form_with(action: "/authenticate") form.field_with(name: "email").value = "my_email#provider.com" form.field_with(name: "password").value = "my_password" form.submit
puts page.search('.label').text

Rspec selenium not finding data after returning from outside url without setting environment to development

I am having a strange problem with feature testing a paypal authorization with rspec using selenium. When returning to my site from paypal, it claims is cannot find the necessary data with that specific id, but it seems to find another piece of data. I printed the data to the terminal in the test and it WAS there. When I changed my environment in the spec_helper (I know this is bad) to development it worked.
Here is the error:
Couldn't find PaypalPreapproval with id=1
And here is the code in my controller
def show
user = User.find(params[:user_id])
preapproval = PaypalPreapproval.find(params[:id])
preapproval.activate
send_welcome_message(user) if user.addresses.count == 1
end
It is the PaypalPreapproval.find(params[:id]) that is causing the error, although the line above seems to be able to find the User with that id.
This is my temporary fix that works in my spec_helper
if Capybara.current_driver == :selenium
ENV["RAILS_ENV"] ||= 'development'
else
ENV["RAILS_ENV"] ||= 'test'
end
Anyone have any ideas?
I solved it. When running selenium it randomly generates a port number and fires up that server. Once your test travels outside of your server (an outside url) your return url needs to include the port that is running your test server. I added this to my spec_helper:
Capybara.server_port = 4000
I already had an environment variable set for my base_url as
ENV['BASE_URL'] = "http://localhost:3000"
and I just specified it to be
ENV['BASE_URL'] = Rails.env.test? ? "http://localhost:4000" : "http://localhost:3000"
Hopefully this saves someone else a half-day of debugging.

How do I use Devise to secure the delayed_job_web interface?

I'm using the delayed_job_web gem to monitor delayed jobs. https://github.com/ejschmitt/delayed_job_web
It is accessible using this line in my routes.rb:
match "/delayed_job" => DelayedJobWeb, :anchor => false
Every other area of my site requires a login using the Devise gem. How do I make this require a login too?
In the readme, they suggest adding the following to the config.rb:
if Rails.env.production?
DelayedJobWeb.use Rack::Auth::Basic do |username, password|
username == 'username'
password == 'password'
end
end
But that just uses plain text browser authentication.
UPDATE:
I tried something similar to the railscast on resque, and I think it's on the verge of working but giving me a redirect loop now:
authenticate :admin do
mount DelayedJobWeb, :at => "/delayed_job"
end
Any thoughts on why would it be giving a redirect loop?
Thanks,
Use authenticated instead of authenticate as described here: http://excid3.com/blog/rails-tip-5-authenticated-root-and-dashboard-routes-with-devise/
Works for me!
You could do something like this define this inside config/routes.rb file
authenticate_user = lambda do |request|
request.env['warden'].authenticate?
end
constraints authenticate_user do
mount DelayedJobWeb, :at => "/delayed_job"
end
Alternately if you have cancan for any other role management library you could do it something like this
I have used both of this in my applications to control access to resque-web depending on the needs of the application
Hope this help
Now it's 2017 I tried the other solutions and they didn't work, but the following admin check does work:
authenticated :user, -> user { user.admin? } do
mount DelayedJobWeb, at: "/delayed_job"
end

Using Cucumber to test controller without a view in Rails

I'm a ruby/rails newbie and the application I'm developing starts with a HTTP post from another website which passes in some data and then displays some data capture screens before calling a web service.
I want to start this project using an outside in approach using Cucumber for integration tests and rspec for functional/unit testing.
Using Cucumber how do I simulate the post from the external website so that I can test the flows with the application.
It doesn't really matter to the application where the call originated; only that the parameters supplied match the expected ones from the referring page. If you depend on a specific HTTP_REFERER being set, check out this answer on how to set a header in Cucumber.
add_headers({'HTTP_REFERER' => 'http://referringsite.com'})
Since you already know which query parameters/headers your app expects from the referring site you can create a setup block that will set these appropriately for each cuke.
If you are using Cucumber with Capybara you can do a HTTP POST like this.
When /^I sign in$/ do
#user = Factory(:user)
get "/login"
page.driver.post sessions_path, :username => #user.username, :password => #user.password
end
Alternatively if you have a view it would be something like this.
When /^I sign in$/ do
#user = Factory(:user)
visit "/login"
fill_in "Username", :with => #user.username
fill_in "Password", :with => #user.password
click_button "Log in"
end

Resources