How can I make tests DRY in Rails and still use Capybara and Warden? (using minitest) -
my intention create few tests same form, , in these tests need capybara fill form completely. still, wanted avoid rewriting code filling form.
i'm not using rspec! i'm using minitest.
the problem i'm facing capybara method visit , warden helper method login_as not accessible capybarahelper module.
i've seen question, created module in test/support folder, methods mentioned still not accessible. how reuse code in capybara
i've seen question, code want reuse doesn't seem fit in setup method nor in teardown method. rails: premake model instance unit tests (for dry purposes)?
i've seen posts saying module should inside test_helper.rb, add more modules file messy.
so i'm wondering i'm doing wrong. i've tried adding following lines capybarahelper didn't help. raised error nomethoderror: undefined methodsetup' capybarahelper:module`.
include devise::test::controllerhelpers include warden::test::helpers is right way reuse code in tests? missing should included in helper module? methods work in test controller using capybarahelper:module.
here error message:
nomethoderror: undefined method `login_as' capybarahelper:module and here error message test using capybarahelper:module.
nomethoderror: undefined method `visit' capybarahelper:module here's test:
require 'test_helper' class travelscontrollertest < actioncontroller::testcase include devise::test::controllerhelpers include warden::test::helpers warden.test_mode! test 'should accept correct fields' capybarahelper.login result = capybarahelper.access_and_fill_travel_page assert_equal "/travels/success/#{travel.last.uuid}", result[:final_path] end end and here's helper created in test/support/capybara/capybara_helper.rb avoid code duplication:
require 'test_helper' require 'capybara/rails' require 'capybara/poltergeist' module capybarahelper def self.access_and_fill_travel_page options = {} options.symbolize_keys! set_js_driver visit(rails.application.routes.url_helpers.root_path) initial_path = current_path #fields fill_in('origin', with: options[:origin] || 'guarulhos') fill_autocomplete('origin', with: options[:origin] || 'guarulhos') fill_in('destination', with: options[:destination] || 'seul') fill_autocomplete('destination', with: options[:destination] || 'seul') fill_in('date_from', with: options[:date_from] || date.today+10) fill_in('date_to', with: options[:date_to] || date.today+26) fill_in('adults', with: options[:adults] || 1) fill_in('children', with: options[:children] || 0) fill_in('babies', with: options[:babies] || 0) find('#travel-submit').click() final_path = current_path return {initial_path: initial_path, final_path: final_path} end def self.fill_autocomplete(field, options = {}) page.execute_script %q{ el = $('input[name=#{field}]').get(0) } page.execute_script %q{ $(el).trigger('focus') } page.execute_script %q{ $(el).trigger('keydown') } page.all('.ui-menu-item', minimum: 1) page.execute_script %q{ item = $('.ui-menu-item').get(0) } page.execute_script %q{ $(item).trigger('mouseenter').click() } end def self.set_js_driver capybara.javascript_driver = :poltergeist capybara.current_driver = capybara.javascript_driver end def self.login user = factorygirl.create(:user) login_as(user, :scope => :user) end end
you should use actiondispatch::integrationtest , not actioncontroller::testcase parent class tests using capybara. actioncontroller::testcase mocks out request phase , large parts of rails. depreciated in rails 5.
instead of calling methods on test helper module should mix them test classes.
class travelsintegrationtest < actiondispatch::integrationtest include devise::test::controllerhelpers include warden::test::helpers include capybarahelper warden.test_mode! test 'should accept correct fields' login # ... end end module capybarahelper def login(user = factorygirl.create(:user)) login_as(user, scope: :user) end end apart lacking in code organization - setup steps setting warden.test_mode! should done in test_helper.rb not repeated across tests. don't throw step definitions single file either. can place them in /test/support/ example.
module sessionhelper def login(user = factorygirl.create(:user)) login_as(user, :scope => :user) end end module travelhelper def access_and_fill_travel_page # ... end end and if want keep dry use inheritance setup test classes:
class baseintegrationtest < actiondispatch::integrationtest include devise::test::controllerhelpers include warden::test::helpers include sessionhelper end class travelsintegrationtest < baseintegrationtest test 'should accept correct fields' login # ... end end
Comments
Post a Comment