在 Cypress 測試中處理電子郵件流#frontend@twiliosendgrid

已發表: 2020-11-24

Twilio SendGrid 發送大量電子郵件。 為了發送我們所有的交易電子郵件——從密碼重置到帳戶電子郵件驗證再到導出 CSV 電子郵件——我們使用我們自己的後端服務。

我們最近通過了發送超過 3 萬億封電子郵件的巨大里程碑。

在我們的測試環境中,我們將電子郵件發送到自託管 Squirrelmail服務器中的測試電子郵件收件箱,以避免將測試電子郵件發送到 Gmail 等實際電子郵件收件箱服務提供商。 許多重要的流程要求用戶檢查他們的電子郵件,單擊可操作的鏈接,重定向回 Web 應用程序,然後在某個下載或驗證成功頁面繼續前進。

我們通過在必要的表格中輸入我們的 Squirrelmail 電子郵件地址、單擊一些按鈕並點擊電子郵件鏈接來手動測試這些功能,以驗證事情是否按預期工作。 我們可以在每次新代碼更改時都這樣做,以確保我們不會在任何地方退步,但是在端到端(E2E)測試中自動化這些步驟會很好,我們可以隨時再次運行。 具體來說,我們希望使用 Cypress 編寫 E2E 測試,因此我們不必每次都在自己的 Web 瀏覽器中手動測試這些可能緩慢且令人困惑的電子郵件流。

在我們進入帖子之前,這裡有幾篇您可能有興趣首先閱讀的文章。

  • 如果您之前從未編寫過 E2E 測試,或者想了解在編寫 E2E 測試時如何思考,您可能想在我們開始之前查看這篇博文。
  • 如果您一般不熟悉使用 Cypress 編寫 E2E 測試,我們強烈建議您查看我們關於為您的 Web 應用程序實施 Cypress 測試的一千英尺概述——這將使您更好地了解 Cypress API。

這篇文章假設您知道一些 Cypress 函數,例如cy.task()來運行我們在 Node 服務器中定義的任意代碼,以幫助我們處理電子郵件。 此外,如果後面的帶有 TypeScript 的代碼片段有點混亂,請查看我們的博客文章,了解我們如何鍵入 Cypress 測試。 您仍然可以通過刪除類型定義並堅持僅使用 JavaScript 的語法來修改您自己的賽普拉斯測試中的代碼。

我們不會介紹如何設置您自己的測試電子郵件收件箱服務器(如 Squirrelmail),但我們將專注於自動化這些與搜索電子郵件、解析匹配的電子郵件內容和跟踪電子郵件鏈接相關的步驟。 假設您有一個測試電子郵件收件箱服務器和您自己的憑據要連接到,這應該可以讓您更好地了解使用和實現哪些功能來處理這些電子郵件流。

我們如何處理賽普拉斯測試中的電子郵件流?

為了測試整個電子郵件流,我們構建了cy.task()插件來:

  • 處理具有特定主題行的電子郵件的連接和過濾電子郵件收件箱
  • 檢索匹配的電子郵件正文內容
  • 無需通過 Squirrelmail UI 登錄即可從用戶的收件箱中刪除電子郵件

我們也走這條路,因為我們不擁有或控制 Squirrelmail UI,並且在 Cypress 測試中無法訪問多個超級域,因為 Squirrelmail UI 的 URL 位於與我們部署的前端應用程序不同的超級域中.

我們首先安裝了一個名為“emailjs-imap-client”的庫來幫助我們設置一個 IMAP 客戶端,通過一些憑據和主機配置連接到我們的 Squirrelmail 收件箱。 使用這個庫,我們將所有與 Squirrelmail 相關的東西封裝在一個名為squirrelmail.ts的模塊中,稍後我們將在我們的plugins/index.ts中導入該模塊以用於我們的cy.task()函數定義。

在涉及電子郵件的測試運行之前,我們應該刪除所有具有相同主題行的電子郵件,以避免誤報意外引用在先前測試中觸發的舊電子郵件。 為了處理這個用例,我們實現了這個任務來刪除用戶收件箱中所有具有匹配主題行的電子郵件,如下所示。


在我們的測試期間,我們觸發了一個操作,該操作將導致一封電子郵件被發送到用戶的 Squirrelmail 電子郵件地址,並且通常需要等待具有匹配主題行的電子郵件到達用戶的電子郵件收件箱。 此過程需要幾秒鐘到幾分鐘不等,具體取決於後端進程的參與程度。 我們需要確保在它到達之前進行輪詢或在測試中提供超時錯誤,以讓我們知道郵件發送部分是否有問題或延遲。 由於我們事先已經刪除了具有匹配主題行的電子郵件,因此如果它確實成功返回,我們可以確定它是從我們的測試運行中觸發的。

以下是我們如何開發等待具有特定主題行的電子郵件(例如“您的電子郵件活動導出”或“發件人驗證”)到達用戶的電子郵件收件箱的功能。

迄今為止:

  • 我們清除了用戶的電子郵件收件箱
  • 測試運行並觸發一封電子郵件發送到用戶的電子郵件收件箱
  • 我們成功等待電子郵件到達用戶的電子郵件收件箱

