diff --git a/.github/workflows/cypress-repeat.yml b/.github/workflows/cypress-repeat.yml index 062ab8d73..633084a24 100644 --- a/.github/workflows/cypress-repeat.yml +++ b/.github/workflows/cypress-repeat.yml @@ -55,7 +55,7 @@ jobs: CYPRESS_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CYPRESS_mailHogUrl: ${{ secrets.CYPRESS_MAILHOG }} + CYPRESS_MAILPITURL: ${{ secrets.CYPRESS_MAILPITURL }} COMMIT_INFO_MESSAGE: Cypress repeat with - ${{ github.event.inputs.spec }} ${{ github.event.inputs.grep }} ${{ github.event.inputs.dashboard_url}} CYPRESS_grep: ${{ github.event.inputs.grep }} STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f67f54fa0..0b2133dc2 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -126,6 +126,7 @@ jobs: CYPRESS_mailHogUrl: ${{ secrets.CYPRESS_MAILHOG }} COMMIT_INFO_MESSAGE: ${{ needs.get-selected-tags-and-containers.outputs.tags }} tests triggered on PR - https://github.com/${{ github.repository }}/pull/${{ github.ref_name }} CYPRESS_grepTags: ${{ needs.get-selected-tags-and-containers.outputs.tags }} + CYPRESS_MAILPITURL: ${{ secrets.CYPRESS_MAILPITURL }} with: parallel: true group: 'UI - Chrome' diff --git a/.github/workflows/tests-nightly.yml b/.github/workflows/tests-nightly.yml index 51337b550..06817500e 100644 --- a/.github/workflows/tests-nightly.yml +++ b/.github/workflows/tests-nightly.yml @@ -148,7 +148,7 @@ jobs: CYPRESS_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CYPRESS_mailHogUrl: ${{ secrets.CYPRESS_MAILHOG }} + CYPRESS_MAILPITURL: ${{ secrets.CYPRESS_MAILPITURL }} COMMIT_INFO_MESSAGE: All tests triggered via ${{ github.event_name}} on ${{ steps.get-env-uri.outputs.ENV_URI }} CYPRESS_grepTags: ${{ env.GREP_TAGS }} STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} @@ -256,7 +256,7 @@ jobs: STRIPE_PUBLIC_KEY: ${{ secrets.STRIPE_PUBLIC_KEY }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CYPRESS_mailHogUrl: ${{ secrets.CYPRESS_MAILHOG }} + CYPRESS_MAILPITURL: ${{ secrets.CYPRESS_MAILPITURL }} COMMIT_INFO_MESSAGE: Triggered via release - ${{github.event.client_payload.project}} ${{github.event.client_payload.version}}, ${{github.event.client_payload.pullRequestUrl}} CYPRESS_grepTags: ${{steps.set-tag-for-tests.outputs.result}} with: diff --git a/cypress/e2e/configuration/plugins/plugins.js b/cypress/e2e/configuration/plugins/plugins.js index b7b8e0dfb..3e776b75d 100644 --- a/cypress/e2e/configuration/plugins/plugins.js +++ b/cypress/e2e/configuration/plugins/plugins.js @@ -68,10 +68,16 @@ describe("As an admin I want to manage plugins", () => { customerRegistration({ email: customerEmail, channel: defaultChannel.slug, - }); - getMailsForUser(customerEmail) - .its("0.Content.Headers.Subject.0") - .should("eq", randomName); + }) + .then(() => { + getMailsForUser(customerEmail) + .mpLatest() + .mpGetMailDetails() + .its("Subject"); + }) + .then(subject => { + expect(subject).to.eq(randomName); + }); }, ); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index ceec0d3f0..c7fb7ea34 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -35,7 +35,7 @@ module.exports = async (on, config) => { config.env.SECOND_USER_NAME = process.env.CYPRESS_SECOND_USER_NAME; config.env.PERMISSIONS_USERS_PASSWORD = process.env.CYPRESS_PERMISSIONS_USERS_PASSWORD; - config.env.mailHogUrl = process.env.CYPRESS_mailHogUrl; + config.env.MAILPITURL = process.env.CYPRESS_MAILPITURL; config.env.grepTags = process.env.CYPRESS_grepTags; config.baseUrl = baseUrl(process.env.CYPRESS_demoTests); diff --git a/cypress/support/api/utils/users.js b/cypress/support/api/utils/users.js index 6397f8df3..b259a5994 100644 --- a/cypress/support/api/utils/users.js +++ b/cypress/support/api/utils/users.js @@ -19,7 +19,7 @@ export function inviteStaffMemberWithFirstPermission({ } /** - * Function mhGetMailsByRecipient first get all emails from mailhog with a timeout, and after that it finds email from recipient. + * Function mpGetMailsByRecipient first get all emails from mailpit with a timeout, and after that it finds email from recipient. * It cloud happened that invite email from saleor has not been received yet, so in this case the action should be retried. */ export function getMailActivationLinkForUser(email, regex, i = 0) { @@ -31,15 +31,16 @@ export function getMailActivationLinkForUser(email, regex, i = 0) { `There is no email invitation for user ${serverStoredEmail}`, ); } - return cy.mhGetMailsByRecipient(serverStoredEmail).then(mails => { + return cy.mpGetMailsByRecipient(serverStoredEmail).then(mails => { if (!mails.length) { cy.wait(10000); getMailActivationLinkForUser(serverStoredEmail, regex, i + 1); } else { cy.wrap(mails) - .mhFirst() + .mpLatest() .should("not.eq", undefined) - .mhGetBody() + .mpGetMailDetails() + .its("Text") .then(body => { const bodyWithoutWhiteSpaces = body.replace(/(\r\n|\n|\r|\s)/gm, ""); return urlRegex.exec(bodyWithoutWhiteSpaces)[1]; @@ -56,13 +57,13 @@ export function getMailActivationLinkForUserAndSubject(email, subject, i = 0) { `There is no email invitation for user ${serverStoredEmail}`, ); } - return cy.mhGetMailsByRecipient(serverStoredEmail).then(mails => { + return cy.mpGetMailsByRecipient(serverStoredEmail).then(mails => { if (!mails.length) { cy.wait(10000); getMailActivationLinkForUserAndSubject(serverStoredEmail, subject, i + 1); } else { cy.wrap(mails) - .mhGetMailsBySubject(subject) + .mpGetMailsBySubject(subject) .then(mailsWithSubject => { if (!mailsWithSubject.length) { cy.wait(10000); @@ -73,9 +74,10 @@ export function getMailActivationLinkForUserAndSubject(email, subject, i = 0) { ); } else { cy.wrap(mailsWithSubject) - .mhFirst() + .mpLatest() .should("not.eq", undefined) - .mhGetBody() + .mpGetMailDetails() + .its("Text") .then(body => { const urlRegex = /\[\w*password\w*\]\(([^\)]*)/; const bodyWithoutWhiteSpaces = body.replace( @@ -98,12 +100,12 @@ export function getMailWithResetPasswordLink(email, subject, i = 0) { `There is no email with reset password for user ${serverStoredEmail}`, ); } - return cy.mhGetMailsByRecipient(serverStoredEmail).then(mails => { + return cy.mpGetMailsByRecipient(serverStoredEmail).then(mails => { if (!mails.length) { cy.wait(3000); getMailWithResetPasswordLink(serverStoredEmail, subject, i + 1); } else { - cy.mhGetMailsBySubject(subject).then(resetPasswordMails => { + cy.mpGetMailsBySubject(subject).then(resetPasswordMails => { if (!resetPasswordMails.length) { cy.wait(3000); getMailWithResetPasswordLink(serverStoredEmail, subject, i + 1); @@ -123,7 +125,7 @@ export function getMailsForUser(email, i = 0) { `There is no email invitation for user ${serverStoredEmail}`, ); } - return cy.mhGetMailsByRecipient(serverStoredEmail).then(mails => { + return cy.mpGetMailsByRecipient(serverStoredEmail).then(mails => { if (!mails.length) { cy.wait(3000); getMailsForUser(serverStoredEmail, i + 1); diff --git a/cypress/support/customCommands/basicOperations/mailpit.js b/cypress/support/customCommands/basicOperations/mailpit.js new file mode 100644 index 000000000..f4e8122aa --- /dev/null +++ b/cypress/support/customCommands/basicOperations/mailpit.js @@ -0,0 +1,64 @@ +const mhApiUrl = path => { + const envValue = Cypress.env("MAILPITURL"); + const basePath = envValue ? envValue : Cypress.config("MAILPITURL"); + return `${basePath}/api${path}`; +}; + +/** + * Mail Collection + */ + +Cypress.Commands.add("mpGetAllMails", (fromLast = 60000) => + cy + .request({ + method: "GET", + url: mhApiUrl("/v1/messages?limit=9999"), + }) + .then(response => { + // by default get mails received in last 60000ms + response.body.messages = response.body.messages.filter(message => { + const fiveMinutesAgo = Date.now() - fromLast; + const mailCreated = new Date(message.Created); + return mailCreated.getTime() > fiveMinutesAgo; + }); + if (typeof response.body === "string") { + return JSON.parse(response.body); + } else { + return response.body; + } + }), +); + +Cypress.Commands.add("mpLatest", { prevSubject: true }, mails => + Array.isArray(mails) && mails.length > 0 ? mails[0] : mails, +); + +Cypress.Commands.add("mpGetMailsBySubject", subject => { + cy.mpGetAllMails() + .its("messages") + .then(mails => mails.filter(mail => mail.Subject === subject)); +}); + +Cypress.Commands.add("mpGetMailsByRecipient", recipient => { + cy.mpGetAllMails() + .its("messages") + .then(mails => + mails.filter(mail => + mail.To.map(recipientObj => `${recipientObj.Address}`).includes( + recipient, + ), + ), + ); +}); + +Cypress.Commands.add("mpGetMailDetails", { prevSubject: true }, mail => + cy + .wrap(mail) + .then(mail => { + cy.request({ + method: "GET", + url: mhApiUrl(`/v1/message/${mail.ID}`), + }); + }) + .its("body"), +); diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js index 9f4717b53..280da1732 100644 --- a/cypress/support/e2e.js +++ b/cypress/support/e2e.js @@ -1,7 +1,7 @@ // / import "cypress-file-upload"; -import "cypress-mailhog"; +import "./customCommands/basicOperations/mailpit"; import "cypress-mochawesome-reporter/register"; import "./customCommands/basicOperations"; import "./customCommands/deleteElementsViaApi"; diff --git a/package-lock.json b/package-lock.json index db8c2a0f1..7d35d3b09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15413,8 +15413,9 @@ } }, "node_modules/cypress-mailhog": { - "version": "1.3.0", - "license": "GPL-2.0", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/cypress-mailhog/-/cypress-mailhog-1.7.0.tgz", + "integrity": "sha512-OBk27OYm4slL5lCtphlHTlFPnrDEmuMeqSTch4/uk92iPzh8+gS4Y1KAmMiZsSDGjQzXi/7Ab5QWo6xmq8evXg==", "optional": true }, "node_modules/cypress-mochawesome-reporter": { @@ -48879,7 +48880,9 @@ "optional": true }, "cypress-mailhog": { - "version": "1.3.0", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/cypress-mailhog/-/cypress-mailhog-1.7.0.tgz", + "integrity": "sha512-OBk27OYm4slL5lCtphlHTlFPnrDEmuMeqSTch4/uk92iPzh8+gS4Y1KAmMiZsSDGjQzXi/7Ab5QWo6xmq8evXg==", "optional": true }, "cypress-mochawesome-reporter": {