16

我需要测试一个量角器测试用例,其中用户注册、接收电子邮件、转到电子邮件中提供的链接并在激活注册表单中填写他/她的详细信息。

问题是如何从电子邮件中获取兑换令牌。我的电子邮件有一个指向激活页面的链接,该页面具有如下身份验证令牌:

http://127.0.0.1:3000/#/signup/redeem/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJlOTRhYzY3MC1kYTNlLTQyYTUtODVkZS02NDU4ZjVmZGMwYjAiLCJzdWIiOiJ0ZXN0QGNvZWYuY28iLCJpYXQiOjE0Mjc0OTM5MDMsImV4cCI6MTQyODA5ODcwM30.

但是我如何获取该令牌以便我可以构建 url,或者我如何单击我的电子邮件中的那个按钮以便我可以完成流程?我正在使用 mailcatcher 来模拟电子邮件。

4

3 回答 3

32

这是我最近解决的问题。希望该解决方案也适用于您的用例。

先决条件:

分步说明:

  1. 安装mail-listener2

    npm install mail-listener2 --save-dev
    
  2. 在您的量角器配置中初始化邮件侦听器并使其全局可用:

    onPrepare: function () {
        var MailListener = require("mail-listener2");
    
        // here goes your email connection configuration
        var mailListener = new MailListener({
            username: "imap-username",
            password: "imap-password",
            host: "imap-host",
            port: 993, // imap port 
            tls: true,
            tlsOptions: { rejectUnauthorized: false },
            mailbox: "INBOX", // mailbox to monitor 
            searchFilter: ["UNSEEN", "FLAGGED"], // the search filter being used after an IDLE notification has been retrieved 
            markSeen: true, // all fetched email willbe marked as seen and not fetched next time 
            fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`, 
            mailParserOptions: {streamAttachments: true}, // options to be passed to mailParser lib. 
            attachments: true, // download attachments as they are encountered to the project directory 
            attachmentOptions: { directory: "attachments/" } // specify a download directory for attachments 
        });
    
        mailListener.start();
    
        mailListener.on("server:connected", function(){
            console.log("Mail listener initialized");
        });
    
        global.mailListener = mailListener;
    }),
    
    onCleanUp: function () {
        mailListener.stop();
    }, 
    
  3. 创建一个getLastEmail()等待email检索 an 的辅助函数:

    function getLastEmail() {
        var deferred = protractor.promise.defer();
        console.log("Waiting for an email...");
    
        mailListener.on("mail", function(mail){
            deferred.fulfill(mail);
        });
        return deferred.promise;
    };
    
  4. 示例测试用例:

    describe("Sample test case", function () {
    
        beforeEach(function () {
            browser.get("/#login");
            browser.waitForAngular();
        });
    
        it("should login with a registration code sent to an email", function () {
            element(by.id("username")).sendKeys("MyUserName");
            element(by.id("password")).sendKeys("MyPassword");
            element(by.id("loginButton")).click();
    
            browser.controlFlow().await(getLastEmail()).then(function (email) {
                expect(email.subject).toEqual("New Registration Code");
                expect(email.headers.to).toEqual("myemail@email.com");
    
                // extract registration code from the email message
                var pattern = /Registration code is: (\w+)/g;
                var regCode = pattern.exec(email.text)[1];
    
                console.log(regCode);
    
             });
        });
    });
    
于 2015-04-01T04:41:35.883 回答
7

我实现的解决方案是使用 mailcatcher API,如果你向下滚动一点,你会发现关于 API 的以下内容:

一个相当 RESTful 的 URL 模式意味着您可以从 /messages 下载 JSON 格式的消息列表,每个消息的元数据使用 /messages/:id.json,然后相关部分使用 /messages/:id.html 和 /messages/:id .plain 用于默认 HTML 和纯文本版本,/messages/:id/:cid 用于按 CID 的单个附件,或带有 /messages/:id.source 的整个消息。

所以我们首先获取整个 json 响应,解析它并获取最新的电子邮件 ID:

// Returns the last email id
function(emails, user) {
    var email, recipient;
    for(var i = emails.length - 1; i >= 0; i--) {
        email = emails[i];
        for(var j = 0; j < email.recipients.length ; j++) {
            recipient = email.recipients[j];
            if(recipient == "<"+user+">") {
                return email.id;
            }
        }
    }
};

使用该电子邮件 ID,我们可以通过点击获取电子邮件的正文/messages/:id.plain(当然还有更多变体,例如获取电子邮件源代码或电子邮件呈现的 html,我们只需要消息)然后我们可以解析正文以获取我们想要的内容,以下是代码:

browser.driver.get(mailcatcherUrl+"/messages");
browser.driver.findElement(by.tagName('body')).getText().then(function(response) {
    var emails, lastEmailId, partialTokens ;
    emails = JSON.parse(response);
    lastEmailId = getLastEmailId(emails, user);
    browser.driver.get(mailcatcherUrl+"/messages/"+lastEmailId+".plain");
    browser.driver.findElement(by.tagName('body')).getText().then(function(lastEmail) {
        // use latestEmail to get what you want.
    });
});

干杯!

于 2016-01-22T13:54:04.147 回答
0

我必须做同样的事情,但我们使用的邮件测试服务器没有 imap 支持。因此,如果有人遇到同样的问题,我使用 mailpop3 npm 库实现了与 alecxe 类似的解决方案。

然而,pop3 客户端的问题是它不充当侦听器,因此我们必须定义一个帮助函数,当我们需要测试最新的电子邮件时,它会连接、登录和获取最新的电子邮件。

像这样的东西:

function getLastEmail() {
  var deferred = protractor.promise.defer();
  var POP3Client = require("mailpop3");
  var client = new POP3Client(port, host, {
          tlserrs: false,
          enabletls: true,
          debug: false
      });

  client.on("connect", function() {
  
          console.log("CONNECT success");
          client.login(username, password);
  
  });

  client.on("login", function(status, rawdata) {
  
      if (status) {
  
          console.log("LOGIN/PASS success");
          client.retr(1);
  
      } else {
  
          console.log("LOGIN/PASS failed");
          client.quit();
  
      }
  });

  client.on("retr", function(status, msgnumber, data, rawdata) {
  
      if (status === true) {
  
          console.log("RETR success for msgnumber " + msgnumber);
          deferred.fulfill(data);
  
      } else {
  
          console.log("RETR failed for msgnumber " + msgnumber);
    
      }
      client.quit();
  });
  return deferred.promise;
}

于 2021-04-04T17:48:22.933 回答