如何在系统测试期间正确设置电子邮件链接中的端口?
How do I set the port correctly in email links during a system test?
我正在编写系统测试以确认整个注册流程在 Rails 7 应用程序中正常工作(使用 Clearance gem 和电子邮件确认 SignInGuard)。
在我“点击”电子邮件中的确认 link 之前,测试工作正常(在使用 Nokogiri 解析之后)。出于某种原因,电子邮件中的 URL 指向我的开发服务器(端口 3000)而不是指向测试服务器(端口 49736、49757、49991,等等)。
我可以查找测试服务器正在使用的当前端口(它每 运行 更改一次)并替换 URL 的端口部分,但这看起来很老套。我是不是漏掉了什么明显的东西或做错了什么?
URL 在邮件中:confirm_email_url(@user.email_confirmation_token)
从rails routes
出发的路线:
Prefix Verb URI Pattern Controller#Action
confirm_email GET /confirm_email/:token(.:format) email_confirmations#update
目前系统测试:
require "application_system_test_case"
require "test_helper"
require "action_mailer/test_helper"
class UserSignUpFlowTest < ApplicationSystemTestCase
include ActionMailer::TestHelper
test "Sign up for a user account" do
time = Time.now
email = "test_user_#{time.to_s(:number)}@example.com"
password = "Password#{time.to_s(:number)}!"
# Sign up (sends confirmation email)
visit sign_up_url
fill_in "Email", with: email
fill_in "Password", with: password
assert_emails 1 do
click_on "Sign up"
sleep 1 # Not sure why this is required... Hotwire/Turbo glitch?
end
assert_selector "span", text: I18n.t("flashes.confirmation_pending")
# Confirm
last_email = ActionMailer::Base.deliveries.last
parsed_email = Nokogiri::HTML(last_email.body.decoded)
target_link = parsed_email.at("a:contains('#{I18n.t("clearance_mailer.confirm_email.link_text")}')")
visit target_link["href"]
# ^^^^^^^^^^^^^^^^^^^^^^^^^
# This is the bit that fails... The link in the email points to my dev server (port 3000) rather than
# the test server (port 49736, 49757, 49991, etc). I only figured this out when my dev server crashed
# and Selenium started choking on a "net::ERR_CONNECTION_REFUSED" error
assert_selector "span", text: I18n.t("flashes.email_confirmed")
end
end
编辑
目前我已经通过将 visit target_link["href"]
替换为 visit hacky_way_to_fix_incorrect_port(target_link["href"])
:
来解决这个问题
private
def hacky_way_to_fix_incorrect_port(url)
uri = URI(url)
return "#{root_url}#{uri.path}"
end
邮件程序中使用的 URL 指定为:
Rails.application.configure.action_mailer.default_url_options
在 config/environments/test.rb
中,我在第一次安装 Clearance 时将端口设置为 3000:
config.action_mailer.default_url_options = {host: "localhost:3000"}
为了修复它,我首先尝试了 specifying the port dynamically,但建议的方法实际上并没有用,而且似乎没有必要。删除端口号足以让我的系统测试通过:
config.action_mailer.default_url_options = {host: "localhost"}
正如 Thomas Walpole 所提到的,之所以有效,是因为 Capybara.always_include_port
设置为 true。使用此设置,尝试访问 http://localhost/confirm_email/<token>
(未指定端口)会自动重新路由到 http://localhost:<port>/confirm_email/<token>
.
always_include_port
设置defaults to false in the Capybara gem but it turns out Rails sets it to true when it starts up the System Test server。
我正在编写系统测试以确认整个注册流程在 Rails 7 应用程序中正常工作(使用 Clearance gem 和电子邮件确认 SignInGuard)。
在我“点击”电子邮件中的确认 link 之前,测试工作正常(在使用 Nokogiri 解析之后)。出于某种原因,电子邮件中的 URL 指向我的开发服务器(端口 3000)而不是指向测试服务器(端口 49736、49757、49991,等等)。
我可以查找测试服务器正在使用的当前端口(它每 运行 更改一次)并替换 URL 的端口部分,但这看起来很老套。我是不是漏掉了什么明显的东西或做错了什么?
URL 在邮件中:confirm_email_url(@user.email_confirmation_token)
从rails routes
出发的路线:
Prefix Verb URI Pattern Controller#Action
confirm_email GET /confirm_email/:token(.:format) email_confirmations#update
目前系统测试:
require "application_system_test_case"
require "test_helper"
require "action_mailer/test_helper"
class UserSignUpFlowTest < ApplicationSystemTestCase
include ActionMailer::TestHelper
test "Sign up for a user account" do
time = Time.now
email = "test_user_#{time.to_s(:number)}@example.com"
password = "Password#{time.to_s(:number)}!"
# Sign up (sends confirmation email)
visit sign_up_url
fill_in "Email", with: email
fill_in "Password", with: password
assert_emails 1 do
click_on "Sign up"
sleep 1 # Not sure why this is required... Hotwire/Turbo glitch?
end
assert_selector "span", text: I18n.t("flashes.confirmation_pending")
# Confirm
last_email = ActionMailer::Base.deliveries.last
parsed_email = Nokogiri::HTML(last_email.body.decoded)
target_link = parsed_email.at("a:contains('#{I18n.t("clearance_mailer.confirm_email.link_text")}')")
visit target_link["href"]
# ^^^^^^^^^^^^^^^^^^^^^^^^^
# This is the bit that fails... The link in the email points to my dev server (port 3000) rather than
# the test server (port 49736, 49757, 49991, etc). I only figured this out when my dev server crashed
# and Selenium started choking on a "net::ERR_CONNECTION_REFUSED" error
assert_selector "span", text: I18n.t("flashes.email_confirmed")
end
end
编辑
目前我已经通过将 visit target_link["href"]
替换为 visit hacky_way_to_fix_incorrect_port(target_link["href"])
:
private
def hacky_way_to_fix_incorrect_port(url)
uri = URI(url)
return "#{root_url}#{uri.path}"
end
邮件程序中使用的 URL 指定为:
Rails.application.configure.action_mailer.default_url_options
在 config/environments/test.rb
中,我在第一次安装 Clearance 时将端口设置为 3000:
config.action_mailer.default_url_options = {host: "localhost:3000"}
为了修复它,我首先尝试了 specifying the port dynamically,但建议的方法实际上并没有用,而且似乎没有必要。删除端口号足以让我的系统测试通过:
config.action_mailer.default_url_options = {host: "localhost"}
正如 Thomas Walpole 所提到的,之所以有效,是因为 Capybara.always_include_port
设置为 true。使用此设置,尝试访问 http://localhost/confirm_email/<token>
(未指定端口)会自动重新路由到 http://localhost:<port>/confirm_email/<token>
.
always_include_port
设置defaults to false in the Capybara gem but it turns out Rails sets it to true when it starts up the System Test server。