現在,我們需要獲取該特定電子郵件的正文內容。

幸運的是,我們可以將匹配的電子郵件正文內容作為字符串返回,稍後我們必須對其進行解析,以便操作鏈接返回到我們控制和擁有的 Web 應用程序。 下面的任務插件在用戶的收件箱中搜索具有匹配主題行的電子郵件,並返回正文內容供我們以後使用。

作為一個簡短的提醒,我們不能簡單地為 Squirrelmail 頁面創建頁面對象,通過 UI 訪問 Squirrelmail,過濾匹配的主題行,打開電子郵件,直接單擊可操作的鏈接,然後愉快地返回我們的網絡應用程序——因為我們不能在同一個賽普拉斯測試中訪問多個超級域。 訪問您無法控製或擁有的頁面和應用程序也更像是一種反模式。

在找到我們在測試中觸發的匹配電子郵件正文內容後,我們必須解析 HTML 內容,找到操作鏈接,觸發對該鏈接的 HTTP 請求,然後按照重定向返回我們的 Web 應用程序。

為了解析電子郵件 HTML 內容並找到操作鏈接部分,我們使用了另一個名為“cheerio”的庫,它加載 HTML 字符串並允許我們調用類似 jQuery 的函數來提取我們需要的操作按鈕或鏈接。 解析出鏈接後,我們使用cy.request()向鏈接發出 HTTP 請求,按照重定向鏈接返回我們在一個超級域上控制和擁有的 Web 應用程序,並繼續驗證我們頁面上的成功狀態重定向到。

在您的情況下,如果您的鏈接已經指向正確的位置,您可能不需要觸發對鏈接的 HTTP 請求並遵循響應的重定向。 如果鏈接 URL 已經直接指向您的 Web 應用程序,那麼沒有什麼可以阻止您提取鏈接路徑並執行cy.visit(linkPath)以重定向回您的應用程序。 對於 Twilio SendGrid 鏈接,如果您的電子郵件啟用了鏈接跟踪,則鏈接可能看起來像“...sendgrid.net?...”,如果您啟用了鏈接品牌,則鏈接可能看起來像“brandlink.com”。 這就是為什麼我們需要發出 HTTP 請求並提取重定向路徑來執行cy.visit(redirectPath) ,因為鏈接的直接“href”與我們的 Web 應用程序不匹配。

下面是一個使用cheerio 查找鏈接、向鏈接發出HTTP 請求並遵循重定向的示例。

結論

我們向您介紹了我們實施的許多cy.task()插件功能,以通過我們收件箱中的匹配電子郵件執行更多讀取和刪除操作。 我們創建這些函數是為了在網頁中觸發這些電子郵件流之前正確重置用戶的電子郵件收件箱狀態,等待電子郵件到達收件箱,最後通過鏈接返回其成功狀態。 我們在下面總結了賽普拉斯測試的關鍵步驟:

  • 使用cy.task(“teardownMatchingEmails”)所有帶有特定主題行的電子郵件以避免誤報。
  • 通過 API 登錄到用戶,然後通過 UI 完成一組步驟以生成要發送到用戶電子郵件收件箱的電子郵件。
  • 通過cy.task(“awaitEmailInSquirrelmailInbox”)輪詢用戶的電子郵件收件箱以接收具有匹配主題行的電子郵件。
  • 使用cy.task(“squirrelmailSearchBySubject”)閱讀具有匹配主題行的電子郵件正文內容。
  • 通過傳入電子郵件正文 HTML 字符串並使用類似 jQuery 的語法搜索元素,解析出與 Cheerio 庫的正確操作鏈接。
  • 通過cy.request(“link”)對解析出的電子郵件鏈接發出 HTTP 請求,然後按照重定向響應返回 Web 應用程序,或者如果鏈接已經與您的超級域匹配,則使用cy.visit(“emailLinkToWebApp”)訪問路徑cy.visit(“emailLinkToWebApp”) .
  • 驗證是否出現成功狀態或在您擁有的頁面上執行更多 UI 步驟。

我們希望這篇博文能鼓勵您從頭到尾徹底進行測試。 我們過去常常避免使用電子郵件流編寫 E2E 測試,但幸運的是,我們找到了一種方法來使用這些 Cypress 測試來節省我們在手動回歸測試所有內容上花費的大量時間。 我們了解到自動化和測試整個快樂路徑流程而不是流程的一部分更有價值 - 除非許多步驟依賴於您不擁有或控制的第三方服務,或者無法將用戶重置為一定的狀態可靠。

如果您對更多與我們為 Web 應用程序編寫賽普拉斯測試相關的博文感興趣,請查看以下文章:

  • 編寫 E2E 測試時要考慮什麼
  • 編寫柏樹測試的 1,000 英尺概述
  • TypeScript 包含 Cypress 測試中的所有內容
  • 配置、組織和整合賽普拉斯測試的想法
  • 將 Cypress 測試與 Docker、Buildkite 和 CICD 集成