Im using cypress for behaviour testing my meteor 3 app. One of those tests checks the content of the registration email, ‘clicks’ the registration link and sets the new users password, thus checking the new user storyboard. I thought I might share some pointers on how to do this in case its useful.
The relevant section of the test looks like:
cy.get("input[name='username']").type('ella')
cy.get("input[name='email']").type('ella@test.com')
cy.get("input[name='firstName']").type('Ella')
cy.get("input[name='lastName']").type('User')
cy.get('button').contains('OK').click()
cy.wait(500) // allow some time for email to register
cy.get('#account-dropdown').click()
cy.get('a.dropdown-item').contains('Sign out').click()
// capture contents of enrollment email and then visit the link contained
cy.task('getLastEmail', 'ella@test.com').then((email) => {
const url = email.body.match(/http:\/\/.*/g)[0]
cy.visit(url)
cy.get("input[name='newpassword1']").type('password')
cy.get("input[name='newpassword2']").type('password')
cy.get('button').contains('Set Password').click()
cy.contains('Hello Ella')
})
Where the user has previously authenticated as a user that has the authority to add a new users. The important bit is the getLastEmail cypress task which is defined in the cypress.config.js file:
const { defineConfig } = require('cypress')
const ms = require('smtp-tester')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on) {
// see https://www.cypress.io/blog/testing-html-emails-using-cypress for useful background
// starts the SMTP server at localhost:7777
const port = 7777
const mailServer = ms.init(port)
console.log('mail server at port %d', port)
// [receiver email]: email text
let lastEmail = {}
const handler = (addr, id, email) => {
// store the email by the receiver email
lastEmail[email.headers.to] = {
body: email.body,
html: email.html,
}
}
// process all emails
mailServer.bind(handler)
on('task', {
getLastEmail(userEmail) {
// cy.task cannot return undefined
// thus we return null as a fallback
return lastEmail[userEmail] || null
},
})
on('after:run', () => {
mailServer.unbind(handler)
mailServer.stop()
})
},
baseUrl: 'http://localhost:3000'
},
...
Hopefully this might be useful to others trying to do the same thing. And please do tell me if you see something dumb.