Feature specs on https pages with capybara + poltergeist - ruby-on-rails

I've been trying to create a feature spec with "js: true" for a https page.
I'm using Rails4.2 + rspec + capybara + poltergeist.
I can test http pages with capybara + poltergeist without any problem. However, I can't find a way to test https pages with capybara + poltergeist.
Can anyone guide me on how to accomplish this?
spec/rails_helper.rb
require 'capybara/rspec'
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(
app,
phantomjs_options: [
'--debug=no',
'--load-images=no',
'--ignore-ssl-errors=yes',
'--ssl-protocol=TLSv1'
],
debug: false
)
end
https_spec.rb
require 'rails_helper'
RSpec.feature 'https' do
let(:admin) { create(:admin) }
scenario 'display admin dashboard', js: true do
login_as(admin, scope: :user)
visit admin_dashboard_index_path
expect(page).to have_text('TEST')
end
end
I get this message
Failures:
1) https display admin dashboard
Failure/Error: Unable to find matching line from backtrace
RuntimeError:
tried to create a new session when on http, but https is required

Maybe this is the solution to your problem:
http://cowjumpedoverthecommodore64.blogspot.com/2013/09/if-your-website-runs-under-ssl-than.html

Related

RSpec - Capybara and Puma - Routing Error

I'm trying to use Capybara as a front-end test suite (Vue) and I'm getting the following error from Puma:
Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
ActionController::RoutingError:
No route matches [GET] "/login"
What is the cause of this and how can I fix this? Is it something to do with the config? Let me know if I should include more code in my question.
rails_helper.rb:
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require "pundit/rspec"
require "capybara/rails"
require "capybara/rspec"
require "capybara/poltergeist"
require 'database_cleaner'
require 'factory_girl'
require 'shoulda/matchers'
require "paperclip/matchers"
require 'support/spec_helpers/warden_controller_helpers'
require 'webmock/rspec'
require 'support/spec_helpers/webmock_helper'
Capybara.javascript_driver = :poltergeist
login_spec.rb:
require 'rails_helper'
RSpec.feature "User login", type: :feature, js: true do
before :each do
#user = User.create!(
first_name: "Bob",
last_name: "Brown",
email: "bob#email.com",
password: "bob1",
has_accepted_terms: true
)
end
scenario "User logs in with correct credentials" do
visit root_path
save_screenshot
click_on 'Log In'
sleep 1
save_screenshot
end
end
So if I run the dev server and go to 'localhost:3000 (which is basically what you're telling Capybara to do) then there is a broken 'Log In' link on the page that points to app.localhost:3000/login which the app doesn't handle. This is because visiting a URL without the app subdomain uses the application.html.haml layout which includes no JS (and therefore no Vue router to handle the /login path). If however I go to app.localhost:3000 in the browser then there's a page with a working Log In link since all the JS is loaded on that page (including the Vue router) because it uses the app.html.haml layout (BaseController)
You need to fix the main homepage link to function correctly and/or configure Capybara to connect to the app subdomain by default
Capybara.app_host = 'http://app.localhost' # hostname with ‘app’ sub domain that resolves to interface the AUT is being run on
Capybara.always_include_port = true
Basically Capybaras telling you your apps main page is broken because it is broken.

Capybara error with Poltergeist and RSpec

