diff --git a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts index 3376c2b7c..5844a7dd5 100644 --- a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts @@ -1,6 +1,7 @@ import environments from "@constants/environments"; import { faker } from "@faker-js/faker"; import { extractProposalIdFromUrl } from "@helpers/string"; +import { invalid, valid } from "@mock/index"; import { Page, expect } from "@playwright/test"; import { AdministrationAndAuditingProps, @@ -27,7 +28,9 @@ const formErrors = { motivation: "motivation-helper-error", rationale: "rationale-helper-error", receivingAddress: "receiving-address-0-text-error", - amount: "amount-0-text-error", + adaAmount: "ada-amount-error", + usdToAdaConversionError: "usd-to-ada-converson-error", + preferredCurrencyError: "preferred-currency-error", constitutionalUrl: "prop-constitution-url-text-error", guardrailsScriptUrl: "prop-guardrails-script-url-input-error", link: "link-0-url-input-error", @@ -131,7 +134,7 @@ export default class BudgetDiscussionSubmissionPage { readonly usaToAdaCnversionRateInput = this.page.getByLabel( "USD to ADA Conversion Rate *" ); //BUG missing test Ids - readonly preferredCurrencyAmountInput = this.page.getByLabel( + readonly preferredCurrencyInput = this.page.getByLabel( "Amount in preferred currency *" ); readonly costBreakdownInput = this.page.getByTestId("cost-breakdown-input"); @@ -418,7 +421,7 @@ export default class BudgetDiscussionSubmissionPage { await this.page .getByTestId(`${costing.preferredCurrency.toLowerCase()}-button`) .click(); - await this.preferredCurrencyAmountInput.fill( + await this.preferredCurrencyInput.fill( costing.AmountInPreferredCurrency.toString() ); await this.costBreakdownInput.fill(costing.costBreakdown); @@ -441,6 +444,18 @@ export default class BudgetDiscussionSubmissionPage { await this.continueBtn.click(); } + async fillCostingSectionExceptAmountInputs() { + const costing = this.generateValidCosting(); + await this.preferredCurrencySelect.click(); + await this.page + .getByTestId(`${costing.preferredCurrency.toLowerCase()}-button`) + .click(); + await this.preferredCurrencyInput.fill( + costing.AmountInPreferredCurrency.toString() + ); + await this.costBreakdownInput.fill(costing.costBreakdown.toString()); + } + async fillupForm( budgetProposal: BudgetProposalProps, stage: BudgetProposalStageEnum = BudgetProposalStageEnum.AdministrationAndAuditing @@ -790,4 +805,86 @@ export default class BudgetDiscussionSubmissionPage { : "No" ); } + + async validateCostingSection(isValid: boolean = true) { + const adaAmount = isValid + ? faker.number.int({ min: 100, max: 10000 }) + : faker.lorem.paragraph(2); + const usdToAdaCnversionRate = isValid + ? faker.number.int({ min: 1, max: 100 }) + : faker.lorem.paragraph(2); + const preferredCurrency = isValid + ? faker.number.int({ min: 100, max: 10000 }) + : faker.lorem.paragraph(2); + await this.adaAmountInput.fill(adaAmount.toString()); + await this.usaToAdaCnversionRateInput.fill( + usdToAdaCnversionRate.toString() + ); + await this.preferredCurrencyInput.fill(preferredCurrency.toString()); + const adaErrorElement = this.page.getByTestId(formErrors.adaAmount); + const usdToAdaConversionRateErrorElement = this.page.getByTestId( + formErrors.usdToAdaConversionError + ); + const preferredCurrencyErrorElement = this.page.getByTestId( + formErrors.preferredCurrencyError + ); + const isAdaAmountErrorVisible = await adaErrorElement.isVisible(); + const isUsdToAdaConversionRateErrorVisible = + await usdToAdaConversionRateErrorElement.isVisible(); + const isPreferredCurrencyErrorVisible = + await preferredCurrencyErrorElement.isVisible(); + + if (isValid) { + await expect(adaErrorElement, { + message: isAdaAmountErrorVisible && `${adaAmount} is an invalid amount`, + }).toBeHidden(); + await expect(usdToAdaConversionRateErrorElement, { + message: + isUsdToAdaConversionRateErrorVisible && + `${usdToAdaCnversionRate} is an invalid amount`, + }).toBeHidden(); + await expect(preferredCurrencyErrorElement, { + message: + isPreferredCurrencyErrorVisible && + `${preferredCurrency} is an invalid amount`, + }).toBeHidden(); + } else { + await expect(adaErrorElement, { + message: !isAdaAmountErrorVisible && `${adaAmount} is a valid amount`, + }).toBeVisible(); + await expect(usdToAdaConversionRateErrorElement, { + message: + !isUsdToAdaConversionRateErrorVisible && + `${usdToAdaCnversionRate} is a valid amount`, + }).toBeVisible(); + await expect(preferredCurrencyErrorElement, { + message: + !isPreferredCurrencyErrorVisible && + `${preferredCurrency} is a valid amount`, + }).toBeVisible(); + } + } + + async validateFurtherInformationSection(isValid: boolean = true) { + const url = isValid ? valid.url() : invalid.url(); + const linkText = isValid + ? faker.internet.displayName() + : faker.lorem.paragraph(40); + + await this.linkTextInput.fill(linkText); + await this.linkUrlInput.fill(url); + + const errorElement = this.page.getByTestId(formErrors.link); + const isErrorVisible = await errorElement.isVisible(); + + if (isValid) { + await expect(errorElement, { + message: isErrorVisible && `${url} is an invalid URL`, + }).toBeHidden(); + } else { + await expect(errorElement, { + message: !isErrorVisible && `${url} is a valid URL`, + }).toBeVisible(); + } + } } diff --git a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts index 698106567..a7366cbc6 100644 --- a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts +++ b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.spec.ts @@ -84,6 +84,8 @@ test.describe("Budget proposal 01 wallet", () => { await expect( budgetProposalSubmissionPage.keyInformationOfGroupInput ).toBeVisible(); + + await expect(budgetProposalSubmissionPage.continueBtn).toBeDisabled(); }); test("12D_2. Should verify all field of “problem statements and proposal benefits” section", async () => { @@ -111,6 +113,7 @@ test.describe("Budget proposal 01 wallet", () => { await expect( budgetProposalSubmissionPage.suplimentaryEndorsementInput ).toBeVisible(); + await expect(budgetProposalSubmissionPage.continueBtn).toBeDisabled(); }); test("12D_3. Should verify all field of “proposal details” section", async () => { @@ -142,6 +145,7 @@ test.describe("Budget proposal 01 wallet", () => { await expect( budgetProposalSubmissionPage.contractingTypeSelect ).toBeVisible(); + await expect(budgetProposalSubmissionPage.continueBtn).toBeDisabled(); }); test("12D_4. Should verify all field of “costing” section", async () => { @@ -160,11 +164,12 @@ test.describe("Budget proposal 01 wallet", () => { budgetProposalSubmissionPage.preferredCurrencySelect ).toBeVisible(); await expect( - budgetProposalSubmissionPage.preferredCurrencyAmountInput + budgetProposalSubmissionPage.preferredCurrencyInput ).toBeVisible(); await expect( budgetProposalSubmissionPage.costBreakdownInput ).toBeVisible(); + await expect(budgetProposalSubmissionPage.continueBtn).toBeDisabled(); }); test("12D_5. Should verify all field of “further information” section", async () => { @@ -191,6 +196,7 @@ test.describe("Budget proposal 01 wallet", () => { await expect( budgetProposalSubmissionPage.intersectNamedAdministratorSelect ).toBeVisible(); + await expect(budgetProposalSubmissionPage.continueBtn).toBeDisabled(); }); }); @@ -203,29 +209,80 @@ test.describe("Budget proposal 01 wallet", () => { proposalInformations ); }); - }); -}); + test.describe("Budget proposal field validation", () => { + test("12E_1. Should accept valid data in “Costing” section", async () => { + test.slow(); // Brute-force testing with 50 random data + const proposalInformation = + budgetProposalSubmissionPage.generateValidBudgetProposalInformation(); + await budgetProposalSubmissionPage.fillupForm( + proposalInformation, + BudgetProposalStageEnum.ProposalDetails + ); -test.describe("Budget proposal field validation", () => { - test.beforeEach(async () => { - await allure.description( - "Field validation tests are pending implementation." - ); - test.skip(); + for (let i = 0; i < 50; i++) { + await budgetProposalSubmissionPage.validateCostingSection(); + } + + await budgetProposalSubmissionPage.fillCostingSectionExceptAmountInputs(); + await expect(budgetProposalSubmissionPage.continueBtn).toBeEnabled(); + }); + + test("12E_2. Should accept valid data in “further information” section", async () => { + test.slow(); // Brute-force testing with 50 random data + const proposalInformation = + budgetProposalSubmissionPage.generateValidBudgetProposalInformation(); + await budgetProposalSubmissionPage.fillupForm( + proposalInformation, + BudgetProposalStageEnum.Costing + ); + + for (let i = 0; i < 50; i++) { + await budgetProposalSubmissionPage.validateFurtherInformationSection(); + } + + for (let i = 0; i < 18; i++) { + await expect(budgetProposalSubmissionPage.addLinkBtn).toBeVisible(); + await budgetProposalSubmissionPage.addLinkBtn.click(); + } + await expect(budgetProposalSubmissionPage.addLinkBtn).toBeHidden(); + await expect(budgetProposalSubmissionPage.continueBtn).toBeEnabled(); + }); + + test("12F_1. Should reject valid data in “Costing” section", async () => { + test.slow(); // Brute-force testing with 50 random data + const proposalInformation = + budgetProposalSubmissionPage.generateValidBudgetProposalInformation(); + await budgetProposalSubmissionPage.fillupForm( + proposalInformation, + BudgetProposalStageEnum.ProposalDetails + ); + + for (let i = 0; i < 50; i++) { + await budgetProposalSubmissionPage.validateCostingSection(false); + } + + await budgetProposalSubmissionPage.fillCostingSectionExceptAmountInputs(); + await expect(budgetProposalSubmissionPage.continueBtn).toBeDisabled(); + }); + + test("12F_2. Should reject invalid data in “further information” section", async () => { + test.slow(); // Brute-force testing with 50 random data + const proposalInformation = + budgetProposalSubmissionPage.generateValidBudgetProposalInformation(); + await budgetProposalSubmissionPage.fillupForm( + proposalInformation, + BudgetProposalStageEnum.Costing + ); + + for (let i = 0; i < 50; i++) { + await budgetProposalSubmissionPage.validateFurtherInformationSection( + false + ); + } + await expect(budgetProposalSubmissionPage.continueBtn).toBeDisabled(); + }); + }); }); - test("12E_1. Should accept valid data in “contact information” section", async ({}) => {}); - test("12E_2. Should accept valid data in “proposal ownership” section", async ({}) => {}); - test("12E_3. Should accept valid data in “problem statements and proposal benefits” section", async ({}) => {}); - test("12E_4. Should accept valid data in “proposal details” section", async ({}) => {}); - test("12E_5. Should accept valid data in “costing” section", async ({}) => {}); - test("12E_6. Should accept valid data in “further information” section", async ({}) => {}); - - test("12F_1. Should reject invalid data in “contact information” section", async ({}) => {}); - test("12F_2. Should reject invalid data in “proposal ownership” section", async ({}) => {}); - test("12F_3. Should reject invalid data in “problem statements and proposal benefits” section", async ({}) => {}); - test("12E_4. Should accept invalid data in “proposal details” section", async ({}) => {}); - test("12F_5. Should reject invalid data in “costing” section", async ({}) => {}); - test("12F_6. Should reject invalid data in “further information” section", async ({}) => {}); }); test("12C. Should save and view draft proposal", async ({ browser }) => {