import { expect, type Locator, type Page } from '@playwright/test'; import { BasePage } from './BasePage'; import { IAppointmentDetails, ICustomerDetails } from '@business-logic/types/CustomerDetails'; import { formatDate, formatTime } from '@impl/utils/DateUtils'; import { AppointmentType, ServiceLocation } from '@business-logic/types/Enums'; import { time } from 'console'; import { step } from '@business-logic/types/Step'; import { ITestData } from '@business-logic/types/ITestData'; export class SchedulePage extends BasePage { readonly page: Page; url = process.env['BASE_URL']! + '/fmg/?fmgPage=schedule'; readonly firstAvailableDate: Locator; readonly firstAvailableTime: Locator; readonly modalContinueButton: Locator; readonly dropOffButton: Locator; readonly dateText: Locator; readonly viewMoreDatesLink: Locator; readonly appointmentDuration: Locator; readonly timeSlots: Locator; constructor(page: Page) { super(page); this.page = page; this.firstAvailableDate = this.page.locator('.selectable-day').locator('nth=0'); this.firstAvailableTime = this.page.locator('label').filter({ hasText: /AM|PM/ }).locator('div').locator('nth=0'); this.modalContinueButton = this.page.getByRole('dialog').getByRole('button', { name: 'Continue' }); this.dropOffButton = this.page.getByText('Drop off your vehicle', { exact: true }); this.dateText = this.page.locator('label.modal-title'); this.viewMoreDatesLink = this.page.getByText(/View more dates/).first(); this.appointmentDuration = this.page.locator('.duration-text-block'); this.timeSlots = this.page.locator('fieldset[aria-labelledby=\'chooseTimeSlot\'] label'); } async scheduleAppointment(appointmentDetails: IAppointmentDetails) { const formattedDate = formatDate(appointmentDetails.appointmentDate!); const formattedTime = formatTime(appointmentDetails.appointmentDate!); const dateInput = this.page.locator(`div[id="${formattedDate}"]`); const timeButton = this.page.locator(`div[aria-label="${formattedTime}"]`); if (await dateInput.isVisible()) { await dateInput.click(); } else { await this.viewMoreDatesLink.click(); await dateInput.click(); } await timeButton.click(); await this.modalContinueButton.click(); } async scheduleFirstAppointment(customerDetails: ICustomerDetails) { while (!(await this.firstAvailableDate.isVisible())) { await this.viewMoreDatesLink.click(); } await this.firstAvailableDate.click().then(async () => { customerDetails.apptDate = `${await this.firstAvailableDate.getAttribute("id")}` }); // const timeSlots = this.timeSlots; const timeSlotCount = await this.timeSlots.count(); const randomIndex = Math.floor(Math.random() * timeSlotCount); const timeSlot = this.timeSlots.nth(randomIndex); await timeSlot.click().then(async () => { customerDetails.apptTime = await this.getFormattedTimeSlot(timeSlot); }); // appointmentmentDetails.serviceLocation === AppointmentType.DropOff ? await this.dropOffButton.click() : await this.firstAvailableTime.click(); customerDetails.apptDuration = (await this.appointmentDuration.innerText()).replace("Duration: ", ""); await this.nextPage(); } async getFormattedTimeSlot(timeSlot: Locator) { const selectedTimeSlot = await timeSlot.innerText(); let formattedTimeSlot: string = ""; if (selectedTimeSlot.toLowerCase().includes("drop off")) { formattedTimeSlot = selectedTimeSlot.includes("overnight") ? "drop off by 5:30 pm on the night of your scheduled appointment. Pick-up time dependent on shop schedule" : "drop off before 9:30 AM"; } else if (selectedTimeSlot.includes("-") || selectedTimeSlot.toLowerCase().includes("Earlybird")) { formattedTimeSlot = selectedTimeSlot.includes("Earlybird") ? "arriving between 8:00 AM - 12:00 PM" : `arriving between ${selectedTimeSlot}`; } else { formattedTimeSlot = `at ${selectedTimeSlot}`; } return formattedTimeSlot; } @step("SchedulePage >> Schedule appointment: ") async handleSchedulePage(testData: Partial) { const { customerDetails } = testData; await this.scheduleFirstAppointment(customerDetails!); } }