I am trying to write a simple spec with Capybara using the Poltergeist driver in RSpec. There doesn't seem to be a problem when tests should fail , however when I am expecting a passing test I get the following error:
~/.rbenv/versions/2.2.3/lib/
ruby/gems/2.2.0/gems/poltergeist-1.6.0/lib/capybara/poltergeist/errors.rb:17:in
`initialize': wrong number of arguments (0 for 2) (ArgumentError)
I navigated to where the the line of code the error was indicating:
class JSErrorItem
attr_reader :message, :stack
def initialize(message, stack)
#message = message
#stack = stack
end
def to_s
[message, stack].join("\n")
end
end
But I was unable to find anywhere that I should be interacting with this constructor.
This is the spec that I am writing
describe 'Sign Up', type: :feature do
it 'should allow user creation through the signup form' do
visit new_user_url host: 'http://localhost:3000'
within('.form') do
fill_in('user[username]', with: 'Example')
fill_in('user[password]', with: 'Password')
fill_in('user[password_confirmation]', with: 'Password')
find(".submit-button").click
puts page.body
expect(page).to have_content('Welcome')
User.last.destroy!
end
end
end
The puts page prints the content of the page as expected but after the error occurs and the remainder of the lines in the spec are not run. Oddly enough the error only occurs when I am expecting the spec to pass. When I am expecting a failing test the entire spec runs without error.
My spec helper was set up as below:
RSpec.configure do |config|
require 'capybara/rspec'
require 'capybara/poltergeist'
require 'capybara/dsl'
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, time_out: 120, phantomjs_options: ['--ignore-ssl-errors=yes'], js_errors: false)
end
Capybara.configure do |c|
c.javascript_driver = :poltergeist
c.default_driver = :poltergeist
c.app_host = 'http://localhost:3000'
end
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
I upgraded Poltergeist to 1.9 and PhantomJS to 2.1 as suggested in the comments and it fixed the issue.

Capybara and poltergeist test failing

I been using :firefox drivers for capyabara and this test was passing but when I switch to poltergeist driver the test been failing now with the following error:
Minitest::UnexpectedError: Capybara::ElementNotFound: Unable to find field "email"
Here is the capybara and poltergeist setup:
def setup
# FactoryGirl.lint
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.start
Capybara.run_server = true
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, :js_errors => false)
end
Capybara.default_driver = :poltergeist
Capybara.current_driver = :poltergeist
Capybara.javascript_driver = :poltergeist
Capybara.app_host = 'http://localhost:4200'
Capybara.server_port = 3000
Capybara.default_max_wait_time = 5
end
Here is the test:
test "User should be able to signin" do
visit '/'
wait_for_ajax
fill_in 'email', with: #user.email
fill_in 'password', with: #user.password
assert true
end
So, when I changed the driver to :selenium the test pass with no error.
How do I setup/fix poltergeist to pass this test?
I took screenshot and it shows loading indicator which is a div that is removed in afterModel Ember hook using the following code:
_ember['default'].$('.ember-load-indicator').remove();
For Ajax calls we have the following function as test helper to wait for ajax calls:
def wait_for_ajax
Timeout.timeout(Capybara.default_wait_time) do
loop until finished_all_ajax_requests?
end
end
def finished_all_ajax_requests?
page.evaluate_script('jQuery.active').zero?
end
I suspect it's a timing issue... When using poltergeist vs a browser, you can get these weird behaviours, where an element is present, but not really loaded hence the error... An easy way to confirm this is by putting a sleep prior to fill_in email... put sleep 10 just to be safe...
Additional tip:
To help debug headless tests, consider adding screenshots on failures -
Add this to the end of your Capybara setup:
Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
"screenshot_#{example.description.gsub(' ', '-').gsub(/^.*\/spec\//,'')}"
end
screenshot_path = "#{PROJECT_ROOT}/screenshot/"
Capybara.save_and_open_page_path = screenshot_path

How correctly config rails test to run it in browser? ( site_prism, cucumber, capybara, selenium webdriver )

I am writing test for rails app, I use site_prism, capybara, selenium and cucumber.
How can I setup Selenium driver to run my tests in browser (firefox)?
For example, it is one of features:
Given /^I navigate to Dashboard page$/ do
#page = DashboardPage.new # Dashboardpage is inheritor of SitePrism::Page
#page.load
#page.login_form.login_field.set 'admin'
#page.login_form.password_field.set 'test'
#page.login_form.signin_button.click
#page.title.include? 'Dashboard'
end
This is my features/support/env.rb config file:
require 'cucumber/rails'
require 'capybara'
require 'capybara/cucumber'
require 'selenium-webdriver'
require 'site_prism'
# cypabara settings
Capybara.default_selector = :css
Capybara.ignore_hidden_elements = false
Capybara.default_wait_time = 20
Capybara.app_host = "http://0.0.0.0:9292"
# selenium setting
Capybara.register_driver :selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
Capybara::Selenium::Driver.new( app, :browser => :firefox, :profile => profile )
end
# enable/disable rescue
ActionController::Base.allow_rescue = false
# DB cleaner strategy
begin
DatabaseCleaner.strategy = :transaction
rescue NameError
raise "You need to add database_cleaner to your Gemfile to use it."
end
# JS strategy
Cucumber::Rails::Database.javascript_strategy = :truncation
I know, with capybara I can run scenario in browser like this:
Capybara.app_host = 'http://0.0.0.0:9292'
session = Capybara::Session.new(:selenium)
session.visit '/home'
session.driver.browser.quit
But! Using site_prism, I just have Page#load method. Maybe I need to integrate load method with capybara session, but how can I do this?
Mostly, I do everything as it's described in documentation (cypabara wiki on github), but my tests runs without browser. And I can't understand why.
Please, help. Thanks.
Actually you've set up browser in selenium setting:
Capybara.register_driver :selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
Capybara::Selenium::Driver.new( app, :browser => :firefox, :profile => profile )
end
By default selenium driver use firefox as default browser.
You can set it in capybara settings:
Capybara.default_driver = :selenium
For site_prism you need such requirements:
require 'capybara'
require 'capybara/dsl'
require 'capybara/cucumber'
require 'selenium-webdriver'
require 'site_prism'

Tests using rspec, capybara and poltergeist return empty html and empty screenshots

So I've been struggling with this for quite some time now and I can't seem to figure our what's going wrong, and couldn't find much on what could possibly cause this issue.
I'm relatively new to Ruby and Rails, as well as test/behavior driven development and am trying to write some acceptance (browser) tests using PhantomJS through Poltergeist, using Rspec and Capybara. I believe some people also call this integration tests (they may be from some perspective), but that's a whole other discussion.
I have a really simple feature that I can't get to do what I want:
require 'feature_helper'
feature 'Logging in', :js => true do
scenario 'with incorrect credentials' do
visit '/login'
puts page.html
save_and_open_page
page.driver.render('_screenshot.png', :full => true)
page.html.should have_selector("title", :text => "hi")
end
end
So. Simple, right. It should just go to /login and throw the HTML content at me, as well I want to see the page using save_and_open_page, and I want it to take a screenshot. I added a simple should have_selector in order to have the test fail in an attempt to get more feedback.
The relative contents of my feature_helper.rb:
require 'spec_helper'
require 'capybara/rspec'
require 'capybara/rails'
require 'capybara/poltergeist'
include Capybara::DSL
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {
:debug => true,
:inspector => true
})
end
Capybara.default_driver = :poltergeist
Capybara.javascript_driver = :poltergeist
FakeWeb.allow_net_connect = %r[^https?://(127.0.0.1|localhost)] # allow phantomjs/poltergeist requests
DatabaseCleaner.strategy = :truncation
RSpec.configure do |config|
config.before :each do
# Set the hostname to something with test
#host = "test.iome:3003"
host! #host
Capybara.default_host = Capybara.app_host = "http://#{#host}/"
Capybara.server_port = 3003
Capybara.reset_sessions!
# Start the database cleaner
config.use_transactional_fixtures = false
DatabaseCleaner.start
end
config.after :each do
DatabaseCleaner.clean
end
end
And also my spec_helper.rb:
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'pry'
require 'fakeweb'
FakeWeb.allow_net_connect = false
It's all fairly simple.
Now, in my console I see the following:
{"name"=>"visit", "args"=>["http://test.iome:3003//login"]}
{"response"=>{"status"=>"fail"}}
{"name"=>"body", "args"=>[]}
{"response"=>"<html><head></head><body></body></html>"}
<html><head></head><body></body></html>
{"name"=>"body", "args"=>[]}
{"response"=>"<html><head></head><body></body></html>"}
{"name"=>"render", "args"=>["_screenshot.png", true]}
{"response"=>true}
{"name"=>"body", "args"=>[]}
{"response"=>"<html><head></head><body></body></html>"}
Also, the screenshot is just a white and empty page. When I tail my log/test.log file, I don't see that a request is being performed. I've tried changing the method visit to get, and that'll make the request, but won't change any of the results.
I've completely run out of ideas of what this could be and it's rather frustrating :(
Final information then about versions:
rspec 2.10.0
capybara 1.1.4
poltergeist 1.0.3
ruby 1.8.7
rails 3.2.13
Unfortunately we're still at ruby 1.8.7, but are working on bumping that version up. Still, I think this shouldn't influence the tests.
Any help would be greatly appreciated!
So eventually I got help from a colleague, and we managed to fix it. We used the lvh.me domain for this, as any request to that domain will resolve in localhost, allowing you to use subdomains without a problem. You could probably also use hostname.127.0.0.1.xip.io for this.
Our spec_helper.rb now looks like this:
# Use capybara in combination with poltergeist for integration tests
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara/poltergeist'
require 'rack_session_access/capybara'
Capybara.default_driver = :poltergeist
Capybara.always_include_port = true
Capybara.app_host = 'http://application-test.lvh.me' # Any lvh.me domain resolves to localhost
Capybara.default_wait_time = 8 # How long capybara should look for html elements
require 'vcr'
VCR.configure do |config|
config.cassette_library_dir = 'spec/vcr_cassettes'
config.hook_into :fakeweb
config.ignore_localhost = true
config.configure_rspec_metadata!
config.ignore_hosts 'codeclimate.com'
end
require 'fakeweb'
FakeWeb.allow_net_connect = false
Because we hooked in VCR to record any requests going out during the first run of the integration tests, all your integration tests, or features, should contain this code:
before(:all) do
FakeWeb.allow_net_connect = true
end
after(:all) do
FakeWeb.allow_net_connect = false
end
If you want to change the subdomain during your specs, you can use the following:
before(:each) do
#original_host = Capybara.app_host
Capybara.app_host = 'http://does-not-exist.lvh.me'
visit '/login'
end
after(:each) do
Capybara.app_host = #original_host
end
Making screenshots can now be done using page.save_screenshot during specs. Hope this helps.

Resources