From 74afade26a52e7b017d6deff39dd0ea459789800 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Tue, 7 Apr 2026 09:06:42 -0400 Subject: [PATCH 01/31] Add secret for regression runs --- azure-pipelines-automated-testing.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-pipelines-automated-testing.yml b/azure-pipelines-automated-testing.yml index df7663f6..cf585a17 100644 --- a/azure-pipelines-automated-testing.yml +++ b/azure-pipelines-automated-testing.yml @@ -52,4 +52,5 @@ stages: npmrcPath: 'playwright-tests/.npmrc' secrets: CCIS_API_AUTH: $(CCIS_API_AUTH) - JIRA_API_KEY: $(JIRA_API_KEY) \ No newline at end of file + JIRA_API_KEY: $(JIRA_API_KEY) + IS_REGRESSION: $(IS_REGRESSION) \ No newline at end of file From f6e5805b00e4f29c6496dee58229198d608bf62b Mon Sep 17 00:00:00 2001 From: JennyNou Date: Tue, 7 Apr 2026 10:15:45 -0400 Subject: [PATCH 02/31] Change method to fix flakiness with address selection --- playwright-tests/pages/PolicyHolderDetailsPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/pages/PolicyHolderDetailsPage.ts b/playwright-tests/pages/PolicyHolderDetailsPage.ts index 2cca536a..d7ab5125 100644 --- a/playwright-tests/pages/PolicyHolderDetailsPage.ts +++ b/playwright-tests/pages/PolicyHolderDetailsPage.ts @@ -45,7 +45,7 @@ export class PolicyHolderDetailsPage extends BasePage { // For essential flows, when address fields are not pre-filled if (!addressValue || addressValue.trim() === '') { await this.addressInputBox.click(); - await this.addressInputBox.fill(customerDetails.address.street); + await this.addressInputBox.pressSequentially(customerDetails.address.street); // Wait for suggestions to load (Google Places has a slight delay) await this.page.locator('.pac-item').first().waitFor({ state: 'visible', timeout: 6000 }); From e3f0eb44c88a935dd8f47a946593ae0586954794 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 09:45:18 -0400 Subject: [PATCH 03/31] Update flow for look up vin on alert --- playwright-tests/pages/VinLookupPage.ts | 2 +- playwright-tests/tests/0000__M.test.ts | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/playwright-tests/pages/VinLookupPage.ts b/playwright-tests/pages/VinLookupPage.ts index 825b37bd..39257997 100644 --- a/playwright-tests/pages/VinLookupPage.ts +++ b/playwright-tests/pages/VinLookupPage.ts @@ -35,7 +35,7 @@ export class VinLookupPage extends BasePage { } } - async triggerBailout() { + async returnToVehicleLookupPage() { await this.continueButton.click(); await this.lookupVinForMe.click(); } diff --git a/playwright-tests/tests/0000__M.test.ts b/playwright-tests/tests/0000__M.test.ts index b7c69e7d..c579734f 100644 --- a/playwright-tests/tests/0000__M.test.ts +++ b/playwright-tests/tests/0000__M.test.ts @@ -573,11 +573,7 @@ async function runWorkflow(page: Page, testCase: TestCase) { }); await test.step('Click Invalid vin Link', async () => { - await vinLookupPage.triggerBailout(); - }); - - await test.step('BailoutPage >> Validate Bailout-' + BailoutCode.VehicleNotFound, async () => { - await bailoutPage.validateBailoutDetails(customerDetails!, BailoutCode.VehicleNotFound); + await vinLookupPage.returnToVehicleLookupPage(); }); return; From 6b07ec4c33f63102e572af2f418242167a77594d Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 09:45:43 -0400 Subject: [PATCH 04/31] Fix flaky locators --- playwright-tests/pages/SchedulePage.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/playwright-tests/pages/SchedulePage.ts b/playwright-tests/pages/SchedulePage.ts index 8c8f3f8c..ede5668b 100644 --- a/playwright-tests/pages/SchedulePage.ts +++ b/playwright-tests/pages/SchedulePage.ts @@ -31,8 +31,8 @@ export class SchedulePage extends BasePage { super(page); this.page = page; - this.inShopButton = this.page.locator('[buttonlabel="At a Safelite shop"]'); - this.mobileButton = this.page.locator('[buttonlabel="Have Safelite come to me"]'); + this.inShopButton = this.page.getByText('At a Safelite shop'); + this.mobileButton = this.page.getByText('Have Safelite come to me'); // For in shop this.moreLocationsButton = this.page.getByRole('button', { name: 'More Locations' }); // For mobile @@ -77,6 +77,7 @@ export class SchedulePage extends BasePage { await (await this.getFirstNonDropOffTimeSlot()).click(); } } else { + await this.inShopButton.click(); await (await this.getFirstNonDropOffTimeSlot()).click(); } } else { From b9f6372a68434516448d433aa7a0e9bce7054b28 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 09:46:19 -0400 Subject: [PATCH 05/31] Update locator to fix flakiness when selecting address --- playwright-tests/pages/PolicyHolderDetailsPage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playwright-tests/pages/PolicyHolderDetailsPage.ts b/playwright-tests/pages/PolicyHolderDetailsPage.ts index d7ab5125..dd708f64 100644 --- a/playwright-tests/pages/PolicyHolderDetailsPage.ts +++ b/playwright-tests/pages/PolicyHolderDetailsPage.ts @@ -48,8 +48,8 @@ export class PolicyHolderDetailsPage extends BasePage { await this.addressInputBox.pressSequentially(customerDetails.address.street); // Wait for suggestions to load (Google Places has a slight delay) - await this.page.locator('.pac-item').first().waitFor({ state: 'visible', timeout: 6000 }); - + await this.page.locator('.pac-item').first().waitFor({ state: 'attached', timeout: 6000 }); + await this.page.locator('.pac-item').first().isVisible(); // Click the first result await this.page.locator('.pac-item').first().click(); From 25472fabef4f75c7712bf06afbad1b1793d57c5e Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 09:48:50 -0400 Subject: [PATCH 06/31] Remove jira secret --- azure-pipelines-automated-testing.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/azure-pipelines-automated-testing.yml b/azure-pipelines-automated-testing.yml index cf585a17..df7663f6 100644 --- a/azure-pipelines-automated-testing.yml +++ b/azure-pipelines-automated-testing.yml @@ -52,5 +52,4 @@ stages: npmrcPath: 'playwright-tests/.npmrc' secrets: CCIS_API_AUTH: $(CCIS_API_AUTH) - JIRA_API_KEY: $(JIRA_API_KEY) - IS_REGRESSION: $(IS_REGRESSION) \ No newline at end of file + JIRA_API_KEY: $(JIRA_API_KEY) \ No newline at end of file From 6ca20a80a08029558b53c52b2ea248c571fdb1dc Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 11:22:57 -0400 Subject: [PATCH 07/31] Test change to see if pipeline flakiness improves --- playwright-tests/pages/BasePage.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/playwright-tests/pages/BasePage.ts b/playwright-tests/pages/BasePage.ts index bf950f07..395d5823 100644 --- a/playwright-tests/pages/BasePage.ts +++ b/playwright-tests/pages/BasePage.ts @@ -129,9 +129,6 @@ export class BasePage { } async waitForURLToChange(startingUrl: string) { - await expect(async () => { - const currentUrl = this.page.url(); - expect(currentUrl).not.toEqual(startingUrl); - }).toPass({ timeout: 70_000 }); + await this.page.waitForURL(url => url.href !== startingUrl, { timeout: 70_000 }); } } \ No newline at end of file From e8cfb14a77dee2dc578128d4a557308e7287be3e Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 12:49:45 -0400 Subject: [PATCH 08/31] Update to test timeout increase --- playwright-tests/pages/BasePage.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/playwright-tests/pages/BasePage.ts b/playwright-tests/pages/BasePage.ts index 395d5823..f3746e4c 100644 --- a/playwright-tests/pages/BasePage.ts +++ b/playwright-tests/pages/BasePage.ts @@ -129,6 +129,9 @@ export class BasePage { } async waitForURLToChange(startingUrl: string) { - await this.page.waitForURL(url => url.href !== startingUrl, { timeout: 70_000 }); + await expect(async () => { + const currentUrl = this.page.url(); + expect(currentUrl).not.toEqual(startingUrl); + }).toPass({ timeout: 80_000 }); } } \ No newline at end of file From 45082aa2f2d2da58a0d7490071fa7d9fc9fa20d5 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 19:42:39 -0400 Subject: [PATCH 09/31] Reduce timeout --- playwright-tests/pages/BasePage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/pages/BasePage.ts b/playwright-tests/pages/BasePage.ts index f3746e4c..bf950f07 100644 --- a/playwright-tests/pages/BasePage.ts +++ b/playwright-tests/pages/BasePage.ts @@ -132,6 +132,6 @@ export class BasePage { await expect(async () => { const currentUrl = this.page.url(); expect(currentUrl).not.toEqual(startingUrl); - }).toPass({ timeout: 80_000 }); + }).toPass({ timeout: 70_000 }); } } \ No newline at end of file From 46e27bc106755f18797462ed27ce406431a329ad Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 19:43:48 -0400 Subject: [PATCH 10/31] Rename test file to match scenario --- ...0_EssentialPartQuestionsAndNotShareVin.ts} | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) rename playwright-tests/tests/{0020_EssentialVehicleLookupBailout.ts => 0020_EssentialPartQuestionsAndNotShareVin.ts} (65%) diff --git a/playwright-tests/tests/0020_EssentialVehicleLookupBailout.ts b/playwright-tests/tests/0020_EssentialPartQuestionsAndNotShareVin.ts similarity index 65% rename from playwright-tests/tests/0020_EssentialVehicleLookupBailout.ts rename to playwright-tests/tests/0020_EssentialPartQuestionsAndNotShareVin.ts index a70e8da0..1d97684b 100644 --- a/playwright-tests/tests/0020_EssentialVehicleLookupBailout.ts +++ b/playwright-tests/tests/0020_EssentialPartQuestionsAndNotShareVin.ts @@ -1,23 +1,31 @@ import ClientData from "@business-logic/data/ClientData"; import TestCase from "@business-logic/types/TestCase"; -import { DamageType, ServiceLocation, ServicePackage, VehicleDamage, VehicleLookupType } from "@business-logic/types/Enums"; +import { DamageType, ServiceLocation, ServicePackage, VehicleDamage, VehicleLookupType, PartQuestionType } from "@business-logic/types/Enums"; import { ITestData } from "@business-logic/types/ITestData" import { faker } from "@faker-js/faker"; import { getNextWeekday } from "@impl/utils/DateUtils"; const nextWeekday = getNextWeekday(); -const essentialVehicleLookupBailoutData: Partial = { +const essentialPartQuestionsAndNotShareVinData: Partial = { clientTag: 'ALL_ESSENTIAL', isDuplicateClaim: false, isPolicyFound: false, endorsements: [], isReplace: false, - partQuestions: undefined, + partQuestions: [ + { + partQuestionType: PartQuestionType.GeneralQuestion1, + isOnPage: true, + optionToSelect: 'Yes' + }, + { + partQuestionType: PartQuestionType.GeneralQuestion2, + isOnPage: true, + optionToSelect: 'Yes' + } + ], isSafelite: true, - bailoutFlags: { - isVehicleLookupBailout: true - }, servicePackage: faker.helpers.enumValue(ServicePackage), customerDetails: { firstName: faker.person.firstName(), @@ -43,19 +51,10 @@ const essentialVehicleLookupBailoutData: Partial = { year: '2020', make: 'BMW', model: '740', - style: '4 door sedan' // TODO: Check correctness of vehicle style + style: '4 door sedan', + vehicleLookupType: VehicleLookupType.RatherNotShareVin, }, - vehicleDamage: [ - // VehicleDamage.WindshieldThreeChips, - VehicleDamage.WindshieldCrack, - // VehicleDamage.DriverFrontDoor, - // VehicleDamage.DriverQuarterPanel, - // VehicleDamage.DriverRearDoor, - // VehicleDamage.PassengerFrontDoor, - // VehicleDamage.PassengerQuarterPanel, - // VehicleDamage.PassengerRearDoor, - // VehicleDamage.RearWindow - ], + vehicleDamage: [VehicleDamage.WindshieldCrack], appointmentDetails: { serviceLocation: ServiceLocation.InShop, shopAddress: '6826 Sawmill Rd, Columbus, OH 43235', @@ -65,17 +64,17 @@ const essentialVehicleLookupBailoutData: Partial = { } const essentialClients = ClientData.getEssentialClients(); -const essentialVehicleLookupBailoutTests: TestCase[] = []; +const essentialPartQuestionsAndNotShareVinTests: TestCase[] = []; for (const client of essentialClients) { - const data = {...essentialVehicleLookupBailoutData}; + const data = {...essentialPartQuestionsAndNotShareVinData}; data.clientTag = client.clientTag; data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false const tc = new TestCase({ - name: `0020 Essential Vehicle Lookup Bailout Client: "${client.accountName}"`, - tags: [`@${client.clientTag}`, `@${client.accountName}`, '@Bailout', '@VehicleLookup', '@Essentials'], + name: `0020 Essential Part Questions and Not Share Vin Client: "${client.accountName}"`, + tags: [`@${client.clientTag}`, `@${client.accountName}`, '@VehicleLookup', '@Essentials'], testData: data }, undefined, '0020'); - essentialVehicleLookupBailoutTests.push(tc); + essentialPartQuestionsAndNotShareVinTests.push(tc); } -export default essentialVehicleLookupBailoutTests; \ No newline at end of file +export default essentialPartQuestionsAndNotShareVinTests; \ No newline at end of file From 512df54bad38cf58ac04ed9b01521e57523a1ce1 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 19:44:28 -0400 Subject: [PATCH 11/31] Update test name and flow in master file --- playwright-tests/tests/0000__M.test.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/playwright-tests/tests/0000__M.test.ts b/playwright-tests/tests/0000__M.test.ts index c579734f..8d949baf 100644 --- a/playwright-tests/tests/0000__M.test.ts +++ b/playwright-tests/tests/0000__M.test.ts @@ -24,7 +24,7 @@ import advancedScenario0001TestCases from "./advanced/0001a_ReplaceInShopCredit" import advancedScenario0003TestCases from "./advanced/0003a_MobileAfterpay"; import essentialReplaceDynamicAdasTests from "./0005_EssentialReplaceDynamicAdas"; import essentialReplaceStaticAdasTests from "./0001_EssentialReplaceStatisAdas"; -import essentialVehicleLookupBailoutTests from "./0020_EssentialVehicleLookupBailout"; +import essentialPartQuestionsAndNotShareVinTests from "./0020_EssentialPartQuestionsAndNotShareVin"; import essentialServiceableBigTruckTestCases from "./0022_EssentialServiceableBigTruck"; import essentialNonServiceableBigTruckTestCases from "./0023_EssentialNonServiceableBigTruck"; import essentialNonServiceableBigTruckVinTestCases from "./0024_EssentialNonServiceableBigTruckVin"; @@ -85,7 +85,7 @@ test.describe.parallel('ISS QA Automation Regression', () => { addSmokeTagToRandomTest(essentialTpaNotEnabledReplace_0017); addSmokeTagToRandomTest(essentialTpaEnabledReplace_0018); addSmokeTagToRandomTest(essentialTpaEnabledReplaceRecal_0019); - addSmokeTagToRandomTest(essentialVehicleLookupBailoutTests); + addSmokeTagToRandomTest(essentialPartQuestionsAndNotShareVinTests); addSmokeTagToRandomTest(essentialServiceableBigTruckTestCases); addSmokeTagToRandomTest(essentialNonServiceableBigTruckTestCases); addSmokeTagToRandomTest(essentialNonServiceableBigTruckVinTestCases); @@ -131,7 +131,7 @@ test.describe.parallel('ISS QA Automation Regression', () => { for (const testCase of essentialUniqueGlassTests) { test(...prepareTest(testCase, run, options, ruleEngine)); } - //Scenario 13 //defect# SSR-2009 + //Scenario 13 for (const testCase of essentialReplaceTestCases) { test(...prepareTest(testCase, run, options, ruleEngine)); } @@ -160,8 +160,8 @@ test.describe.parallel('ISS QA Automation Regression', () => { test(...prepareTest(testCase, run, options, ruleEngine)); } //Scenario 20 - for (const testCase of essentialVehicleLookupBailoutTests) { - test(...prepareTest(testCase, run, options, ruleEngine)); //skipping this until SSR-2004 is fixed + for (const testCase of essentialPartQuestionsAndNotShareVinTests) { + test(...prepareTest(testCase, run, options, ruleEngine)); } // Scenario 22 for (const testCase of essentialServiceableBigTruckTestCases) { @@ -191,7 +191,6 @@ test.describe.parallel('ISS QA Automation Regression', () => { } // Scenario 0003a - // Note: payment will fail in dev. Payment (PIA) works fine in SYS for (const testCase of advancedScenario0003TestCases) { test(...prepareTest(testCase, run, options, ruleEngine)); } @@ -256,7 +255,6 @@ test.describe.parallel('ISS QA Automation Regression', () => { } // Scenario 0016a - // FIXME: Defect was created INSR-2138 for (const testCase of advancedScenario0016TestCases) { test(...prepareTest(testCase, run, options, ruleEngine)); } @@ -276,7 +274,7 @@ test.describe.parallel('ISS QA Automation Regression', () => { test(...prepareTest(testCase, run, options, ruleEngine)); } - // Scenario 0020a : There's a defect open INSR-2149 + // Scenario 0020a for (const testCase of advancedScenario0020TestCases) { test(...prepareTest(testCase, run, options, ruleEngine)); } @@ -645,14 +643,12 @@ async function runWorkflow(page: Page, testCase: TestCase) { if (capabilityQuestions && capabilityQuestions.length > 0) { await capabilityQuestionsPage.validateURL(capabilityQuestionsPage.issPageValue); - await capabilityQuestionsPage.validatePartQuestions(capabilityQuestions); await capabilityQuestionsPage.selectPartQuestionResponses(capabilityQuestions); await capabilityQuestionsPage.nextPage(); } if (partQuestions && partQuestions.length > 0) { await partQuestionsPage.validateURL(partQuestionsPage.issPageValue); - await partQuestionsPage.validatePartQuestions(partQuestions); await partQuestionsPage.selectPartQuestionResponses(partQuestions); await partQuestionsPage.nextPage(); } From afe20817df3c7b37f1b71ed88c8eb644d743fcc7 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 19:44:57 -0400 Subject: [PATCH 12/31] Add no vin flow on lookup page --- playwright-tests/business-logic/types/Enums.ts | 3 ++- playwright-tests/pages/VehicleLookupPage.ts | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/playwright-tests/business-logic/types/Enums.ts b/playwright-tests/business-logic/types/Enums.ts index 9280ab00..da4f2f1e 100644 --- a/playwright-tests/business-logic/types/Enums.ts +++ b/playwright-tests/business-logic/types/Enums.ts @@ -68,7 +68,8 @@ export enum VehicleDamage { export enum VehicleLookupType { Vin, Address, - LicensePlateNumber + LicensePlateNumber, + RatherNotShareVin } export enum ServiceLocation { diff --git a/playwright-tests/pages/VehicleLookupPage.ts b/playwright-tests/pages/VehicleLookupPage.ts index 8e8433d3..b847918e 100644 --- a/playwright-tests/pages/VehicleLookupPage.ts +++ b/playwright-tests/pages/VehicleLookupPage.ts @@ -12,6 +12,7 @@ export class VehicleLookupPage extends BasePage { readonly addressLookupButton: Locator; readonly licenseLookupButton: Locator; readonly vinLookupPage: VinLookupPage; + readonly ratherNotShareVinButton: Locator; readonly vehicleLookupAddressPage: VehicleLookupAddressPage; readonly vehicleLookupLicensePage: VehicleLookupLicensePage; issPageValue = 'vehicle-lookup'; @@ -22,6 +23,7 @@ export class VehicleLookupPage extends BasePage { this.vinLookupButton = page.getByLabel('Provide my VIN', { exact: true }); this.addressLookupButton = page.getByLabel('Provide my home address', { exact: true }); this.licenseLookupButton = page.getByLabel('Provide my license plate #', { exact: true }); + this.ratherNotShareVinButton = page.getByText(/rather not share my vin/i); this.vinLookupPage = new VinLookupPage(page); // this.validateURL(this.url); @@ -41,6 +43,10 @@ export class VehicleLookupPage extends BasePage { await this.selectVinLookup(); await this.nextPage(); break; + case VehicleLookupType.RatherNotShareVin: + await this.selectRatherNotShareVin(); + await this.nextPage(); + break; default: console.error('VehicleLookupPage >> DATA ISSUE: VehicleLookupType not provided'); break; @@ -58,4 +64,8 @@ export class VehicleLookupPage extends BasePage { async selectLicenseLookup(){ await this.licenseLookupButton.click(); } + + async selectRatherNotShareVin(){ + await this.ratherNotShareVinButton.click(); + } } From f8b6d7f3726f6eca9674c676143590210659d4f8 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 8 Apr 2026 19:45:38 -0400 Subject: [PATCH 13/31] Update parts page --- playwright-tests/pages/PartQuestionsPage.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/playwright-tests/pages/PartQuestionsPage.ts b/playwright-tests/pages/PartQuestionsPage.ts index 1591b132..ed18eabb 100644 --- a/playwright-tests/pages/PartQuestionsPage.ts +++ b/playwright-tests/pages/PartQuestionsPage.ts @@ -11,17 +11,6 @@ export class PartQuestionsPage extends BasePage { this.page = page; } - async validatePartQuestions(partQuestions: IPartQuestion[]) { - for (const pq of partQuestions) { - const partQuestionOptions = this.page.locator(`fieldset[aria-labelledby="${pq.partQuestionType}"]`); - if (pq.isOnPage) { - await expect(partQuestionOptions).toBeAttached(); - } else { - await expect(partQuestionOptions).not.toBeAttached(); - } - } - } - async selectPartQuestionResponses(partQuestions: IPartQuestion[]) { for (const pq of partQuestions) { const parentobject=this.page.locator(`fieldset[aria-labelledby="${pq.partQuestionType}"]`); From cd17eb0bcd20ac09dfb7f77e0bfee23c48cad660 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Thu, 9 Apr 2026 10:12:01 -0400 Subject: [PATCH 14/31] Add retry to test pipeline flakiness --- playwright-tests/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/playwright.config.ts b/playwright-tests/playwright.config.ts index 94842ffb..0ae2e894 100644 --- a/playwright-tests/playwright.config.ts +++ b/playwright-tests/playwright.config.ts @@ -68,7 +68,7 @@ export default defineConfig({ /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ - retries: process.env.CI ? 1 : 0, + retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 4 : 5, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ From 6181e0d13d49ba69da3f6cb3097b1028c4bdb595 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Thu, 9 Apr 2026 11:18:46 -0400 Subject: [PATCH 15/31] Increase timeout for debugging --- playwright-tests/pages/BasePage.ts | 4 ++-- playwright-tests/playwright.config.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/playwright-tests/pages/BasePage.ts b/playwright-tests/pages/BasePage.ts index bf950f07..6a9d61f0 100644 --- a/playwright-tests/pages/BasePage.ts +++ b/playwright-tests/pages/BasePage.ts @@ -30,7 +30,7 @@ export class BasePage { await expect(async () => { const currentUrl = this.page.url(); if (currentUrl === startingUrl) { - await this.continueButton.click({ timeout: 1000 }); + await this.continueButton.click({ timeout: 5_000 }); } //this causes the schedule page to fail //await expect(this.buttonLoadSpin).toHaveCount(0, {timeout: 180000}); @@ -101,7 +101,7 @@ export class BasePage { let referralSequenceNumber = mainSessionStorage.order.referralSequenceNumber as number; if (referralNumber == null) { for (let i = 1; i <= 20; i++) { - if (!referralNumber == null) break; + if (referralNumber !== null) break; await this.page.waitForTimeout(500); mainSessionStorage = JSON.parse(await this.page.evaluate('localStorage.getItem(\'main\')')); referralNumber = mainSessionStorage.order.referralNumber as number; diff --git a/playwright-tests/playwright.config.ts b/playwright-tests/playwright.config.ts index 0ae2e894..480ca1c7 100644 --- a/playwright-tests/playwright.config.ts +++ b/playwright-tests/playwright.config.ts @@ -91,9 +91,11 @@ export default defineConfig({ baseURL: process.env.BASE_URL || 'https://selfservice.test.glassclaim.com', trace: 'on-first-retry', headless: process.env.CI ? true : false, + video: 'retain-on-failure', + viewport: { width: 1920, height: 1080 }, screenshot: "only-on-failure", - actionTimeout: 60_000, - navigationTimeout: 60_000 + actionTimeout: process.env.CI ? 90_000 : 60_000, + navigationTimeout: process.env.CI ? 90_000 : 60_000 }, /* Configure projects for major browsers */ From 8dfde74672171ce55d0f47aba5e95d733161ecd2 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Thu, 9 Apr 2026 12:22:04 -0400 Subject: [PATCH 16/31] Test flakiness --- playwright-tests/pages/BasePage.ts | 2 +- playwright-tests/playwright.config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/playwright-tests/pages/BasePage.ts b/playwright-tests/pages/BasePage.ts index 6a9d61f0..a1e068af 100644 --- a/playwright-tests/pages/BasePage.ts +++ b/playwright-tests/pages/BasePage.ts @@ -132,6 +132,6 @@ export class BasePage { await expect(async () => { const currentUrl = this.page.url(); expect(currentUrl).not.toEqual(startingUrl); - }).toPass({ timeout: 70_000 }); + }).toPass({ timeout: 90_000 }); } } \ No newline at end of file diff --git a/playwright-tests/playwright.config.ts b/playwright-tests/playwright.config.ts index 480ca1c7..13912c86 100644 --- a/playwright-tests/playwright.config.ts +++ b/playwright-tests/playwright.config.ts @@ -70,7 +70,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 4 : 5, + workers: process.env.CI ? 2 : 5, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI? [ ['junit'], From 9b849aac04c38046ca932ce0b8520a364750a5cd Mon Sep 17 00:00:00 2001 From: JennyNou Date: Thu, 9 Apr 2026 13:05:42 -0400 Subject: [PATCH 17/31] Try 1 worker instead of 2 --- playwright-tests/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/playwright.config.ts b/playwright-tests/playwright.config.ts index 13912c86..5e632267 100644 --- a/playwright-tests/playwright.config.ts +++ b/playwright-tests/playwright.config.ts @@ -70,7 +70,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 2 : 5, + workers: process.env.CI ? 1 : 5, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI? [ ['junit'], From ec3c83adfe681ca2350e923fe5fdee1bc31bac9d Mon Sep 17 00:00:00 2001 From: JennyNou Date: Fri, 10 Apr 2026 12:29:01 -0400 Subject: [PATCH 18/31] Add flag for when Safelite can recalibrate --- .../business-logic/types/ITestData.ts | 1 + playwright-tests/pages/SchedulePage.ts | 17 +++++++++++++++++ playwright-tests/tests/0000__M.test.ts | 16 +++++++++------- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/playwright-tests/business-logic/types/ITestData.ts b/playwright-tests/business-logic/types/ITestData.ts index d3a19d34..79598973 100644 --- a/playwright-tests/business-logic/types/ITestData.ts +++ b/playwright-tests/business-logic/types/ITestData.ts @@ -39,6 +39,7 @@ export interface ITestData { isRecalNotification: boolean, isRecalWarning: boolean, isRecalVehicle: boolean, + isCanSafeliteRecalibrate: boolean, // Can Safelite recalibrate the vehicle? If no, modal displays after clicking time slot and continue isSeparateApptsWarning: boolean, // IF true, check for the separate appts warning on VehicleDamagePage isAuthenticationRequired: boolean, isMoldingQuestion: boolean, diff --git a/playwright-tests/pages/SchedulePage.ts b/playwright-tests/pages/SchedulePage.ts index ede5668b..921cddb9 100644 --- a/playwright-tests/pages/SchedulePage.ts +++ b/playwright-tests/pages/SchedulePage.ts @@ -25,6 +25,11 @@ export class SchedulePage extends BasePage { readonly dateText: Locator; readonly viewMoreDatesLink: Locator; + readonly recalAcknowledgementModal: Locator; + readonly learnMoreLinkRecalAcknowledgementModal: Locator; + readonly recalAcknowledgementCheckBox: Locator; + readonly continueButtonRecalAcknowledgementModal: Locator; + readonly continueButton: Locator; constructor(page: Page) { @@ -50,6 +55,12 @@ export class SchedulePage extends BasePage { this.dateText = this.page.locator('[class="modal-header mb-2 mt-2"]'); this.viewMoreDatesLink = this.page.getByRole('button', { name: 'More Right arrow icon' }); + // Recal acknowledgement modal when Safelite cannot recalibrate the vehicle + this.recalAcknowledgementModal = this.page.getByLabel('ModalComponentLabel'); + this.learnMoreLinkRecalAcknowledgementModal = this.page.getByRole('link', { name: 'Learn more' }); + this.recalAcknowledgementCheckBox = this.page.getByRole('checkbox', { name: /I acknowledge/i }); + this.continueButtonRecalAcknowledgementModal = this.page.locator('#RecalAckModalWidget').getByRole('button', { name: 'Continue' }); + this.continueButton = this.page.locator('#stacked').locator('button:has-text("Continue")'); } @@ -111,4 +122,10 @@ export class SchedulePage extends BasePage { const nonDropOff = timeSlots.filter({ hasNotText: /Drop & Go/i }); return nonDropOff.first(); } + + async validateRecalAcknowledgementModal() { + await this.learnMoreLinkRecalAcknowledgementModal.click(); + await this.recalAcknowledgementCheckBox.click(); + await this.continueButtonRecalAcknowledgementModal.click(); + } } \ No newline at end of file diff --git a/playwright-tests/tests/0000__M.test.ts b/playwright-tests/tests/0000__M.test.ts index 8d949baf..1d3dca5a 100644 --- a/playwright-tests/tests/0000__M.test.ts +++ b/playwright-tests/tests/0000__M.test.ts @@ -379,7 +379,7 @@ async function runWorkflow(page: Page, testCase: TestCase) { isRecalWarning, servicePackage, hasOemEndorsement, hasStateLawPopup, otherVehiclesOnPolicy, isUseVehicleFromAddressLookup, isSeparateApptsWarning, vehiclePartQuestions, editVehicleDetails, isAddressLookupValidations, hasMilitaryWarning, capabilityQuestions, isUseVehicleOnPolicy, - isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin, isRecalVehicle } = testCase.testData; + isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin, isRecalVehicle, isCanSafeliteRecalibrate } = testCase.testData; let { isPolicyFound } = testCase.testData; // Allow isPolicyFound to be re-assigned @@ -732,7 +732,7 @@ async function runWorkflow(page: Page, testCase: TestCase) { await expect(async () => { await providerPreferencePage.stateLawModalOkayButton.waitFor({ state: 'visible' }); await providerPreferencePage.stateLawModalOkayButton.click(); - }).toPass({ timeout: 30000 }); + }).toPass({ timeout: 60_000 }); }); } @@ -829,13 +829,15 @@ async function runWorkflow(page: Page, testCase: TestCase) { await test.step('SchedulePage >> Select day and time', async () => { await schedulePage.validateURL(schedulePage.issPageValue); - if (appointmentDetails?.serviceLocation === ServiceLocation.Mobile) { - await schedulePage.scheduleMobile(appointmentDetails); + if (isCanSafeliteRecalibrate === false) { + await schedulePage.validateRecalAcknowledgementModal(); + await schedulePage.scheduleInShop(appointmentDetails!); + } else if (appointmentDetails?.serviceLocation === ServiceLocation.InShop || appointmentDetails?.serviceLocation === ServiceLocation.DropOff) { + await schedulePage.scheduleInShop(appointmentDetails!); + } else { + await schedulePage.scheduleMobile(appointmentDetails!); } - if (appointmentDetails?.serviceLocation === ServiceLocation.InShop || appointmentDetails?.serviceLocation === ServiceLocation.DropOff) { - await schedulePage.scheduleInShop(appointmentDetails); - } }); From 9b5ff7488aa1455d3d6c58075d7db22b457887d1 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Fri, 10 Apr 2026 12:29:18 -0400 Subject: [PATCH 19/31] Remove extra click --- playwright-tests/pages/ServicePackagesPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/pages/ServicePackagesPage.ts b/playwright-tests/pages/ServicePackagesPage.ts index 83c0b133..98070447 100644 --- a/playwright-tests/pages/ServicePackagesPage.ts +++ b/playwright-tests/pages/ServicePackagesPage.ts @@ -32,7 +32,7 @@ export class ServicePackagesPage extends BasePage { try {await this.wiperModal.waitFor({ state: 'visible', timeout: 5000 }); await this.wiperModalCloseButton.click(); } catch { - await this.continueButton.click(); + console.log('Wiper modal not displayed'); } } else if (servicePackage === ServicePackage.GlassOnly) { await this.glassOnlyPackageButton.check(); From 2e7f660f61f0c6e94c6f45f35cc74bc67d20c41c Mon Sep 17 00:00:00 2001 From: JennyNou Date: Fri, 10 Apr 2026 12:29:38 -0400 Subject: [PATCH 20/31] Increase timeout to fix flaky test --- playwright-tests/pages/VehicleSelectionPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/pages/VehicleSelectionPage.ts b/playwright-tests/pages/VehicleSelectionPage.ts index 9c61f3de..1dc752e2 100644 --- a/playwright-tests/pages/VehicleSelectionPage.ts +++ b/playwright-tests/pages/VehicleSelectionPage.ts @@ -27,7 +27,7 @@ export class VehicleSelectionPage extends BasePage { await this.yearDropdown.selectOption(vehicleDetails.year); await this.yearDropdown.press('Tab'); await this.makeDropdown.selectOption(vehicleDetails.make); - await expect(this.modelDropdown).toBeEditable({ timeout: 5000 }); + await expect(this.modelDropdown).toBeEditable({ timeout: 6000 }); await this.makeDropdown.press('Tab'); await this.modelDropdown.selectOption(vehicleDetails.model); await expect(this.styleDropdown).toBeEditable({ timeout: 2000 }); From f2a3b0910200a0ae658de474ce12b949147d6780 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Fri, 10 Apr 2026 12:31:05 -0400 Subject: [PATCH 21/31] Add can Safelite recalibrate to big truck test scenarios --- playwright-tests/tests/0022_EssentialServiceableBigTruck.ts | 4 +--- .../tests/advanced/0031a_ReplaceServiceableBigTruck.ts | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/playwright-tests/tests/0022_EssentialServiceableBigTruck.ts b/playwright-tests/tests/0022_EssentialServiceableBigTruck.ts index f3014dee..3d4da669 100644 --- a/playwright-tests/tests/0022_EssentialServiceableBigTruck.ts +++ b/playwright-tests/tests/0022_EssentialServiceableBigTruck.ts @@ -13,9 +13,6 @@ const essentialServiceableBigTruckData: Partial = { isPolicyFound: false, endorsements: [], isReplace: true, - bailoutFlags: { - isHeavyTruckVehicleBailout: true, - }, vehiclePartQuestions: [ { partQuestionType: PartQuestionType.WindshieldColor, @@ -24,6 +21,7 @@ const essentialServiceableBigTruckData: Partial = { }, ], isSafelite: true, + isCanSafeliteRecalibrate: false, servicePackage: faker.helpers.enumValue(ServicePackage), customerDetails: { firstName: faker.person.firstName(), diff --git a/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts b/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts index b4fb227e..aa28bae3 100644 --- a/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts +++ b/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts @@ -31,6 +31,7 @@ const advancedScenario0031Data: Partial = { isDuplicateClaim: false, isPolicyFound: true, isNoComp: false, + isCanSafeliteRecalibrate: false, hasStateLawPopup: false, endorsements: undefined, vehiclePartQuestions: [ From 8e419769de9fc11be122b583d8b9d96f5e9d2903 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Tue, 14 Apr 2026 10:09:52 -0400 Subject: [PATCH 22/31] Fix TPA repair flow --- .../business-logic/types/ITestData.ts | 1 + playwright-tests/pages/TpaSubmitPage.ts | 2 ++ playwright-tests/tests/0000__M.test.ts | 9 ++++++++- .../tests/advanced/0008a_RepairTpa.ts | 16 ++-------------- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/playwright-tests/business-logic/types/ITestData.ts b/playwright-tests/business-logic/types/ITestData.ts index 79598973..2214c384 100644 --- a/playwright-tests/business-logic/types/ITestData.ts +++ b/playwright-tests/business-logic/types/ITestData.ts @@ -45,4 +45,5 @@ export interface ITestData { isMoldingQuestion: boolean, isNonServiceable: boolean, // For the flow where a a non-serviceable vehicle is selected on lookup isNonServiceableVin: boolean, // For the flow where a serviceable vehicle is selected on lookup, but then the VIN of a non-serviceable vehicle is entered + isRepairTPA: boolean, } diff --git a/playwright-tests/pages/TpaSubmitPage.ts b/playwright-tests/pages/TpaSubmitPage.ts index 49891145..fe7743f8 100644 --- a/playwright-tests/pages/TpaSubmitPage.ts +++ b/playwright-tests/pages/TpaSubmitPage.ts @@ -24,6 +24,8 @@ export class TpaSubmitPage extends BasePage { async validateDeductible(claimDetails: IClaimDetails, isUnverifiedPolicyAfterVehicleLookup: boolean, isPolicyFound: boolean) { const deductibleTextValue = await this.deductible.textContent(); + await expect(this.deductible).toBeVisible(); + if (claimDetails.policyDeductible !== -1 && !isUnverifiedPolicyAfterVehicleLookup) { expect.soft(deductibleTextValue).toContain(claimDetails.policyDeductible.toLocaleString()); } else diff --git a/playwright-tests/tests/0000__M.test.ts b/playwright-tests/tests/0000__M.test.ts index 1d3dca5a..96bc1a98 100644 --- a/playwright-tests/tests/0000__M.test.ts +++ b/playwright-tests/tests/0000__M.test.ts @@ -379,7 +379,7 @@ async function runWorkflow(page: Page, testCase: TestCase) { isRecalWarning, servicePackage, hasOemEndorsement, hasStateLawPopup, otherVehiclesOnPolicy, isUseVehicleFromAddressLookup, isSeparateApptsWarning, vehiclePartQuestions, editVehicleDetails, isAddressLookupValidations, hasMilitaryWarning, capabilityQuestions, isUseVehicleOnPolicy, - isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin, isRecalVehicle, isCanSafeliteRecalibrate } = testCase.testData; + isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin, isRecalVehicle, isCanSafeliteRecalibrate, isRepairTPA } = testCase.testData; let { isPolicyFound } = testCase.testData; // Allow isPolicyFound to be re-assigned @@ -788,6 +788,13 @@ async function runWorkflow(page: Page, testCase: TestCase) { await providerPreferencePage.scheduleTPAWithoutAdas(); }); } + + if (!isSafelite && isRepairTPA) { + await test.step('ProviderPreferencePage >> Schedule repair with TPA without Adas', async () => { + await providerPreferencePage.validateURL(providerPreferencePage.issPageValue); + await providerPreferencePage.scheduleTPAWithoutAdas(); + }); + } } // TPA Flow if (!isPolicyFound || !(isItac || isNoComp) || isUnverifiedPolicyAfterVehicleLookup) { diff --git a/playwright-tests/tests/advanced/0008a_RepairTpa.ts b/playwright-tests/tests/advanced/0008a_RepairTpa.ts index 85b353be..621ea38d 100644 --- a/playwright-tests/tests/advanced/0008a_RepairTpa.ts +++ b/playwright-tests/tests/advanced/0008a_RepairTpa.ts @@ -33,20 +33,8 @@ const advancedScenario0008Data: Partial = { isDuplicateClaim: false, isPolicyFound: true, isNoComp: false, - hasStateLawPopup: true, - endorsements: undefined, - vehiclePartQuestions: [ - // { - // partQuestionType: PartQuestionType.WindshieldColor, - // isOnPage: true, - // optionToSelect: 'Green Tint' - // }, - // { - // partQuestionType: PartQuestionType.PassengerRearColor, - // isOnPage: true, - // optionToSelect: 'Green Tint' - // }, - ], + hasStateLawPopup: false, + isRepairTPA: true, isSafelite: false, servicePackage: faker.helpers.enumValue(ServicePackage), customerDetails: customerDetails, From 7481abb6202685b1269c926b78b2ca188ccba647 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 15 Apr 2026 08:05:42 -0400 Subject: [PATCH 23/31] Add Adyen experiment to test suite --- .../experiments/api/v1/experiments/run.json | 15 +++++++++++++++ .../experiments/api/v1/experiments/run.json | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/playwright-tests/tests/mockResponses/0002a_Advanced_Replace_Deductible_Client/experiments/api/v1/experiments/run.json b/playwright-tests/tests/mockResponses/0002a_Advanced_Replace_Deductible_Client/experiments/api/v1/experiments/run.json index f3d25831..fffb8f9b 100644 --- a/playwright-tests/tests/mockResponses/0002a_Advanced_Replace_Deductible_Client/experiments/api/v1/experiments/run.json +++ b/playwright-tests/tests/mockResponses/0002a_Advanced_Replace_Deductible_Client/experiments/api/v1/experiments/run.json @@ -14,6 +14,21 @@ "settings": { "DisplayPIAInsurance": "true" } + }, + { + "universeName": "NextGenAdyenPaymentTest", + "universeId": 848, + "testName": "NextGenAdyenPaymentIntegration_V1", + "testId": 727, + "variationName": "YesShowAdyenPaymentIntergration_V1_TEST", + "variationId": 1855, + "isActive": true, + "isExposed": true, + "userPartitionNumber": 26, + "assignmentId": 16698635, + "settings": { + "ISS_Enable_Adyen_V1": "true" + } } ] } \ No newline at end of file diff --git a/playwright-tests/tests/mockResponses/common/experiments/api/v1/experiments/run.json b/playwright-tests/tests/mockResponses/common/experiments/api/v1/experiments/run.json index 38a3b7f8..0472dc19 100644 --- a/playwright-tests/tests/mockResponses/common/experiments/api/v1/experiments/run.json +++ b/playwright-tests/tests/mockResponses/common/experiments/api/v1/experiments/run.json @@ -14,6 +14,21 @@ "settings": { "DisplayPIAInsurance": "true" } + }, + { + "universeName": "NextGenAdyenPaymentTest", + "universeId": 848, + "testName": "NextGenAdyenPaymentIntegration_V1", + "testId": 727, + "variationName": "YesShowAdyenPaymentIntergration_V1_TEST", + "variationId": 1855, + "isActive": true, + "isExposed": true, + "userPartitionNumber": 26, + "assignmentId": 16698635, + "settings": { + "ISS_Enable_Adyen_V1": "true" + } } ] } \ No newline at end of file From 00427136bf514185d451940f8ad0267809105949 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 15 Apr 2026 08:06:54 -0400 Subject: [PATCH 24/31] Update payment details to use Adyen in each test scenario --- playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts | 2 +- .../tests/advanced/0002a_ReplaceOemEndorsement.ts | 2 +- playwright-tests/tests/advanced/0003a_MobileAfterpay.ts | 2 +- playwright-tests/tests/advanced/0010a_RearGlass.ts | 2 +- playwright-tests/tests/advanced/0011a_ItacNoAdas.ts | 2 +- playwright-tests/tests/advanced/0012a_ItacDropOff.ts | 4 ++-- playwright-tests/tests/advanced/0014a_NoCompAdas.ts | 2 +- playwright-tests/tests/advanced/0016a_NoCompAllGlass.ts | 2 +- playwright-tests/tests/advanced/0018a_NoCompGlassOnly.ts | 2 +- playwright-tests/tests/advanced/0019a_NoCompEditVehicle.ts | 2 +- playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts | 2 +- playwright-tests/tests/advanced/0030a_APIErrorBailout.ts | 2 +- .../tests/advanced/0031a_ReplaceServiceableBigTruck.ts | 2 +- .../tests/advanced/0032a_DeclineNonServiceableBigTruck.ts | 2 +- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts b/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts index 0a7c5d4d..1c6d70dd 100644 --- a/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts +++ b/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts @@ -59,7 +59,7 @@ const advancedScenario0001Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultCreditCardDetails() + paymentDetailsAdyen: ClientData.getDefaultCreditCardDetailsAdyen() } // TODO: Add validation for deductible/covered amount diff --git a/playwright-tests/tests/advanced/0002a_ReplaceOemEndorsement.ts b/playwright-tests/tests/advanced/0002a_ReplaceOemEndorsement.ts index 07adbdf3..c124598f 100644 --- a/playwright-tests/tests/advanced/0002a_ReplaceOemEndorsement.ts +++ b/playwright-tests/tests/advanced/0002a_ReplaceOemEndorsement.ts @@ -106,7 +106,7 @@ const advancedScenario0002Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultPaypalDetails() + paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0003a_MobileAfterpay.ts b/playwright-tests/tests/advanced/0003a_MobileAfterpay.ts index 6243fa2e..9ea2e07b 100644 --- a/playwright-tests/tests/advanced/0003a_MobileAfterpay.ts +++ b/playwright-tests/tests/advanced/0003a_MobileAfterpay.ts @@ -74,7 +74,7 @@ const advancedScenario0003Data: Partial = { serviceAddress: customerAddress, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultAfterpayDetails() + paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0010a_RearGlass.ts b/playwright-tests/tests/advanced/0010a_RearGlass.ts index c793e224..bc4e0c8f 100644 --- a/playwright-tests/tests/advanced/0010a_RearGlass.ts +++ b/playwright-tests/tests/advanced/0010a_RearGlass.ts @@ -54,7 +54,7 @@ const advancedScenario0010Data: Partial = { // }, ], isSafelite: true, - servicePackage: faker.helpers.enumValue(ServicePackage), + servicePackage: ServicePackage.Premium, customerDetails: customerDetails, claimDetails: { policyNumber: policyNumber, diff --git a/playwright-tests/tests/advanced/0011a_ItacNoAdas.ts b/playwright-tests/tests/advanced/0011a_ItacNoAdas.ts index 8bffcbf0..7d3a1b04 100644 --- a/playwright-tests/tests/advanced/0011a_ItacNoAdas.ts +++ b/playwright-tests/tests/advanced/0011a_ItacNoAdas.ts @@ -94,7 +94,7 @@ const advancedScenario0011Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultPaypalDetails() + paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0012a_ItacDropOff.ts b/playwright-tests/tests/advanced/0012a_ItacDropOff.ts index 213ec490..9f393b66 100644 --- a/playwright-tests/tests/advanced/0012a_ItacDropOff.ts +++ b/playwright-tests/tests/advanced/0012a_ItacDropOff.ts @@ -44,7 +44,7 @@ const advancedScenario0012Data: Partial = { ], partQuestions: undefined, isSafelite: true, - servicePackage: faker.helpers.enumValue(ServicePackage), + servicePackage: ServicePackage.GlassOnly, customerDetails: customerDetails, claimDetails: { policyNumber: policyNumber, @@ -68,7 +68,7 @@ const advancedScenario0012Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultAfterpayDetails() + paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0014a_NoCompAdas.ts b/playwright-tests/tests/advanced/0014a_NoCompAdas.ts index 919833c0..a88d2ba9 100644 --- a/playwright-tests/tests/advanced/0014a_NoCompAdas.ts +++ b/playwright-tests/tests/advanced/0014a_NoCompAdas.ts @@ -68,7 +68,7 @@ const advancedScenario0014Data: Partial = { alternateServiceZip: '43016', appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultAfterpayDetails() + paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0016a_NoCompAllGlass.ts b/playwright-tests/tests/advanced/0016a_NoCompAllGlass.ts index e336e3ea..23796265 100644 --- a/playwright-tests/tests/advanced/0016a_NoCompAllGlass.ts +++ b/playwright-tests/tests/advanced/0016a_NoCompAllGlass.ts @@ -103,7 +103,7 @@ const advancedScenario0016Data: Partial = { serviceAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultPaypalDetails() + paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0018a_NoCompGlassOnly.ts b/playwright-tests/tests/advanced/0018a_NoCompGlassOnly.ts index 94619a0b..9cb32f2a 100644 --- a/playwright-tests/tests/advanced/0018a_NoCompGlassOnly.ts +++ b/playwright-tests/tests/advanced/0018a_NoCompGlassOnly.ts @@ -71,7 +71,7 @@ const advancedScenario0018Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultAfterpayDetails() + paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0019a_NoCompEditVehicle.ts b/playwright-tests/tests/advanced/0019a_NoCompEditVehicle.ts index d9b4c818..48ce03b8 100644 --- a/playwright-tests/tests/advanced/0019a_NoCompEditVehicle.ts +++ b/playwright-tests/tests/advanced/0019a_NoCompEditVehicle.ts @@ -73,7 +73,7 @@ const advancedScenario0019Data: Partial = { serviceAddress: customerAddress, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultPaypalDetails() + paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts b/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts index 358dfbd5..9e3eb79e 100644 --- a/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts +++ b/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts @@ -72,7 +72,7 @@ const advancedScenario0028aData: Partial = { serviceAddress: customerAddress, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultCreditCardDetails() + paymentDetailsAdyen: ClientData.getDefaultCreditCardDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts b/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts index e392adc2..d7712082 100644 --- a/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts +++ b/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts @@ -67,7 +67,7 @@ const advancedScenario0030aData: Partial = { serviceAddress: customerAddress, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultCreditCardDetails() + paymentDetailsAdyen: ClientData.getDefaultCreditCardDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts b/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts index aa28bae3..bf4218e5 100644 --- a/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts +++ b/playwright-tests/tests/advanced/0031a_ReplaceServiceableBigTruck.ts @@ -66,7 +66,7 @@ const advancedScenario0031Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultPaypalDetails()//ClientData.getDefaultCreditCardDetails() + paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen() } // TODO: Add validation for deductible/covered amount diff --git a/playwright-tests/tests/advanced/0032a_DeclineNonServiceableBigTruck.ts b/playwright-tests/tests/advanced/0032a_DeclineNonServiceableBigTruck.ts index b2433ced..20185f72 100644 --- a/playwright-tests/tests/advanced/0032a_DeclineNonServiceableBigTruck.ts +++ b/playwright-tests/tests/advanced/0032a_DeclineNonServiceableBigTruck.ts @@ -63,7 +63,7 @@ const advancedScenario0032Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetails: ClientData.getDefaultPaypalDetails(),//ClientData.getDefaultCreditCardDetails() + paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen(), isNonServiceable: true, } From 61028aa66249eff871b25a50a2d80da284a1d006 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 15 Apr 2026 08:16:28 -0400 Subject: [PATCH 25/31] Update client data with Adyen payment methods --- .../business-logic/data/ClientData.ts | 39 ++++++++++++++++++- .../advanced/0001a_ReplaceInShopCredit.ts | 2 +- .../tests/advanced/0028a_ItacCancelMyClaim.ts | 2 +- .../tests/advanced/0030a_APIErrorBailout.ts | 2 +- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/playwright-tests/business-logic/data/ClientData.ts b/playwright-tests/business-logic/data/ClientData.ts index 1f1c2da6..a6948d69 100644 --- a/playwright-tests/business-logic/data/ClientData.ts +++ b/playwright-tests/business-logic/data/ClientData.ts @@ -1,5 +1,5 @@ import { IClient } from "@business-logic/types/Client"; -import { IPaymentDetails } from "@business-logic/types/CustomerDetails"; +import { IPaymentDetails, IPaymentDetailsAdyen } from "@business-logic/types/CustomerDetails"; import { PaymentType } from "@business-logic/types/Enums"; const essentialClients: IClient[] = [ @@ -223,6 +223,19 @@ const defaultCreditCardDetails: IPaymentDetails = { } } +const creditCardDetailsAdyen: IPaymentDetailsAdyen = { + paymentType: PaymentType.Credit, + cardNumber: '4151500000000008', + expirationDate: '03/30', + cvv: '737', + billingAddress: { + street: '123 Test Road', + city: 'Columbus', + state: 'Ohio', + postalCode: '43028', + } +} + const defaultAfterpayDetails: IPaymentDetails = { paymentType: PaymentType.AfterPay, username: 'itqatest@safelite.com', @@ -233,12 +246,24 @@ const defaultAfterpayDetails: IPaymentDetails = { cvv: '000' } +const afterpayDetailsAdyen: IPaymentDetailsAdyen = { + paymentType: PaymentType.AfterPay, + username: 'itqatest@safelite.com', + password: 'Safelite1', +} + const defaultPaypalDetails: IPaymentDetails = { paymentType: PaymentType.Paypal, username:'Itqatest@safelite.com', password: 'Safelite1' } +const paypalDetailsAdyen: IPaymentDetailsAdyen = { + paymentType: PaymentType.Paypal, + username: 'Itqatest@safelite.com', + password: 'Safelite1' +} + export default class ClientData { static getEssentialClients() { return essentialClients; @@ -264,10 +289,22 @@ export default class ClientData { return defaultCreditCardDetails; } + static getCreditCardDetailsAdyen() { + return creditCardDetailsAdyen; + } + static getDefaultAfterpayDetails() { return defaultAfterpayDetails; } + static getAfterpayDetailsAdyen() { + return afterpayDetailsAdyen; + } + + static getPaypalDetailsAdyen() { + return paypalDetailsAdyen; + } + static getDefaultPaypalDetails() { return defaultPaypalDetails; } diff --git a/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts b/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts index 1c6d70dd..baa6a433 100644 --- a/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts +++ b/playwright-tests/tests/advanced/0001a_ReplaceInShopCredit.ts @@ -59,7 +59,7 @@ const advancedScenario0001Data: Partial = { shopAddress: undefined, appointmentDate: nextWeekday }, - paymentDetailsAdyen: ClientData.getDefaultCreditCardDetailsAdyen() + paymentDetailsAdyen: ClientData.getCreditCardDetailsAdyen() } // TODO: Add validation for deductible/covered amount diff --git a/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts b/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts index 9e3eb79e..56e5888b 100644 --- a/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts +++ b/playwright-tests/tests/advanced/0028a_ItacCancelMyClaim.ts @@ -72,7 +72,7 @@ const advancedScenario0028aData: Partial = { serviceAddress: customerAddress, appointmentDate: nextWeekday }, - paymentDetailsAdyen: ClientData.getDefaultCreditCardDetailsAdyen() + paymentDetailsAdyen: ClientData.getCreditCardDetailsAdyen() } diff --git a/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts b/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts index d7712082..295c3aed 100644 --- a/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts +++ b/playwright-tests/tests/advanced/0030a_APIErrorBailout.ts @@ -67,7 +67,7 @@ const advancedScenario0030aData: Partial = { serviceAddress: customerAddress, appointmentDate: nextWeekday }, - paymentDetailsAdyen: ClientData.getDefaultCreditCardDetailsAdyen() + paymentDetailsAdyen: ClientData.getCreditCardDetailsAdyen() } From b8f4ac13e584f4e0c3c5034210e296b972894b7f Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 15 Apr 2026 08:18:39 -0400 Subject: [PATCH 26/31] Add assertions to fix flaky tests --- playwright-tests/pages/ProviderPreferencePage.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/playwright-tests/pages/ProviderPreferencePage.ts b/playwright-tests/pages/ProviderPreferencePage.ts index 50b1a617..d35c54ad 100644 --- a/playwright-tests/pages/ProviderPreferencePage.ts +++ b/playwright-tests/pages/ProviderPreferencePage.ts @@ -42,6 +42,8 @@ export class ProviderPreferencePage extends BasePage { async selectProvider(isSafelite: boolean) { if (isSafelite) { + await expect(this.scheduleNowButton).toBeVisible(); + await expect(this.scheduleNowButton).toBeEnabled(); await this.scheduleNowButton.click(); await this.nextPage(); } From 1c178c7761fb8a164601f57099e299d0964a8b96 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 15 Apr 2026 08:19:16 -0400 Subject: [PATCH 27/31] Add payment adyen page --- playwright-tests/pages/PaymentAdyenPage.ts | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 playwright-tests/pages/PaymentAdyenPage.ts diff --git a/playwright-tests/pages/PaymentAdyenPage.ts b/playwright-tests/pages/PaymentAdyenPage.ts new file mode 100644 index 00000000..94c00e6f --- /dev/null +++ b/playwright-tests/pages/PaymentAdyenPage.ts @@ -0,0 +1,46 @@ +import { type Locator, type Page } from '@playwright/test'; +import { BasePage } from './BasePage'; +import { IPaymentDetailsAdyen } from '@business-logic/types/CustomerDetails'; + +export class PaymentAdyenPage extends BasePage { + readonly page: Page; + + readonly cardNumberTextField: Locator; + readonly expiryDateTextField: Locator; + readonly securityCodeTextField: Locator; + readonly billingAddressTextField: Locator; + readonly cityTextField: Locator; + readonly stateDropDown: Locator; + readonly payButton: Locator; + + readonly afterPayButton: Locator; + readonly afterPayLaunchButton: Locator; + readonly applePayButton: Locator; + + issPageValue = 'payment-page-adyen'; + + constructor(page: Page) { + super(page); + this.page = page; + + //Credit Card Fields + this.cardNumberTextField = this.page.locator('iframe[title="Iframe for card number"]').contentFrame().getByRole('textbox', { name: 'Card number' }); + this.expiryDateTextField = this.page.locator('iframe[title="Iframe for expiry date"]').contentFrame().getByRole('textbox', { name: 'Expiry date' }); + this.securityCodeTextField = this.page.locator('iframe[title="Iframe for security code"]').contentFrame().getByRole('textbox', { name: 'CVV/CVC' }); + this.billingAddressTextField = this.page.getByRole('textbox', { name: 'Address' }); + this.cityTextField = this.page.getByRole('textbox', { name: 'City' }); + this.stateDropDown = this.page.getByRole('combobox', { name: 'State' }); + this.payButton = this.page.getByRole('button', { name: 'Pay $' }); + } + + async populateCreditCardDetails(paymentDetailsAdyen: IPaymentDetailsAdyen){ + await this.cardNumberTextField.fill(paymentDetailsAdyen.cardNumber!); + await this.expiryDateTextField.fill(paymentDetailsAdyen.expirationDate!); + await this.securityCodeTextField.fill(paymentDetailsAdyen.cvv!); + await this.billingAddressTextField.fill(paymentDetailsAdyen.billingAddress!.street); + await this.cityTextField.fill(paymentDetailsAdyen.billingAddress!.city); + await this.stateDropDown.fill(paymentDetailsAdyen.billingAddress!.state); + await this.stateDropDown.press('Enter'); + } + +} \ No newline at end of file From 10a761d007235d7fd5617ddc008201b80d88f78e Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 15 Apr 2026 08:20:24 -0400 Subject: [PATCH 28/31] Update payment steps to use Adyen --- playwright-tests/pages/AfterpayPage.ts | 6 +- playwright-tests/pages/PaymentMethodPage.ts | 61 ++++++++++++++++----- playwright-tests/pages/PaymentPage.ts | 1 - playwright-tests/pages/PaypalPage.ts | 10 ++-- 4 files changed, 54 insertions(+), 24 deletions(-) diff --git a/playwright-tests/pages/AfterpayPage.ts b/playwright-tests/pages/AfterpayPage.ts index 2f13ed04..e70ef387 100644 --- a/playwright-tests/pages/AfterpayPage.ts +++ b/playwright-tests/pages/AfterpayPage.ts @@ -1,6 +1,6 @@ import { Locator, Page } from "@playwright/test"; import { BasePage } from "./BasePage"; -import { IClaimDetails, IPaymentDetails } from "@business-logic/types/CustomerDetails"; +import { IClaimDetails, IPaymentDetails, IPaymentDetailsAdyen } from "@business-logic/types/CustomerDetails"; import { ServicePackage } from "@business-logic/types/Enums"; export class AfterpayPage extends BasePage { @@ -33,11 +33,11 @@ export class AfterpayPage extends BasePage { await this.submitButton.click(); } - async executeAfterpayPayment(paymentDetails: IPaymentDetails, claimDetails: IClaimDetails, servicePackage: ServicePackage) { + async executeAfterpayPayment(paymentDetailsAdyen: IPaymentDetailsAdyen, claimDetails: IClaimDetails, servicePackage: ServicePackage) { const confirmButtonOrPaymentOptions = this.confirmButton.or(this.selectAfterpayWithoutInterestButton); - await this.login(paymentDetails.password!); + await this.login(paymentDetailsAdyen.password!); await this.page.locator('div[data-testid=\'loading-icon-svg\']').filter({ visible: true}).first().waitFor({ state: 'hidden' }); await confirmButtonOrPaymentOptions.waitFor({ state: 'visible' }); diff --git a/playwright-tests/pages/PaymentMethodPage.ts b/playwright-tests/pages/PaymentMethodPage.ts index d7c7ef9c..b74dd22c 100644 --- a/playwright-tests/pages/PaymentMethodPage.ts +++ b/playwright-tests/pages/PaymentMethodPage.ts @@ -1,18 +1,24 @@ import { expect, type Locator, type Page } from '@playwright/test'; import { BasePage } from './BasePage'; -import { IClaimDetails, IPaymentDetails } from '@business-logic/types/CustomerDetails'; +import { IClaimDetails, IPaymentDetails, IPaymentDetailsAdyen } from '@business-logic/types/CustomerDetails'; import { PaymentType, ServicePackage } from '@business-logic/types/Enums'; import { PaymentPage } from './PaymentPage'; import { AfterpayPage } from './AfterpayPage'; import { PaypalPage } from './PaypalPage'; +import { PaymentAdyenPage } from './PaymentAdyenPage'; export class PaymentMethodPage extends BasePage { readonly page: Page; readonly paypalPage: PaypalPage; readonly paymentPage: PaymentPage; + readonly paymentAdyenPage: PaymentAdyenPage; readonly payNowButton: Locator; readonly paypalButton: Locator; + readonly payPalAdyenButton: Locator; + readonly payPalLaunchAdyenButton: Locator; + readonly afterpayAdyenButton: Locator; + readonly afterpayLaunchAdyenButton: Locator; readonly payInFourButton: Locator; readonly payAtAppointmentButton: Locator; @@ -28,9 +34,20 @@ export class PaymentMethodPage extends BasePage { this.page = page; this.paypalPage = new PaypalPage(page); this.paymentPage = new PaymentPage(page); + this.paymentAdyenPage = new PaymentAdyenPage(page); this.payNowButton = this.page.locator('[buttonlabel="Pay now"]'); // credit and paypal options behind this button this.paypalButton = this.page.frameLocator('iframe[name="card-frame"]').locator('div[id="paypalParentDiv"]'); + + // Ayden Paypal button + this.payPalAdyenButton = this.page.getByRole('radio', { name: 'PayPal' }); + this.payPalLaunchAdyenButton = this.page.frameLocator('iframe[title="PayPal-paypal"]:first-of-type').locator('div[role="link"][class*="paypal-button"]'); + + // Ayden Afterpay buttons + this.afterpayAdyenButton = this.page.getByRole('radio', { name: 'Afterpay' }); + this.afterpayLaunchAdyenButton = this.page.getByRole('button', { name: 'Continue to Afterpay' }); + + this.payInFourButton = this.page.locator('[buttonlabel="Pay in 4 installments"]'); // Afterpay this.payAtAppointmentButton = this.page.locator('[buttonlabel="Pay at my appointment"]'); @@ -40,22 +57,24 @@ export class PaymentMethodPage extends BasePage { this.submitButton = this.page.getByRole('button', { name: 'Submit' }); } - async executePayment(paymentDetails: IPaymentDetails, claimDetails: IClaimDetails, servicePackage: ServicePackage) { + async executePayment(paymentDetails: IPaymentDetails, paymentDetailsAdyen: IPaymentDetailsAdyen, claimDetails: IClaimDetails, servicePackage: ServicePackage) { const browserContext = this.page.context(); - switch (paymentDetails.paymentType) { - case PaymentType.Credit: + switch (paymentDetailsAdyen?.paymentType ?? paymentDetails?.paymentType) { case PaymentType.Credit: await this.payNowButton.click(); await this.textReminderNoButton.click(); await this.continueToCheckoutButton.click(); - await this.selectCreditCard(paymentDetails); + await this.selectCreditCard(paymentDetailsAdyen); break; case PaymentType.Paypal: await this.payNowButton.click(); await this.textReminderNoButton.click(); await this.continueToCheckoutButton.click(); - await this.selectPaypal(); - await this.paypalPage.completePaypalPurchase(paymentDetails); + + const paypalPopup = await this.selectPaypal(); + const paypalPage = new PaypalPage(paypalPopup); + + await paypalPage.completePaypalPurchase(paymentDetailsAdyen); break; case PaymentType.AfterPay: await this.payInFourButton.click(); @@ -63,11 +82,11 @@ export class PaymentMethodPage extends BasePage { await this.continueToCheckoutButton.click(); // Capture popup - const afterpayPopup = await browserContext.waitForEvent('page'); - const afterpayPage = new AfterpayPage(afterpayPopup); + const afterpayPage = await this.selectAfterpayAdyen(); + const afterpayAdyenPage = new AfterpayPage(afterpayPage); // Execute payment - await afterpayPage.executeAfterpayPayment(paymentDetails, claimDetails, servicePackage); + await afterpayAdyenPage.executeAfterpayPayment(paymentDetailsAdyen, claimDetails, servicePackage); break; case PaymentType.PayAtService: @@ -80,13 +99,25 @@ export class PaymentMethodPage extends BasePage { break; } } - - async selectPaypal() { - await this.paypalButton.click(); + async selectAfterpayAdyen(): Promise { + await this.afterpayAdyenButton.click(); + await this.afterpayLaunchAdyenButton.click(); + //await this.page.waitForLoadState('networkidle'); + return this.page; } - async selectCreditCard(paymentDetails: IPaymentDetails) { - await this.paymentPage.populateCreditCardDetails(paymentDetails); + async selectPaypal(): Promise { + await this.payPalAdyenButton.click(); + const paypalPage = this.page.waitForEvent('popup'); + await this.payPalLaunchAdyenButton.click(); + const paypalPopup = await paypalPage; + await paypalPopup.waitForLoadState(); + return paypalPopup; + } + + async selectCreditCard(paymentDetailsAdyen: IPaymentDetailsAdyen) { + await this.paymentAdyenPage.populateCreditCardDetails(paymentDetailsAdyen); + await this.paymentAdyenPage.payButton.click(); } async selectPayAtAppointment() { diff --git a/playwright-tests/pages/PaymentPage.ts b/playwright-tests/pages/PaymentPage.ts index 4ba47ee6..fff2edd3 100644 --- a/playwright-tests/pages/PaymentPage.ts +++ b/playwright-tests/pages/PaymentPage.ts @@ -1,6 +1,5 @@ import { type Locator, type Page } from '@playwright/test'; import { BasePage } from './BasePage'; -import { AfterpayPage } from './AfterpayPage'; import { IPaymentDetails } from '@business-logic/types/CustomerDetails'; export class PaymentPage extends BasePage { diff --git a/playwright-tests/pages/PaypalPage.ts b/playwright-tests/pages/PaypalPage.ts index 05178dd9..8f97a019 100644 --- a/playwright-tests/pages/PaypalPage.ts +++ b/playwright-tests/pages/PaypalPage.ts @@ -1,6 +1,6 @@ import { expect, type Locator, type Page } from "@playwright/test"; import { BasePage } from "./BasePage"; -import { IPaymentDetails } from "@business-logic/types/CustomerDetails"; +import { IPaymentDetailsAdyen } from "@business-logic/types/CustomerDetails"; export class PaypalPage extends BasePage { readonly page: Page; @@ -13,7 +13,7 @@ export class PaypalPage extends BasePage { constructor(page: Page) { super(page); this.page = page; - this.usernameTextBox = page.locator("#email"); + this.usernameTextBox = page.getByRole("textbox", { name: "Email or mobile number" }); this.nextButton = page.getByRole("button", { name: "Next" }); this.passwordTextBox = page.getByRole("textbox", { name: "Password" }); this.paypalLoginButton = page.getByRole("button", { @@ -23,16 +23,16 @@ export class PaypalPage extends BasePage { this.payButton = page.getByRole("button", { name: "Pay $" }); } - async completePaypalPurchase(paymentDetails: IPaymentDetails) { + async completePaypalPurchase(paymentDetailsAdyen: IPaymentDetailsAdyen) { await expect(async () => { - await this.usernameTextBox.fill(paymentDetails.username!); + await this.usernameTextBox.fill(paymentDetailsAdyen.username!); await this.nextButton.waitFor({ state: 'visible', timeout: 5000 }); await this.nextButton.click(); await expect(this.passwordTextBox).toBeVisible({ timeout: 5000 }); }).toPass({ timeout: 30000 }); - await this.passwordTextBox.fill(paymentDetails.password!); + await this.passwordTextBox.fill(paymentDetailsAdyen.password!); await this.paypalLoginButton.click(); await this.payButton.click(); } From 2ebc4b9c770b18cb82698bb589f34abbc5f73a39 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Wed, 15 Apr 2026 08:23:26 -0400 Subject: [PATCH 29/31] Add Adyen type --- .../business-logic/types/CustomerDetails.ts | 10 ++++++++++ playwright-tests/business-logic/types/ITestData.ts | 5 +++-- playwright-tests/tests/0000__M.test.ts | 4 ++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/playwright-tests/business-logic/types/CustomerDetails.ts b/playwright-tests/business-logic/types/CustomerDetails.ts index 1020694f..f722565a 100644 --- a/playwright-tests/business-logic/types/CustomerDetails.ts +++ b/playwright-tests/business-logic/types/CustomerDetails.ts @@ -72,6 +72,16 @@ export interface IPaymentDetails { billingAddress?: IAddress, } +export interface IPaymentDetailsAdyen { + paymentType: PaymentType, + username?: string, + password?: string, + cardNumber?: string, + expirationDate?: string, + cvv?: string, + billingAddress?: IAddress, +} + // export interface IVehicleDamage { // isRearWindowDamage?: boolean, // windshieldDamage?: WindshieldDamage, diff --git a/playwright-tests/business-logic/types/ITestData.ts b/playwright-tests/business-logic/types/ITestData.ts index 2214c384..a457644c 100644 --- a/playwright-tests/business-logic/types/ITestData.ts +++ b/playwright-tests/business-logic/types/ITestData.ts @@ -1,5 +1,5 @@ import { ServicePackage, VehicleDamage } from "./Enums" -import { IAppointmentDetails, IClaimDetails, ICustomerDetails, IEndorsementDetails, IPartQuestion, IPaymentDetails, IVehicleDetails, IAddressVehicleDetails } from "./CustomerDetails" +import { IAppointmentDetails, IClaimDetails, ICustomerDetails, IEndorsementDetails, IPartQuestion, IPaymentDetails, IPaymentDetailsAdyen, IVehicleDetails, IAddressVehicleDetails } from "./CustomerDetails" import IBailoutFlags from "./IBailoutFlags" export interface ITestData { @@ -35,7 +35,8 @@ export interface ITestData { otherVehiclesOnPolicy: IVehicleDetails[], // IF defined, we validate that the vehicles are present. vehicleDamage: VehicleDamage[], // Array of vehicle damage appointmentDetails: IAppointmentDetails, - paymentDetails: IPaymentDetails // Payment information + paymentDetails: IPaymentDetails, // Payment information + paymentDetailsAdyen: IPaymentDetailsAdyen, // Adyen Payment information isRecalNotification: boolean, isRecalWarning: boolean, isRecalVehicle: boolean, diff --git a/playwright-tests/tests/0000__M.test.ts b/playwright-tests/tests/0000__M.test.ts index 96bc1a98..787b5704 100644 --- a/playwright-tests/tests/0000__M.test.ts +++ b/playwright-tests/tests/0000__M.test.ts @@ -375,7 +375,7 @@ async function runWorkflow(page: Page, testCase: TestCase) { // Destructure data for easy access const { customerDetails, claimDetails, vehicleDetails, addressVehicleDetails, vehicleDamage, appointmentDetails, isSafelite, endorsements, - partQuestions, paymentDetails, isNoComp, isItac, isRecalNotification, isUnverifiedPolicyAfterVehicleLookup, + partQuestions, paymentDetails, paymentDetailsAdyen, isNoComp, isItac, isRecalNotification, isUnverifiedPolicyAfterVehicleLookup, isRecalWarning, servicePackage, hasOemEndorsement, hasStateLawPopup, otherVehiclesOnPolicy, isUseVehicleFromAddressLookup, isSeparateApptsWarning, vehiclePartQuestions, editVehicleDetails, isAddressLookupValidations, hasMilitaryWarning, capabilityQuestions, isUseVehicleOnPolicy, @@ -879,7 +879,7 @@ async function runWorkflow(page: Page, testCase: TestCase) { if (isPolicyFound && (isUseVehicleOnPolicy ?? true) && claimDetails!.policyDeductible > 0) { await test.step('PaymentMethodPage >> Execute Payment', async () => { await paymentMethodPage.validateURL(paymentMethodPage.issPageValue); - await paymentMethodPage.executePayment(paymentDetails!, claimDetails!, servicePackage!); + await paymentMethodPage.executePayment(paymentDetails!, paymentDetailsAdyen!, claimDetails!, servicePackage!); await paymentMethodPage.nextPage(); }); From e26f4edb598bed6419d163f68f26b067dadb2dfa Mon Sep 17 00:00:00 2001 From: JennyNou <167806377+JennyNou@users.noreply.github.com> Date: Wed, 15 Apr 2026 11:41:46 -0400 Subject: [PATCH 30/31] Turn video off for regression run pipeline --- playwright-tests/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-tests/playwright.config.ts b/playwright-tests/playwright.config.ts index 5e632267..682ee0fc 100644 --- a/playwright-tests/playwright.config.ts +++ b/playwright-tests/playwright.config.ts @@ -91,7 +91,7 @@ export default defineConfig({ baseURL: process.env.BASE_URL || 'https://selfservice.test.glassclaim.com', trace: 'on-first-retry', headless: process.env.CI ? true : false, - video: 'retain-on-failure', + video: 'off', viewport: { width: 1920, height: 1080 }, screenshot: "only-on-failure", actionTimeout: process.env.CI ? 90_000 : 60_000, From 22afb1e398b565d12729b847766704a4884257f0 Mon Sep 17 00:00:00 2001 From: JennyNou <167806377+JennyNou@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:04:05 -0400 Subject: [PATCH 31/31] Update logic to use session storage and reduce retries --- playwright-tests/pages/BasePage.ts | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/playwright-tests/pages/BasePage.ts b/playwright-tests/pages/BasePage.ts index a1e068af..d8452aec 100644 --- a/playwright-tests/pages/BasePage.ts +++ b/playwright-tests/pages/BasePage.ts @@ -96,24 +96,23 @@ export class BasePage { } async logReferralNumber() { - let mainSessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'main\')')); - let referralNumber = mainSessionStorage.order.referralNumber as number; - let referralSequenceNumber = mainSessionStorage.order.referralSequenceNumber as number; - if (referralNumber == null) { - for (let i = 1; i <= 20; i++) { - if (referralNumber !== null) break; - await this.page.waitForTimeout(500); - mainSessionStorage = JSON.parse(await this.page.evaluate('localStorage.getItem(\'main\')')); - referralNumber = mainSessionStorage.order.referralNumber as number; - referralSequenceNumber = mainSessionStorage.order.referralSequenceNumber as number; - } + let referralNumber: number | null = null; + let referralSequenceNumber: number | null = null; + for (let i = 0; i < 3; i++) { + const main = JSON.parse(await this.page.evaluate(() => sessionStorage.getItem('main')) ?? 'null'); + referralNumber = main?.order?.referralNumber ?? null; + referralSequenceNumber = main?.order?.referralSequenceNumber ?? null; + if (referralNumber !== null) break; + await this.page.waitForTimeout(500); + } + if (referralNumber === null) { + console.warn('Referral Number could not be retrieved after retries.'); + return; } - await test.step(`Referral Number:${referralNumber} Referral Sequence Number:${referralSequenceNumber}`, async () => { console.log(`Referral Number:${referralNumber}`); console.log(`Referral Sequence Number:${referralSequenceNumber}`); }); - } async validateURL(issPageValue: string) {