javascriptemailtestingprotractormailcatcher

Fetching values from email in protractor test case


I need to test a protractor test case in which a user signs up, receives an email, goes to the link provided in the email and fills up his/her details in activation signup form.

The problem is how can I get the redeem token from the email. My email has a link to the activation page which has the auth token like following:

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

But how do I fetch that token so that I can build the url or how can I click that button in my email so that I can complete the flow ? I am using mailcatcher to simulate email.


Solution

  • This is something I've solved recently. Hope the solution would also apply for your use-case.

    Prerequisites:

    Step by step instructions:

    1. Install mail-listener2:

      npm install mail-listener2 --save-dev
      
    2. In your protractor config initialize Mail Listener and make it available globally:

      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. Create a helper getLastEmail() function which would wait for an email to be retrieved:

      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. Example test case:

      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);
      
               });
          });
      });