qe-fe-automation
Version:
FE test automation framework using cypress
431 lines (388 loc) • 16.2 kB
text/typescript
import { Logs, Timeouts, utilitySelector, Utility, DaysToMove } from '@utility-lib/index';
import { FlightBookingParams } from '@flight-modal/index';
import {
HotelSearchResults,
hotelSearchResultSelector,
HotelCheckout
} from '@hotel-lib/index';
import { ChatBox, chatBookingSelectors } from './chat';
import { FlightCheckout } from '@flight-lib/index';
const chatbotBookingSelectors = {
locationInput: 'input[data-testid="Form__groupItem"]',
getText: '[data-testid="DynamicList__AirportItem"]',
wrapperButton: '[class*="messageAnim-enter-done"] button'
};
export enum Directions {
TO = 'To',
FROM = 'From',
HOTEL_LOCATION = 'Hotel location',
DEPARTING_FROM = 'Departing from',
ARRIVING_AT = 'Arriving at',
PICKUP = 'Pick-up',
DROPOFF = 'Drop-off'
}
const options: Intl.DateTimeFormatOptions = {
weekday: 'short',
month: 'short',
day: 'numeric',
year: 'numeric'
};
export type FlightBookingData = {
flightBookingParams: FlightBookingParams;
departingFrom: Directions;
arrivingAt: Directions;
isChangeFlight?: boolean;
};
export class ChatBooking {
static bookTripFlight(
flightBookingData: FlightBookingData,
daysToMove: DaysToMove,
numberOfFlights = 2
) {
const {
flightBookingParams,
departingFrom,
arrivingAt,
isChangeFlight = false
} = flightBookingData;
switch (numberOfFlights) {
case 1:
ChatBox.replyToAva('One-way');
break;
case 2:
ChatBox.replyToAva('Roundtrip');
break;
}
cy.allure().logStep('Book round trip flight');
ChatBooking.selectAirport(departingFrom, flightBookingParams.locations[0]);
ChatBooking.selectAirport(arrivingAt, flightBookingParams.locations[1]);
if (!isChangeFlight) {
this.selectDates(daysToMove);
}
this.clickLetsGoButton(false);
cy.wait(['@waitForGetFlightResults', '@waitForSentMessage']);
cy.wait(Timeouts.MAX_TIMEOUT_120_SEC.timeout);
ChatBox.waitUntilAvaStopTyping();
this.clickLetsGoButton(true);
ChatBooking.selectTripFlight(numberOfFlights);
this.clickLetsGoButton(true);
cy.get(chatBookingSelectors.getChatMsgBody).then(($element) => {
if (
$element.text().includes(`I couldn't find any results that match your search.`)
) {
cy.allure().logStep(`I couldn't find any results that match your search.`);
cy.wait(Timeouts.MEDIUM_TIMEOUT_30_SEC.timeout);
cy.get(chatBookingSelectors.letsGoButton).as('letsGoButton');
cy.get('@letsGoButton').should('be.enabled');
cy.get('@letsGoButton').scrollIntoView();
cy.get('@letsGoButton').click({ force: true });
ChatBooking.selectTripFlight(numberOfFlights);
}
});
this.flightCheckout(flightBookingParams);
}
static continueBookTripFlight(
flightBookingData: FlightBookingData,
numberOfFlights = 2
) {
this.clickLetsGoButton(false);
cy.wait(Timeouts.MAX_TIMEOUT_120_SEC.timeout);
ChatBox.waitUntilAvaStopTyping();
this.clickLetsGoButton(true);
ChatBooking.selectTripFlight(numberOfFlights);
cy.get(chatBookingSelectors.getChatMsgBody).then(($element) => {
if (
$element.text().includes(`I couldn't find any results that match your search.`)
) {
cy.allure().logStep(`I couldn't find any results that match your search.`);
cy.wait(Timeouts.MEDIUM_TIMEOUT_30_SEC.timeout);
cy.get(chatBookingSelectors.letsGoButton).as('letsGoButton');
cy.get('@letsGoButton').should('be.enabled');
cy.get('@letsGoButton').scrollIntoView();
cy.get('@letsGoButton').click({ force: true });
ChatBooking.selectTripFlight(numberOfFlights);
}
});
this.flightCheckout(flightBookingData.flightBookingParams);
}
static changeFlight(flightBookingParams: FlightBookingParams) {
const selectAirport = (index: number, location: string) => {
cy.get(chatbotBookingSelectors.locationInput)
.eq(index)
.then((element) => {
cy.wrap(element).click({ force: true });
cy.wait(Timeouts.SHORT_TIMEOUT_2_SEC.timeout);
cy.wrap(element).clear();
cy.wait(Timeouts.SHORT_TIMEOUT_2_SEC.timeout);
cy.wrap(element).type(location);
cy.wrap(element)
.invoke('val')
.then((text) => {
const selectLocationFromDropDown = text as string;
const replacedText = selectLocationFromDropDown.replace(' - ', ' ');
cy.log('Typed Text: ' + replacedText);
cy.get(chatbotBookingSelectors.getText).contains(replacedText).click();
});
});
};
cy.get(chatbotBookingSelectors.wrapperButton)
.contains('Edit details & search')
.click();
cy.wait(Timeouts.SHORT_TIMEOUT_2_SEC.timeout);
selectAirport(0, flightBookingParams.locations[0]);
selectAirport(1, flightBookingParams.locations[1]);
}
static changeFlightOptions(buttonName: string) {
cy.get(chatbotBookingSelectors.wrapperButton).contains(buttonName).click();
ChatBooking.selectFlight(chatBookingSelectors.flightChangeCards);
cy.wait(['@amplitudeBrowserSDK']);
cy.get(chatBookingSelectors.chatButton).contains('Book it').click();
cy.wait('@waitForSentMessage');
}
static selectAirport(direction: Directions, airport: string) {
cy.allure().logStep(`Select ${direction} airport: ${airport}`);
ChatBooking.clickAddFiledButton(direction);
cy.get(chatBookingSelectors.airportInput(direction)).type(airport);
cy.wait('@waitForLocation');
cy.get(chatBookingSelectors.airportsFromAutocomplete(airport)).click();
}
static clickAddFiledButton(fieldName: string, buttonName = 'Add') {
cy.allure().logStep(`Click ${buttonName} button for ${fieldName} field`);
cy.get(chatBookingSelectors.formFields).contains(fieldName).click();
}
static selectDates(inputDaysToMove: DaysToMove) {
cy.allure().logStep('Select dates for next month');
const shiftedDates = Utility.shiftingDates(inputDaysToMove);
ChatBooking.clickAddFiledButton('Date');
cy.get(chatBookingSelectors.calendar).should('be.visible');
if (shiftedDates.monthsToShift > 0) {
Cypress._.times(shiftedDates.monthsToShift, () => {
cy.get(chatBookingSelectors.calendarNextMonthButton).click();
});
}
ChatBooking.selectDayInCalendar(shiftedDates.chosenCheckinDay);
if (shiftedDates.chosenCheckinDay != shiftedDates.chosenCheckoutDay) {
if (shiftedDates.monthsToShiftToCheckoutDay > 0) {
Cypress._.times(shiftedDates.monthsToShiftToCheckoutDay, () => {
cy.get(chatBookingSelectors.calendarNextMonthButton).click();
});
}
ChatBooking.selectDayInCalendar(shiftedDates.chosenCheckoutDay);
}
}
static enterShiftedDates(inputDaysToMove: DaysToMove) {
Utility.shiftingDates(inputDaysToMove);
cy.task('getDataFromCache', 'selectedCheckInDate').then(
(selectedCheckInDate: any) => {
cy.task('getDataFromCache', 'selectedCheckoutDate').then(
(selectedCheckoutDate: any) => {
const checkInDate = new Date(selectedCheckInDate);
const checkoutDate = new Date(selectedCheckoutDate);
const checkoutYear = checkInDate.getFullYear();
const formatter = new Intl.DateTimeFormat('en-US', options);
const checkInFormatted = formatter.format(checkInDate);
const checkoutFormatted = formatter.format(checkoutDate);
const checkInFormattedWithoutYear = checkInFormatted.replace(/,\s\d{4}$/, '');
const checkoutFormattedWithoutYear = checkoutFormatted.replace(
/,\s\d{4}$/,
''
);
const formattedActual = `${checkInFormattedWithoutYear} - ${checkoutFormattedWithoutYear}, ${checkoutYear}`;
ChatBox.typeMsgToAva(formattedActual);
}
);
}
);
}
static selectDayInCalendar(day: number) {
cy.allure().logStep(`Select ${day} day in calendar`);
cy.get(chatBookingSelectors.calendarDayButtons)
.children(chatBookingSelectors.disabledCalendarDayButton)
.contains(day)
.click();
}
static selectTripFlight(numberOfFlights = 2) {
cy.allure().logStep('Select round trip flight');
Cypress._.times(numberOfFlights, () => {
ChatBooking.selectFlight(chatBookingSelectors.flightCards);
});
cy.wait(['@waitForSentMessage', '@amplitudeBrowserSDK']);
}
static selectFlight(selector: string, index = 0, retry = 0) {
cy.allure().logStep('Select flight');
cy.wait(Timeouts.MEDIUM_TIMEOUT_30_SEC.timeout);
cy.get(chatBookingSelectors.flightCardsList).then((element) => {
if (!element.text().includes('Select')) {
cy.wait(Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout);
}
});
cy.get(selector).should('be.visible').eq(index).as('flightCard');
cy.get('@flightCard').contains('Select').click();
cy.wait('@waitForFlightStatus').then((interception) => {
if (interception.response?.statusCode !== 200) {
if (retry > 5) {
throw new Error(`Failed to select flight. Tried ${retry} times.`);
}
retry++;
Logs.logToCypressAndAllure('Retry to select another flight. Attempt: ' + retry);
cy.get(chatBookingSelectors.paginatorNextButton).click();
ChatBooking.selectFlight(selector, ++index, retry);
}
});
}
static checkIsChatMinimized() {
cy.allure().logStep('Check if chat is minimized');
cy.get(chatBookingSelectors.chatView).should((chat) => {
expect(chat, 'Chat should be minimized').not.exist;
});
}
static bookHotel(location: string, daysToMove: DaysToMove) {
cy.allure().logStep('Book hotel');
this.selectAirport(Directions.HOTEL_LOCATION, location);
this.selectDates(daysToMove);
ChatBox.getHotelLocationText();
this.hotelCheckout();
}
static hotelCheckout() {
cy.get(chatBookingSelectors.letsGoButton).click();
cy.wait('@waitForHotelSearch');
this.expectHotelDatesAreCorrect();
HotelSearchResults.selectHotel(0);
HotelSearchResults.selectRoomOption();
HotelCheckout.waitToBeLoaded();
HotelCheckout.checkoutFLow('Business');
HotelCheckout.expectHotelBookedSuccessfully('Hotel confirmed!');
}
static bookCar(
pickupLocation: string,
dropoffLocation: string,
daysToMove: DaysToMove
) {
ChatBooking.selectDates(daysToMove);
ChatBooking.selectAirport(Directions.PICKUP, pickupLocation);
ChatBooking.selectAirport(Directions.DROPOFF, dropoffLocation);
ChatBooking.clickLetsGoButton(false);
}
static clickLetsGoButton(withWaiting = true) {
cy.allure().logStep('Click lets go button');
if (withWaiting) {
cy.get(chatBookingSelectors.getChatMsgBody).then(($element) => {
if (
$element.text().includes(`I couldn't find any results that match your search.`)
) {
cy.allure().logStep(`I couldn't find any results that match your search.`);
cy.wait(Timeouts.MEDIUM_TIMEOUT_30_SEC.timeout);
cy.get(chatBookingSelectors.letsGoButton).as('letsGoButton');
cy.get('@letsGoButton').should('be.enabled');
cy.get('@letsGoButton').scrollIntoView();
cy.get('@letsGoButton').click({ force: true });
}
});
} else {
cy.get(chatBookingSelectors.letsGoButton)
.should('be.enabled')
.click({ force: true });
}
}
static flightCheckout(flightBookingParams: FlightBookingParams) {
FlightCheckout.waitToPageBeLoaded();
FlightCheckout.expectNumberOfTravelers(1);
ChatBooking.expectFlightSummaryIsCorrect(flightBookingParams.flightTripType);
FlightCheckout.verifyFlightLocation(flightBookingParams);
FlightCheckout.saveTripInformation();
FlightCheckout.checkCancellationPolicy();
FlightCheckout.acceptOutOfPolicyFlight();
FlightCheckout.updateContactDetails();
FlightCheckout.validateIfPassportAndVisaInfoRequired();
FlightCheckout.checkIn(flightBookingParams.checkInType);
FlightCheckout.bookAndPay(flightBookingParams);
FlightCheckout.expectFlightSuccessfullyConfirmed(
flightBookingParams.flightConfirmText
);
}
static expectHotelLocationIsCorrect() {
cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
cy.get(hotelSearchResultSelector.selectHotel).should('be.visible');
cy.task('getDataFromCache', 'locationText').then((chatLocationInput: any) => {
cy.log('chat Location Input ' + chatLocationInput);
HotelSearchResults.getHotelLocationInput();
cy.task('getDataFromCache', 'getHotelLocationInput').then(
(getHotelLocationInputText: any) => {
cy.log('Hotel location from search result' + getHotelLocationInputText);
expect(getHotelLocationInputText).to.equal(chatLocationInput);
}
);
});
}
static expectHotelDatesAreCorrect() {
cy.get(hotelSearchResultSelector.selectHotel).should('be.visible');
cy.task('getDataFromCache', 'selectedCheckInDate').then(
(selectedCheckInDate: any) => {
cy.task('getDataFromCache', 'selectedCheckoutDate').then(
(selectedCheckoutDate: any) => {
const checkInDate = new Date(selectedCheckInDate);
const checkoutDate = new Date(selectedCheckoutDate);
const checkoutYear = checkInDate.getFullYear();
const formatter = new Intl.DateTimeFormat('en-US', options);
const checkInFormatted = formatter.format(checkInDate);
const checkoutFormatted = formatter.format(checkoutDate);
const checkInFormattedWithoutYear = checkInFormatted.replace(/,\s\d{4}$/, '');
const checkoutFormattedWithoutYear = checkoutFormatted.replace(
/,\s\d{4}$/,
''
);
const formattedActual = `${checkInFormattedWithoutYear} - ${checkoutFormattedWithoutYear}, ${checkoutYear}`;
HotelSearchResults.getDatesFromCalendar();
cy.task('getDataFromCache', 'getDatesFromCalendar').then((dates: any) => {
cy.log('chat box date:' + formattedActual);
cy.log('hotel search results dates:' + dates);
expect(dates).to.equal(formattedActual);
});
}
);
}
);
}
static expectFlightSummaryIsCorrect(flightType: string) {
switch (flightType) {
case 'ONEWAY':
flightType = 'One-way';
break;
case 'ROUNDTRIP':
flightType = 'Roundtrip';
break;
}
cy.get(utilitySelector.checkoutSummary).should('contain.text', flightType);
cy.task('getDataFromCache', 'selectedCheckInDate').then(
(selectedCheckInDate: any) => {
cy.task('getDataFromCache', 'selectedCheckoutDate').then(
(selectedCheckoutDate: any) => {
const checkInDate = new Date(selectedCheckInDate);
const checkoutDate = new Date(selectedCheckoutDate);
const formatter = new Intl.DateTimeFormat('en-US', options);
const checkInFormatted = formatter.format(checkInDate);
const checkoutFormatted = formatter.format(checkoutDate);
const checkInFormattedWithoutYear = checkInFormatted.replace(/,\s\d{4}$/, '');
const checkoutFormattedWithoutYear = checkoutFormatted.replace(
/,\s\d{4}$/,
''
);
cy.get(utilitySelector.checkoutSummary).then((checkoutSummary) => {
const summaryText = checkoutSummary.text();
expect(summaryText).to.contain(checkInFormattedWithoutYear);
expect(summaryText).to.contain(checkoutFormattedWithoutYear);
});
}
);
}
);
}
static changeHotelBookingFlow(location: string) {
cy.wait(Timeouts.SHORT_TIMEOUT_5_SEC.timeout);
cy.get(chatBookingSelectors.formFields).contains(Directions.HOTEL_LOCATION).click();
cy.get(chatBookingSelectors.airportInput(Directions.HOTEL_LOCATION)).type(location);
cy.wait('@waitForLocation');
cy.get(chatBookingSelectors.airportsFromAutocomplete(location)).click();
this.hotelCheckout();
}
}