如何使用 capybara 访问电子邮件中的链接

Posted

技术标签:

【中文标题】如何使用 capybara 访问电子邮件中的链接【英文标题】:How to visit a link inside an email using capybara 【发布时间】:2014-10-04 02:15:28 【问题描述】:

我是黄瓜和水豚的新手。我有一个应用程序来测试其流程是:'提交表单后,将向用户发送一封电子邮件,其中包含指向另一个应用程序的链接。为了访问该应用程序,我们必须打开邮件并单击链接,该链接将重定向到该应用程序。'。我无权访问邮件 ID。有没有办法提取该链接并继续流程? 请提供一些可能的方法。

问候, 阿比塞克·达斯

【问题讨论】:

【参考方案1】:

在您的测试中,使用您需要的任何方式来触发您的应用程序发送电子邮件。发送电子邮件后,使用正则表达式从电子邮件正文中的链接中查找 URL(请注意,这仅适用于包含单个链接的电子邮件),然后使用 Capybara 访问该 URL 的路径以继续你的测试:

path_regex = /(?:"https?\:\/\/.*?)(\/.*?)(?:")/    

email = ActionMailer::Base.deliveries.last
path = email.body.match(path_regex)[1]
visit(path)

正则表达式解释

正则表达式 (regex) 本身由正斜杠划分,而这个正则表达式特别由三个 组成,每个组由一对括号划分。第一组和第三组都以?: 开头,表示它们是非捕获 组,而第二组是捕获 组(不是?:)。我将在下面解释这种区别的重要性。

第一组(?:"https?\:\/\/.*?)是:

非捕获组,?: 匹配单个双引号 " 我们匹配引用,因为我们预计 URL 位于链接标记的 href="..." 属性中 后跟字符串http 可选地后跟一个小写ss? 问号与前面的匹配,在本例中为s,可选 后跟一个冒号和两个正斜杠,\:\/\/ 注意反斜杠,用于转义在正则表达式中具有特殊含义的字符 后跟通配符.*?,它将匹配任何字符任意多次,直到达到正则表达式中的下一个匹配 句点或通配符匹配任何字符 星号 * 可无限次重复前面的匹配,具体取决于后面的连续匹配 问号使其成为 惰性 匹配,这意味着通配符将匹配尽可能少的字符,同时仍允许满足正则表达式中的下一个匹配

第二组(\/.*?) 是一个捕获组:

匹配单个正斜杠\/ 这将匹配 URL 的主机部分之后的第一个正斜杠(例如 http://www.example.com/ 末尾的斜杠),因为 http:// 中的斜杠已经被第一个组匹配 后跟另一个惰性通配符.*?

第三组(?:")是:

另一个非捕获组,?: 匹配单个双引号 "

因此,我们的第二组将匹配从主机后面的正斜杠开始到但不包括 href="..." 末尾的双引号的 URL 部分。

当我们使用我们的正则表达式调用match 方法时,它会返回一个MatchData 的实例,它的行为很像一个数组。索引0 处的元素是一个包含整个匹配字符串(来自正则表达式中的所有组)的字符串,而后续索引处的元素仅包含与正则表达式的捕获组匹配的字符串部分(仅我们的第二组,在这种情况下)。因此,为了获得第二组的对应匹配项——也就是我们想要使用 Capybara 访问的路径——我们在索引 1 处获取元素。

【讨论】:

实际上,当填写并提交表单时,会向服务器发送请求,服务器通过电子邮件将链接发送给相应的用户。 我需要为此添加一些特定的宝石吗?它显示'未知错误:'URL'必须是字符串'错误。 听起来match 方法没有返回正确的路径。您能否修改您的问题以包含电子邮件的正文(上面我的代码 sn-p 中的email.body)? 谢谢,布赖恩...我上传了一个新问题..同时也在寻找解决方案。 我重新验证了代码。它在步骤'path = email.body.match(path_regex)[1]'和'未知错误'中显示'未定义方法'body' for "":string:步骤“访问(路径)”的“URL”必须是字符串错误..【参考方案2】:

您可以使用 Nokogiri 解析电子邮件正文并找到您要点击的链接。

假设你想点击一个链接更改我的密码

email = ActionMailer::Base.deliveries.last
html = Nokogiri::HTML(email.html_part.body.to_s)
target_url = html.at("a:contains('Change my password')")['href']
visit target_url

我认为这比使用正则表达式更具语义性和鲁棒性。例如,如果电子邮件有很多链接,这将起作用。

【讨论】:

使用email.html_part.body 只获取正文的html部分。如果你有文本类型的正文,email.body将会失败。【参考方案3】:

如果您正在使用或愿意使用capybara-email gem,现在有一种更简单的方法来执行此操作。假设您已向recipient@email.com 生成了一封电子邮件,其中包含链接“fancy link”。

然后您可以在您的测试套件中执行此操作:

open_email('recipient@email.com') # Allows the current_email method
current_email.click_link 'fancy link'

【讨论】:

以上是关于如何使用 capybara 访问电子邮件中的链接的主要内容,如果未能解决你的问题,请参考以下文章

使用 Capybara,如何切换到带有“_blank”目标的链接的新窗口?

Cucumber 和 Capybara,单击非链接或按钮元素

Capybara 歧义解析

如何在测试之间重复使用 Capybara 会话?

Capybara -> 如何使用本地方法的结果

使用 Capybara 在新窗口中打开链接