From dbfe9b7f78e7127ae543e6d76f386f00c2528c31 Mon Sep 17 00:00:00 2001 From: Karolina Rakoczy Date: Fri, 15 Mar 2024 12:37:59 +0100 Subject: [PATCH] [TEST] [E2E] Added test for setting balance and exporting gift cards (#4650) * Added test for setting balance and exporting gift cards * add changeset * Fixes after review * Fixes after review * Fix mailpit url * Fix mailpit env variable * Fix mailpit url * changes after review --- .changeset/nervous-toes-fail.md | 5 +++ .env.template | 3 +- .github/actions/run-pw-tests/action.yml | 5 +++ .github/workflows/pr-automation.yml | 1 + .github/workflows/run-test-cron.yml | 1 + .github/workflows/run-test-manual.yml | 1 + playwright/api/mailpit.ts | 21 +++++++++--- .../pages/dialogs/exportGiftCardsDialog.ts | 16 ++++++++++ .../pages/dialogs/setGiftCardBalanceDialog.ts | 18 +++++++++++ playwright/pages/giftCardsPage.ts | 23 ++++++++++--- playwright/tests/girftCards.spec.ts | 32 ++++++++++++++++++- 11 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 .changeset/nervous-toes-fail.md create mode 100644 playwright/pages/dialogs/exportGiftCardsDialog.ts create mode 100644 playwright/pages/dialogs/setGiftCardBalanceDialog.ts diff --git a/.changeset/nervous-toes-fail.md b/.changeset/nervous-toes-fail.md new file mode 100644 index 00000000000..1f0d3878f53 --- /dev/null +++ b/.changeset/nervous-toes-fail.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": minor +--- + +Rewritten tests for setting balance and exporting gift cards diff --git a/.env.template b/.env.template index f96894d0095..e0811286c9d 100644 --- a/.env.template +++ b/.env.template @@ -9,7 +9,8 @@ CYPRESS_USER_PASSWORD=xxxx CYPRESS_SECOND_USER_NAME=xxxx CYPRESS_PERMISSIONS_USERS_PASSWORD=xxxx CYPRESS_baseUrl=http://localhost:9000/ -CYPRESS_MAILPITURL=xxxx +CYPRESS_MAILPITURL=xxxx +MAILPITURL=xxxx #For playwright E2E_USER_NAME=xxxx E2E_USER_PASSWORD=xxxx diff --git a/.github/actions/run-pw-tests/action.yml b/.github/actions/run-pw-tests/action.yml index c5300bc0372..9c868592f9d 100644 --- a/.github/actions/run-pw-tests/action.yml +++ b/.github/actions/run-pw-tests/action.yml @@ -19,6 +19,10 @@ inputs: SHARD: description: "Shard number" required: true + MAILPITURL: + description: "mailpit uri" + required: true + runs: using: "composite" steps: @@ -43,6 +47,7 @@ runs: E2E_USER_PASSWORD: ${{ inputs.E2E_USER_PASSWORD }} E2E_PERMISSIONS_USERS_PASSWORD: ${{ inputs.E2E_PERMISSIONS_USERS_PASSWORD }} SHARD_NUMBER: ${{ inputs.SHARD }} + MAILPITURL: ${{ inputs.MAILPITURL }} run: npm run qa:pw-e2e -- --shard "$SHARD_NUMBER" - name: Upload blob report to GitHub Actions Artifacts diff --git a/.github/workflows/pr-automation.yml b/.github/workflows/pr-automation.yml index 87cd9fa05e7..9447c52b496 100644 --- a/.github/workflows/pr-automation.yml +++ b/.github/workflows/pr-automation.yml @@ -208,6 +208,7 @@ jobs: E2E_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }} E2E_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }} E2E_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }} + MAILPITURL: ${{ secrets.CYPRESS_MAILPITURL }} merge-reports: if: '!cancelled()' diff --git a/.github/workflows/run-test-cron.yml b/.github/workflows/run-test-cron.yml index 63583df2cc1..fe2d1f689b2 100644 --- a/.github/workflows/run-test-cron.yml +++ b/.github/workflows/run-test-cron.yml @@ -63,6 +63,7 @@ jobs: E2E_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }} E2E_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }} E2E_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }} + MAILPITURL: ${{ secrets.CYPRESS_MAILPITURL }} merge-reports: if: '!cancelled()' diff --git a/.github/workflows/run-test-manual.yml b/.github/workflows/run-test-manual.yml index eb3f1fbc144..c53c940356e 100644 --- a/.github/workflows/run-test-manual.yml +++ b/.github/workflows/run-test-manual.yml @@ -70,6 +70,7 @@ jobs: E2E_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }} E2E_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }} E2E_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }} + MAILPITURL: ${{ secrets.CYPRESS_MAILPITURL }} merge-reports: if: '!cancelled()' diff --git a/playwright/api/mailpit.ts b/playwright/api/mailpit.ts index c764dc621f3..1cb7405d103 100644 --- a/playwright/api/mailpit.ts +++ b/playwright/api/mailpit.ts @@ -1,8 +1,7 @@ import { URL_LIST } from "@data/url"; import { APIRequestContext, expect } from "@playwright/test"; -const MAILPIT_URI = process.env.CYPRESS_MAILPITURL || "no mailpit url provided"; -const mailpitUrl = "https://" + MAILPIT_URI; +const mailpitUrl = process.env.MAILPITURL || "no mailpit url provided"; export class MailpitService { readonly request: APIRequestContext; @@ -31,6 +30,19 @@ export class MailpitService { return latestEmailsJson; } + async getEmailsFromTime(fromTime = 10000){ + const latestEmails = await this.getLastEmails() + + latestEmails.messages = latestEmails.messages.filter( + (message: { Created: string }) => { + const timeMinusLastMs = Date.now() - fromTime; + const mailCreated = new Date(message.Created); + return mailCreated.getTime() > timeMinusLastMs; + }, + ); + return latestEmails; + } + async getEmailDetails(mailId: string) { const emailDetails = await this.request.get( `${mailpitUrl}/api/v1/message/${mailId}`, @@ -45,7 +57,7 @@ export class MailpitService { await expect .poll( async () => { - const emails = await this.getLastEmails(); + const emails = await this.getEmailsFromTime(); userEmails = await emails.messages.filter((mails: { To: any[] }) => mails.To.map( (recipientObj: { Address: any }) => `${recipientObj.Address}`, @@ -55,7 +67,7 @@ export class MailpitService { return userEmails.length; }, { - message: `User: ${userEmail} messages were not found`, + message: `User: ${userEmail} messages were not found.`, intervals: [2000, 3000, 5000, 5000], timeout: 15000, }, @@ -63,6 +75,7 @@ export class MailpitService { .toBeGreaterThanOrEqual(1); return userEmails; } + async checkDoesUserReceivedExportedData( userEmail: string, mailSubject: string, diff --git a/playwright/pages/dialogs/exportGiftCardsDialog.ts b/playwright/pages/dialogs/exportGiftCardsDialog.ts new file mode 100644 index 00000000000..eb1691c4fde --- /dev/null +++ b/playwright/pages/dialogs/exportGiftCardsDialog.ts @@ -0,0 +1,16 @@ +import { Page } from "@playwright/test"; + +export class ExportGiftCardsDialog { + readonly page: Page; + + constructor(page: Page, readonly submitButton = page.getByTestId("submit")) { + this.page = page; + } + + async exportGiftCardCodes(fileExtension: string) { + const fileExtensionCheckbox = this.page.getByTestId(fileExtension); + await fileExtensionCheckbox.click(); + await this.submitButton.click(); + await this.submitButton.waitFor({state: "hidden"}) + } +} diff --git a/playwright/pages/dialogs/setGiftCardBalanceDialog.ts b/playwright/pages/dialogs/setGiftCardBalanceDialog.ts new file mode 100644 index 00000000000..c960c43e2f2 --- /dev/null +++ b/playwright/pages/dialogs/setGiftCardBalanceDialog.ts @@ -0,0 +1,18 @@ +import { Page } from "@playwright/test"; + +export class SetGiftCardsBalanceDialog { + readonly page: Page; + + constructor( + page: Page, + readonly submitButton = page.getByTestId("submit"), + readonly enterAmountInput = page.locator('[name="balanceAmount"]'), + ) { + this.page = page; + } + + async setBalance(balance: string){ + await this.enterAmountInput.fill(balance); + await this.submitButton.click(); + } +} diff --git a/playwright/pages/giftCardsPage.ts b/playwright/pages/giftCardsPage.ts index b0faf3ddbe5..d6d145972ec 100644 --- a/playwright/pages/giftCardsPage.ts +++ b/playwright/pages/giftCardsPage.ts @@ -5,6 +5,8 @@ import { ResendGiftCardCodeDialog } from "@dialogs/resendGiftCardCodeDialog"; import { MetadataSeoPage } from "@pageElements/metadataSeoPage"; import { BasePage } from "@pages/basePage"; import type { Page } from "@playwright/test"; +import { ExportGiftCardsDialog } from "@dialogs/exportGiftCardsDialog"; +import { SetGiftCardsBalanceDialog } from "@dialogs/setGiftCardBalanceDialog"; export class GiftCardsPage extends BasePage { readonly page: Page; @@ -12,6 +14,8 @@ export class GiftCardsPage extends BasePage { readonly resendGiftCardCodeDialog: ResendGiftCardCodeDialog; readonly metadataSeoPage: MetadataSeoPage; readonly deleteDialog: DeleteDialog; + readonly exportGiftCardsDialog: ExportGiftCardsDialog; + readonly setGiftCardsBalanceDialog: SetGiftCardsBalanceDialog; constructor( page: Page, @@ -21,6 +25,9 @@ export class GiftCardsPage extends BasePage { readonly deactivateButton = page.getByTestId("enable-button"), readonly saveButton = page.getByTestId("button-bar-confirm"), readonly cardExpiresCheckbox = page.locator("[name='cardExpires']"), + readonly exportCardCodesButton = page.getByTestId("exportCodesMenuItem"), + readonly setBalanceButton = page.getByTestId("set-balance-button"), + readonly showMoreMenuButton = page.getByTestId("show-more-button"), ) { super(page); this.page = page; @@ -28,6 +35,8 @@ export class GiftCardsPage extends BasePage { this.resendGiftCardCodeDialog = new ResendGiftCardCodeDialog(page); this.metadataSeoPage = new MetadataSeoPage(page); this.deleteDialog = new DeleteDialog(page); + this.exportGiftCardsDialog = new ExportGiftCardsDialog(page); + this.setGiftCardsBalanceDialog = new SetGiftCardsBalanceDialog(page); } async clickIssueCardButton() { @@ -45,18 +54,24 @@ export class GiftCardsPage extends BasePage { async clickDeactivateButton() { await this.deactivateButton.click(); } + async clickExportGiftCards() { + await this.exportCardCodesButton.click(); + } async clickResendCodeButton() { await this.resendCodeButton.click(); } + async clickSetBalance() { + await this.setBalanceButton.click(); + } + async clickShowMoreMenu(){ + await this.showMoreMenuButton.click(); + } async gotoGiftCardsListView() { await this.page.goto(URL_LIST.giftCards); } async gotoExistingGiftCardView(giftCardId: string) { const existingGiftCardUrl = URL_LIST.giftCards + giftCardId; - await console.log( - "Navigating to existing gift card: " + existingGiftCardUrl, - ); - + console.log("Navigating to existing gift card: " + existingGiftCardUrl); await this.page.goto(existingGiftCardUrl); } } diff --git a/playwright/tests/girftCards.spec.ts b/playwright/tests/girftCards.spec.ts index 36d2f731f78..6538892b515 100644 --- a/playwright/tests/girftCards.spec.ts +++ b/playwright/tests/girftCards.spec.ts @@ -1,11 +1,15 @@ import { GIFT_CARDS } from "@data/e2eTestData"; import { GiftCardsPage } from "@pages/giftCardsPage"; import { expect, test } from "@playwright/test"; +import { MailpitService } from "@api/mailpit"; + test.use({ storageState: "playwright/.auth/admin.json" }); let giftCardsPage: GiftCardsPage; -test.beforeEach(({ page }) => { +let mailpitService: MailpitService; +test.beforeEach(({ page, request }) => { giftCardsPage = new GiftCardsPage(page); + mailpitService = new MailpitService(request); }); test("TC: SALEOR_105 Issue gift card @e2e @gift", async () => { @@ -100,3 +104,29 @@ test("TC: SALEOR_111 Bulk delete gift cards @e2e @gift", async () => { ), ).toEqual([]); }); +test("TC: SALEOR_112 Set gift card balance @e2e @gift", async () => { + await giftCardsPage.gotoExistingGiftCardView(GIFT_CARDS.giftCardToBeEdited.id); + await giftCardsPage.clickSetBalance(); + await giftCardsPage.setGiftCardsBalanceDialog.setBalance("34") + await giftCardsPage.expectSuccessBanner(); +}); +test("TC: SALEOR_113 Export gift card codes in XLSX file @e2e @gift", async () => { + await giftCardsPage.gotoGiftCardsListView(); + await giftCardsPage.clickShowMoreMenu(); + await giftCardsPage.clickExportGiftCards(); + await giftCardsPage.exportGiftCardsDialog.exportGiftCardCodes("XLSX"); + await mailpitService.checkDoesUserReceivedExportedData( + process.env.E2E_USER_NAME!, + "Your exported gift cards data is ready", + ); +}); +test("TC: SALEOR_114 Export gift card codes in CSV file @e2e @gift", async () => { + await giftCardsPage.gotoGiftCardsListView(); + await giftCardsPage.clickShowMoreMenu(); + await giftCardsPage.clickExportGiftCards(); + await giftCardsPage.exportGiftCardsDialog.exportGiftCardCodes("CSV"); + await mailpitService.checkDoesUserReceivedExportedData( + process.env.E2E_USER_NAME!, + "Your exported gift cards data is ready", + ); +}); \ No newline at end of file