Removes the explicit URL declaration from the page classes. The URL validation and navigation are now handled directly within the tests, providing greater flexibility and control over test execution and removing the need to manage URLs within each page object.
110 lines
No EOL
5.2 KiB
TypeScript
110 lines
No EOL
5.2 KiB
TypeScript
import { expect, type Locator, type Page } from '@playwright/test';
|
|
import { BasePage } from './BasePage';
|
|
import { IAppointmentDetails } from 'safelite-playwright-core';
|
|
import { formatDate, formatTime } from 'safelite-playwright-core';
|
|
import { AppointmentTimeslot } from 'safelite-playwright-core';
|
|
import { ProgressBarPercentages } from 'framework/localTypes/Enums';
|
|
import { time } from 'console';
|
|
import { step } from 'framework/localTypes/Step';
|
|
import { ITestData } from 'framework/TestData';
|
|
|
|
export class SchedulePage extends BasePage {
|
|
readonly page: Page;
|
|
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(testData: Partial<ITestData>) {
|
|
const { appointmentDetails, customerDetails } = testData;
|
|
while (!(await this.firstAvailableDate.isVisible())) {
|
|
|
|
if (appointmentDetails?.appointmentTimeSlot == AppointmentTimeslot.EarlyBird) {
|
|
await this.mockScheduleResponseForEarlyBird(customerDetails!);
|
|
}
|
|
await this.viewMoreDatesLink.click();
|
|
}
|
|
|
|
if (appointmentDetails?.appointmentTimeSlot == AppointmentTimeslot.EarlyBird) {
|
|
await this.page.locator(`.selectable-days, [id='${customerDetails?.apptDate}']`).click();
|
|
const earlyBirdTimeSlot = this.timeSlots.filter({ hasText: "Earlybird" }).first();
|
|
await earlyBirdTimeSlot.click().then(async () => {
|
|
customerDetails!.apptTime = await this.getFormattedTimeSlot(earlyBirdTimeSlot);
|
|
});
|
|
}
|
|
else {
|
|
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 === ServiceLocation.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.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<ITestData>) {
|
|
|
|
await this.validateProgressBar(ProgressBarPercentages.SchedulePage);
|
|
await this.scheduleFirstAppointment(testData);
|
|
}
|
|
}
|