qe-fe-automation
Version:
FE test automation framework using cypress
353 lines (318 loc) • 12.7 kB
text/typescript
import { Utility, utilitySelector, Timeouts } from '@utility-lib/index';
import {
TrainTripType,
TrainSearchResults,
TrainSearch,
tripItinerarySelectors
} from '@train-lib/index';
export const trainCheckoutSelector = {
acknowledgment:
'[class="train-checkout-summary__payment__terms-conditions__header"] [type="checkbox"]',
bookTrain: '.train-checkout-summary__payment__button button',
tripCheckout: '.ta-trip-checkout',
loader: '[class^="loading-container"]',
saveTripInfo: '[qaid="tripCheckoutCreateButton"]',
bookingStatus: '.booking-success__left__title',
tripInfoButton:
'[qaid="trainCheckoutTripCheckout"] [class^="ta-trip-checkout__actions"]',
homeSearch: '[class^="main-header__new-logo"] [href="/app/user2/search"]',
renameTrip: '[formcontrolname="tripName"]',
seatButton: '.train-seat .train-seat__content',
ticketContainer: '.ticket__content',
ticketContinue:
'[class^="ticket__message-container rebranding"] button .ta-button__content',
ticketTypeTitle: '[class^="ticket__option"] .ticket__option__title',
seatPreferences: '.train-seat__content button',
skipSeatMaps: '.seat-map-block__header__actions',
trainSeat: '.train-seat__content',
trainCheckoutPageSummary: '.checkout-card__content',
totalBookingCharge: '.summary__total span:nth-child(2)',
totalBookingChargeCurrency: '.charge-item__amount span',
tripInvitationTitle: '.itinerary__content-body__invitation-label',
bookingSuccessClose: '.booking-success__close__icon',
toastMessage: '[class^="ta-toastr-event__message"]',
summaryAmount: '[class="charge-item__right"] [class="charge-item__amount"]',
chargeItemAmount: '.charge-item__amount',
extras: '[class^="train-extras"] [type="checkbox"]',
summaryItem: '[class^="train-checkout-summary__item"]',
summaryAmountInDetail: '[class="charge-item__right"]',
summaryTotal: '.summary__total',
bahnCard: '[class="reminders__rows"] [class="reminders__highlight"]',
trainImage: '[class="ta-trip-checkout__picture"]',
summaryItemTitle: '[class="summary__item__title"]',
disabledButton: '.train-checkout-summary__payment__button [disabled="true"]',
checkedAck: '[class="ta-icon ta-checkbox__icon show"]',
seatNumber: '[class="ta-tag ta-tag--size-small ta-tag--strong-black"]'
};
export class TrainCheckout {
static setTripInfo() {
cy.allure().logStep('set trip information');
cy.wait(Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout);
let maxRetries = 3;
function clickSaveTripInfo() {
cy.get(trainCheckoutSelector.saveTripInfo, Timeouts.MAX_TIMEOUT_120_SEC)
.should('have.length.greaterThan', 0)
.then(($btn) => {
if ($btn.length > 0) {
cy.get(trainCheckoutSelector.saveTripInfo)
.contains(' Save trip info ')
.click();
cy.allure().logStep('add to this trip');
} else {
cy.allure().logStep('save trip information not required');
if (maxRetries > 0) {
maxRetries--;
clickSaveTripInfo();
}
}
});
}
clickSaveTripInfo();
}
static skipSeatMaps() {
cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
cy.get(utilitySelector.bodySelector).then((body) => {
const matchingElements = body.find(trainCheckoutSelector.skipSeatMaps);
if (matchingElements.length > 0) {
cy.allure().logStep('Seat maps were skipped');
const elementsArray = matchingElements.toArray();
elementsArray.forEach((element, index) => {
cy.wrap(element).contains('Continue without selection').click({ force: true });
if (index < elementsArray.length - 1) {
cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
}
});
} else {
cy.allure().logStep('Seat maps not required');
}
});
}
static seatPreferences() {
cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
cy.get(utilitySelector.bodySelector).then(($body) => {
cy.allure().logStep('Seat Preferences continue without selection');
if ($body.text().includes('Continue without selection')) {
cy.contains('Continue without selection').click({ force: true });
} else {
cy.allure().logStep('Seat Preferences not found');
cy.log('seat preference not found');
}
});
}
static renameTrip(tripName: string) {
cy.wait('@waitForContract');
cy.contains('Rename trip', Timeouts.MEDIUM_TIMEOUT_60_SEC).click();
cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
cy.clearInputAndType(trainCheckoutSelector.renameTrip, `${tripName}{enter}`);
cy.allure().logStep('renameRoundTrips');
}
static selectTicketType(ticketTypeTitle: string) {
cy.log('select ticket type if it finds');
cy.get(utilitySelector.bodySelector).then((body) => {
if (body.find(trainCheckoutSelector.ticketContinue).length > 0) {
cy.get(trainCheckoutSelector.ticketTypeTitle).contains(`${ticketTypeTitle}`);
cy.get(trainCheckoutSelector.ticketContinue).click();
cy.allure().logStep(`${ticketTypeTitle} ticket selected`);
} else {
cy.allure().logStep('no ticket selection found');
}
});
}
static selectSeatPreference(preference: string) {
cy.allure().logStep(`select ${preference}`);
cy.get(utilitySelector.bodySelector).then((seatPreference) => {
if (seatPreference.find(trainCheckoutSelector.trainSeat).length > 0) {
cy.get(trainCheckoutSelector.seatButton).contains(`${preference}`).click();
cy.allure().logStep('continue without selection');
} else {
cy.allure().logStep('no seat preference');
}
});
}
static setNewTripName() {
cy.get(trainCheckoutSelector.tripCheckout, Timeouts.MEDIUM_TIMEOUT_60_SEC).should(
'be.visible'
);
Utility.createNewTrip();
Utility.saveTripInformation();
}
static acceptAcknowledgement() {
cy.get(trainCheckoutSelector.acknowledgment).click({ force: true });
cy.allure().logStep('acknowledgement accepted');
}
static bookTrain() {
cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout);
cy.get(trainCheckoutSelector.bookTrain).then(($button) => {
cy.wrap($button).scrollIntoView();
cy.wrap($button).should('be.visible');
cy.wrap($button).click({ force: true });
cy.allure().logStep('book train');
});
}
static switchToNewLocationIfCheckoutFail() {
//! let's check the stability of the test first.
//! if the test fails then we can switch to new train search location
//! and try again
cy.get(utilitySelector.bodySelector).then((checkOutFail) => {
if (checkOutFail.find(trainCheckoutSelector.toastMessage).length > 0) {
cy.get(trainCheckoutSelector.homeSearch).eq(0).click();
cy.allure().logStep('go back to train search page');
}
});
}
static expectBookingStatus(status: string) {
cy.get(trainCheckoutSelector.bookingStatus, { timeout: 240000 }).contains(
`${status}`
);
cy.allure().logStep(`booking status is ${status}`);
}
static confirmBooking() {
cy.allure().logStep('Checking whether booking confirmed.');
cy.get(tripItinerarySelectors.bookingConfirmationModal).should('be.visible');
cy.get(tripItinerarySelectors.bookingConfirmationPopup)
.find(tripItinerarySelectors.bookingConfirmationPopupCloseIcon)
.click();
cy.get(tripItinerarySelectors.bookingConfirmationModal).should('have.length', 0);
}
static confirmTripByInvitation() {
cy.get(trainCheckoutSelector.tripInvitationTitle).should(
'contain.text',
'Trip by invitation'
);
}
static swapToNewLocationsSNCF() {
TrainSearch.visitTrainSearch('Business');
TrainSearch.selectTripTileType(TrainTripType.ONEWAY);
TrainSearch.setOrigin('Lille, FR');
TrainSearch.setDestination('Nice, FR');
TrainSearch.selectFutureTrainDate();
TrainSearch.searchTrain();
TrainSearchResults.expectSearchResultPresent();
TrainSearchResults.expectProviderIsPresent('SNCF');
TrainSearchResults.selectProvider('SNCF');
TrainSearchResults.proceedToCheckoutPage();
TrainCheckout.renameTrip('One-Way Trip SNCF');
TrainCheckout.setTripInfo();
TrainCheckout.selectSeatPreference(' Continue without selection ');
TrainCheckout.acceptAcknowledgement();
TrainCheckout.bookTrain();
TrainCheckout.expectBookingStatus('Train booking confirmed!');
}
static expectBookingStatusSNCF(status: string) {
cy.get(utilitySelector.bodySelector).then((body) => {
if (body.find(trainCheckoutSelector.bookingStatus).length > 0) {
cy.get(
trainCheckoutSelector.bookingStatus,
Timeouts.MAX_TIMEOUT_120_SEC
).contains(`${status}`);
cy.allure().logStep(`booking status is ${status}`);
} else {
cy.allure().logStep('Booking failed');
cy.contains(' Edit search ').click();
TrainCheckout.swapToNewLocationsSNCF();
}
});
}
static storeBookingData() {
cy.get(trainCheckoutSelector.totalBookingCharge).then((element) => {
cy.task('putDataInCache', {
key: 'trainTotalBookingCharge',
data: element.text().trim()
});
});
cy.get(trainCheckoutSelector.totalBookingChargeCurrency)
//.eq(1)
.then((element) => {
cy.task('putDataInCache', {
key: 'trainTotalBookingChargeCurrency',
data: element.text().trim()
});
});
}
static checkTripFeeInCheckoutPageSummary(fee: string) {
cy.get(trainCheckoutSelector.trainCheckoutPageSummary)
.should('contain', fee)
.should('be.exist');
}
static BookingSuccessModelClose() {
cy.get(trainCheckoutSelector.bookingSuccessClose).click();
}
static getTotalSummaryAmount() {
cy.get(trainCheckoutSelector.summaryAmount)
.eq(2)
.invoke('text')
.then((text) => {
const numericPart = text.match(/[\d.]+/) || ['0'];
const subTotalAmount = parseFloat(numericPart[0]);
cy.log('Sub total amount: ' + subTotalAmount);
cy.task('putDataInCache', {
key: 'trainTicketSubTotalAmount',
data: subTotalAmount
});
});
cy.get(trainCheckoutSelector.chargeItemAmount)
.invoke('text')
.then((text) => {
const amount = parseFloat(text.replace(/[^\d.,]/g, '').replace(',', '.'));
const totalAmountWithoutSeat = amount.toFixed(2);
cy.log(`Extracted amount: ${totalAmountWithoutSeat}`);
cy.task('putDataInCache', {
key: 'totalAmountWithoutSeat',
data: totalAmountWithoutSeat
});
});
}
static selectDbSeat() {
cy.get(trainCheckoutSelector.extras).should('be.visible');
cy.get('[class="ta-toggle toggle-size-regular"]')
.should('be.visible')
.then(($elements) => {
// Click all available seats
$elements.each((index) => {
cy.get('[class="ta-toggle toggle-size-regular"]').eq(index).click();
cy.wait('@waitForSeatAdded');
});
});
}
static expectSeatReservationAddedInSummaryOfCharges() {
cy.get(trainCheckoutSelector.summaryAmount).should(
'contain.text',
'Seat reservation '
);
cy.get(trainCheckoutSelector.summaryAmountInDetail)
.eq(1)
.invoke('text')
.then((text) => {
const numericPart = text.match(/[\d.,]+/) || ['0'];
const chargeAmount = parseFloat(numericPart[0].replace(/,/g, ''));
cy.log('Sub total amount :' + chargeAmount);
cy.task('putDataInCache', {
key: 'seatReservationPrice',
data: chargeAmount
});
});
}
static expectBahnCardPresentInCheckout(bahnCardType: string, loyaltyCard = false) {
if (loyaltyCard === true) {
cy.get(trainCheckoutSelector.bahnCard).should('be.visible');
cy.get(trainCheckoutSelector.bahnCard).should('contain.text', bahnCardType);
}
}
static expectNoOfTravelers(noOfTravelers: number) {
cy.get(trainCheckoutSelector.summaryItemTitle)
.eq(0)
.should('contain.text', noOfTravelers);
cy.allure().logStep(`expect ${noOfTravelers} travelers`);
}
static expectSeatNumberIsPresent() {
cy.get(trainCheckoutSelector.seatNumber)
.invoke('text')
.then((seatNumberFoundInCheckout) => {
cy.log('Seat number found:', seatNumberFoundInCheckout);
cy.task('getDataFromCache', 'seatNumberFound').then((seatNumber: any) => {
cy.log('seat Number Found: ======::::>>>>', seatNumber);
expect(seatNumber).to.equal(seatNumber);
});
});
}
}