Reputation: 713
When I run my system test using rails test:system
I receive the following error:
Error:
PaymentSessionsTest#test_payment_succesful_if_valid_details_provided:
NoMethodError: undefined method `expect' for #<PaymentSessionsTest:0x00007fffd82485d0>
Did you mean? exec
test/system/payment_sessions_test.rb:26:in `block in <class:PaymentSessionsTest>'
I am writing my first system test for rails and I have a page that takes a while to load. From the Capybara documentation it recommends using the expect
method eg. expect(page).to have_current_path(payment_success_url)
which will use Capybara's waiting behaviour (so the test doesn't time out before the page has loaded). However, when I do this I receive the error above.
I'm a little confused as to whether expect
is part of Capybara or RSpec. It's in Capybara's documentation so I assume it should just work but I'm currently stuck.
# test\system\payment_sessions_test.rb
require "application_system_test_case"
class PaymentSessionsTest < ApplicationSystemTestCase
setup do
@event = events(:one)
end
test "payment successful if valid details provided" do
# Enter payment details on invite page
visit event_url(@event)
fill_in "Your name", with: "John Doe"
fill_in "Email", with: "[email protected]"
fill_in "Gift amount", with: "20"
click_on "Pay"
# Stripe Checkout
fill_in "cardNumber", with: "4242424242424242"
fill_in "cardExpiry", with: "01#{Date.today.next_year.strftime("%y")}" # grab year always as next year in 2 digit format
fill_in "cardCvc", with: "123"
fill_in "Name on card", with: "Mr John Doe"
fill_in "billingPostalCode", with: "N1 7GU"
click_on "Pay"
# Payment success page
expect(page).to have_current_path(payment_success_url) # ensure Capybara waits for page to load after clicking Pay
assert_selector "h1", text: "Payment successful!"
end
end
# test\application_system_test_case.rb
require "test_helper"
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :selenium, using: :chrome, screen_size: [1400, 900]
# driven_by :selenium, using: :headless_chrome
def setup
# ensure url helpers use correct host and port for system tests
Rails.application.routes.default_url_options[:host] = Capybara.current_session.server.host
Rails.application.routes.default_url_options[:port] = Capybara.current_session.server.port
end
end
# test\test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'
require 'bcrypt' # required for devise (used when creating encrypted password for user fixtures)
require 'pry'
class ActiveSupport::TestCase
include HashidsHelper
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
include Devise::Test::IntegrationHelpers # include devise test helpers in all tests
setup do
# set hashid for each event record
# NB. can't set using fixtures as event.id is dynamic
FixMissingHashidsService.run
end
end
# Gemfile
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of chromedriver to run system tests with Chrome
# gem 'chromedriver-helper'
# Using chromedriver in Windows, added to path, via WSL1
end
expect
run fine)Upvotes: 0
Views: 2136
Reputation: 713
I solved this by doing the following:
expect
line from the test (this is indeed part of RSpec and not Capybara - thanks @artur.prado)Capybara.default_max_wait_time = 20
to application_system_test_case.rb
(I set 20 because the Stripe Checkout test gateway is very slow. The beauty of Capybara being that it doesn't wait the whole 20 seconds, just 'up to' 20 seconds - it will run as soon as it is able). There may be other implications to doing this, given Capybara sets the default at 2 seconds. Given this test is interacting with a 3rd party domain I am ok with it, but buyer beware.# test\application_system_test_case.rb
require "test_helper"
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :selenium, using: :chrome, screen_size: [1400, 900]
# driven_by :selenium, using: :headless_chrome
Capybara.default_max_wait_time = 20 # Stripe Checkout test gateway is slooooow
def setup
# ensure url helpers use correct host and port for system tests
Rails.application.routes.default_url_options[:host] = Capybara.current_session.server.host
Rails.application.routes.default_url_options[:port] = Capybara.current_session.server.port
end
end
EDIT: Instead of setting max wait time globally, see better option in Thomas's answer.
Upvotes: 0
Reputation: 33
For this issue, defining matcher
outside rspec
should solve the problem. Adding the next two lines on top of this file will enable you to use expect
method outside the context of RSpec
require "application_system_test_case"
require "minitest/autorun" # new line
require "rspec/expectations/minitest_integration" # new line
class PaymentSessionsTest < ApplicationSystemTestCase
setup do
@event = events(:one)
end
test "payment successful if valid details provided" do
# Enter payment details on invite page
visit event_url(@event)
fill_in "Your name", with: "John Doe"
fill_in "Email", with: "[email protected]"
fill_in "Gift amount", with: "20"
click_on "Pay"
# Stripe Checkout
fill_in "cardNumber", with: "4242424242424242"
fill_in "cardExpiry", with: "01#{Date.today.next_year.strftime("%y")}" #
grab year always as next year in 2 digit format
fill_in "cardCvc", with: "123"
fill_in "Name on card", with: "Mr John Doe"
fill_in "billingPostalCode", with: "N1 7GU"
click_on "Pay"
# Payment success page
expect(page).to have_current_path(payment_success_url) # ensure Capybara
waits for page to load after clicking Pay
assert_selector "h1", text: "Payment successful!"
end
end
Upvotes: 0
Reputation: 49890
As mentioned by Artur, expect
is part of RSpec. If you're using minitest then you need to use the mintest assertions provided by Capybara, which you're already doing with assert_selector
. The one you're missing is assert_current_path
- https://rubydoc.info/github/teamcapybara/capybara/Capybara/Minitest/Assertions#assert_current_path-instance_method
assert_current_path(payment_success_url)
Since you're using a 3rd-party service directly in your tests timings are going to be slow and you may need to increase Capybaras waiting time. There are multiple ways to do that
Globally
Capybara.default_max_wait_time = 20
in one of your setup files
This has the downside of potentially increasing time until failure in all of your tests
For a block of actions. This increases the max wait time for all assertions inside the block (individual max not total)
Capybara.using_wait_time(20) do
assert_current_path(payment_success_url)
assert_selector "h1", text: "Payment successful!"
end
Most calls accept a wait parameter to change the value just for that call - which probably makes the most sense in this instance
assert_current_path(payment_success_url, wait: 20)
Note: you might want to look into using something like https://github.com/thoughtbot/fake_stripe rather than hitting Stripe directly during most of your tests for performance reasons
Note: you should always prefer one of the Capybara provided assertions over plain assert
when dealing with anything relating to the browser in your system tests.
Upvotes: 3
Reputation: 72
expect
belongs to the RSpec
. It is indeed in the Capybara docs, but under the RSpec section, that's why you are getting the error message. Try to use assert instead.
Upvotes: 0