diff --git a/e2e/.gitignore b/e2e/.gitignore index 9184aec07..97fa540a1 100644 --- a/e2e/.gitignore +++ b/e2e/.gitignore @@ -1,5 +1,5 @@ node_modules/ /playwright/.cache/ +/test-results/ /playwright-report/ /playwright/.cache/ -/e2e-reports/ \ No newline at end of file diff --git a/e2e/data/localization.ts b/e2e/data/localization.ts index 799315c8b..ace60ea47 100644 --- a/e2e/data/localization.ts +++ b/e2e/data/localization.ts @@ -1,20 +1,20 @@ -import bgLocalizationCommonJson from '../../public/locales/bg/common.json'; -import enLocalizationCommonJson from '../../public/locales/en/common.json'; +import bgLocalizationCommonJson from '../../../frontend/public/locales/bg/common.json'; +import enLocalizationCommonJson from '../../../frontend/public/locales/en/common.json'; -import bgLocalizationIndexJson from '../../public/locales/bg/index.json'; -import enLocalizationIndexJson from '../../public/locales/en/index.json'; +import bgLocalizationIndexJson from '../../../frontend/public/locales/bg/index.json'; +import enLocalizationIndexJson from '../../../frontend/public/locales/en/index.json'; -import bgLocalizationSupportJson from '../../public/locales/bg/support.json'; -import enLocalizationSupportJson from '../../public/locales/en/support.json'; +import bgLocalizationSupportJson from '../../../frontend/public/locales/bg/support.json'; +import enLocalizationSupportJson from '../../../frontend/public/locales/en/support.json'; -import bgLocalizationValidationJson from '../../public/locales/bg/validation.json'; -import enLocalizationValidationJson from '../../public/locales/en/validation.json'; +import bgLocalizationValidationJson from '../../../frontend/public/locales/bg/validation.json'; +import enLocalizationValidationJson from '../../../frontend/public/locales/en/validation.json'; -import bgLocalizationCampaignsJson from '../../public/locales/bg/campaigns.json'; -import enLocalizationCampaignsJson from '../../public/locales/en/campaigns.json'; +import bgLocalizationCampaignsJson from '../../../frontend/public/locales/bg/campaigns.json'; +import enLocalizationCampaignsJson from '../../../frontend/public/locales/en/campaigns.json'; -import bgLocalizationOneTimeDonationJson from '../../public/locales/bg/one-time-donation.json'; -import enLocalizationOneTimeDonationJson from '../../public/locales/en/one-time-donation.json'; +import bgLocalizationOneTimeDonationJson from '../../../frontend/public/locales/bg/one-time-donation.json'; +import enLocalizationOneTimeDonationJson from '../../../frontend/public/locales/en/one-time-donation.json'; // All these constants are used in the E2E test pages to manipulate web elements in a respective language // Common localization terms diff --git a/e2e/pages/web-pages/base.page.ts b/e2e/pages/web-pages/base.page.ts index b77fe4f44..e6e387391 100644 --- a/e2e/pages/web-pages/base.page.ts +++ b/e2e/pages/web-pages/base.page.ts @@ -1,6 +1,5 @@ import { expect, Locator, Page } from '@playwright/test'; -// Here we define all base methods, which are inherited into the other pages export class BasePage { protected page: Page; @@ -53,11 +52,11 @@ export class BasePage { * @param {any} options * @param {number} timeoutParam */ - async waitForElementToBeReadyBySelector(elementSelector: string, options?: any, timeoutParam: number = 10000): Promise { + async waitForElementToBeReadyBySelector(elementSelector: string, options: any, timeoutParam: number = 10000): Promise { if (options) { - await this.page.locator(elementSelector, options).first().waitFor({state: 'visible', timeout: timeoutParam}); + await this.page.locator(elementSelector, options).waitFor({state: 'visible', timeout: timeoutParam}); } else { - await this.page.locator(elementSelector).first().waitFor({state: 'visible', timeout: timeoutParam}); + await this.page.waitForSelector(elementSelector, {state: 'visible', timeout: timeoutParam}); } } @@ -374,7 +373,6 @@ export class BasePage { * @param {string} elementSelector */ async getCountOfElementsBySelector(elementSelector: string): Promise { - await this.waitForElementToBePresentedBySelector(elementSelector); return this.page.locator(elementSelector).count(); } diff --git a/e2e/pages/web-pages/campaigns/campaigns.page.ts b/e2e/pages/web-pages/campaigns/campaigns.page.ts index b12f7077e..0c33d38be 100644 --- a/e2e/pages/web-pages/campaigns/campaigns.page.ts +++ b/e2e/pages/web-pages/campaigns/campaigns.page.ts @@ -1,6 +1,6 @@ import { expect, Locator, Page } from '@playwright/test'; import { LanguagesEnum } from '../../../data/enums/languages.enum'; -import { bgLocalizationCampaigns, enLocalizationCampaigns } from '../../../data/localization'; +import { bgLocalizationCampaigns, bgLocalizationIndex, enLocalizationCampaigns } from '../../../data/localization'; import { HomePage } from '../home.page'; @@ -39,14 +39,13 @@ export class CampaignsPage extends HomePage { * @param {LanguagesEnum} language, the default is BG */ async clickCampaignSchoolChildrenVarna(language: LanguagesEnum = LanguagesEnum.BG): Promise { - await this.clickH5HeadingByText(language, this.campaignSchoolVarnaText, null); + await this.clickH5HeadingByText(language, this.campaignSchoolVarnaText); } /** * Get filter buttons count on the Campaigns page */ async getFilterButtonsCount(): Promise { - await this.waitForElementToBeReadyBySelector(this.filterButtonsCommonSelector); return this.getCountOfElementsBySelector(this.filterButtonsCommonSelector); } @@ -55,7 +54,7 @@ export class CampaignsPage extends HomePage { * @param {LanguagesEnum} language - the default value is BG */ async isCampaignsHeadingVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH1HeadingVisible(language, this.bgMainCampaignsHeading, this.enMainCampaignsHeading); + return this.isH1HeadingVisible(this.bgMainCampaignsHeading, this.enMainCampaignsHeading, language); } /** @@ -71,7 +70,7 @@ export class CampaignsPage extends HomePage { * @param {LanguagesEnum} language - the default value is BG */ async isSchoolChildrenVarnaHeadingVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH1HeadingVisible(language, this.campaignSchoolVarnaText, null); + return this.isH1HeadingVisible(this.campaignSchoolVarnaText, null, language); } /** @@ -79,7 +78,7 @@ export class CampaignsPage extends HomePage { * @param {LanguagesEnum} language, the default is BG */ async clickCampaignCrisisCenter(language: LanguagesEnum = LanguagesEnum.BG): Promise { - await this.clickH5HeadingByText(language, this.campaignCrisisCenterText, null); + await this.clickH5HeadingByText(language, this.campaignCrisisCenterText); } /** @@ -87,7 +86,7 @@ export class CampaignsPage extends HomePage { * @param {LanguagesEnum} language - the default value is BG */ async isCrisiCenterHeading1Visible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH1HeadingVisible(language, this.campaignCrisisCenterText, null); + return this.isH1HeadingVisible(this.campaignCrisisCenterText, null, language); } /** @@ -95,7 +94,7 @@ export class CampaignsPage extends HomePage { * @param {LanguagesEnum} language - the default value is BG */ async isCrisiCenterHeading4Visible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH4HeadingVisible(language, this.campaignCrisisCenterText, null); + return this.isH4HeadingVisible(this.campaignCrisisCenterText, null, language); } /** diff --git a/e2e/pages/web-pages/campaigns/donation.page.ts b/e2e/pages/web-pages/campaigns/donation.page.ts index 6876f9ae0..555d51cde 100644 --- a/e2e/pages/web-pages/campaigns/donation.page.ts +++ b/e2e/pages/web-pages/campaigns/donation.page.ts @@ -215,6 +215,6 @@ export class DonationPage extends CampaignsPage { * @param {LanguagesEnum} language - the default value is BG */ async isSuccessfulDonationTitleVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH4HeadingVisible(language, this.bgSuccessfulDonationTitle, this.enSuccessfulDonationTitle); + return this.isH4HeadingVisible(this.bgSuccessfulDonationTitle, this.enSuccessfulDonationTitle, language); } } diff --git a/e2e/pages/web-pages/header.page.ts b/e2e/pages/web-pages/header.page.ts index 2eea64504..597b72ed0 100644 --- a/e2e/pages/web-pages/header.page.ts +++ b/e2e/pages/web-pages/header.page.ts @@ -58,16 +58,15 @@ export class HeaderPage extends BasePage { /** * Click on the header submenu navigation link by text - * @param {LanguagesEnum} language * @param {string} navTextBg * @param {string} navTextEn + * @param {LanguagesEnum} language */ - async clickHeaderSubmenuNavLink(language: LanguagesEnum, navTextBg: string, navTextEn: string): Promise { + async clickHeaderSubmenuNavLink(navTextBg: string, navTextEn: string, language: LanguagesEnum): Promise { + await this.waitForElementToBePresentedBySelector(this.headerSubmenuLinks); if (language === LanguagesEnum.BG) { - await this.waitForElementToBeReadyBySelector(this.headerSubmenuLinks, {hasText: navTextBg}); await this.clickElement(this.headerSubmenuLinks, {hasText: navTextBg}); } else if (language === LanguagesEnum.EN) { - await this.waitForElementToBeReadyBySelector(this.headerSubmenuLinks, {hasText: navTextEn}); await this.clickElement(this.headerSubmenuLinks, {hasText: navTextEn}); } else { throw new Error("Invalid language selection. Please, check 'languages.enum.ts'."); @@ -94,7 +93,7 @@ export class HeaderPage extends BasePage { */ async clickCampaignsHeaderNavButton(language: LanguagesEnum = LanguagesEnum.BG): Promise { await this.clickHeaderNavLink(this.bgCampaignsNavLink, this.enCampaignsNavLink, language); - await this.clickHeaderSubmenuNavLink(language, this.bgAllCampaignsNavLink, this.enAllCampaignsNavLink); + await this.clickHeaderSubmenuNavLink(this.bgAllCampaignsNavLink, this.enAllCampaignsNavLink, language); } /** @@ -111,7 +110,7 @@ export class HeaderPage extends BasePage { */ async clickJoinUsHeaderNavButton(language: LanguagesEnum = LanguagesEnum.BG): Promise { await this.clickAboutUsHeaderNavButton(language); - await this.clickHeaderSubmenuNavLink(language, this.bgJoinUsNavLink, this.enJoinUsNavLink); + await this.clickHeaderSubmenuNavLink(this.bgJoinUsNavLink, this.enJoinUsNavLink, language); } /** diff --git a/e2e/pages/web-pages/home.page.ts b/e2e/pages/web-pages/home.page.ts index 558cf0e25..13231ba74 100644 --- a/e2e/pages/web-pages/home.page.ts +++ b/e2e/pages/web-pages/home.page.ts @@ -70,63 +70,73 @@ export class HomePage extends BasePage { } /** - * Check if Heading is visible by CSS Selector and text with timeout - * @param {string} elementSelector - * @param {LanguagesEnum} language + * Check if H1 heading is visible by text with timeout * @param {string} headingBg * @param {string | null} headingEn + * @param {LanguagesEnum} language */ - async isHeadingVisibleBySelector(elementSelector: string, language: LanguagesEnum, headingBg: string, headingEn: string | null): Promise { - await this.waitForElementToBePresentedByLocator(this.page.locator(elementSelector).first()); + async isH1HeadingVisible(headingBg: string, headingEn: string | null, language: LanguagesEnum): Promise { + await this.waitForElementToBePresentedByLocator(this.page.locator(this.containerRootElement).first()); if (language === LanguagesEnum.BG) { - return this.isElementVisibleBySelectorWithTimeout(elementSelector, {hasText: headingBg}); + return this.isElementVisibleBySelectorWithTimeout(this.h1HeadingsSelector, {hasText: headingBg}); } else if (language === LanguagesEnum.EN) { - return this.isElementVisibleBySelectorWithTimeout(elementSelector, {hasText: headingEn}); + return this.isElementVisibleBySelectorWithTimeout(this.h1HeadingsSelector, {hasText: headingEn}); } else { throw new Error("Language not found!"); } } - - /** - * Check if H1 heading is visible by text with timeout - * @param {LanguagesEnum} language - * @param {string} headingBg - * @param {string | null} headingEn - */ - async isH1HeadingVisible(language: LanguagesEnum, headingBg: string, headingEn: string | null): Promise { - return this.isHeadingVisibleBySelector(this.h1HeadingsSelector, language, headingBg, headingEn); - } - + /** * Check if H4 heading is visible by text with timeout - * @param {LanguagesEnum} language * @param {string} headingBg * @param {string | null} headingEn + * @param {LanguagesEnum} language */ - async isH4HeadingVisible(language: LanguagesEnum, headingBg: string, headingEn: string | null): Promise { - return this.isHeadingVisibleBySelector(this.h4HeadingsSelector, language, headingBg, headingEn); + async isH4HeadingVisible(headingBg: string, headingEn: string | null, language: LanguagesEnum): Promise { + await this.waitForElementToBePresentedByLocator(this.page.locator(this.containerRootElement).first()); + if (language === LanguagesEnum.BG) { + return this.isElementVisibleBySelectorWithTimeout(this.h4HeadingsSelector, {hasText: headingBg}); + } else if (language === LanguagesEnum.EN) { + return this.isElementVisibleBySelectorWithTimeout(this.h4HeadingsSelector, {hasText: headingEn}); + } else { + throw new Error("Language not found!"); + } } /** * Check if H5 heading is visible by text with timeout - * @param {LanguagesEnum} language * @param {string} headingBg * @param {string | null} headingEn + * @param {LanguagesEnum} language */ - async isH5HeadingVisible(language: LanguagesEnum, headingBg: string, headingEn: string | null): Promise { - return this.isHeadingVisibleBySelector(this.h5HeadingsSelector, language, headingBg, headingEn); + async isH5HeadingVisible(language: LanguagesEnum, headingBg: string | null, headingEn?: string): Promise { + await this.waitForElementToBePresentedByLocator(this.page.locator(this.containerRootElement).first()); + if (language === LanguagesEnum.BG) { + return this.isElementVisibleBySelectorWithTimeout(this.h5HeadingsSelector, {hasText: headingBg}); + } else if (language === LanguagesEnum.EN) { + return this.isElementVisibleBySelectorWithTimeout(this.h5HeadingsSelector, {hasText: headingEn}); + } else { + throw new Error("Language not found!"); + } } /** * Check if H6 heading is visible by text with timeout - * @param {LanguagesEnum} language * @param {string} headingBg * @param {string | null} headingEn + * @param {LanguagesEnum} language */ - async isH6HeadingVisible(language: LanguagesEnum, headingBg: string, headingEn: string | null): Promise { - return this.isHeadingVisibleBySelector(this.h6HeadingsSelector, language, headingBg, headingEn); + async isH6HeadingVisible(language: LanguagesEnum, headingBg: string | null, headingEn?: string): Promise { + await this.waitForElementToBePresentedByLocator(this.page.locator(this.containerRootElement).first()); + if (language === LanguagesEnum.BG) { + return this.isElementVisibleBySelectorWithTimeout(this.h6HeadingsSelector, {hasText: headingBg}); + } else if (language === LanguagesEnum.EN) { + return this.isElementVisibleBySelectorWithTimeout(this.h6HeadingsSelector, {hasText: headingEn}); + } else { + throw new Error("Language not found!"); + } } - + /** * Check if H6 homepage FAQ heading is visible with timeout * @param {LanguagesEnum} language @@ -166,9 +176,9 @@ export class HomePage extends BasePage { * Click H5 heading by text * @param {LanguagesEnum} language * @param {string} headingBg - * @param {string | null} headingEn + * @param {string} headingEn */ - async clickH5HeadingByText(language: LanguagesEnum = LanguagesEnum.BG, headingBg: string, headingEn: string | null): Promise { + async clickH5HeadingByText(language: LanguagesEnum = LanguagesEnum.BG, headingBg: string, headingEn?: string): Promise { if (await this.isH5HeadingVisible(language, headingBg, headingEn)) { if (language === LanguagesEnum.BG) { await this.scrollToElementCenterBySelector(this.h5HeadingsSelector, {hasText: headingBg}); @@ -207,35 +217,35 @@ export class HomePage extends BasePage { } /** - * Check if "How we work" heading is visible with timeout + * Check if 'Kak raboti Podkrepi/How we work' heading is visible with timeout * @param {LanguagesEnum} language - the default value is BG */ async isHowWeWorkHeadingVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH4HeadingVisible(language, this.bgHowDoesPodkrepiWork, this.enHowDoesPodkrepiWork); + return this.isH4HeadingVisible(this.bgHowDoesPodkrepiWork, this.enHowDoesPodkrepiWork, language); } /** - * Check if "Who is behind Podkrepi" heading is visible with timeout + * Check if 'Koi stoi zad Podkrepi/Who is behind Podkrepi' heading is visible with timeout * @param {LanguagesEnum} language - the default value is BG */ async isTeamSectionHeadingVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH4HeadingVisible(language, this.bgTeamSection, this.enTeamSection); + return this.isH4HeadingVisible(this.bgTeamSection, this.enTeamSection, language); } /** - * Check if "Join Podkrepi" heading is visible with timeout + * Check if 'Prisyedinete se kym Podkrepi/Join Podkrepi' heading is visible with timeout * @param {LanguagesEnum} language - the default value is BG */ async isJoinPodkrepiSectionHeadingVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH4HeadingVisible(language, this.bgJoinPodkrepiSection, this.enJoinPodkrepiSection); + return this.isH4HeadingVisible(this.bgJoinPodkrepiSection, this.enJoinPodkrepiSection, language); } /** - * Check if "FAQ" heading is visible with timeout + * Check if 'Chesto zadavani vyprosi/FAQ' heading is visible with timeout * @param {LanguagesEnum} language - the default value is BG */ async isFaqSectionHeadingVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH4HeadingVisible(language, this.bgFaqSection, this.enFaqSection); + return this.isH4HeadingVisible(this.bgFaqSection, this.enFaqSection, language); } /** @@ -247,7 +257,7 @@ export class HomePage extends BasePage { } /** - * Check if "What is Podkrepi" FAQ list item is visible with timeout + * Check if 'What is Podkrepi' FAQ list item is visible with timeout */ async isPodkrepiFaqListAnswerVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { const faqAnswerText = await this.getTextOfHomeH6FaqAnswer(language); diff --git a/e2e/pages/web-pages/support.page.ts b/e2e/pages/web-pages/support.page.ts index aa23b48b5..61700913b 100644 --- a/e2e/pages/web-pages/support.page.ts +++ b/e2e/pages/web-pages/support.page.ts @@ -136,7 +136,7 @@ export class SupportPage extends HomePage { * @param {string} language */ async isThankYouSupportH4HeadingVisible(language: LanguagesEnum = LanguagesEnum.BG): Promise { - return this.isH4HeadingVisible(language, this.bgThankYouForSupportH4, this.enThankYouForSupportH4); + return this.isH4HeadingVisible(this.bgThankYouForSupportH4, this.enThankYouForSupportH4, language); } /** diff --git a/e2e/tests/regression/donation-flow/anon-donation-custom.spec.ts b/e2e/tests/regression/donation-flow/anon-donation-custom.spec.ts index 27a6fd016..da1fb063b 100644 --- a/e2e/tests/regression/donation-flow/anon-donation-custom.spec.ts +++ b/e2e/tests/regression/donation-flow/anon-donation-custom.spec.ts @@ -33,8 +33,7 @@ test.describe.serial('Anonymous contributor is able to donate custom amount - BG campaignsPage = new CampaignsPage(page); donationPage = new DonationPage(page); stripeCheckoutPage = new StripeCheckoutPage(page); - // For local executions use method navigateToLocalhostHomepage(); - // await homepage.navigateToLocalhostHomepage(); + // TODO Change here to localhost and leave comment for the devs await homepage.navigateToDevEnvHomepage(); }); @@ -89,16 +88,16 @@ test.describe.serial('Anonymous contributor is able to donate custom amount - BG expect(await donationPage.isSendAWishStepActive(), "Send a wish step is not active.").toBeTruthy(); }); - test('After sending a wish, the user is redirected to Stripe', async () => { + test('The user is able to send a wish', async () => { await donationPage.fillSendAWishField("E2E test - anonymous donation."); await donationPage.clickFinishButton(); + }); + + test('The user is able to pay via Stripe', async () => { const stripeTotalAmount = await stripeCheckoutPage.getTotalAmountText(); const actualStripeEmail = await stripeCheckoutPage.getReadonlyEmailText(); expect.soft(stripeTotalAmount, "The Stripe total donation amount is not correct.").toContain("13.56"); expect(actualStripeEmail, "The user e-mail is not sent correctly to Stripe.").toEqual(testEmail); - }); - - test('The user is able to pay via Stripe', async () => { await stripeCheckoutPage.fillPaymentForm([anonDonationTestData.cardNumber, anonDonationTestData.cardExpDate, anonDonationTestData.cardCvc, anonDonationTestData.billingName, anonDonationTestData.country]); diff --git a/e2e/tests/regression/donation-flow/anon-donation-fixed.spec.ts b/e2e/tests/regression/donation-flow/anon-donation-fixed.spec.ts index efb682ede..c4c242d96 100644 --- a/e2e/tests/regression/donation-flow/anon-donation-fixed.spec.ts +++ b/e2e/tests/regression/donation-flow/anon-donation-fixed.spec.ts @@ -34,8 +34,7 @@ test.describe.serial('Anonymous contributor is able to donate fixed amount - EN campaignsPage = new CampaignsPage(page); donationPage = new DonationPage(page); stripeCheckoutPage = new StripeCheckoutPage(page); - // For local executions use method navigateToLocalhostHomepage(); - // await homepage.navigateToLocalhostHomepage(); + // TODO Change here to localhost and leave comment for the devs await homepage.navigateToDevEnvHomepage(); await headerPage.changeanguageHeaderButtonToBe(LanguagesEnum.EN); }); @@ -56,7 +55,6 @@ test.describe.serial('Anonymous contributor is able to donate fixed amount - EN test('The total charge, fee tax and donation amount are visible on the Campaign page', async () => { await campaignsPage.clickDonationSupportButton(); await donationPage.checkPageUrlByRegExp(campaignDonationCrisisCenterPageUrl); - // TODO: Remove the next line when the followin bug is fixed: https://github.com/podkrepi-bg/frontend/issues/1247 await headerPage.changeanguageHeaderButtonToBe(LanguagesEnum.EN); expect.soft(await donationPage.isSelectAmountStepActive(LanguagesEnum.EN), "Select Amount step is not active.").toBeTruthy(); await donationPage.selectRadioButtonByLabelText(["10"]); @@ -93,20 +91,114 @@ test.describe.serial('Anonymous contributor is able to donate fixed amount - EN expect(await donationPage.isSendAWishStepActive(LanguagesEnum.EN), "Send a wish step is not active.").toBeTruthy(); }); - test('After sending a wish, the user is redirected to Stripe', async () => { + test('The user is able to send a wish', async () => { await donationPage.fillSendAWishField("E2E test - anonymous donation."); await donationPage.clickFinishButton(LanguagesEnum.EN); + }); + + test('The user is able to pay via Stripe', async () => { const stripeTotalAmount = await stripeCheckoutPage.getTotalAmountText(); const actualStripeEmail = await stripeCheckoutPage.getReadonlyEmailText(); expect.soft(stripeTotalAmount, "The Stripe total donation amount is not correct.").toContain("20.75"); expect(actualStripeEmail, "The user e-mail is not sent correctly to Stripe.").toEqual(testEmail); - }); - - test('The user is able to pay via Stripe', async () => { await stripeCheckoutPage.fillPaymentForm([anonDonationTestData.cardNumber, anonDonationTestData.cardExpDate, anonDonationTestData.cardCvc, anonDonationTestData.billingName, anonDonationTestData.country]); - // Now we're redirected to the Donation page + // TODO Log bug for unexpected problem when the language is changed expect.soft(await donationPage.isSuccessfulDonationTitleVisible(LanguagesEnum.EN), "'We thank you for your help and trust!' title is not visible.").toBeTruthy(); expect(await donationPage.isPaymentStepActive(LanguagesEnum.EN), "Payment step is not active.").toBeTruthy(); }); }); + +// test.describe('Anonymous donation - fixed amount', async () => { + +// test('test anonymous donation on staging - fixed amount', async ({ page }) => { +// // Go to https://dev.podkrepi.bg/ +// await page.goto('https://dev.podkrepi.bg/') + +// // Click text=Дарете сега >> nth=0 +// await page.locator('text=Дарете сега').first().click() +// await expect(page).toHaveURL( +// 'https://dev.podkrepi.bg/campaigns/donation/krizisen-centur-za-postradali-ot-nasilie-shans-za-nov-zhivot', +// ) + +// // Click label:has-text("10 лв.") +// await page.locator('label:has-text("10 лв.")').click() + +// // Click text=Искам да покрия таксите за плащане с карта издадена в: +// await page.locator('text=Искам да покрия таксата за карта издадена в:').click() + +// // Click text=10,65 лв. +// await page.locator('text=10,65 лв.').click() + +// // Click text=0,65 лв. >> nth=1 +// await page.locator('text=0,65 лв.').nth(1).click() + +// // Click text=10,00 лв. +// await page.locator('text=10,00 лв.').click() + +// // Click text=Напред +// await page.locator('text=Напред').click() + +// // Click text=Дарете анонимно +// await page.locator('text=Дарете анонимно').click() + +// // Click input[name="personsEmail"] +// await page.locator('input[name="personsEmail"]').click() + +// // Fill input[name="personsEmail"] +// await page.locator('input[name="personsEmail"]').fill('test@example.com') + +// // Click text=Напред +// await page.locator('text=Напред').click() + +// // Click textarea[name="message"] +// await page.locator('textarea[name="message"]').click() + +// // Fill textarea[name="message"] +// await page.locator('textarea[name="message"]').fill('e2e test') + +// // Click text=Премини към плащане +// await page.locator('text=Премини към плащане').click() + +// // await page.waitForURL((url: string) => +// // url.toString().startsWith('https://checkout.stripe.com/pay/cs_test_'), +// // ) + +// await expect(page.url()).toContain('https://checkout.stripe.com/pay/cs_test_') + +// // Click [placeholder="\31 234 1234 1234 1234"] +// await page.locator('[placeholder="\\31 234 1234 1234 1234"]').click() + +// // Fill [placeholder="\31 234 1234 1234 1234"] +// await page.locator('[placeholder="\\31 234 1234 1234 1234"]').fill('4242 4242 4242 4242') + +// // Click [placeholder="MM \/ YY"] +// await page.locator('[placeholder="MM \\/ YY"]').click() + +// // Fill [placeholder="MM \/ YY"] +// await page.locator('[placeholder="MM \\/ YY"]').fill('04 / 242') + +// // Click [placeholder="CVC"] +// await page.locator('[placeholder="CVC"]').click() + +// // Fill [placeholder="CVC"] +// await page.locator('[placeholder="CVC"]').fill('4242') + +// // Click [data-testid="hosted-payment-submit-button"] +// await page.locator('[data-testid="hosted-payment-submit-button"]').click() + +// // Fill input[name="billingName"] +// await page.locator('input[name="billingName"]').fill('e2e tester') + +// // Click [data-testid="hosted-payment-submit-button"] +// await page.locator('[data-testid="hosted-payment-submit-button"]').click() + +// // Go to https://dev.podkrepi.bg/campaigns/donation/krizisen-centur-za-postradali-ot-nasilie-shans-za-nov-zhivot?success=true +// await page.goto( +// 'https://dev.podkrepi.bg/campaigns/donation/krizisen-centur-za-postradali-ot-nasilie-shans-za-nov-zhivot?success=true', +// ) + +// // Click text=Благодарим за доверието и подкрепата! +// await expect(page.locator('text=Благодарим за доверието и подкрепата!')).toBeDefined() +// }) +// }); \ No newline at end of file diff --git a/e2e/tests/regression/donation.spec.ts b/e2e/tests/regression/donation.spec.ts new file mode 100644 index 000000000..0291ad5f6 --- /dev/null +++ b/e2e/tests/regression/donation.spec.ts @@ -0,0 +1,112 @@ +import { test, expect } from '@playwright/test' +import { expectCopied } from '../../utils/helpers' +import { HomePage } from '../../pages/web-pages/home.page'; + + +test.beforeEach(async ({ page }) => { + let homepage: HomePage; + homepage = new HomePage(page) + await homepage.navigateToDevEnvHomepage(); + // await page.goto('http://localhost:3040/', { waitUntil: 'networkidle' }) + await page.locator('button:not([disabled]):has-text("Подкрепете сега")').first().click() + await page.waitForURL((url) => url.pathname.includes('/campaigns/donation')) +}) + +test.describe('donation page init', () => { + test('test rendering and defaults', async ({ page }) => { + await expect( + page.locator('label', { has: page.locator('text=Карта') }).locator('input[type="radio"]'), + ).toBeChecked() + await expect( + page + .locator('label', { has: page.locator('text=Банков превод') }) + .locator('input[type="radio"]'), + ).not.toBeChecked() + }) +}) + +test.describe('anonymous user card donation flow', () => { + test('choosing a predefined value and donating', async ({ page }) => { + // Choose a predefined value from the radio buttons + await page.locator('input[value="card"]').check() + await page.locator('input[value="500"]').check() + + // Click checkbox to cover the tax by stripe + await page.locator('input[name="cardIncludeFees"]').check() + await page.locator('button:has-text("Напред")').click() + + page.locator('text=Дарете анонимно').click() + await page.locator('button:has-text("Напред")').click() + + await page.fill('textarea', 'е2е_tester') + await page.locator('button:has-text("Премини към плащане")').click() + + await expect(page.locator('text=BGN 5.00')).toBeDefined() + await page.locator('input[name="email"]').fill('anon_e2e_tester@podkrepi.bg') + await page.locator('input[name="cardNumber"]').fill('4242424242424242') + await page.locator('input[name="cardExpiry"]').fill('0424') + await page.locator('input[name="cardCvc"]').fill('123') + await page.locator('input[name="billingName"]').fill('John Doe') + await page.locator('select[name="billingCountry"]').selectOption('BG') + + await page.locator('button[data-testid="hosted-payment-submit-button"]').click() + + await page.waitForURL((url) => url.pathname.includes('/campaigns/donation')) + + expect(page.locator('text=Благодарим за доверието и подкрепата!')).toBeDefined() + }) + + test('choosing a custom value and donating', async ({ page }) => { + // Choose a predefined value from the radio buttons + await page.locator('input[value="card"]').check() + await page.locator('input[value="other"]').check() + // Need to take the first here because MUICollapse animations creates a copy + await page.locator('input[name="otherAmount"]').first().type('6') + + // Click checkbox to cover the tax by stripe + await page.locator('input[name="cardIncludeFees"]').check() + await page.locator('button:has-text("Напред")').click() + + page.locator('text=Дарете анонимно').click() + await page.locator('button:has-text("Напред")').click() + + await page.fill('textarea', 'е2е_tester') + await page.locator('button:has-text("Премини към плащане")').click() + + await expect(page.locator('text=BGN 6.58')).toBeDefined() + await page.locator('input[name="email"]').fill('anon_e2e_tester@podkrepi.bg') + await page.locator('input[name="cardNumber"]').fill('4242424242424242') + await page.locator('input[name="cardExpiry"]').fill('0424') + await page.locator('input[name="cardCvc"]').fill('123') + await page.locator('input[name="billingName"]').fill('John Doe') + await page.locator('select[name="billingCountry"]').selectOption('BG') + + await page.locator('button[data-testid="hosted-payment-submit-button"]').click() + + await page.waitForURL((url) => url.pathname.includes('/campaigns/donation')) + expect(page.url().search('success=true')).not.toBe(-1) + + expect(page.locator('text=Благодарим за доверието и подкрепата!')).toBeDefined() + }) +}) + +test.describe('user bank transfer donation flow', () => { + test('check copied values', async ({ page }) => { + // Choose a predefined value from the radio buttons + await page.locator('input[value="bank"]').check() + expect(await page.locator('text="Копирай"').count()).toBe(4) + + if (page.context().browser()?.browserType().name() === 'chromium') { + await page.context().grantPermissions(['clipboard-read', 'clipboard-write']) + await page.locator('text="Копирай"').nth(0).click() + await expectCopied(page, 'Сдружение Подкрепи БГ') + await page.locator('text="Копирай"').nth(1).click() + await expectCopied(page, 'Уникредит Булбанк') + await page.locator('text="Копирай"').nth(2).click() + await expectCopied(page, 'BG66UNCR70001524349032') + await page.locator('text="Копирай"').nth(3).click() + const reference = await page.locator('p[data-testid="payment-reference-field"]').innerText() + await expectCopied(page, reference) + } + }) +}) diff --git a/e2e/tests/regression/support-as-member.spec.ts b/e2e/tests/regression/support-as-member.spec.ts index 645be40d0..be9ceeb33 100644 --- a/e2e/tests/regression/support-as-member.spec.ts +++ b/e2e/tests/regression/support-as-member.spec.ts @@ -33,8 +33,7 @@ test.describe.serial('Support page - Join us as member - BG language version', a homepage = new HomePage(page); headerPage = new HeaderPage(page); supportPage = new SupportPage(page); - // For local executions use method navigateToLocalhostHomepage(); - // await homepage.navigateToLocalhostHomepage(); + // TODO Change here to localhost and leave comment for the devs await homepage.navigateToDevEnvHomepage(); await headerPage.clickJoinUsHeaderNavButton(); }); diff --git a/e2e/tests/smoke/smoke-campaigns.spec.ts b/e2e/tests/smoke/smoke-campaigns.spec.ts index c3de0a383..116f61031 100644 --- a/e2e/tests/smoke/smoke-campaigns.spec.ts +++ b/e2e/tests/smoke/smoke-campaigns.spec.ts @@ -1,3 +1,33 @@ +// import { test, expect } from '@playwright/test' + +// test.beforeEach(async ({ page }) => { +// await page.goto('/') +// await page.locator('button[data-testid="jumbotron-donate-button"]').click() +// await page.waitForURL('/campaigns') +// }) + +// test.describe('campaigns page', () => { +// test('test rendering and defaults', async ({ page }) => { +// expect(page.locator('text=Кампании')).toBeDefined() +// expect(page.locator('text=Подкрепете кауза днес!')).toBeDefined() +// }) +// test('click donate button of active campaign', async ({ page }) => { +// await page.locator('button:has-text("Подкрепете сега"):not([disabled])').first().click() +// await page.waitForURL((url) => url.pathname.includes('/campaigns/donation')) +// expect(page.locator('text=Как желаете да дарите?')).toBeDefined() +// expect(page.locator('text=Карта')).toBeDefined() +// expect(page.locator('text=5 лв.')).toBeDefined() +// }) +// test('successful campaign has a disabled donate button', async ({ page }) => { +// expect(page.locator('button:has-text("Подкрепете сега"):is([disabled])')).toBeDefined() +// }) +// test('click show more button leads to campaign details', async ({ page }) => { +// await page.locator('text="Вижте повече"').first().click() +// await page.waitForURL((url) => url.pathname.includes('/campaigns/')) +// expect(page.locator('text=Сподели')).toBeDefined() +// }) +// }) + import { test, expect, Page } from '@playwright/test' import { CampaignsPage } from '../../pages/web-pages/campaigns/campaigns.page'; import { DonationPage } from '../../pages/web-pages/campaigns/donation.page'; @@ -6,7 +36,7 @@ import { HomePage } from '../../pages/web-pages/home.page'; // This spec contains smoke E2E tests for the Campaigns page // The tests are dependent, the whole describe should be runned -test.describe('Campaigns page smoke tests - BG language version', async () => { +test.describe.only('Campaigns page smoke tests - BG language version', async () => { let page: Page; let homepage: HomePage; @@ -21,8 +51,7 @@ test.describe('Campaigns page smoke tests - BG language version', async () => { headerPage = new HeaderPage(page); campaignsPage = new CampaignsPage(page); donationPage = new DonationPage(page); - // For local executions use method navigateToLocalhostHomepage(); - // await homepage.navigateToLocalhostHomepage(); + // TODO Change here to localhost and leave comment for the devs await homepage.navigateToDevEnvHomepage(); await headerPage.clickCampaignsHeaderNavButton(); }); diff --git a/e2e/tests/smoke/smoke-homepage.spec.ts b/e2e/tests/smoke/smoke-homepage.spec.ts index be6226c98..3da7178dc 100644 --- a/e2e/tests/smoke/smoke-homepage.spec.ts +++ b/e2e/tests/smoke/smoke-homepage.spec.ts @@ -12,9 +12,8 @@ test.describe('Homepage smoke tests - BG language version', async () => { homepage = new HomePage(page); }); + // TODO Change here to localhost and leave comment for the devs test.beforeEach(async () => { - // For local executions use method navigateToLocalhostHomepage(); - // await homepage.navigateToLocalhostHomepage(); await homepage.navigateToDevEnvHomepage(); });