I have a rich frontend in my application. Some of my tests not works well with poltergeist, because of animations and AJAX requests, but works fine with selenium.
How can i use them together in one project and in one test session?
If you're using the standard RSpec configuration with Capybara (require 'capybara/rspec') then you can override the normal driver that would be used for a given test with :driver metadata
it "should do something", driver: :selenium do
# will use the selenium driver for this test
end
it "should do something else", driver: :poltergeist do
# will use the poltergeist driver for this test
end
that could also be specified on the enclosing feature if you want the whole feature to use a specific driver
feature "blah balh", driver: :selenium do
# all scenarios here would use the selenium driver unless overridden with their own :driver metadata
I found solution.
Created macros in spec/support/selenium_macros.rb:
module SeleniumMacros
def use_selenium_webdriver
before(:all) do
Capybara.javascript_driver = :selenium
Capybara.current_driver = :selenium
end
after(:all) do
Capybara.current_driver = :poltergeist
Capybara.javascript_driver = :poltergeist
end
end
end
spec/rails_helper.rb
RSpec.configure do |config|
config.extend SeleniumMacros, type: :feature # add macros for acceptance tests
using example
spec/features/example_feature_spec.rb
feature 'Add files to question' do
use_selenium_webdriver
this feature will be work with selenium, after it will be executed it activates poltergeist webdriver.
P.S. Sorry for my english.
Related
A Rails app that uses remote testing to test a CakePHP app running on a Vagrant Ubuntu VM.
My OS is macOS High Sierra.
'rspec/rails'
'capybara/rails'
'capybara/mechanize'
'capybara/poltergeist'
'phantomjs'
If I run rspec ./spec/features/my_tests_folder/,
the first 2 tests in the folder always pass and the rest always end up with Capybara::Poltergeist::TimeoutError:.
If I run any of the tests in that folder individually, they ALL pass ALWAYS.
There are 7 test files total. They each have 1 feature with 1 scenario. All are js: true.
I have tried increasing :timeout in Capybara.register_driver and increasing default_max_wait_time in Capybara.configure. Neither changed the outcome.
I've also played around with Capybara.reset! after and before each test. It didn't seem to matter, either.
When I ran this with config.order = :random, sometimes 5 out of 7 had the erros, sometimes only 2 out of 7. But, there were always some errors and some passing. Also, every test was in the errors group at least once.
I'm running out of ideas. What could cause something like this?
UPDATE (to include Capybara and Poltergeist configs and example of a failing test):
Configs in rails_helper.rb:
Capybara.register_driver :poltergeist do |app|
options = {
:timeout => 90, # default is 30
:js_errors => false,
:phantomjs => Phantomjs.path,
# :debug => true
}
Capybara::Poltergeist::Driver.new(app, options)
end
Capybara.register_driver :mechanize do |app|
driver = Capybara::Mechanize::Driver.new(app)
driver.configure do |agent|
agent.user_agent_alias = 'Mac Safari'
end
driver
end
Capybara.configure do |config|
config.run_server = false
config.app_host = "http://my_vm_domain.com"
config.javascript_driver = :poltergeist
config.default_driver = :mechanize
config.default_max_wait_time = 10 # default is 2
end
Example of failing test (not failing, but getting Capybara::Poltergeist::TimeoutError:):
require 'rails_helper'
feature 'agente visualiza estoques de um passeio', js: true do
scenario 'com sucesso' do
agente_log_in
visit '/roteiro/show/723'
find(:partial_href, 'new_passeio/723').click
select 'Passeio Teste', from: 'passeio_produto'
fill_in 'passeio_data', with: '11/11/2017'
within('button#estoque_controls_0') do
within('div#estoque_0_hora') do
expect(page).to have_content('07:30')
end
within('span#estoque_0_vagas') do
expect(page).to have_content('3')
end
end
within('button#estoque_controls_1') do
within('div#estoque_1_hora') do
expect(page).to have_content('10:00')
end
within('span#estoque_1_vagas') do
expect(page).to have_content('5')
end
end
end
end
Code from agente_log_in.rb in support folder:
def agente_log_in
Capybara.app_host = "http://my_vm_domain.com"
visit '/usuario/logout'
visit '/'
fill_in 'data[AdmUsuario][usuario]', with: 'agente'
fill_in 'data[AdmUsuario][senha]', with: 'pa$$w0rd'
click_on 'Entrar'
end
Code for that :partial_href find:
module Selectors
Capybara.add_selector(:partial_href) do
xpath {|href| XPath.descendant[XPath.attr(:href).contains(href)] }
end
end
Everything is fine with the other tests that are in the app's other folders. They're also fine if I run the tests in this folder individually. The problem only seems to happen when I run THIS specific folder as a whole.
After including the extra information requested by Thomas Walpole, I continued searching and studying possibilities.
I eventually came across poltergeist's issue #781 on GitHub, which describes a situation very similar to mine, and eventually presents a wait_for_ajax solution.
Before implementing it in my project, I read more about waiting for Ajax and found this post very helpful, too.
In the end, I chose jasonfb's code from GitHub because it seemed more thorough and informative.
It worked like a charm! My tests now pass consistently. I was even able to remove customization for :timeout and default_max_wait_time.
The CakePHP app in question is very js heavy and the specific part that this folder tests is particularly full of Ajax requests.
I have the following code:
RSpec.configure do |config|
# ...
config.before(:each, billy: true) do
Capybara.current_driver = :poltergeist_billy
end
config.after(:each, billy: true) do
Capybara.use_default_driver
end
end
So every spec tagged with :billy is executed with :poltergeist_billy capybara driver.
But I have plenty of drivers in my application. I want to restore previously used driver, not just to fall back to default when I execute billy-test.
What's the best way to restore the driver and where should I keep this variable?
I would like to switch to webkit_billy (the Javascript driver of Puffing Billy gem) only in certain tests. I want to be able to use:
describe "xxx", billy: true do
end
This should signal to RSpec that I want to switch to puffing billy driver.
I wrote this in spec_helper.rb but it's not working:
config.before(:each) do |example|
if [:billy].include? example.metadata[:type]
Capybara.current_driver = :webkit_billy
Capybara.javascript_driver = :webkit_billy
else
Capybara.current_driver = :webkit
Capybara.javascript_driver = :webkit
end
end
Capybara.javascript_driver is only used (with normal configuration) when js: true metadata is added to the test so there is no need to keep resetting the value of javascript_driver to :webkit_billy since all that would do is affect any further tests with the js metadata. You can see the default behavior implementation (when you require capybara/rspec) here
What this does is initially set the driver for the test to whatever Capybara.default_driver is, then if the js metadata exists it sets the driver to the value of Capybara.javascript_driver, and then if driver metadata exists it sets it to that - ie. driver metadata takes priority over 'js' and if nothing you just get default_driver. What this means is without any extra additions you could just specify driver: :webkit_billy on a test and get :webkit_billy used for that test.
To add your desired behavior of being able to specify billy: true you just need
RSpec.configure do |config|
config.before(:each, billy: true) do
Capybara.current_driver = :webkit_billy
end
end
somewhere after you've required 'capybara/rspec' but before your database cleaner configuration is defined. Then set Capybara.default_driver to whatever driver you want to use when no metadata is specified, and Capybara.javascript_driver to whatever driver you want to use when js metadata is specified. So - if you wanted to always use the :webkit driver (other than when billy is specified) set Capybara.default_driver = :webkit and you never need to specify js: true , but can always make specific tests use rack_test by adding driver: :rack_test metadata to a specific test.
Note: This supposes you are using the recommended database_cleaner config - https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example - which changes database strategy based on the actual driver being used and not just based on the presence of the js metadata.
how about you try this:
config.before(:each, billy: true) do |example|
Capybara.current_driver = :webkit_billy
Capybara.javascript_driver = :webkit_billy
end
or to go your current approach, you'd do:
config.before(:each) do |example|
if example.metadata[:billy] # this should either be true or nil
Capybara.current_driver = :webkit_billy
Capybara.javascript_driver = :webkit_billy
else
Capybara.current_driver = :webkit
Capybara.javascript_driver = :webkit
end
end
My setup is using poltergeist as the Capybara driver for all my tests, both JS and non-JS.
# spec/rails_helper.rb
require "capybara/poltergeist"
# ...
# ...
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, js_errors: true)
end
Capybara.configure do |config|
config.ignore_hidden_elements = true
Capybara.default_driver = :poltergeist
Capybara.javascript_driver = :poltergeist
end
I have some tests where I confirm that certain features on my app are still working even with javascript disabled. For those tests, I of course disable javascript with js: false.
describe "accessibility" do
describe "JavaScript disabled", js: false do
before(:each) { visit root_path }
it "user can still log in" do
# ...
end
end
end
However, I'm noticing that these js:false tests still use JavaScript. I can confirm this by printing debug statements to the console log in JavaScript.
Is there a way to disable JavaScript when using poltergeist? Or is it always enabled? Is it even valid to use poltergeist as a non-JS driver?
Thanks!
No, there doesn't seem to be a way to use poltergeist without Javascript (unless you modify poltergeist yourself). According to this Github issue it would require support in phantomjs, which is available in a patch but not in master.
I am using Cucumber with Selenium, FixtureReplacement and DatabaseCleaner.
Funnily enough, my data I created with FixtureReplacement is not accessible from my tests.
I have added an own rails environment for selenium and I am using an own profile for my enhanced selenium features.
My cucumber setup for the selenium profile is:
Webrat.configure do |config|
config.mode = :selenium
config.application_environment = :selenium
end
Cucumber::Rails::World.use_transactional_fixtures = false
require "database_cleaner"
# Clean the database once when starting
DatabaseCleaner.clean_with :truncation
DatabaseCleaner.strategy = :truncation
Before do
DatabaseCleaner.start
include FixtureReplacement
end
After do
DatabaseCleaner.clean
end
# this is necessary to have webrat "wait_for" the response body to be available
# when writing steps that match against the response body returned by selenium
World(Webrat::Selenium::Matchers)
FixtureReplacement works well, I have tested it in the Rails console.
I am running my selenium features with:
RAILS_ENV=selenium cucumber -p selenium features/enhanced/test.feature
Does anybody know a solution to this problem?
Best regards
I wonder if you are using Database Cleaner correctly? In my env.rb, I am using it like this:
Before do
require 'database_cleaner'
require 'database_cleaner/cucumber'
DatabaseCleaner.strategy = :truncation
end
This works for me when using Factory Girl.
This had nothing to do with Fixtures. I thought I cannot access my data, because I couldn't login.
The following fixed it:
Cucumber + selenium fails randomly