import { expect, type Locator, type Page } from '@playwright/test'; import { BasePage } from './BasePage'; import { IAppointmentDetails } from '@business-logic/types/CustomerDetails'; import { ServiceLocation } from '@business-logic/types/Enums'; import { AddressForm } from './forms/AddressForm'; import { faker } from '@faker-js/faker'; export class ServiceLocationPage extends BasePage { readonly page: Page; readonly addressForm: AddressForm; // Initial selection readonly inShopButton: Locator; readonly mobileButton: Locator; readonly dropOffButton: Locator; readonly RecalWarningMessage1: Locator; readonly RecalWarningMessage2: Locator; readonly militaryWarningMessage: Locator; // For in-shop and drop off readonly selectAShopOptions: Locator; readonly firstAppointmentButton: Locator; readonly changeZipButton: Locator; readonly updateZipTextBox: Locator; readonly saveZipButton: Locator; // For mobile readonly enterServiceAddressButton: Locator; readonly serviceAddressTextBox: Locator; readonly aptNumberTextBox: Locator; readonly cityTextBox: Locator; readonly stateDropDown: Locator; readonly zipCodeTextBox: Locator; readonly vehicleProtectedYesButton: Locator; readonly vehicleProtectedNoButton: Locator; readonly saveAddressButton: Locator; issPageValue = 'service-location'; constructor(page: Page) { super(page); this.page = page; this.addressForm = new AddressForm(page); // Initial selection this.inShopButton = this.page.locator('[buttonlabel="In-shop"]'); this.mobileButton = this.page.locator('[buttonlabel="Mobile"]') this.dropOffButton = this.page.locator('[buttonlabel="Drop-off"]'); this.RecalWarningMessage1 = this.page.getByText(/We're not able to provide mobile service/); this.RecalWarningMessage2 = this.page.getByText(/advanced safety system recalibration needs to be done in our shop./); this.militaryWarningMessage = this.page.locator('[class*="widget-name-AlertMilitaryBaseZipWidget"]'); // For in-shop and drop off this.selectAShopOptions = this.page.locator('[class="shop-question"]'); // this.firstAppointmentButton = this.page.locator('div').filter({ hasText: /Appts/}).first(); this.firstAppointmentButton = this.page.locator('#availabilityIndicator').first(); this.changeZipButton = this.page.locator('[id="serviceZipLinkPromptId"]'); this.updateZipTextBox = this.page.getByRole('textbox', { name: 'Update your service ZIP code'}); this.saveZipButton = this.page.getByRole('button', { name: 'Save ZIP code' }); // For mobile this.enterServiceAddressButton = this.page.getByRole('link', { name: 'Enter your service address' }); this.serviceAddressTextBox = this.page.getByRole('textbox', { name: 'Street Address' }); this.aptNumberTextBox = this.page.getByRole('textbox', { name: 'Apt. number'}); this.cityTextBox = this.page.getByRole('textbox', { name: 'City' }); this.stateDropDown = this.page.getByRole('combobox', { name: 'State' }); this.zipCodeTextBox = this.page.getByRole('textbox', { name: 'Zip code' }); this.vehicleProtectedYesButton = this.page.locator('label').filter({ hasText: 'Yes' }).locator('div'); this.vehicleProtectedNoButton = this.page.locator('label').filter({ hasText: 'No' }).locator('div'); this.saveAddressButton = this.page.getByRole('button', { name: 'Save Address' }); } async selectLocation(appointmentDetails: IAppointmentDetails){ if (appointmentDetails.alternateServiceZip) { await this.changeZipButton.click(); await this.fillAndValidate(this.updateZipTextBox, appointmentDetails.alternateServiceZip); await this.saveZipButton.click(); } switch(appointmentDetails.serviceLocation) { case ServiceLocation.Mobile: await this.scheduleMobile(appointmentDetails); break; case ServiceLocation.InShop: await this.scheduleInShop(appointmentDetails); break; case ServiceLocation.DropOff: await this.scheduleDropOff(appointmentDetails); break; } } async scheduleInShop(appointmentDetails?: IAppointmentDetails) { await this.inShopButton.click(); if (appointmentDetails && appointmentDetails.shopAddress) { await this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).check(); } else { await this.firstAppointmentButton.click(); } } async scheduleMobile(appointmentDetails: IAppointmentDetails){ if (appointmentDetails.serviceAddress) { await this.mobileButton.click(); await this.enterServiceAddressButton.click(); await this.addressForm.populateAddress({ address: appointmentDetails.serviceAddress! }); if (faker.datatype.boolean()) { await this.vehicleProtectedYesButton.check(); } else { await this.vehicleProtectedNoButton.check(); } await this.saveAddressButton.click(); } else { console.error('ServiceLocationPage >> Please supply an address') } } async scheduleDropOff(appointmentDetails?: IAppointmentDetails){ await this.dropOffButton.click(); if (appointmentDetails && appointmentDetails.shopAddress) { await this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).check(); } else { await this.firstAppointmentButton.click(); } } async validateRecalWarning(){ await expect(this.RecalWarningMessage1).toBeVisible(); await expect(this.RecalWarningMessage2).toBeVisible(); } }