I'm trying to test mailers in some system tests. I'm using Ruby 3.0.2, Rails 6.1.4, Capybara 3.26, Selenium-webdriver and I'm writing tests in Minitest. The below tests fails when it gets to the assert_equal ['[email protected]'], mail.to line:
orders_test.rb:
test "check full payment with cheque flow" do
LineItem.delete_all
Order.delete_all
visit store_index_url
click_on 'Add to cart', match: :first
click_on 'Checkout'
fill_in 'order_name', with: 'Dave Thomas'
fill_in 'order_address', with: '123 Main Street'
fill_in 'order_email', with: '[email protected]'
assert_no_selector "#order_routing_number"
select 'Cheque', from: 'Pay type'
fill_in 'Routing #', with: '123456'
fill_in 'Account #', with: '678901'
assert_selector "#order_routing_number"
assert_selector "#order_account_number"
perform_enqueued_jobs do
click_button 'Place order'
end
orders = Order.all
assert_equal 1, orders.size
order = orders.first
assert_equal 'Dave Thomas', order.name
assert_equal '123 Main Street', order.address
assert_equal '[email protected]', order.email
assert_equal 'Cheque', order.pay_type
assert_equal 1, order.line_items.size
mail = ActionMailer::Base.deliveries.last
assert_equal ['[email protected]'], mail.to
assert_equal 'James Kemp<[email protected]>', mail[:from].value
assert_equal 'Order received; thanks', mail.subject
end
With the following error:
Error:
OrdersTest#test_check_full_payment_with_cheque_flow:
NoMethodError: undefined method `to' for nil:NilClass
test/system/orders_test.rb:62:in `block in <class:OrdersTest>'
Error:
OrdersTest#test_check_full_payment_with_cheque_flow:
ActionView::Template::Error: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
Reading error message suggestion and googling others' solutions suggests to put config.action_mailer.default_url_options = { :host => 'www.example.com' } in config/environments/test. When I put this line in it then throws an error from the same assert_equal ... mail.to line as the above error throws this error:
Error:
OrdersTest#test_check_full_payment_with_cheque_flow:
DRb::DRbRemoteError: undefined method `to' for nil:NilClass (NoMethodError)
test/system/orders_test.rb:62:in `block in <class:OrdersTest>'
Error:
OrdersTest#test_check_full_payment_with_cheque_flow:
DRb::DRbRemoteError: No route matches {:action=>"show", :controller=>"line_items", :locale=>#<LineItem id: 1, product_id: 298486374, cart_id: nil, created_at: "2021-11-07 16:53:19.133389000 +0000", updated_at: "2021-11-07 16:53:19.966253000 +0000", quantity: 1, order_id: 980190963>}, missing required keys: [:id]
Did you mean? line_items_url
line_item_path
line_items_path
edit_line_item_url (ActionView::Template::Error)
app/views/line_items/_line_item.html.erb:13
The code works fine in development mode, without any default_url_options explicitly specified in config anywhere.
Can anyone advise what the issue is here and how I should correct it?
(FYI - This is from the Agile Web Development with Rail 6 tutorial, ch.17.)
You are being told that the
tomethod is getting called on a nil, somailis nil. Hence there is no mail in the deliveries array.The reason this would be occurring is that when using a Javascript driver, the Capybara tests and the Rails server run in different processes and communicate asynchronously. Hence they will each have a different
deliveriesarray, and you cannot check emails this way.Normally you stick to the contents of the webpage when using Capybara. You can check the database if you like, because the tests and server communicate through the database, and Capybara maintains two connections to the same database, however even there if you use database transactions and such you can get into trouble.
However in general you can't check anything that isn't the webpage or database.
You might choose to check emails through unit or request/integration tests instead, or look for a solution like the
capybara-emailgem if you wish to do it in a system/feature test, which does add that functionality, although I haven't used it in a while and I'm not sure how up to date it is.