Merge branch 'develop' into feature/humphries/INSR-8883
This commit is contained in:
commit
1f36c2b5fa
52 changed files with 956 additions and 263 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import { IClient } from "@business-logic/types/Client";
|
import { IClient } from "@business-logic/types/Client";
|
||||||
import { IPaymentDetails } from "@business-logic/types/CustomerDetails";
|
import { IPaymentDetails, IPaymentDetailsAdyen } from "@business-logic/types/CustomerDetails";
|
||||||
import { PaymentType } from "@business-logic/types/Enums";
|
import { PaymentType } from "@business-logic/types/Enums";
|
||||||
|
|
||||||
const essentialClients: IClient[] = [
|
const essentialClients: IClient[] = [
|
||||||
|
|
@ -223,6 +223,19 @@ const defaultCreditCardDetails: IPaymentDetails = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const creditCardDetailsAdyen: IPaymentDetailsAdyen = {
|
||||||
|
paymentType: PaymentType.Credit,
|
||||||
|
cardNumber: '4151500000000008',
|
||||||
|
expirationDate: '03/30',
|
||||||
|
cvv: '737',
|
||||||
|
billingAddress: {
|
||||||
|
street: '123 Test Road',
|
||||||
|
city: 'Columbus',
|
||||||
|
state: 'Ohio',
|
||||||
|
postalCode: '43028',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const defaultAfterpayDetails: IPaymentDetails = {
|
const defaultAfterpayDetails: IPaymentDetails = {
|
||||||
paymentType: PaymentType.AfterPay,
|
paymentType: PaymentType.AfterPay,
|
||||||
username: 'itqatest@safelite.com',
|
username: 'itqatest@safelite.com',
|
||||||
|
|
@ -233,12 +246,24 @@ const defaultAfterpayDetails: IPaymentDetails = {
|
||||||
cvv: '000'
|
cvv: '000'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const afterpayDetailsAdyen: IPaymentDetailsAdyen = {
|
||||||
|
paymentType: PaymentType.AfterPay,
|
||||||
|
username: 'itqatest@safelite.com',
|
||||||
|
password: 'Safelite1',
|
||||||
|
}
|
||||||
|
|
||||||
const defaultPaypalDetails: IPaymentDetails = {
|
const defaultPaypalDetails: IPaymentDetails = {
|
||||||
paymentType: PaymentType.Paypal,
|
paymentType: PaymentType.Paypal,
|
||||||
username:'Itqatest@safelite.com',
|
username:'Itqatest@safelite.com',
|
||||||
password: 'Safelite1'
|
password: 'Safelite1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const paypalDetailsAdyen: IPaymentDetailsAdyen = {
|
||||||
|
paymentType: PaymentType.Paypal,
|
||||||
|
username: 'Itqatest@safelite.com',
|
||||||
|
password: 'Safelite1'
|
||||||
|
}
|
||||||
|
|
||||||
export default class ClientData {
|
export default class ClientData {
|
||||||
static getEssentialClients() {
|
static getEssentialClients() {
|
||||||
return essentialClients;
|
return essentialClients;
|
||||||
|
|
@ -264,10 +289,22 @@ export default class ClientData {
|
||||||
return defaultCreditCardDetails;
|
return defaultCreditCardDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getCreditCardDetailsAdyen() {
|
||||||
|
return creditCardDetailsAdyen;
|
||||||
|
}
|
||||||
|
|
||||||
static getDefaultAfterpayDetails() {
|
static getDefaultAfterpayDetails() {
|
||||||
return defaultAfterpayDetails;
|
return defaultAfterpayDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getAfterpayDetailsAdyen() {
|
||||||
|
return afterpayDetailsAdyen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getPaypalDetailsAdyen() {
|
||||||
|
return paypalDetailsAdyen;
|
||||||
|
}
|
||||||
|
|
||||||
static getDefaultPaypalDetails() {
|
static getDefaultPaypalDetails() {
|
||||||
return defaultPaypalDetails;
|
return defaultPaypalDetails;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,16 @@ export interface IPaymentDetails {
|
||||||
billingAddress?: IAddress,
|
billingAddress?: IAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPaymentDetailsAdyen {
|
||||||
|
paymentType: PaymentType,
|
||||||
|
username?: string,
|
||||||
|
password?: string,
|
||||||
|
cardNumber?: string,
|
||||||
|
expirationDate?: string,
|
||||||
|
cvv?: string,
|
||||||
|
billingAddress?: IAddress,
|
||||||
|
}
|
||||||
|
|
||||||
// export interface IVehicleDamage {
|
// export interface IVehicleDamage {
|
||||||
// isRearWindowDamage?: boolean,
|
// isRearWindowDamage?: boolean,
|
||||||
// windshieldDamage?: WindshieldDamage,
|
// windshieldDamage?: WindshieldDamage,
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,8 @@ export enum VehicleDamage {
|
||||||
export enum VehicleLookupType {
|
export enum VehicleLookupType {
|
||||||
Vin,
|
Vin,
|
||||||
Address,
|
Address,
|
||||||
LicensePlateNumber
|
LicensePlateNumber,
|
||||||
|
RatherNotShareVin
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ServiceLocation {
|
export enum ServiceLocation {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ServicePackage, VehicleDamage } from "./Enums"
|
import { ServicePackage, VehicleDamage } from "./Enums"
|
||||||
import { IAppointmentDetails, IClaimDetails, ICustomerDetails, IEndorsementDetails, IPartQuestion, IPaymentDetails, IVehicleDetails, IAddressVehicleDetails } from "./CustomerDetails"
|
import { IAppointmentDetails, IClaimDetails, ICustomerDetails, IEndorsementDetails, IPartQuestion, IPaymentDetails, IPaymentDetailsAdyen, IVehicleDetails, IAddressVehicleDetails } from "./CustomerDetails"
|
||||||
import IBailoutFlags from "./IBailoutFlags"
|
import IBailoutFlags from "./IBailoutFlags"
|
||||||
|
|
||||||
export interface ITestData {
|
export interface ITestData {
|
||||||
|
|
@ -35,13 +35,16 @@ export interface ITestData {
|
||||||
otherVehiclesOnPolicy: IVehicleDetails[], // IF defined, we validate that the vehicles are present.
|
otherVehiclesOnPolicy: IVehicleDetails[], // IF defined, we validate that the vehicles are present.
|
||||||
vehicleDamage: VehicleDamage[], // Array of vehicle damage
|
vehicleDamage: VehicleDamage[], // Array of vehicle damage
|
||||||
appointmentDetails: IAppointmentDetails,
|
appointmentDetails: IAppointmentDetails,
|
||||||
paymentDetails: IPaymentDetails // Payment information
|
paymentDetails: IPaymentDetails, // Payment information
|
||||||
|
paymentDetailsAdyen: IPaymentDetailsAdyen, // Adyen Payment information
|
||||||
isRecalNotification: boolean,
|
isRecalNotification: boolean,
|
||||||
isRecalWarning: boolean,
|
isRecalWarning: boolean,
|
||||||
isRecalVehicle: boolean,
|
isRecalVehicle: boolean,
|
||||||
|
isCanSafeliteRecalibrate: boolean, // Can Safelite recalibrate the vehicle? If no, modal displays after clicking time slot and continue
|
||||||
isSeparateApptsWarning: boolean, // IF true, check for the separate appts warning on VehicleDamagePage
|
isSeparateApptsWarning: boolean, // IF true, check for the separate appts warning on VehicleDamagePage
|
||||||
isAuthenticationRequired: boolean,
|
isAuthenticationRequired: boolean,
|
||||||
isMoldingQuestion: boolean,
|
isMoldingQuestion: boolean,
|
||||||
isNonServiceable: boolean, // For the flow where a a non-serviceable vehicle is selected on lookup
|
isNonServiceable: boolean, // For the flow where a a non-serviceable vehicle is selected on lookup
|
||||||
isNonServiceableVin: boolean, // For the flow where a serviceable vehicle is selected on lookup, but then the VIN of a non-serviceable vehicle is entered
|
isNonServiceableVin: boolean, // For the flow where a serviceable vehicle is selected on lookup, but then the VIN of a non-serviceable vehicle is entered
|
||||||
|
isRepairTPA: boolean,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Locator, Page } from "@playwright/test";
|
import { Locator, Page } from "@playwright/test";
|
||||||
import { BasePage } from "./BasePage";
|
import { BasePage } from "./BasePage";
|
||||||
import { IClaimDetails, IPaymentDetails } from "@business-logic/types/CustomerDetails";
|
import { IClaimDetails, IPaymentDetails, IPaymentDetailsAdyen } from "@business-logic/types/CustomerDetails";
|
||||||
import { ServicePackage } from "@business-logic/types/Enums";
|
import { ServicePackage } from "@business-logic/types/Enums";
|
||||||
|
|
||||||
export class AfterpayPage extends BasePage {
|
export class AfterpayPage extends BasePage {
|
||||||
|
|
@ -33,11 +33,11 @@ export class AfterpayPage extends BasePage {
|
||||||
await this.submitButton.click();
|
await this.submitButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async executeAfterpayPayment(paymentDetails: IPaymentDetails, claimDetails: IClaimDetails, servicePackage: ServicePackage) {
|
async executeAfterpayPayment(paymentDetailsAdyen: IPaymentDetailsAdyen, claimDetails: IClaimDetails, servicePackage: ServicePackage) {
|
||||||
|
|
||||||
const confirmButtonOrPaymentOptions = this.confirmButton.or(this.selectAfterpayWithoutInterestButton);
|
const confirmButtonOrPaymentOptions = this.confirmButton.or(this.selectAfterpayWithoutInterestButton);
|
||||||
|
|
||||||
await this.login(paymentDetails.password!);
|
await this.login(paymentDetailsAdyen.password!);
|
||||||
|
|
||||||
await this.page.locator('div[data-testid=\'loading-icon-svg\']').filter({ visible: true}).first().waitFor({ state: 'hidden' });
|
await this.page.locator('div[data-testid=\'loading-icon-svg\']').filter({ visible: true}).first().waitFor({ state: 'hidden' });
|
||||||
await confirmButtonOrPaymentOptions.waitFor({ state: 'visible' });
|
await confirmButtonOrPaymentOptions.waitFor({ state: 'visible' });
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export class BasePage {
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
const currentUrl = this.page.url();
|
const currentUrl = this.page.url();
|
||||||
if (currentUrl === startingUrl) {
|
if (currentUrl === startingUrl) {
|
||||||
await this.continueButton.click({ timeout: 1000 });
|
await this.continueButton.click({ timeout: 5_000 });
|
||||||
}
|
}
|
||||||
//this causes the schedule page to fail
|
//this causes the schedule page to fail
|
||||||
//await expect(this.buttonLoadSpin).toHaveCount(0, {timeout: 180000});
|
//await expect(this.buttonLoadSpin).toHaveCount(0, {timeout: 180000});
|
||||||
|
|
@ -96,24 +96,23 @@ export class BasePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
async logReferralNumber() {
|
async logReferralNumber() {
|
||||||
let mainSessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'main\')'));
|
let referralNumber: number | null = null;
|
||||||
let referralNumber = mainSessionStorage.order.referralNumber as number;
|
let referralSequenceNumber: number | null = null;
|
||||||
let referralSequenceNumber = mainSessionStorage.order.referralSequenceNumber as number;
|
for (let i = 0; i < 3; i++) {
|
||||||
if (referralNumber == null) {
|
const main = JSON.parse(await this.page.evaluate(() => sessionStorage.getItem('main')) ?? 'null');
|
||||||
for (let i = 1; i <= 20; i++) {
|
referralNumber = main?.order?.referralNumber ?? null;
|
||||||
if (!referralNumber == null) break;
|
referralSequenceNumber = main?.order?.referralSequenceNumber ?? null;
|
||||||
await this.page.waitForTimeout(500);
|
if (referralNumber !== null) break;
|
||||||
mainSessionStorage = JSON.parse(await this.page.evaluate('localStorage.getItem(\'main\')'));
|
await this.page.waitForTimeout(500);
|
||||||
referralNumber = mainSessionStorage.order.referralNumber as number;
|
}
|
||||||
referralSequenceNumber = mainSessionStorage.order.referralSequenceNumber as number;
|
if (referralNumber === null) {
|
||||||
}
|
console.warn('Referral Number could not be retrieved after retries.');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await test.step(`Referral Number:${referralNumber} Referral Sequence Number:${referralSequenceNumber}`, async () => {
|
await test.step(`Referral Number:${referralNumber} Referral Sequence Number:${referralSequenceNumber}`, async () => {
|
||||||
console.log(`Referral Number:${referralNumber}`);
|
console.log(`Referral Number:${referralNumber}`);
|
||||||
console.log(`Referral Sequence Number:${referralSequenceNumber}`);
|
console.log(`Referral Sequence Number:${referralSequenceNumber}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async validateURL(issPageValue: string) {
|
async validateURL(issPageValue: string) {
|
||||||
|
|
@ -132,6 +131,6 @@ export class BasePage {
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
const currentUrl = this.page.url();
|
const currentUrl = this.page.url();
|
||||||
expect(currentUrl).not.toEqual(startingUrl);
|
expect(currentUrl).not.toEqual(startingUrl);
|
||||||
}).toPass({ timeout: 70_000 });
|
}).toPass({ timeout: 90_000 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -11,17 +11,6 @@ export class PartQuestionsPage extends BasePage {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
async validatePartQuestions(partQuestions: IPartQuestion[]) {
|
|
||||||
for (const pq of partQuestions) {
|
|
||||||
const partQuestionOptions = this.page.locator(`fieldset[aria-labelledby="${pq.partQuestionType}"]`);
|
|
||||||
if (pq.isOnPage) {
|
|
||||||
await expect(partQuestionOptions).toBeAttached();
|
|
||||||
} else {
|
|
||||||
await expect(partQuestionOptions).not.toBeAttached();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async selectPartQuestionResponses(partQuestions: IPartQuestion[]) {
|
async selectPartQuestionResponses(partQuestions: IPartQuestion[]) {
|
||||||
for (const pq of partQuestions) {
|
for (const pq of partQuestions) {
|
||||||
const parentobject=this.page.locator(`fieldset[aria-labelledby="${pq.partQuestionType}"]`);
|
const parentobject=this.page.locator(`fieldset[aria-labelledby="${pq.partQuestionType}"]`);
|
||||||
|
|
|
||||||
46
playwright-tests/pages/PaymentAdyenPage.ts
Normal file
46
playwright-tests/pages/PaymentAdyenPage.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { type Locator, type Page } from '@playwright/test';
|
||||||
|
import { BasePage } from './BasePage';
|
||||||
|
import { IPaymentDetailsAdyen } from '@business-logic/types/CustomerDetails';
|
||||||
|
|
||||||
|
export class PaymentAdyenPage extends BasePage {
|
||||||
|
readonly page: Page;
|
||||||
|
|
||||||
|
readonly cardNumberTextField: Locator;
|
||||||
|
readonly expiryDateTextField: Locator;
|
||||||
|
readonly securityCodeTextField: Locator;
|
||||||
|
readonly billingAddressTextField: Locator;
|
||||||
|
readonly cityTextField: Locator;
|
||||||
|
readonly stateDropDown: Locator;
|
||||||
|
readonly payButton: Locator;
|
||||||
|
|
||||||
|
readonly afterPayButton: Locator;
|
||||||
|
readonly afterPayLaunchButton: Locator;
|
||||||
|
readonly applePayButton: Locator;
|
||||||
|
|
||||||
|
issPageValue = 'payment-page-adyen';
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
super(page);
|
||||||
|
this.page = page;
|
||||||
|
|
||||||
|
//Credit Card Fields
|
||||||
|
this.cardNumberTextField = this.page.locator('iframe[title="Iframe for card number"]').contentFrame().getByRole('textbox', { name: 'Card number' });
|
||||||
|
this.expiryDateTextField = this.page.locator('iframe[title="Iframe for expiry date"]').contentFrame().getByRole('textbox', { name: 'Expiry date' });
|
||||||
|
this.securityCodeTextField = this.page.locator('iframe[title="Iframe for security code"]').contentFrame().getByRole('textbox', { name: 'CVV/CVC' });
|
||||||
|
this.billingAddressTextField = this.page.getByRole('textbox', { name: 'Address' });
|
||||||
|
this.cityTextField = this.page.getByRole('textbox', { name: 'City' });
|
||||||
|
this.stateDropDown = this.page.getByRole('combobox', { name: 'State' });
|
||||||
|
this.payButton = this.page.getByRole('button', { name: 'Pay $' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async populateCreditCardDetails(paymentDetailsAdyen: IPaymentDetailsAdyen){
|
||||||
|
await this.cardNumberTextField.fill(paymentDetailsAdyen.cardNumber!);
|
||||||
|
await this.expiryDateTextField.fill(paymentDetailsAdyen.expirationDate!);
|
||||||
|
await this.securityCodeTextField.fill(paymentDetailsAdyen.cvv!);
|
||||||
|
await this.billingAddressTextField.fill(paymentDetailsAdyen.billingAddress!.street);
|
||||||
|
await this.cityTextField.fill(paymentDetailsAdyen.billingAddress!.city);
|
||||||
|
await this.stateDropDown.fill(paymentDetailsAdyen.billingAddress!.state);
|
||||||
|
await this.stateDropDown.press('Enter');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,24 @@
|
||||||
import { expect, type Locator, type Page } from '@playwright/test';
|
import { expect, type Locator, type Page } from '@playwright/test';
|
||||||
import { BasePage } from './BasePage';
|
import { BasePage } from './BasePage';
|
||||||
import { IClaimDetails, IPaymentDetails } from '@business-logic/types/CustomerDetails';
|
import { IClaimDetails, IPaymentDetails, IPaymentDetailsAdyen } from '@business-logic/types/CustomerDetails';
|
||||||
import { PaymentType, ServicePackage } from '@business-logic/types/Enums';
|
import { PaymentType, ServicePackage } from '@business-logic/types/Enums';
|
||||||
import { PaymentPage } from './PaymentPage';
|
import { PaymentPage } from './PaymentPage';
|
||||||
import { AfterpayPage } from './AfterpayPage';
|
import { AfterpayPage } from './AfterpayPage';
|
||||||
import { PaypalPage } from './PaypalPage';
|
import { PaypalPage } from './PaypalPage';
|
||||||
|
import { PaymentAdyenPage } from './PaymentAdyenPage';
|
||||||
|
|
||||||
export class PaymentMethodPage extends BasePage {
|
export class PaymentMethodPage extends BasePage {
|
||||||
readonly page: Page;
|
readonly page: Page;
|
||||||
readonly paypalPage: PaypalPage;
|
readonly paypalPage: PaypalPage;
|
||||||
readonly paymentPage: PaymentPage;
|
readonly paymentPage: PaymentPage;
|
||||||
|
readonly paymentAdyenPage: PaymentAdyenPage;
|
||||||
|
|
||||||
readonly payNowButton: Locator;
|
readonly payNowButton: Locator;
|
||||||
readonly paypalButton: Locator;
|
readonly paypalButton: Locator;
|
||||||
|
readonly payPalAdyenButton: Locator;
|
||||||
|
readonly payPalLaunchAdyenButton: Locator;
|
||||||
|
readonly afterpayAdyenButton: Locator;
|
||||||
|
readonly afterpayLaunchAdyenButton: Locator;
|
||||||
readonly payInFourButton: Locator;
|
readonly payInFourButton: Locator;
|
||||||
readonly payAtAppointmentButton: Locator;
|
readonly payAtAppointmentButton: Locator;
|
||||||
|
|
||||||
|
|
@ -28,9 +34,20 @@ export class PaymentMethodPage extends BasePage {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.paypalPage = new PaypalPage(page);
|
this.paypalPage = new PaypalPage(page);
|
||||||
this.paymentPage = new PaymentPage(page);
|
this.paymentPage = new PaymentPage(page);
|
||||||
|
this.paymentAdyenPage = new PaymentAdyenPage(page);
|
||||||
|
|
||||||
this.payNowButton = this.page.locator('[buttonlabel="Pay now"]'); // credit and paypal options behind this button
|
this.payNowButton = this.page.locator('[buttonlabel="Pay now"]'); // credit and paypal options behind this button
|
||||||
this.paypalButton = this.page.frameLocator('iframe[name="card-frame"]').locator('div[id="paypalParentDiv"]');
|
this.paypalButton = this.page.frameLocator('iframe[name="card-frame"]').locator('div[id="paypalParentDiv"]');
|
||||||
|
|
||||||
|
// Ayden Paypal button
|
||||||
|
this.payPalAdyenButton = this.page.getByRole('radio', { name: 'PayPal' });
|
||||||
|
this.payPalLaunchAdyenButton = this.page.frameLocator('iframe[title="PayPal-paypal"]:first-of-type').locator('div[role="link"][class*="paypal-button"]');
|
||||||
|
|
||||||
|
// Ayden Afterpay buttons
|
||||||
|
this.afterpayAdyenButton = this.page.getByRole('radio', { name: 'Afterpay' });
|
||||||
|
this.afterpayLaunchAdyenButton = this.page.getByRole('button', { name: 'Continue to Afterpay' });
|
||||||
|
|
||||||
|
|
||||||
this.payInFourButton = this.page.locator('[buttonlabel="Pay in 4 installments"]'); // Afterpay
|
this.payInFourButton = this.page.locator('[buttonlabel="Pay in 4 installments"]'); // Afterpay
|
||||||
this.payAtAppointmentButton = this.page.locator('[buttonlabel="Pay at my appointment"]');
|
this.payAtAppointmentButton = this.page.locator('[buttonlabel="Pay at my appointment"]');
|
||||||
|
|
||||||
|
|
@ -40,22 +57,24 @@ export class PaymentMethodPage extends BasePage {
|
||||||
this.submitButton = this.page.getByRole('button', { name: 'Submit' });
|
this.submitButton = this.page.getByRole('button', { name: 'Submit' });
|
||||||
}
|
}
|
||||||
|
|
||||||
async executePayment(paymentDetails: IPaymentDetails, claimDetails: IClaimDetails, servicePackage: ServicePackage) {
|
async executePayment(paymentDetails: IPaymentDetails, paymentDetailsAdyen: IPaymentDetailsAdyen, claimDetails: IClaimDetails, servicePackage: ServicePackage) {
|
||||||
const browserContext = this.page.context();
|
const browserContext = this.page.context();
|
||||||
|
|
||||||
switch (paymentDetails.paymentType) {
|
switch (paymentDetailsAdyen?.paymentType ?? paymentDetails?.paymentType) { case PaymentType.Credit:
|
||||||
case PaymentType.Credit:
|
|
||||||
await this.payNowButton.click();
|
await this.payNowButton.click();
|
||||||
await this.textReminderNoButton.click();
|
await this.textReminderNoButton.click();
|
||||||
await this.continueToCheckoutButton.click();
|
await this.continueToCheckoutButton.click();
|
||||||
await this.selectCreditCard(paymentDetails);
|
await this.selectCreditCard(paymentDetailsAdyen);
|
||||||
break;
|
break;
|
||||||
case PaymentType.Paypal:
|
case PaymentType.Paypal:
|
||||||
await this.payNowButton.click();
|
await this.payNowButton.click();
|
||||||
await this.textReminderNoButton.click();
|
await this.textReminderNoButton.click();
|
||||||
await this.continueToCheckoutButton.click();
|
await this.continueToCheckoutButton.click();
|
||||||
await this.selectPaypal();
|
|
||||||
await this.paypalPage.completePaypalPurchase(paymentDetails);
|
const paypalPopup = await this.selectPaypal();
|
||||||
|
const paypalPage = new PaypalPage(paypalPopup);
|
||||||
|
|
||||||
|
await paypalPage.completePaypalPurchase(paymentDetailsAdyen);
|
||||||
break;
|
break;
|
||||||
case PaymentType.AfterPay:
|
case PaymentType.AfterPay:
|
||||||
await this.payInFourButton.click();
|
await this.payInFourButton.click();
|
||||||
|
|
@ -63,11 +82,11 @@ export class PaymentMethodPage extends BasePage {
|
||||||
await this.continueToCheckoutButton.click();
|
await this.continueToCheckoutButton.click();
|
||||||
|
|
||||||
// Capture popup
|
// Capture popup
|
||||||
const afterpayPopup = await browserContext.waitForEvent('page');
|
const afterpayPage = await this.selectAfterpayAdyen();
|
||||||
const afterpayPage = new AfterpayPage(afterpayPopup);
|
const afterpayAdyenPage = new AfterpayPage(afterpayPage);
|
||||||
|
|
||||||
// Execute payment
|
// Execute payment
|
||||||
await afterpayPage.executeAfterpayPayment(paymentDetails, claimDetails, servicePackage);
|
await afterpayAdyenPage.executeAfterpayPayment(paymentDetailsAdyen, claimDetails, servicePackage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PaymentType.PayAtService:
|
case PaymentType.PayAtService:
|
||||||
|
|
@ -80,13 +99,25 @@ export class PaymentMethodPage extends BasePage {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async selectAfterpayAdyen(): Promise<Page> {
|
||||||
async selectPaypal() {
|
await this.afterpayAdyenButton.click();
|
||||||
await this.paypalButton.click();
|
await this.afterpayLaunchAdyenButton.click();
|
||||||
|
//await this.page.waitForLoadState('networkidle');
|
||||||
|
return this.page;
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectCreditCard(paymentDetails: IPaymentDetails) {
|
async selectPaypal(): Promise<Page> {
|
||||||
await this.paymentPage.populateCreditCardDetails(paymentDetails);
|
await this.payPalAdyenButton.click();
|
||||||
|
const paypalPage = this.page.waitForEvent('popup');
|
||||||
|
await this.payPalLaunchAdyenButton.click();
|
||||||
|
const paypalPopup = await paypalPage;
|
||||||
|
await paypalPopup.waitForLoadState();
|
||||||
|
return paypalPopup;
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectCreditCard(paymentDetailsAdyen: IPaymentDetailsAdyen) {
|
||||||
|
await this.paymentAdyenPage.populateCreditCardDetails(paymentDetailsAdyen);
|
||||||
|
await this.paymentAdyenPage.payButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectPayAtAppointment() {
|
async selectPayAtAppointment() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { type Locator, type Page } from '@playwright/test';
|
import { type Locator, type Page } from '@playwright/test';
|
||||||
import { BasePage } from './BasePage';
|
import { BasePage } from './BasePage';
|
||||||
import { AfterpayPage } from './AfterpayPage';
|
|
||||||
import { IPaymentDetails } from '@business-logic/types/CustomerDetails';
|
import { IPaymentDetails } from '@business-logic/types/CustomerDetails';
|
||||||
|
|
||||||
export class PaymentPage extends BasePage {
|
export class PaymentPage extends BasePage {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { expect, type Locator, type Page } from "@playwright/test";
|
import { expect, type Locator, type Page } from "@playwright/test";
|
||||||
import { BasePage } from "./BasePage";
|
import { BasePage } from "./BasePage";
|
||||||
import { IPaymentDetails } from "@business-logic/types/CustomerDetails";
|
import { IPaymentDetailsAdyen } from "@business-logic/types/CustomerDetails";
|
||||||
|
|
||||||
export class PaypalPage extends BasePage {
|
export class PaypalPage extends BasePage {
|
||||||
readonly page: Page;
|
readonly page: Page;
|
||||||
|
|
@ -13,7 +13,7 @@ export class PaypalPage extends BasePage {
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
super(page);
|
super(page);
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.usernameTextBox = page.locator("#email");
|
this.usernameTextBox = page.getByRole("textbox", { name: "Email or mobile number" });
|
||||||
this.nextButton = page.getByRole("button", { name: "Next" });
|
this.nextButton = page.getByRole("button", { name: "Next" });
|
||||||
this.passwordTextBox = page.getByRole("textbox", { name: "Password" });
|
this.passwordTextBox = page.getByRole("textbox", { name: "Password" });
|
||||||
this.paypalLoginButton = page.getByRole("button", {
|
this.paypalLoginButton = page.getByRole("button", {
|
||||||
|
|
@ -23,16 +23,16 @@ export class PaypalPage extends BasePage {
|
||||||
this.payButton = page.getByRole("button", { name: "Pay $" });
|
this.payButton = page.getByRole("button", { name: "Pay $" });
|
||||||
}
|
}
|
||||||
|
|
||||||
async completePaypalPurchase(paymentDetails: IPaymentDetails) {
|
async completePaypalPurchase(paymentDetailsAdyen: IPaymentDetailsAdyen) {
|
||||||
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await this.usernameTextBox.fill(paymentDetails.username!);
|
await this.usernameTextBox.fill(paymentDetailsAdyen.username!);
|
||||||
await this.nextButton.waitFor({ state: 'visible', timeout: 5000 });
|
await this.nextButton.waitFor({ state: 'visible', timeout: 5000 });
|
||||||
await this.nextButton.click();
|
await this.nextButton.click();
|
||||||
await expect(this.passwordTextBox).toBeVisible({ timeout: 5000 });
|
await expect(this.passwordTextBox).toBeVisible({ timeout: 5000 });
|
||||||
}).toPass({ timeout: 30000 });
|
}).toPass({ timeout: 30000 });
|
||||||
|
|
||||||
await this.passwordTextBox.fill(paymentDetails.password!);
|
await this.passwordTextBox.fill(paymentDetailsAdyen.password!);
|
||||||
await this.paypalLoginButton.click();
|
await this.paypalLoginButton.click();
|
||||||
await this.payButton.click();
|
await this.payButton.click();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,11 @@ export class PolicyHolderDetailsPage extends BasePage {
|
||||||
// For essential flows, when address fields are not pre-filled
|
// For essential flows, when address fields are not pre-filled
|
||||||
if (!addressValue || addressValue.trim() === '') {
|
if (!addressValue || addressValue.trim() === '') {
|
||||||
await this.addressInputBox.click();
|
await this.addressInputBox.click();
|
||||||
await this.addressInputBox.fill(customerDetails.address.street);
|
await this.addressInputBox.pressSequentially(customerDetails.address.street);
|
||||||
|
|
||||||
// Wait for suggestions to load (Google Places has a slight delay)
|
// Wait for suggestions to load (Google Places has a slight delay)
|
||||||
await this.page.locator('.pac-item').first().waitFor({ state: 'visible', timeout: 6000 });
|
await this.page.locator('.pac-item').first().waitFor({ state: 'attached', timeout: 6000 });
|
||||||
|
await this.page.locator('.pac-item').first().isVisible();
|
||||||
// Click the first result
|
// Click the first result
|
||||||
await this.page.locator('.pac-item').first().click();
|
await this.page.locator('.pac-item').first().click();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ export class ProviderPreferencePage extends BasePage {
|
||||||
|
|
||||||
async selectProvider(isSafelite: boolean) {
|
async selectProvider(isSafelite: boolean) {
|
||||||
if (isSafelite) {
|
if (isSafelite) {
|
||||||
|
await expect(this.scheduleNowButton).toBeVisible();
|
||||||
|
await expect(this.scheduleNowButton).toBeEnabled();
|
||||||
await this.scheduleNowButton.click();
|
await this.scheduleNowButton.click();
|
||||||
await this.nextPage();
|
await this.nextPage();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,19 @@ export class SchedulePage extends BasePage {
|
||||||
readonly dateText: Locator;
|
readonly dateText: Locator;
|
||||||
readonly viewMoreDatesLink: Locator;
|
readonly viewMoreDatesLink: Locator;
|
||||||
|
|
||||||
|
readonly recalAcknowledgementModal: Locator;
|
||||||
|
readonly learnMoreLinkRecalAcknowledgementModal: Locator;
|
||||||
|
readonly recalAcknowledgementCheckBox: Locator;
|
||||||
|
readonly continueButtonRecalAcknowledgementModal: Locator;
|
||||||
|
|
||||||
readonly continueButton: Locator;
|
readonly continueButton: Locator;
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
super(page);
|
super(page);
|
||||||
this.page = page;
|
this.page = page;
|
||||||
|
|
||||||
this.inShopButton = this.page.locator('[buttonlabel="At a Safelite shop"]');
|
this.inShopButton = this.page.getByText('At a Safelite shop');
|
||||||
this.mobileButton = this.page.locator('[buttonlabel="Have Safelite come to me"]');
|
this.mobileButton = this.page.getByText('Have Safelite come to me');
|
||||||
// For in shop
|
// For in shop
|
||||||
this.moreLocationsButton = this.page.getByRole('button', { name: 'More Locations' });
|
this.moreLocationsButton = this.page.getByRole('button', { name: 'More Locations' });
|
||||||
// For mobile
|
// For mobile
|
||||||
|
|
@ -50,6 +55,12 @@ export class SchedulePage extends BasePage {
|
||||||
this.dateText = this.page.locator('[class="modal-header mb-2 mt-2"]');
|
this.dateText = this.page.locator('[class="modal-header mb-2 mt-2"]');
|
||||||
this.viewMoreDatesLink = this.page.getByRole('button', { name: 'More Right arrow icon' });
|
this.viewMoreDatesLink = this.page.getByRole('button', { name: 'More Right arrow icon' });
|
||||||
|
|
||||||
|
// Recal acknowledgement modal when Safelite cannot recalibrate the vehicle
|
||||||
|
this.recalAcknowledgementModal = this.page.getByLabel('ModalComponentLabel');
|
||||||
|
this.learnMoreLinkRecalAcknowledgementModal = this.page.getByRole('link', { name: 'Learn more' });
|
||||||
|
this.recalAcknowledgementCheckBox = this.page.getByRole('checkbox', { name: /I acknowledge/i });
|
||||||
|
this.continueButtonRecalAcknowledgementModal = this.page.locator('#RecalAckModalWidget').getByRole('button', { name: 'Continue' });
|
||||||
|
|
||||||
this.continueButton = this.page.locator('#stacked').locator('button:has-text("Continue")');
|
this.continueButton = this.page.locator('#stacked').locator('button:has-text("Continue")');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,6 +88,7 @@ export class SchedulePage extends BasePage {
|
||||||
await (await this.getFirstNonDropOffTimeSlot()).click();
|
await (await this.getFirstNonDropOffTimeSlot()).click();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
await this.inShopButton.click();
|
||||||
await (await this.getFirstNonDropOffTimeSlot()).click();
|
await (await this.getFirstNonDropOffTimeSlot()).click();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -110,4 +122,10 @@ export class SchedulePage extends BasePage {
|
||||||
const nonDropOff = timeSlots.filter({ hasNotText: /Drop & Go/i });
|
const nonDropOff = timeSlots.filter({ hasNotText: /Drop & Go/i });
|
||||||
return nonDropOff.first();
|
return nonDropOff.first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async validateRecalAcknowledgementModal() {
|
||||||
|
await this.learnMoreLinkRecalAcknowledgementModal.click();
|
||||||
|
await this.recalAcknowledgementCheckBox.click();
|
||||||
|
await this.continueButtonRecalAcknowledgementModal.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +32,7 @@ export class ServicePackagesPage extends BasePage {
|
||||||
try {await this.wiperModal.waitFor({ state: 'visible', timeout: 5000 });
|
try {await this.wiperModal.waitFor({ state: 'visible', timeout: 5000 });
|
||||||
await this.wiperModalCloseButton.click();
|
await this.wiperModalCloseButton.click();
|
||||||
} catch {
|
} catch {
|
||||||
await this.continueButton.click();
|
console.log('Wiper modal not displayed');
|
||||||
}
|
}
|
||||||
} else if (servicePackage === ServicePackage.GlassOnly) {
|
} else if (servicePackage === ServicePackage.GlassOnly) {
|
||||||
await this.glassOnlyPackageButton.check();
|
await this.glassOnlyPackageButton.check();
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ export class TpaSubmitPage extends BasePage {
|
||||||
async validateDeductible(claimDetails: IClaimDetails, isUnverifiedPolicyAfterVehicleLookup: boolean, isPolicyFound: boolean) {
|
async validateDeductible(claimDetails: IClaimDetails, isUnverifiedPolicyAfterVehicleLookup: boolean, isPolicyFound: boolean) {
|
||||||
const deductibleTextValue = await this.deductible.textContent();
|
const deductibleTextValue = await this.deductible.textContent();
|
||||||
|
|
||||||
|
await expect(this.deductible).toBeVisible();
|
||||||
|
|
||||||
if (claimDetails.policyDeductible !== -1 && !isUnverifiedPolicyAfterVehicleLookup) {
|
if (claimDetails.policyDeductible !== -1 && !isUnverifiedPolicyAfterVehicleLookup) {
|
||||||
expect.soft(deductibleTextValue).toContain(claimDetails.policyDeductible.toLocaleString());
|
expect.soft(deductibleTextValue).toContain(claimDetails.policyDeductible.toLocaleString());
|
||||||
} else
|
} else
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export class VehicleLookupPage extends BasePage {
|
||||||
readonly addressLookupButton: Locator;
|
readonly addressLookupButton: Locator;
|
||||||
readonly licenseLookupButton: Locator;
|
readonly licenseLookupButton: Locator;
|
||||||
readonly vinLookupPage: VinLookupPage;
|
readonly vinLookupPage: VinLookupPage;
|
||||||
|
readonly ratherNotShareVinButton: Locator;
|
||||||
readonly vehicleLookupAddressPage: VehicleLookupAddressPage;
|
readonly vehicleLookupAddressPage: VehicleLookupAddressPage;
|
||||||
readonly vehicleLookupLicensePage: VehicleLookupLicensePage;
|
readonly vehicleLookupLicensePage: VehicleLookupLicensePage;
|
||||||
issPageValue = 'vehicle-lookup';
|
issPageValue = 'vehicle-lookup';
|
||||||
|
|
@ -22,6 +23,7 @@ export class VehicleLookupPage extends BasePage {
|
||||||
this.vinLookupButton = page.getByLabel('Provide my VIN', { exact: true });
|
this.vinLookupButton = page.getByLabel('Provide my VIN', { exact: true });
|
||||||
this.addressLookupButton = page.getByLabel('Provide my home address', { exact: true });
|
this.addressLookupButton = page.getByLabel('Provide my home address', { exact: true });
|
||||||
this.licenseLookupButton = page.getByLabel('Provide my license plate #', { exact: true });
|
this.licenseLookupButton = page.getByLabel('Provide my license plate #', { exact: true });
|
||||||
|
this.ratherNotShareVinButton = page.getByText(/rather not share my vin/i);
|
||||||
this.vinLookupPage = new VinLookupPage(page);
|
this.vinLookupPage = new VinLookupPage(page);
|
||||||
|
|
||||||
// this.validateURL(this.url);
|
// this.validateURL(this.url);
|
||||||
|
|
@ -41,6 +43,10 @@ export class VehicleLookupPage extends BasePage {
|
||||||
await this.selectVinLookup();
|
await this.selectVinLookup();
|
||||||
await this.nextPage();
|
await this.nextPage();
|
||||||
break;
|
break;
|
||||||
|
case VehicleLookupType.RatherNotShareVin:
|
||||||
|
await this.selectRatherNotShareVin();
|
||||||
|
await this.nextPage();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('VehicleLookupPage >> DATA ISSUE: VehicleLookupType not provided');
|
console.error('VehicleLookupPage >> DATA ISSUE: VehicleLookupType not provided');
|
||||||
break;
|
break;
|
||||||
|
|
@ -58,4 +64,8 @@ export class VehicleLookupPage extends BasePage {
|
||||||
async selectLicenseLookup(){
|
async selectLicenseLookup(){
|
||||||
await this.licenseLookupButton.click();
|
await this.licenseLookupButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async selectRatherNotShareVin(){
|
||||||
|
await this.ratherNotShareVinButton.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export class VehicleSelectionPage extends BasePage {
|
||||||
await this.yearDropdown.selectOption(vehicleDetails.year);
|
await this.yearDropdown.selectOption(vehicleDetails.year);
|
||||||
await this.yearDropdown.press('Tab');
|
await this.yearDropdown.press('Tab');
|
||||||
await this.makeDropdown.selectOption(vehicleDetails.make);
|
await this.makeDropdown.selectOption(vehicleDetails.make);
|
||||||
await expect(this.modelDropdown).toBeEditable({ timeout: 5000 });
|
await expect(this.modelDropdown).toBeEditable({ timeout: 6000 });
|
||||||
await this.makeDropdown.press('Tab');
|
await this.makeDropdown.press('Tab');
|
||||||
await this.modelDropdown.selectOption(vehicleDetails.model);
|
await this.modelDropdown.selectOption(vehicleDetails.model);
|
||||||
await expect(this.styleDropdown).toBeEditable({ timeout: 2000 });
|
await expect(this.styleDropdown).toBeEditable({ timeout: 2000 });
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ export class VinLookupPage extends BasePage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async triggerBailout() {
|
async returnToVehicleLookupPage() {
|
||||||
await this.continueButton.click();
|
await this.continueButton.click();
|
||||||
await this.lookupVinForMe.click();
|
await this.lookupVinForMe.click();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,9 @@ export default defineConfig({
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
forbidOnly: !!process.env.CI,
|
forbidOnly: !!process.env.CI,
|
||||||
/* Retry on CI only */
|
/* Retry on CI only */
|
||||||
retries: process.env.CI ? 1 : 0,
|
retries: process.env.CI ? 2 : 0,
|
||||||
/* Opt out of parallel tests on CI. */
|
/* Opt out of parallel tests on CI. */
|
||||||
workers: process.env.CI ? 4 : 5,
|
workers: process.env.CI ? 1 : 5,
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: process.env.CI? [
|
reporter: process.env.CI? [
|
||||||
['junit'],
|
['junit'],
|
||||||
|
|
@ -91,9 +91,11 @@ export default defineConfig({
|
||||||
baseURL: process.env.BASE_URL || 'https://selfservice.test.glassclaim.com',
|
baseURL: process.env.BASE_URL || 'https://selfservice.test.glassclaim.com',
|
||||||
trace: 'on-first-retry',
|
trace: 'on-first-retry',
|
||||||
headless: process.env.CI ? true : false,
|
headless: process.env.CI ? true : false,
|
||||||
|
video: 'off',
|
||||||
|
viewport: { width: 1920, height: 1080 },
|
||||||
screenshot: "only-on-failure",
|
screenshot: "only-on-failure",
|
||||||
actionTimeout: 60_000,
|
actionTimeout: process.env.CI ? 90_000 : 60_000,
|
||||||
navigationTimeout: 60_000
|
navigationTimeout: process.env.CI ? 90_000 : 60_000
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Configure projects for major browsers */
|
/* Configure projects for major browsers */
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import advancedScenario0001TestCases from "./advanced/0001a_ReplaceInShopCredit"
|
||||||
import advancedScenario0003TestCases from "./advanced/0003a_MobileAfterpay";
|
import advancedScenario0003TestCases from "./advanced/0003a_MobileAfterpay";
|
||||||
import essentialReplaceDynamicAdasTests from "./0005_EssentialReplaceDynamicAdas";
|
import essentialReplaceDynamicAdasTests from "./0005_EssentialReplaceDynamicAdas";
|
||||||
import essentialReplaceStaticAdasTests from "./0001_EssentialReplaceStatisAdas";
|
import essentialReplaceStaticAdasTests from "./0001_EssentialReplaceStatisAdas";
|
||||||
import essentialVehicleLookupBailoutTests from "./0020_EssentialVehicleLookupBailout";
|
import essentialPartQuestionsAndNotShareVinTests from "./0020_EssentialPartQuestionsAndNotShareVin";
|
||||||
import essentialServiceableBigTruckTestCases from "./0022_EssentialServiceableBigTruck";
|
import essentialServiceableBigTruckTestCases from "./0022_EssentialServiceableBigTruck";
|
||||||
import essentialNonServiceableBigTruckTestCases from "./0023_EssentialNonServiceableBigTruck";
|
import essentialNonServiceableBigTruckTestCases from "./0023_EssentialNonServiceableBigTruck";
|
||||||
import essentialNonServiceableBigTruckVinTestCases from "./0024_EssentialNonServiceableBigTruckVin";
|
import essentialNonServiceableBigTruckVinTestCases from "./0024_EssentialNonServiceableBigTruckVin";
|
||||||
|
|
@ -85,7 +85,7 @@ test.describe.parallel('ISS QA Automation Regression', () => {
|
||||||
addSmokeTagToRandomTest(essentialTpaNotEnabledReplace_0017);
|
addSmokeTagToRandomTest(essentialTpaNotEnabledReplace_0017);
|
||||||
addSmokeTagToRandomTest(essentialTpaEnabledReplace_0018);
|
addSmokeTagToRandomTest(essentialTpaEnabledReplace_0018);
|
||||||
addSmokeTagToRandomTest(essentialTpaEnabledReplaceRecal_0019);
|
addSmokeTagToRandomTest(essentialTpaEnabledReplaceRecal_0019);
|
||||||
addSmokeTagToRandomTest(essentialVehicleLookupBailoutTests);
|
addSmokeTagToRandomTest(essentialPartQuestionsAndNotShareVinTests);
|
||||||
addSmokeTagToRandomTest(essentialServiceableBigTruckTestCases);
|
addSmokeTagToRandomTest(essentialServiceableBigTruckTestCases);
|
||||||
addSmokeTagToRandomTest(essentialNonServiceableBigTruckTestCases);
|
addSmokeTagToRandomTest(essentialNonServiceableBigTruckTestCases);
|
||||||
addSmokeTagToRandomTest(essentialNonServiceableBigTruckVinTestCases);
|
addSmokeTagToRandomTest(essentialNonServiceableBigTruckVinTestCases);
|
||||||
|
|
@ -131,7 +131,7 @@ test.describe.parallel('ISS QA Automation Regression', () => {
|
||||||
for (const testCase of essentialUniqueGlassTests) {
|
for (const testCase of essentialUniqueGlassTests) {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine));
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
//Scenario 13 //defect# SSR-2009
|
//Scenario 13
|
||||||
for (const testCase of essentialReplaceTestCases) {
|
for (const testCase of essentialReplaceTestCases) {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine));
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
|
|
@ -160,8 +160,8 @@ test.describe.parallel('ISS QA Automation Regression', () => {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine));
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
//Scenario 20
|
//Scenario 20
|
||||||
for (const testCase of essentialVehicleLookupBailoutTests) {
|
for (const testCase of essentialPartQuestionsAndNotShareVinTests) {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine)); //skipping this until SSR-2004 is fixed
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
// Scenario 22
|
// Scenario 22
|
||||||
for (const testCase of essentialServiceableBigTruckTestCases) {
|
for (const testCase of essentialServiceableBigTruckTestCases) {
|
||||||
|
|
@ -191,7 +191,6 @@ test.describe.parallel('ISS QA Automation Regression', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scenario 0003a
|
// Scenario 0003a
|
||||||
// Note: payment will fail in dev. Payment (PIA) works fine in SYS
|
|
||||||
for (const testCase of advancedScenario0003TestCases) {
|
for (const testCase of advancedScenario0003TestCases) {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine));
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
|
|
@ -256,7 +255,6 @@ test.describe.parallel('ISS QA Automation Regression', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scenario 0016a
|
// Scenario 0016a
|
||||||
// FIXME: Defect was created INSR-2138
|
|
||||||
for (const testCase of advancedScenario0016TestCases) {
|
for (const testCase of advancedScenario0016TestCases) {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine));
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +274,7 @@ test.describe.parallel('ISS QA Automation Regression', () => {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine));
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scenario 0020a : There's a defect open INSR-2149
|
// Scenario 0020a
|
||||||
for (const testCase of advancedScenario0020TestCases) {
|
for (const testCase of advancedScenario0020TestCases) {
|
||||||
test(...prepareTest(testCase, run, options, ruleEngine));
|
test(...prepareTest(testCase, run, options, ruleEngine));
|
||||||
}
|
}
|
||||||
|
|
@ -377,11 +375,11 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
// Destructure data for easy access
|
// Destructure data for easy access
|
||||||
const { customerDetails, claimDetails, vehicleDetails, addressVehicleDetails, vehicleDamage,
|
const { customerDetails, claimDetails, vehicleDetails, addressVehicleDetails, vehicleDamage,
|
||||||
appointmentDetails, isSafelite, endorsements,
|
appointmentDetails, isSafelite, endorsements,
|
||||||
partQuestions, paymentDetails, isNoComp, isItac, isRecalNotification, isUnverifiedPolicyAfterVehicleLookup,
|
partQuestions, paymentDetails, paymentDetailsAdyen, isNoComp, isItac, isRecalNotification, isUnverifiedPolicyAfterVehicleLookup,
|
||||||
isRecalWarning, servicePackage, hasOemEndorsement, hasStateLawPopup, otherVehiclesOnPolicy, isUseVehicleFromAddressLookup,
|
isRecalWarning, servicePackage, hasOemEndorsement, hasStateLawPopup, otherVehiclesOnPolicy, isUseVehicleFromAddressLookup,
|
||||||
isSeparateApptsWarning, vehiclePartQuestions, editVehicleDetails, isAddressLookupValidations,
|
isSeparateApptsWarning, vehiclePartQuestions, editVehicleDetails, isAddressLookupValidations,
|
||||||
hasMilitaryWarning, capabilityQuestions, isUseVehicleOnPolicy,
|
hasMilitaryWarning, capabilityQuestions, isUseVehicleOnPolicy,
|
||||||
isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin, isRecalVehicle } = testCase.testData;
|
isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin, isRecalVehicle, isCanSafeliteRecalibrate, isRepairTPA } = testCase.testData;
|
||||||
|
|
||||||
let { isPolicyFound } = testCase.testData; // Allow isPolicyFound to be re-assigned
|
let { isPolicyFound } = testCase.testData; // Allow isPolicyFound to be re-assigned
|
||||||
|
|
||||||
|
|
@ -573,11 +571,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Click Invalid vin Link', async () => {
|
await test.step('Click Invalid vin Link', async () => {
|
||||||
await vinLookupPage.triggerBailout();
|
await vinLookupPage.returnToVehicleLookupPage();
|
||||||
});
|
|
||||||
|
|
||||||
await test.step('BailoutPage >> Validate Bailout-' + BailoutCode.VehicleNotFound, async () => {
|
|
||||||
await bailoutPage.validateBailoutDetails(customerDetails!, BailoutCode.VehicleNotFound);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -649,14 +643,12 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
|
|
||||||
if (capabilityQuestions && capabilityQuestions.length > 0) {
|
if (capabilityQuestions && capabilityQuestions.length > 0) {
|
||||||
await capabilityQuestionsPage.validateURL(capabilityQuestionsPage.issPageValue);
|
await capabilityQuestionsPage.validateURL(capabilityQuestionsPage.issPageValue);
|
||||||
await capabilityQuestionsPage.validatePartQuestions(capabilityQuestions);
|
|
||||||
await capabilityQuestionsPage.selectPartQuestionResponses(capabilityQuestions);
|
await capabilityQuestionsPage.selectPartQuestionResponses(capabilityQuestions);
|
||||||
await capabilityQuestionsPage.nextPage();
|
await capabilityQuestionsPage.nextPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (partQuestions && partQuestions.length > 0) {
|
if (partQuestions && partQuestions.length > 0) {
|
||||||
await partQuestionsPage.validateURL(partQuestionsPage.issPageValue);
|
await partQuestionsPage.validateURL(partQuestionsPage.issPageValue);
|
||||||
await partQuestionsPage.validatePartQuestions(partQuestions);
|
|
||||||
await partQuestionsPage.selectPartQuestionResponses(partQuestions);
|
await partQuestionsPage.selectPartQuestionResponses(partQuestions);
|
||||||
await partQuestionsPage.nextPage();
|
await partQuestionsPage.nextPage();
|
||||||
}
|
}
|
||||||
|
|
@ -740,7 +732,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await providerPreferencePage.stateLawModalOkayButton.waitFor({ state: 'visible' });
|
await providerPreferencePage.stateLawModalOkayButton.waitFor({ state: 'visible' });
|
||||||
await providerPreferencePage.stateLawModalOkayButton.click();
|
await providerPreferencePage.stateLawModalOkayButton.click();
|
||||||
}).toPass({ timeout: 30000 });
|
}).toPass({ timeout: 60_000 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -796,6 +788,13 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
await providerPreferencePage.scheduleTPAWithoutAdas();
|
await providerPreferencePage.scheduleTPAWithoutAdas();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isSafelite && isRepairTPA) {
|
||||||
|
await test.step('ProviderPreferencePage >> Schedule repair with TPA without Adas', async () => {
|
||||||
|
await providerPreferencePage.validateURL(providerPreferencePage.issPageValue);
|
||||||
|
await providerPreferencePage.scheduleTPAWithoutAdas();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TPA Flow
|
// TPA Flow
|
||||||
if (!isPolicyFound || !(isItac || isNoComp) || isUnverifiedPolicyAfterVehicleLookup) {
|
if (!isPolicyFound || !(isItac || isNoComp) || isUnverifiedPolicyAfterVehicleLookup) {
|
||||||
|
|
@ -837,13 +836,15 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
await test.step('SchedulePage >> Select day and time', async () => {
|
await test.step('SchedulePage >> Select day and time', async () => {
|
||||||
await schedulePage.validateURL(schedulePage.issPageValue);
|
await schedulePage.validateURL(schedulePage.issPageValue);
|
||||||
|
|
||||||
if (appointmentDetails?.serviceLocation === ServiceLocation.Mobile) {
|
if (isCanSafeliteRecalibrate === false) {
|
||||||
await schedulePage.scheduleMobile(appointmentDetails);
|
await schedulePage.validateRecalAcknowledgementModal();
|
||||||
|
await schedulePage.scheduleInShop(appointmentDetails!);
|
||||||
|
} else if (appointmentDetails?.serviceLocation === ServiceLocation.InShop || appointmentDetails?.serviceLocation === ServiceLocation.DropOff) {
|
||||||
|
await schedulePage.scheduleInShop(appointmentDetails!);
|
||||||
|
} else {
|
||||||
|
await schedulePage.scheduleMobile(appointmentDetails!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appointmentDetails?.serviceLocation === ServiceLocation.InShop || appointmentDetails?.serviceLocation === ServiceLocation.DropOff) {
|
|
||||||
await schedulePage.scheduleInShop(appointmentDetails);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -878,7 +879,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
if (isPolicyFound && (isUseVehicleOnPolicy ?? true) && claimDetails!.policyDeductible > 0) {
|
if (isPolicyFound && (isUseVehicleOnPolicy ?? true) && claimDetails!.policyDeductible > 0) {
|
||||||
await test.step('PaymentMethodPage >> Execute Payment', async () => {
|
await test.step('PaymentMethodPage >> Execute Payment', async () => {
|
||||||
await paymentMethodPage.validateURL(paymentMethodPage.issPageValue);
|
await paymentMethodPage.validateURL(paymentMethodPage.issPageValue);
|
||||||
await paymentMethodPage.executePayment(paymentDetails!, claimDetails!, servicePackage!);
|
await paymentMethodPage.executePayment(paymentDetails!, paymentDetailsAdyen!, claimDetails!, servicePackage!);
|
||||||
await paymentMethodPage.nextPage();
|
await paymentMethodPage.nextPage();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,31 @@
|
||||||
import ClientData from "@business-logic/data/ClientData";
|
import ClientData from "@business-logic/data/ClientData";
|
||||||
import TestCase from "@business-logic/types/TestCase";
|
import TestCase from "@business-logic/types/TestCase";
|
||||||
import { DamageType, ServiceLocation, ServicePackage, VehicleDamage, VehicleLookupType } from "@business-logic/types/Enums";
|
import { DamageType, ServiceLocation, ServicePackage, VehicleDamage, VehicleLookupType, PartQuestionType } from "@business-logic/types/Enums";
|
||||||
import { ITestData } from "@business-logic/types/ITestData"
|
import { ITestData } from "@business-logic/types/ITestData"
|
||||||
import { faker } from "@faker-js/faker";
|
import { faker } from "@faker-js/faker";
|
||||||
import { getNextWeekday } from "@impl/utils/DateUtils";
|
import { getNextWeekday } from "@impl/utils/DateUtils";
|
||||||
|
|
||||||
const nextWeekday = getNextWeekday();
|
const nextWeekday = getNextWeekday();
|
||||||
|
|
||||||
const essentialVehicleLookupBailoutData: Partial<ITestData> = {
|
const essentialPartQuestionsAndNotShareVinData: Partial<ITestData> = {
|
||||||
clientTag: 'ALL_ESSENTIAL',
|
clientTag: 'ALL_ESSENTIAL',
|
||||||
isDuplicateClaim: false,
|
isDuplicateClaim: false,
|
||||||
isPolicyFound: false,
|
isPolicyFound: false,
|
||||||
endorsements: [],
|
endorsements: [],
|
||||||
isReplace: false,
|
isReplace: false,
|
||||||
partQuestions: undefined,
|
partQuestions: [
|
||||||
|
{
|
||||||
|
partQuestionType: PartQuestionType.GeneralQuestion1,
|
||||||
|
isOnPage: true,
|
||||||
|
optionToSelect: 'Yes'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
partQuestionType: PartQuestionType.GeneralQuestion2,
|
||||||
|
isOnPage: true,
|
||||||
|
optionToSelect: 'Yes'
|
||||||
|
}
|
||||||
|
],
|
||||||
isSafelite: true,
|
isSafelite: true,
|
||||||
bailoutFlags: {
|
|
||||||
isVehicleLookupBailout: true
|
|
||||||
},
|
|
||||||
servicePackage: faker.helpers.enumValue(ServicePackage),
|
servicePackage: faker.helpers.enumValue(ServicePackage),
|
||||||
customerDetails: {
|
customerDetails: {
|
||||||
firstName: faker.person.firstName(),
|
firstName: faker.person.firstName(),
|
||||||
|
|
@ -43,19 +51,10 @@ const essentialVehicleLookupBailoutData: Partial<ITestData> = {
|
||||||
year: '2020',
|
year: '2020',
|
||||||
make: 'BMW',
|
make: 'BMW',
|
||||||
model: '740',
|
model: '740',
|
||||||
style: '4 door sedan' // TODO: Check correctness of vehicle style
|
style: '4 door sedan',
|
||||||
|
vehicleLookupType: VehicleLookupType.RatherNotShareVin,
|
||||||
},
|
},
|
||||||
vehicleDamage: [
|
vehicleDamage: [VehicleDamage.WindshieldCrack],
|
||||||
// VehicleDamage.WindshieldThreeChips,
|
|
||||||
VehicleDamage.WindshieldCrack,
|
|
||||||
// VehicleDamage.DriverFrontDoor,
|
|
||||||
// VehicleDamage.DriverQuarterPanel,
|
|
||||||
// VehicleDamage.DriverRearDoor,
|
|
||||||
// VehicleDamage.PassengerFrontDoor,
|
|
||||||
// VehicleDamage.PassengerQuarterPanel,
|
|
||||||
// VehicleDamage.PassengerRearDoor,
|
|
||||||
// VehicleDamage.RearWindow
|
|
||||||
],
|
|
||||||
appointmentDetails: {
|
appointmentDetails: {
|
||||||
serviceLocation: ServiceLocation.InShop,
|
serviceLocation: ServiceLocation.InShop,
|
||||||
shopAddress: '6826 Sawmill Rd, Columbus, OH 43235',
|
shopAddress: '6826 Sawmill Rd, Columbus, OH 43235',
|
||||||
|
|
@ -65,17 +64,17 @@ const essentialVehicleLookupBailoutData: Partial<ITestData> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const essentialClients = ClientData.getEssentialClients();
|
const essentialClients = ClientData.getEssentialClients();
|
||||||
const essentialVehicleLookupBailoutTests: TestCase[] = [];
|
const essentialPartQuestionsAndNotShareVinTests: TestCase[] = [];
|
||||||
for (const client of essentialClients) {
|
for (const client of essentialClients) {
|
||||||
const data = {...essentialVehicleLookupBailoutData};
|
const data = {...essentialPartQuestionsAndNotShareVinData};
|
||||||
data.clientTag = client.clientTag;
|
data.clientTag = client.clientTag;
|
||||||
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
|
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
|
||||||
const tc = new TestCase({
|
const tc = new TestCase({
|
||||||
name: `0020 Essential Vehicle Lookup Bailout Client: "${client.accountName}"`,
|
name: `0020 Essential Part Questions and Not Share Vin Client: "${client.accountName}"`,
|
||||||
tags: [`@${client.clientTag}`, `@${client.accountName}`, '@Bailout', '@VehicleLookup', '@Essentials'],
|
tags: [`@${client.clientTag}`, `@${client.accountName}`, '@VehicleLookup', '@Essentials'],
|
||||||
testData: data
|
testData: data
|
||||||
}, undefined, '0020');
|
}, undefined, '0020');
|
||||||
essentialVehicleLookupBailoutTests.push(tc);
|
essentialPartQuestionsAndNotShareVinTests.push(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default essentialVehicleLookupBailoutTests;
|
export default essentialPartQuestionsAndNotShareVinTests;
|
||||||
|
|
@ -13,9 +13,6 @@ const essentialServiceableBigTruckData: Partial<ITestData> = {
|
||||||
isPolicyFound: false,
|
isPolicyFound: false,
|
||||||
endorsements: [],
|
endorsements: [],
|
||||||
isReplace: true,
|
isReplace: true,
|
||||||
bailoutFlags: {
|
|
||||||
isHeavyTruckVehicleBailout: true,
|
|
||||||
},
|
|
||||||
vehiclePartQuestions: [
|
vehiclePartQuestions: [
|
||||||
{
|
{
|
||||||
partQuestionType: PartQuestionType.WindshieldColor,
|
partQuestionType: PartQuestionType.WindshieldColor,
|
||||||
|
|
@ -24,6 +21,7 @@ const essentialServiceableBigTruckData: Partial<ITestData> = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
isSafelite: true,
|
isSafelite: true,
|
||||||
|
isCanSafeliteRecalibrate: false,
|
||||||
servicePackage: faker.helpers.enumValue(ServicePackage),
|
servicePackage: faker.helpers.enumValue(ServicePackage),
|
||||||
customerDetails: {
|
customerDetails: {
|
||||||
firstName: faker.person.firstName(),
|
firstName: faker.person.firstName(),
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ const advancedScenario0001Data: Partial<ITestData> = {
|
||||||
shopAddress: undefined,
|
shopAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultCreditCardDetails()
|
paymentDetailsAdyen: ClientData.getCreditCardDetailsAdyen()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add validation for deductible/covered amount
|
// TODO: Add validation for deductible/covered amount
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ const advancedScenario0002Data: Partial<ITestData> = {
|
||||||
shopAddress: undefined,
|
shopAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultPaypalDetails()
|
paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ const advancedScenario0003Data: Partial<ITestData> = {
|
||||||
serviceAddress: customerAddress,
|
serviceAddress: customerAddress,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultAfterpayDetails()
|
paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,20 +33,8 @@ const advancedScenario0008Data: Partial<ITestData> = {
|
||||||
isDuplicateClaim: false,
|
isDuplicateClaim: false,
|
||||||
isPolicyFound: true,
|
isPolicyFound: true,
|
||||||
isNoComp: false,
|
isNoComp: false,
|
||||||
hasStateLawPopup: true,
|
hasStateLawPopup: false,
|
||||||
endorsements: undefined,
|
isRepairTPA: true,
|
||||||
vehiclePartQuestions: [
|
|
||||||
// {
|
|
||||||
// partQuestionType: PartQuestionType.WindshieldColor,
|
|
||||||
// isOnPage: true,
|
|
||||||
// optionToSelect: 'Green Tint'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// partQuestionType: PartQuestionType.PassengerRearColor,
|
|
||||||
// isOnPage: true,
|
|
||||||
// optionToSelect: 'Green Tint'
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
isSafelite: false,
|
isSafelite: false,
|
||||||
servicePackage: faker.helpers.enumValue(ServicePackage),
|
servicePackage: faker.helpers.enumValue(ServicePackage),
|
||||||
customerDetails: customerDetails,
|
customerDetails: customerDetails,
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ const advancedScenario0010Data: Partial<ITestData> = {
|
||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
isSafelite: true,
|
isSafelite: true,
|
||||||
servicePackage: faker.helpers.enumValue(ServicePackage),
|
servicePackage: ServicePackage.Premium,
|
||||||
customerDetails: customerDetails,
|
customerDetails: customerDetails,
|
||||||
claimDetails: {
|
claimDetails: {
|
||||||
policyNumber: policyNumber,
|
policyNumber: policyNumber,
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ const advancedScenario0011Data: Partial<ITestData> = {
|
||||||
shopAddress: undefined,
|
shopAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultPaypalDetails()
|
paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ const advancedScenario0012Data: Partial<ITestData> = {
|
||||||
],
|
],
|
||||||
partQuestions: undefined,
|
partQuestions: undefined,
|
||||||
isSafelite: true,
|
isSafelite: true,
|
||||||
servicePackage: faker.helpers.enumValue(ServicePackage),
|
servicePackage: ServicePackage.GlassOnly,
|
||||||
customerDetails: customerDetails,
|
customerDetails: customerDetails,
|
||||||
claimDetails: {
|
claimDetails: {
|
||||||
policyNumber: policyNumber,
|
policyNumber: policyNumber,
|
||||||
|
|
@ -68,7 +68,7 @@ const advancedScenario0012Data: Partial<ITestData> = {
|
||||||
shopAddress: undefined,
|
shopAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultAfterpayDetails()
|
paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ const advancedScenario0014Data: Partial<ITestData> = {
|
||||||
alternateServiceZip: '43016',
|
alternateServiceZip: '43016',
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultAfterpayDetails()
|
paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ const advancedScenario0016Data: Partial<ITestData> = {
|
||||||
serviceAddress: undefined,
|
serviceAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultPaypalDetails()
|
paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ const advancedScenario0018Data: Partial<ITestData> = {
|
||||||
shopAddress: undefined,
|
shopAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultAfterpayDetails()
|
paymentDetailsAdyen: ClientData.getAfterpayDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ const advancedScenario0019Data: Partial<ITestData> = {
|
||||||
serviceAddress: customerAddress,
|
serviceAddress: customerAddress,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultPaypalDetails()
|
paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ const advancedScenario0028aData: Partial<ITestData> = {
|
||||||
serviceAddress: customerAddress,
|
serviceAddress: customerAddress,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultCreditCardDetails()
|
paymentDetailsAdyen: ClientData.getCreditCardDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ const advancedScenario0030aData: Partial<ITestData> = {
|
||||||
serviceAddress: customerAddress,
|
serviceAddress: customerAddress,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultCreditCardDetails()
|
paymentDetailsAdyen: ClientData.getCreditCardDetailsAdyen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const advancedScenario0031Data: Partial<ITestData> = {
|
||||||
isDuplicateClaim: false,
|
isDuplicateClaim: false,
|
||||||
isPolicyFound: true,
|
isPolicyFound: true,
|
||||||
isNoComp: false,
|
isNoComp: false,
|
||||||
|
isCanSafeliteRecalibrate: false,
|
||||||
hasStateLawPopup: false,
|
hasStateLawPopup: false,
|
||||||
endorsements: undefined,
|
endorsements: undefined,
|
||||||
vehiclePartQuestions: [
|
vehiclePartQuestions: [
|
||||||
|
|
@ -65,7 +66,7 @@ const advancedScenario0031Data: Partial<ITestData> = {
|
||||||
shopAddress: undefined,
|
shopAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultPaypalDetails()//ClientData.getDefaultCreditCardDetails()
|
paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add validation for deductible/covered amount
|
// TODO: Add validation for deductible/covered amount
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ const advancedScenario0032Data: Partial<ITestData> = {
|
||||||
shopAddress: undefined,
|
shopAddress: undefined,
|
||||||
appointmentDate: nextWeekday
|
appointmentDate: nextWeekday
|
||||||
},
|
},
|
||||||
paymentDetails: ClientData.getDefaultPaypalDetails(),//ClientData.getDefaultCreditCardDetails()
|
paymentDetailsAdyen: ClientData.getPaypalDetailsAdyen(),
|
||||||
isNonServiceable: true,
|
isNonServiceable: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,21 @@
|
||||||
"settings": {
|
"settings": {
|
||||||
"DisplayPIAInsurance": "true"
|
"DisplayPIAInsurance": "true"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"universeName": "NextGenAdyenPaymentTest",
|
||||||
|
"universeId": 848,
|
||||||
|
"testName": "NextGenAdyenPaymentIntegration_V1",
|
||||||
|
"testId": 727,
|
||||||
|
"variationName": "YesShowAdyenPaymentIntergration_V1_TEST",
|
||||||
|
"variationId": 1855,
|
||||||
|
"isActive": true,
|
||||||
|
"isExposed": true,
|
||||||
|
"userPartitionNumber": 26,
|
||||||
|
"assignmentId": 16698635,
|
||||||
|
"settings": {
|
||||||
|
"ISS_Enable_Adyen_V1": "true"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -14,6 +14,21 @@
|
||||||
"settings": {
|
"settings": {
|
||||||
"DisplayPIAInsurance": "true"
|
"DisplayPIAInsurance": "true"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"universeName": "NextGenAdyenPaymentTest",
|
||||||
|
"universeId": 848,
|
||||||
|
"testName": "NextGenAdyenPaymentIntegration_V1",
|
||||||
|
"testId": 727,
|
||||||
|
"variationName": "YesShowAdyenPaymentIntergration_V1_TEST",
|
||||||
|
"variationId": 1855,
|
||||||
|
"isActive": true,
|
||||||
|
"isExposed": true,
|
||||||
|
"userPartitionNumber": 26,
|
||||||
|
"assignmentId": 16698635,
|
||||||
|
"settings": {
|
||||||
|
"ISS_Enable_Adyen_V1": "true"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
import packageNames from '@/constants/package-names';
|
||||||
|
import { paymentMethods } from '@/constants/payment-method-constants';
|
||||||
|
|
||||||
const analyticsPageEvents = Object.freeze({
|
const analyticsPageEvents = Object.freeze({
|
||||||
ENTRY: 'ENTRY',
|
ENTRY: 'ENTRY',
|
||||||
EVENT: 'EVENT'
|
EVENT: 'EVENT'
|
||||||
|
|
@ -40,4 +43,18 @@ const ValueToLogTypes = Object.freeze({
|
||||||
LAST_5: 'last_5'
|
LAST_5: 'last_5'
|
||||||
});
|
});
|
||||||
|
|
||||||
export { analyticsPageEvents, GaCategories, GaActions, GaLabels, GaEvents, ValueToLogTypes };
|
const analyticsPaymentTypeMap = new Map([
|
||||||
|
[paymentMethods.AFTERPAY, 'after_pay'],
|
||||||
|
[paymentMethods.CREDIT_CARD, 'credit_card'],
|
||||||
|
[paymentMethods.PAY_AT_TIME_OF_SERVICE, 'pay_at_service'],
|
||||||
|
[paymentMethods.PAYPAL, 'pay_pal'],
|
||||||
|
[paymentMethods.APPLEPAY, 'apple_pay'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const analyticsServicePackageMap = new Map([
|
||||||
|
[packageNames.TIER_ONE, 'basic'],
|
||||||
|
[packageNames.TIER_TWO, 'essentials'],
|
||||||
|
[packageNames.TIER_THREE, 'essentialsplus']
|
||||||
|
]);
|
||||||
|
|
||||||
|
export { analyticsPageEvents, GaCategories, GaActions, GaLabels, GaEvents, ValueToLogTypes, analyticsPaymentTypeMap, analyticsServicePackageMap };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import applicationConfig from './application-config';
|
|
||||||
|
|
||||||
const ACCOUNT_BASE_URL = '/account/api/v1/account';
|
const ACCOUNT_BASE_URL = '/account/api/v1/account';
|
||||||
const ANALYTICS_BASE_URL = '/analytics/api/v1/analytics';
|
const ANALYTICS_BASE_URL = '/analytics/api/v1/analytics';
|
||||||
const CLIENT_AUTH_BASE_URL = '/clientauth/api/v1/clientauth';
|
const CLIENT_AUTH_BASE_URL = '/clientauth/api/v1/clientauth';
|
||||||
|
|
@ -8,19 +6,13 @@ const COVERAGE_BASE_URL = '/coverage/api/v1/coverage';
|
||||||
const EXPERIMENTS_BASE_URL = '/experiments/api/v1/experiments';
|
const EXPERIMENTS_BASE_URL = '/experiments/api/v1/experiments';
|
||||||
const LOCATION_BASE_URL = '/location/api/v1/location';
|
const LOCATION_BASE_URL = '/location/api/v1/location';
|
||||||
const ORDER_BASE_URL = '/order/api/v1/order';
|
const ORDER_BASE_URL = '/order/api/v1/order';
|
||||||
const PARTS_BASE_URL = '/parts/api/v2/parts';
|
|
||||||
const PARTS_V1_BASE_URL = '/parts/api/v1/parts';
|
const PARTS_V1_BASE_URL = '/parts/api/v1/parts';
|
||||||
|
const PARTS_V2_BASE_URL = '/parts/api/v2/parts';
|
||||||
const PRICE_BASE_URL = '/price/api/v1/price';
|
const PRICE_BASE_URL = '/price/api/v1/price';
|
||||||
const SCHEDULE_BASE_URL = '/schedule/api/v1/schedule';
|
const SCHEDULE_BASE_URL = '/schedule/api/v1/schedule';
|
||||||
const VEHICLE_BASE_URL = '/vehicle/api/v1/vehicle';
|
const VEHICLE_BASE_URL = '/vehicle/api/v1/vehicle';
|
||||||
const PAYMENT_BASE_URL = '/payment/api/v1/payment';
|
const PAYMENT_BASE_URL = '/payment/api/v1/payment';
|
||||||
|
|
||||||
const isLocalOrDev = (() => {
|
|
||||||
const currentEnv = (applicationConfig?.CURRENT_ENVIRONMENT || '').toLowerCase();
|
|
||||||
return currentEnv === 'localhost' || currentEnv === 'dev';
|
|
||||||
})();
|
|
||||||
const PARTS_EFFECTIVE_BASE_URL = isLocalOrDev ? PARTS_BASE_URL : PARTS_V1_BASE_URL;
|
|
||||||
|
|
||||||
const endpoints = Object.freeze({
|
const endpoints = Object.freeze({
|
||||||
GetRouteInfo: {
|
GetRouteInfo: {
|
||||||
url: (applicationAbbreviation) => `${CONTENT_BASE_URL}/${applicationAbbreviation}/RouteInfo`,
|
url: (applicationAbbreviation) => `${CONTENT_BASE_URL}/${applicationAbbreviation}/RouteInfo`,
|
||||||
|
|
@ -51,7 +43,7 @@ const endpoints = Object.freeze({
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
GetMobilePremiumFee: {
|
GetMobilePremiumFee: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/mobile-premium-fee`,
|
url: `${PARTS_V1_BASE_URL}/mobile-premium-fee`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetVehicleYears: {
|
GetVehicleYears: {
|
||||||
|
|
@ -71,15 +63,15 @@ const endpoints = Object.freeze({
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetDamageOptions: {
|
GetDamageOptions: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/damage-options`,
|
url: `${PARTS_V1_BASE_URL}/damage-options`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetPartsOrQuestions: {
|
GetPartsOrQuestions: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/parts-or-questions`,
|
url: `${PARTS_V1_BASE_URL}/parts-or-questions`,
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
GetParts: {
|
GetParts: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/parts`,
|
url: `${PARTS_V1_BASE_URL}/parts`,
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
GetITACPriceOrderItems: {
|
GetITACPriceOrderItems: {
|
||||||
|
|
@ -108,19 +100,19 @@ const endpoints = Object.freeze({
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetCapabilityQuestions: {
|
GetCapabilityQuestions: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/capability-questions`,
|
url: `${PARTS_V1_BASE_URL}/capability-questions`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetPartFromCapabilityAnswer: {
|
GetPartFromCapabilityAnswer: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/part-from-capability-answer`,
|
url: `${PARTS_V1_BASE_URL}/part-from-capability-answer`,
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
GetWipers: {
|
GetWipers: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/wipers`,
|
url: `${PARTS_V1_BASE_URL}/wipers`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetRainDefense: {
|
GetRainDefense: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/rain-repel`,
|
url: `${PARTS_V1_BASE_URL}/rain-repel`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetRecalParts: {
|
GetRecalParts: {
|
||||||
|
|
@ -132,19 +124,19 @@ const endpoints = Object.freeze({
|
||||||
zipCode,
|
zipCode,
|
||||||
applicationName,
|
applicationName,
|
||||||
referralSequenceNumber
|
referralSequenceNumber
|
||||||
) => `${PARTS_EFFECTIVE_BASE_URL}/recal-parts/${carId}/${partNumber}/${recalibrationType}/${parentAccountNumber}/${zipCode}/${applicationName}/${referralSequenceNumber}`,
|
) => `${PARTS_V1_BASE_URL}/recal-parts/${carId}/${partNumber}/${recalibrationType}/${parentAccountNumber}/${zipCode}/${applicationName}/${referralSequenceNumber}`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetGlassFees: {
|
GetGlassFees: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/glass-fees`,
|
url: `${PARTS_V1_BASE_URL}/glass-fees`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetSupportingItems: {
|
GetSupportingItems: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/supporting-items`,
|
url: `${PARTS_V1_BASE_URL}/supporting-items`,
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
GetMobileFeePart: {
|
GetMobileFeePart: {
|
||||||
url: `${PARTS_EFFECTIVE_BASE_URL}/mobile-fee`,
|
url: `${PARTS_V2_BASE_URL}/mobile-fee`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
},
|
},
|
||||||
GetServiceabilityDetails: {
|
GetServiceabilityDetails: {
|
||||||
|
|
|
||||||
|
|
@ -86,3 +86,17 @@ export function getPropertyCaseInsensitive(obj, property) {
|
||||||
while (prop = props.pop()) if (prop.toLowerCase() === property.toLowerCase()) return prop;
|
while (prop = props.pop()) if (prop.toLowerCase() === property.toLowerCase()) return prop;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
|
||||||
|
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
||||||
|
if (!arrayOfObjects) return null;
|
||||||
|
|
||||||
|
return arrayOfObjects.sort((a, b) => {
|
||||||
|
if (a[propertyName] < b[propertyName]) return -1;
|
||||||
|
if (a[propertyName] > b[propertyName]) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import partTypeStrings from '@/constants/part-type-strings';
|
import partTypeStrings from '@/constants/part-type-strings';
|
||||||
import { deepClone } from '@/helpers/object-helper';
|
import { deepClone, getNonFalseValuesOfPropertyInArrayOfObjects } from '@/helpers/object-helper';
|
||||||
|
|
||||||
const recalPartTypes = [partTypeStrings.RECALIBRATION, partTypeStrings.ADAS_RECALIBRATION];
|
const recalPartTypes = [partTypeStrings.RECALIBRATION, partTypeStrings.ADAS_RECALIBRATION];
|
||||||
|
|
||||||
|
|
@ -73,6 +73,31 @@ export function containsRecalParts(lineItems) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isRecalOrder(lineItems) {
|
||||||
|
return (containsRecalParts(lineItems) && getHasRecalibrationPart(lineItems));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getHasRecalibrationPart(lineItems) {
|
||||||
|
const hasRequiresRecalibration = getNonFalseValuesOfPropertyInArrayOfObjects(lineItems.glassParts, 'requiresRecalibration')?.length > 0;
|
||||||
|
const hasRecalibrationType = getNonFalseValuesOfPropertyInArrayOfObjects(lineItems.glassParts, 'recalibrationType')?.length > 0;
|
||||||
|
|
||||||
|
if (hasRequiresRecalibration) {
|
||||||
|
if (hasRecalibrationType) {
|
||||||
|
// Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType'
|
||||||
|
return (
|
||||||
|
getNonFalseValuesOfPropertyInArrayOfObjects(
|
||||||
|
lineItems.glassParts,
|
||||||
|
'recalibrationType'
|
||||||
|
)[0].toLowerCase() !== 'unknown'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Has 'requiresRecalibration' but no 'recalibrationType' at all
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Does not have 'requiresRecalibration'
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
export function anyPartWithRequiresRecalFlag(lineItems) {
|
export function anyPartWithRequiresRecalFlag(lineItems) {
|
||||||
if (!lineItems) {
|
if (!lineItems) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import coverageType from '@/constants/coverage-type';
|
||||||
import { deepClone } from '@/helpers/object-helper';
|
import { deepClone } from '@/helpers/object-helper';
|
||||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||||
import { paymentMethods } from '@/constants/payment-method-constants';
|
import { paymentMethods } from '@/constants/payment-method-constants';
|
||||||
|
import partTypeStrings from '@/constants/part-type-strings';
|
||||||
|
import packageNames from '@/constants/package-names';
|
||||||
|
|
||||||
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
|
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
|
||||||
|
|
||||||
|
|
@ -27,7 +29,9 @@ jest.mock('@/helpers/cms-content-helper', () => ({
|
||||||
const mockMixin = {
|
const mockMixin = {
|
||||||
methods: {
|
methods: {
|
||||||
getCmsContent: jest.fn(),
|
getCmsContent: jest.fn(),
|
||||||
setCmsContent: jest.fn()
|
setCmsContent: jest.fn(),
|
||||||
|
savePageDataToStore: jest.fn(),
|
||||||
|
pushEventToGA: jest.fn()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -152,7 +156,8 @@ const sessionStorage = {
|
||||||
currentDeductible: {
|
currentDeductible: {
|
||||||
replace: 100,
|
replace: 100,
|
||||||
repair: 0
|
repair: 0
|
||||||
}
|
},
|
||||||
|
isUnverified: false
|
||||||
};
|
};
|
||||||
|
|
||||||
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}, mixin = mockMixin) {
|
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}, mixin = mockMixin) {
|
||||||
|
|
@ -778,7 +783,8 @@ describe('OrderConfirmation.vue', () => {
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}),
|
}),
|
||||||
setCmsContent: jest.fn()
|
setCmsContent: jest.fn(),
|
||||||
|
savePageDataToStore: jest.fn()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -827,7 +833,8 @@ describe('OrderConfirmation.vue', () => {
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}),
|
}),
|
||||||
setCmsContent: jest.fn()
|
setCmsContent: jest.fn(),
|
||||||
|
savePageDataToStore: jest.fn()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -955,6 +962,251 @@ describe('OrderConfirmation.vue', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('Methods', () => {
|
describe('Methods', () => {
|
||||||
|
describe('handleAnalyticsEvents', () => {
|
||||||
|
let mixin;
|
||||||
|
beforeEach(() => {
|
||||||
|
mixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn(),
|
||||||
|
setCmsContent: jest.fn(),
|
||||||
|
savePageDataToStore: jest.fn(),
|
||||||
|
pushEventToGA: jest.fn()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA with confirmation event for mobile repair', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE;
|
||||||
|
order.damage.isRepair = true;
|
||||||
|
order.isVerified = false;
|
||||||
|
order.isMobileAppointment = true;
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('confirmation', 'safelite', expect.stringContaining('mobile'), true);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA with confirmation event for in-shop replace', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP;
|
||||||
|
order.damage.isRepair = false;
|
||||||
|
order.isVerified = true;
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('confirmation', 'safelite', expect.stringContaining('replace'), true);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for payment PIA successful when payment.isPayInAdvance is true', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.payment.isPayInAdvance = true;
|
||||||
|
order.payment.paymentMethod = paymentMethods.CREDIT_CARD;
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('payment_page', 'pia_successful', expect.any(String), true);
|
||||||
|
});
|
||||||
|
test('should not call pushEventToGA for PIA when payment.isPayInAdvance is false', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.payment.isPayInAdvance = false;
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const paymentPageCalls = mixin.methods.pushEventToGA.mock.calls.filter(call => call[0] === 'payment_page');
|
||||||
|
expect(paymentPageCalls.length).toBe(0);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for service package when submittedOrder.servicePackage exists', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.servicePackage = packageNames.TIER_ONE;
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('service_package', 'package_purchased', expect.any(String), true);
|
||||||
|
});
|
||||||
|
test('should not call pushEventToGA for service package when submittedOrder.servicePackage is null', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.servicePackage = null;
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const servicePackageCalls = mixin.methods.pushEventToGA.mock.calls.filter(call => call[0] === 'service_package');
|
||||||
|
expect(servicePackageCalls.length).toBe(0);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for total price when isFirstLoad is true and cart total greater than 0', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
const expectedTotal = 100;
|
||||||
|
order.lineItems.glassParts = [{ partType: 'WINDSHIELD', sellingPrice: expectedTotal }];
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.handleAnalyticsEvents(true);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('total_price', expectedTotal.toString(), expect.any(String), true);
|
||||||
|
});
|
||||||
|
test('should not call pushEventToGA for total price when isFirstLoad is false', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
const expectedTotal = 100;
|
||||||
|
order.lineItems.glassParts = [{ partType: 'WINDSHIELD', sellingPrice: expectedTotal }];
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
useMainStore().pageData = jest.fn().mockReturnValue({ isFirstLoad: false });
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const totalPriceCalls = mixin.methods.pushEventToGA.mock.calls.filter(call => call[0] === 'total_price');
|
||||||
|
expect(totalPriceCalls.length).toBe(0);
|
||||||
|
});
|
||||||
|
test('should not call pushEventToGA for total price when cart total is 0', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
const expectedTotal = 0;
|
||||||
|
order.lineItems.glassParts = [{ partType: 'WINDSHIELD', sellingPrice: 0 }];
|
||||||
|
order.insuranceCoverage.coverageType = coverageType.ITAC;
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const totalPriceCalls = mixin.methods.pushEventToGA.mock.calls.filter(call => call[0] === 'total_price');
|
||||||
|
expect(totalPriceCalls.length).toBe(0);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for rain defense purchased when hasRainRepel is true', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.lineItems.vaps = [{ partType: partTypeStrings.RAIN_DEFENSE }];
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('rain_defense', 'purchased', expect.any(String), true);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for rain defense no_purchase when hasRainRepel is false', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.lineItems.vaps = [];
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('rain_defense', 'no_purchase', expect.any(String), true);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for visitor_info_confirmation with ClientSite referring_site', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('visitor_info_confirmation', 'referring_site', 'ClientSite', true);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for visitor_info_confirmation with client_name', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('visitor_info_confirmation', 'client_name', expect.any(String), true);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for wipers purchased when hasWipers is true', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.lineItems.vaps = [{ partType: partTypeStrings.FRONT_WIPER }];
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const mixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn().mockReturnValue([{ Text: 'Front Beam' }]),
|
||||||
|
setCmsContent: jest.fn(),
|
||||||
|
savePageDataToStore: jest.fn(),
|
||||||
|
pushEventToGA: jest.fn()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('wipers', 'purchased', expect.any(String), true);
|
||||||
|
});
|
||||||
|
test('should call pushEventToGA for wipers no_purchase when hasWipers is false', () => {
|
||||||
|
// Arrange
|
||||||
|
const order = deepClone(sessionStorage);
|
||||||
|
order.lineItems.vaps = [];
|
||||||
|
const mockStoreActions = () => {
|
||||||
|
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
|
||||||
|
|
||||||
|
// handleAnalyticsEvents is called on mount, no need to act
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mixin.methods.pushEventToGA).toHaveBeenCalledWith('wipers', 'no_purchase', 'none_none', true);
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('formatDate', () => {
|
describe('formatDate', () => {
|
||||||
test.each([
|
test.each([
|
||||||
['Wednesday, April 22, 2020', '2020-04-22'],
|
['Wednesday, April 22, 2020', '2020-04-22'],
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
:isRepair="isRepair" />
|
:isRepair="isRepair" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="displayWipers"
|
v-if="hasWipers"
|
||||||
class="wiper-details confirmation-section">
|
class="wiper-details confirmation-section">
|
||||||
<span class="wipers-title">{{ wipersTitle }}</span>
|
<span class="wipers-title">{{ wipersTitle }}</span>
|
||||||
<span
|
<span
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
class="wipers-body">{{ description }}</span>
|
class="wipers-body">{{ description }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="displayRainRepel"
|
v-if="hasRainRepel"
|
||||||
class="rain-repel-details confirmation-section">
|
class="rain-repel-details confirmation-section">
|
||||||
<span class="rain-repel-title">{{ rainRepelTitle }}</span>
|
<span class="rain-repel-title">{{ rainRepelTitle }}</span>
|
||||||
<span class="rain-repel-body">{{ rainRepelBody }}</span>
|
<span class="rain-repel-body">{{ rainRepelBody }}</span>
|
||||||
|
|
@ -135,6 +135,10 @@ import widgetFields from '@/constants/cms-widget-fields.js';
|
||||||
import { getGlassList } from '@/helpers/damage-helper';
|
import { getGlassList } from '@/helpers/damage-helper';
|
||||||
import partTypeStrings from '@/constants/part-type-strings';
|
import partTypeStrings from '@/constants/part-type-strings';
|
||||||
import coverageType from '@/constants/coverage-type';
|
import coverageType from '@/constants/coverage-type';
|
||||||
|
import { analyticsPaymentTypeMap, analyticsServicePackageMap } from '@/constants/analytics';
|
||||||
|
import { containsRecalParts } from '@/helpers/recal-helper';
|
||||||
|
import issPageValues from '@/router/router-constants/issPage-values';
|
||||||
|
import { getCartTotal } from '@/helpers/cart-helper';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'order-confirmation',
|
name: 'order-confirmation',
|
||||||
|
|
@ -199,6 +203,7 @@ export default {
|
||||||
hasRecalibrationPart,
|
hasRecalibrationPart,
|
||||||
referralNumber: referralNumber?.toString(),
|
referralNumber: referralNumber?.toString(),
|
||||||
isNoComp: this.submittedOrder.insuranceCoverage.coverageType === coverageType.NO_COMP,
|
isNoComp: this.submittedOrder.insuranceCoverage.coverageType === coverageType.NO_COMP,
|
||||||
|
isITAC: this.submittedOrder.insuranceCoverage.coverageType === coverageType.ITAC,
|
||||||
widgets: {
|
widgets: {
|
||||||
siteHeader: 'SiteHeaderWidget',
|
siteHeader: 'SiteHeaderWidget',
|
||||||
emailConfirmation: 'EmailConfirmationWordingWidget',
|
emailConfirmation: 'EmailConfirmationWordingWidget',
|
||||||
|
|
@ -418,10 +423,16 @@ export default {
|
||||||
// Temporarily set return true to see cart in localhost or dev environment
|
// Temporarily set return true to see cart in localhost or dev environment
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
displayWipers() {
|
hasWipers() {
|
||||||
const hasWiperPart = this.submittedOrder.lineItems.vaps.some((part) => part.partType.toLowerCase().includes('wiper'));
|
const hasWiperPart = this.submittedOrder.lineItems.vaps.some((part) => part.partType.toLowerCase().includes('wiper'));
|
||||||
return hasWiperPart;
|
return hasWiperPart;
|
||||||
},
|
},
|
||||||
|
hasFrontWiper() {
|
||||||
|
return this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.FRONT_WIPER);
|
||||||
|
},
|
||||||
|
hasRearWiper() {
|
||||||
|
return this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.REAR_WIPER);
|
||||||
|
},
|
||||||
wipersTitle() {
|
wipersTitle() {
|
||||||
return this.getCmsContent(
|
return this.getCmsContent(
|
||||||
this.widgets.wipersText,
|
this.widgets.wipersText,
|
||||||
|
|
@ -431,13 +442,10 @@ export default {
|
||||||
wipersBody() {
|
wipersBody() {
|
||||||
const wiperTypesOnOrder = [];
|
const wiperTypesOnOrder = [];
|
||||||
|
|
||||||
const hasFrontWiper = this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.FRONT_WIPER);
|
if (this.hasFrontWiper) {
|
||||||
const hasRearWiper = this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.REAR_WIPER);
|
|
||||||
|
|
||||||
if (hasFrontWiper) {
|
|
||||||
wiperTypesOnOrder.push(partTypeStrings.FRONT_WIPER);
|
wiperTypesOnOrder.push(partTypeStrings.FRONT_WIPER);
|
||||||
}
|
}
|
||||||
if (hasRearWiper) {
|
if (this.hasRearWiper) {
|
||||||
wiperTypesOnOrder.push(partTypeStrings.REAR_WIPER);
|
wiperTypesOnOrder.push(partTypeStrings.REAR_WIPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -447,7 +455,7 @@ export default {
|
||||||
|
|
||||||
return wiperDescriptions;
|
return wiperDescriptions;
|
||||||
},
|
},
|
||||||
displayRainRepel() {
|
hasRainRepel() {
|
||||||
return this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.RAIN_DEFENSE);
|
return this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.RAIN_DEFENSE);
|
||||||
},
|
},
|
||||||
rainRepelTitle() {
|
rainRepelTitle() {
|
||||||
|
|
@ -508,6 +516,10 @@ export default {
|
||||||
if (this.carrierUrl) {
|
if (this.carrierUrl) {
|
||||||
this.$refs.siteFooter.updateButtonText(`Go back to ${this.carrierName}`);
|
this.$refs.siteFooter.updateButtonText(`Go back to ${this.carrierName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isFirstLoad = this.mainStore.pageData(issPageValues.ORDER_CONFIRMATION)?.isFirstLoad ?? true;
|
||||||
|
this.savePageDataToStore(issPageValues.ORDER_CONFIRMATION, { isFirstLoad: false });
|
||||||
|
this.handleAnalyticsEvents(isFirstLoad);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
|
|
@ -611,6 +623,72 @@ export default {
|
||||||
|
|
||||||
const vapsTypeDescription = vapsItemDescriptions?.find((entry) => entry?.Name === vapsPartType);
|
const vapsTypeDescription = vapsItemDescriptions?.find((entry) => entry?.Name === vapsPartType);
|
||||||
return vapsTypeDescription?.Text ?? '';
|
return vapsTypeDescription?.Text ?? '';
|
||||||
|
},
|
||||||
|
handleAnalyticsEvents(isFirstLoad) {
|
||||||
|
const mobileOrInshop = this.submittedOrder.isMobileAppointment ? 'mobile' : 'in_shop';
|
||||||
|
const verifiedOrNotVerified = this.submittedOrder.isVerified ? 'verified' : 'not_verified';
|
||||||
|
const repairOrReplace = this.submittedOrder.isRepair ? 'repair' : 'replace';
|
||||||
|
this.pushEventToGA('confirmation', 'safelite', `${mobileOrInshop}_${repairOrReplace}_${verifiedOrNotVerified}`, true);
|
||||||
|
|
||||||
|
if (this.payment.isPayInAdvance) {
|
||||||
|
const paymentMethodForAnalytics = analyticsPaymentTypeMap.get(this.payment.paymentMethod);
|
||||||
|
this.pushEventToGA('payment_page', 'pia_successful', paymentMethodForAnalytics, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.submittedOrder.servicePackage) {
|
||||||
|
const servicePackageForAnalytics = analyticsServicePackageMap.get(this.submittedOrder.servicePackage);
|
||||||
|
this.pushEventToGA('service_package', 'package_purchased', servicePackageForAnalytics, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containsRecalParts(this.submittedOrder.lineItems)) {
|
||||||
|
let coverageType = '';
|
||||||
|
if (this.isITAC) {
|
||||||
|
coverageType = 'ITAC';
|
||||||
|
} else if (this.isNoComp) {
|
||||||
|
coverageType = 'no_comp';
|
||||||
|
} else if (this.submittedOrder.isVerified) {
|
||||||
|
coverageType = 'verified';
|
||||||
|
} else {
|
||||||
|
coverageType = 'unverified';
|
||||||
|
}
|
||||||
|
const recalibrationType = this.submittedOrder.lineItems.glassParts?.find((part) => part.requiresRecalibration)?.recalibrationType;
|
||||||
|
this.pushEventToGA(`recalibration_scheduled_${coverageType}`, this.vehicle.carId, `recal_type_${recalibrationType}`.replace(/ /g, '_').toLowerCase(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ymms = `${this.vehicle.year}_${this.vehicle.make}_${this.vehicle.model}_${this.vehicle.style}`;
|
||||||
|
if (isFirstLoad && getCartTotal(this.submittedOrder) > 0) {
|
||||||
|
this.pushEventToGA('total_price', getCartTotal(this.submittedOrder).toString(), ymms, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pushEventToGA('rain_defense', this.hasRainRepel ? 'purchased' : 'no_purchase', ymms, true);
|
||||||
|
|
||||||
|
// TODO: Check if we're coming from SFA and add relevant events
|
||||||
|
// eslint-disable-next-line
|
||||||
|
if (false) {
|
||||||
|
this.pushEventToGA('visitor_info_confirmation', 'referring_site', 'SFA', null);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.pushEventToGA('visitor_info_confirmation', 'referring_site', 'ClientSite', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pushEventToGA('visitor_info_confirmation', 'client_name', this.mainStore.accountNameForEvents, true);
|
||||||
|
|
||||||
|
const wiperAction = this.hasWipers ? 'purchased' : 'no_purchase';
|
||||||
|
|
||||||
|
let wiperLabel = this.wipersBody.join('_').toLowerCase().replace('<br />', '').replace(/beam/g, '').replace(/blades/g, '').trim().replace(/ /g, '_');
|
||||||
|
if (wiperLabel.indexOf('front') < 0 && wiperLabel.indexOf('rear') < 0) {
|
||||||
|
wiperLabel = 'none_none';
|
||||||
|
} else {
|
||||||
|
if (wiperLabel.indexOf('front') < 0) {
|
||||||
|
wiperLabel = 'front_none_' + wiperLabel;
|
||||||
|
}
|
||||||
|
if (wiperLabel.indexOf('rear') < 0) {
|
||||||
|
wiperLabel = wiperLabel + '_rear_none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wiperLabel = wiperLabel.replace(/__/g, '_');
|
||||||
|
|
||||||
|
this.pushEventToGA('wipers', wiperAction, wiperLabel, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ import { mapAdyenToIssPaymentMethod, mapIssToAdyenPaymentMethod } from '@/helper
|
||||||
import { createAdyenCheckout } from "@/helpers/adyen-helper";
|
import { createAdyenCheckout } from "@/helpers/adyen-helper";
|
||||||
import { Dropin } from "@adyen/adyen-web/auto";
|
import { Dropin } from "@adyen/adyen-web/auto";
|
||||||
import applicationConfig from '@/constants/application-config';
|
import applicationConfig from '@/constants/application-config';
|
||||||
|
import { analyticsPaymentTypeMap } from '@/constants/analytics';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'payment-page-adyen',
|
name: 'payment-page-adyen',
|
||||||
|
|
@ -118,6 +119,7 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
showIssLoadingModal(true);
|
showIssLoadingModal(true);
|
||||||
|
this.pushEventToGA('payment_page', 'Mode', 'Adyen', true);
|
||||||
this.initializeAdyen().finally(() => {
|
this.initializeAdyen().finally(() => {
|
||||||
showIssLoadingModal(false);
|
showIssLoadingModal(false);
|
||||||
});
|
});
|
||||||
|
|
@ -353,6 +355,8 @@ export default {
|
||||||
},
|
},
|
||||||
async paymentFailedPayLater() {
|
async paymentFailedPayLater() {
|
||||||
this.showIssLoadingModal(true);
|
this.showIssLoadingModal(true);
|
||||||
|
const paymentMethod = analyticsPaymentTypeMap.get(this.piaType);
|
||||||
|
this.pushEventToGA('transaction_declined_displayed', 'save_your_appointment_clicked', `${paymentMethod}_declined`, true);
|
||||||
this.mainStore.savePaymentMethodChoice(paymentMethods.PAY_AT_TIME_OF_SERVICE);
|
this.mainStore.savePaymentMethodChoice(paymentMethods.PAY_AT_TIME_OF_SERVICE);
|
||||||
await submitWorkOrder({ submitType: submitType.SAFELITE });
|
await submitWorkOrder({ submitType: submitType.SAFELITE });
|
||||||
this.$router.navigate(
|
this.$router.navigate(
|
||||||
|
|
@ -523,6 +527,8 @@ export default {
|
||||||
const paymentMethodFromSession = adyenResponse?.paymentMethod;
|
const paymentMethodFromSession = adyenResponse?.paymentMethod;
|
||||||
|
|
||||||
const paymentMethod = mapAdyenToIssPaymentMethod(paymentMethodFromSession);
|
const paymentMethod = mapAdyenToIssPaymentMethod(paymentMethodFromSession);
|
||||||
|
const paymentMethodForAnalytics = analyticsPaymentTypeMap.get(paymentMethod);
|
||||||
|
this.pushEventToGA('PIA', 'Pay Today', paymentMethodForAnalytics, true, null, 0);
|
||||||
|
|
||||||
this.mainStore.savePaymentMethodChoice(paymentMethod);
|
this.mainStore.savePaymentMethodChoice(paymentMethod);
|
||||||
|
|
||||||
|
|
@ -544,6 +550,10 @@ export default {
|
||||||
|
|
||||||
await global.$logger.logError(stringToLog);
|
await global.$logger.logError(stringToLog);
|
||||||
|
|
||||||
|
const paymentMethodForAnalytics = analyticsPaymentTypeMap.get(this.piaType);
|
||||||
|
this.pushEventToGA('transaction_declined_displayed', `${paymentMethodForAnalytics}_declined`, 'true', true, null, 0);
|
||||||
|
this.pushEventToGA('payment_page', 'pia_failed', paymentMethodForAnalytics, true, null, result?.resultCode);
|
||||||
|
|
||||||
this.hasPaymentFailureError = true;
|
this.hasPaymentFailureError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -556,6 +566,9 @@ export default {
|
||||||
const stringToLog = `ADYEN ERROR. Name = ${error?.name}. Details = ${error?.message}.`;
|
const stringToLog = `ADYEN ERROR. Name = ${error?.name}. Details = ${error?.message}.`;
|
||||||
|
|
||||||
await global.$logger.logError(stringToLog);
|
await global.$logger.logError(stringToLog);
|
||||||
|
const paymentMethodForAnalytics = analyticsPaymentTypeMap.get(this.piaType);
|
||||||
|
this.pushEventToGA('transaction_declined_displayed', `${paymentMethodForAnalytics}_declined`, 'true', true, null, 0);
|
||||||
|
this.pushEventToGA('payment_page', 'pia_error', paymentMethodForAnalytics, true, null, error?.name);
|
||||||
|
|
||||||
this.hasPaymentFailureError = true;
|
this.hasPaymentFailureError = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import navigationScenarios from '@/router/router-constants/navigation-scenarios'
|
||||||
import submitType from '@/constants/submit-type';
|
import submitType from '@/constants/submit-type';
|
||||||
import showIssLoadingModal from '@/helpers/loading-modal-helper';
|
import showIssLoadingModal from '@/helpers/loading-modal-helper';
|
||||||
import { paymentMethods } from '@/constants/payment-method-constants';
|
import { paymentMethods } from '@/constants/payment-method-constants';
|
||||||
|
import { analyticsPaymentTypeMap } from '@/constants/analytics';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'payment-return-adyen',
|
name: 'payment-return-adyen',
|
||||||
|
|
@ -58,6 +59,7 @@ export default {
|
||||||
const sessionInfo = await getSessionInfo(sessionId, result.sessionResult);
|
const sessionInfo = await getSessionInfo(sessionId, result.sessionResult);
|
||||||
|
|
||||||
const paymentMethod = mapAdyenToIssPaymentMethod(sessionInfo?.paymentMethod);
|
const paymentMethod = mapAdyenToIssPaymentMethod(sessionInfo?.paymentMethod);
|
||||||
|
const paymentMethodForAnalytics = analyticsPaymentTypeMap.get(paymentMethod);
|
||||||
const amountDue = getCartTotal(store.order);
|
const amountDue = getCartTotal(store.order);
|
||||||
const ccToken = generateCcToken(sessionInfo);
|
const ccToken = generateCcToken(sessionInfo);
|
||||||
if (paymentMethod === paymentMethods.AFTERPAY) {
|
if (paymentMethod === paymentMethods.AFTERPAY) {
|
||||||
|
|
@ -67,6 +69,7 @@ export default {
|
||||||
ccToken.expMonth = "03";
|
ccToken.expMonth = "03";
|
||||||
ccToken.expYear = "2030";
|
ccToken.expYear = "2030";
|
||||||
}
|
}
|
||||||
|
this.pushEventToGA('PIA', 'Pay Today', paymentMethodForAnalytics, true, null, 0);
|
||||||
|
|
||||||
store.savePaymentMethodChoice(paymentMethod);
|
store.savePaymentMethodChoice(paymentMethod);
|
||||||
store.updateCreditCardToken(ccToken);
|
store.updateCreditCardToken(ccToken);
|
||||||
|
|
@ -95,6 +98,11 @@ export default {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
piaType() {
|
||||||
|
return this.mainStore.payment.paymentMethod;
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
finalizeAdyenPayment(sessionId, redirectResult) {
|
finalizeAdyenPayment(sessionId, redirectResult) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
@ -111,6 +119,10 @@ export default {
|
||||||
const stringToLog = `ADYEN PAYMENT NOT AUTHORIZED. Code = ${result?.resultCode}. Id = ${sessionId}`;
|
const stringToLog = `ADYEN PAYMENT NOT AUTHORIZED. Code = ${result?.resultCode}. Id = ${sessionId}`;
|
||||||
|
|
||||||
global.$logger.logError(stringToLog);
|
global.$logger.logError(stringToLog);
|
||||||
|
|
||||||
|
const paymentMethodForAnalytics = analyticsPaymentTypeMap.get(this.piaType);
|
||||||
|
this.pushEventToGA('transaction_declined_displayed', `${paymentMethodForAnalytics}_declined`, 'true', true, null, 0);
|
||||||
|
this.pushEventToGA('payment_page', 'pia_failed', paymentMethodForAnalytics, true, null, result?.resultCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
reject({
|
reject({
|
||||||
|
|
@ -123,6 +135,10 @@ export default {
|
||||||
const stringToLog = `ADYEN ERROR. Name = ${error?.name}. Details = ${error?.message}.`;
|
const stringToLog = `ADYEN ERROR. Name = ${error?.name}. Details = ${error?.message}.`;
|
||||||
|
|
||||||
global.$logger.logError(stringToLog);
|
global.$logger.logError(stringToLog);
|
||||||
|
|
||||||
|
const paymentMethodForAnalytics = analyticsPaymentTypeMap.get(this.piaType);
|
||||||
|
this.pushEventToGA('transaction_declined_displayed', `${paymentMethodForAnalytics}_declined`, 'true', true, null, 0);
|
||||||
|
this.pushEventToGA('payment_page', 'pia_error', paymentMethodForAnalytics, true, null, error?.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
reject({
|
reject({
|
||||||
|
|
|
||||||
|
|
@ -487,6 +487,7 @@ export default {
|
||||||
logEvents() {
|
logEvents() {
|
||||||
const vehicleString = this.mainStore.order.vehicle.make + '_' + this.mainStore.order.vehicle.model + '_' + this.mainStore.order.vehicle.style;
|
const vehicleString = this.mainStore.order.vehicle.make + '_' + this.mainStore.order.vehicle.model + '_' + this.mainStore.order.vehicle.style;
|
||||||
this.pushEventToGA("CAR SUBMISSION", this.mainStore.order.vehicle.year?.toString(), vehicleString, true, null, 0);
|
this.pushEventToGA("CAR SUBMISSION", this.mainStore.order.vehicle.year?.toString(), vehicleString, true, null, 0);
|
||||||
|
this.pushEventToGA('forward_progress', 'continue_clicked', 'vehicle_damage_2', true);
|
||||||
|
|
||||||
if (this.isWindshieldRepair) {
|
if (this.isWindshieldRepair) {
|
||||||
this.pushEventToGA("damage", "selected", "repair", true, null, null);
|
this.pushEventToGA("damage", "selected", "repair", true, null, null);
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,10 @@ import {
|
||||||
ValueToLogTypes
|
ValueToLogTypes
|
||||||
} from '@/constants/analytics';
|
} from '@/constants/analytics';
|
||||||
import { getCartTotal, getSubtotal } from '@/helpers/cart-helper';
|
import { getCartTotal, getSubtotal } from '@/helpers/cart-helper';
|
||||||
import { getRecalPartNumbers } from "@/helpers/recal-helper";
|
import { getRecalPartNumbers, isRecalOrder } from "@/helpers/recal-helper";
|
||||||
import coverageStatuses from '@/constants/coverage-statuses';
|
import coverageStatuses from '@/constants/coverage-statuses';
|
||||||
import coverageType from '@/constants/coverage-type';
|
import coverageType from '@/constants/coverage-type';
|
||||||
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||||
import issPageValues from '@/router/router-constants/issPage-values';
|
import issPageValues from '@/router/router-constants/issPage-values';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
|
|
||||||
|
|
@ -128,11 +129,6 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
pushValueToGA() {
|
pushValueToGA() {
|
||||||
const gaSiteType = {
|
|
||||||
['siteType']: useMainStore().issConfig.siteType
|
|
||||||
};
|
|
||||||
this.pushGenericObjectToGA(gaSiteType);
|
|
||||||
|
|
||||||
const gaServiceType = {
|
const gaServiceType = {
|
||||||
['service_type']: useMainStore().order?.serviceLocation?.appointmentType?.toLowerCase()
|
['service_type']: useMainStore().order?.serviceLocation?.appointmentType?.toLowerCase()
|
||||||
};
|
};
|
||||||
|
|
@ -141,6 +137,195 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
pushOrderToDataLayer() {
|
||||||
|
// helper check for if an object is defined (but maybe falsey)
|
||||||
|
const isDefined = (x) => x !== null && x !== undefined;
|
||||||
|
const store = useMainStore();
|
||||||
|
|
||||||
|
// Get correct order object
|
||||||
|
const hasSubmittedOrder = store.hasSubmittedOrder();
|
||||||
|
const submittedOrder = store.getSubmittedOrder();
|
||||||
|
const order = hasSubmittedOrder ? submittedOrder : store.order;
|
||||||
|
const deviceId = getDeviceIdValue();
|
||||||
|
const sid = getSessionIdValue();
|
||||||
|
|
||||||
|
// Begin assembling payload for data layer
|
||||||
|
const payload = {};
|
||||||
|
|
||||||
|
payload.appName = "ISS";
|
||||||
|
payload.siteType = store.issConfig.siteType;
|
||||||
|
payload.pageName = this.getPageNameByQueryString();
|
||||||
|
payload.deviceId = deviceId;
|
||||||
|
payload.sessionId = sid;
|
||||||
|
payload.clientName = store.issConfig.clientName;
|
||||||
|
payload.lossCause = order.policy?.damageCause ?? "";
|
||||||
|
|
||||||
|
// Service Zip
|
||||||
|
if (
|
||||||
|
order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||||
|
isDefined(order.serviceLocation.zipCode)
|
||||||
|
) {
|
||||||
|
payload.serviceZipCode = order.serviceLocation.zipCode;
|
||||||
|
} else if (
|
||||||
|
isDefined(order.serviceLocation.appointmentType) &&
|
||||||
|
order.serviceLocation.appointmentType !== AppointmentTypeStrings.MOBILE &&
|
||||||
|
isDefined(order.serviceLocation.provider.address.zipCode)
|
||||||
|
) {
|
||||||
|
payload.serviceZipCode = order.serviceLocation.provider.address.zipCode;
|
||||||
|
} else {
|
||||||
|
payload.serviceZipCode = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Damage Type
|
||||||
|
if (isDefined(order.damage.isRepair)) {
|
||||||
|
payload.damageType = order.damage.isRepair ? "repair" : "replace";
|
||||||
|
} else {
|
||||||
|
payload.damageType = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account Type - always insurance for ISS
|
||||||
|
payload.accountType = "insurance";
|
||||||
|
|
||||||
|
// Promo Codes
|
||||||
|
const promos = order.lineItems.promos ?? [];
|
||||||
|
if (promos.length === 0) {
|
||||||
|
payload.promoCodes = "";
|
||||||
|
} else {
|
||||||
|
const promoCodes = promos.map((promo) => promo.promoCode);
|
||||||
|
const promoString = promoCodes.reduce((prev, next) => `${prev},${next}`);
|
||||||
|
payload.promoCodes = promoString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vehicle info
|
||||||
|
if (isDefined(order.vehicle.year)) {
|
||||||
|
// Ensure cast to string.
|
||||||
|
payload.vehicleYear = `${order.vehicle.year}`;
|
||||||
|
} else {
|
||||||
|
payload.vehicleYear = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDefined(order.vehicle.make)) {
|
||||||
|
payload.vehicleMake = order.vehicle.make;
|
||||||
|
} else {
|
||||||
|
payload.vehicleMake = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDefined(order.vehicle.model)) {
|
||||||
|
payload.vehicleModel = order.vehicle.model;
|
||||||
|
} else {
|
||||||
|
payload.vehicleModel = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDefined(order.vehicle.style)) {
|
||||||
|
payload.vehicleStyle = order.vehicle.style;
|
||||||
|
} else {
|
||||||
|
payload.vehicleStyle = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glass pieces
|
||||||
|
const glass = order.damage.glassToReplace ?? [];
|
||||||
|
if (glass.length === 0) {
|
||||||
|
payload.glassToReplace = "";
|
||||||
|
} else {
|
||||||
|
const glassNames = glass.map((g) => `${g.glassLocation}/${g.glassName}`);
|
||||||
|
const glassString = glassNames.reduce((prev, next) => `${prev},${next}`);
|
||||||
|
|
||||||
|
payload.glassToReplace = glassString;
|
||||||
|
}
|
||||||
|
|
||||||
|
//EON
|
||||||
|
if (order.eon) {
|
||||||
|
payload.eon = order.eon;
|
||||||
|
} else {
|
||||||
|
payload.eon = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Work Order Id
|
||||||
|
if (order.workOrderId) {
|
||||||
|
const parsedId = parseInt(order.workOrderId);
|
||||||
|
if (!isNaN(parsedId)) {
|
||||||
|
payload.workOrderId = parsedId;
|
||||||
|
} else {
|
||||||
|
payload.workOrderId = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
payload.workOrderId = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider Ctu
|
||||||
|
if (isDefined(order.serviceLocation.zipCodeCtu)) {
|
||||||
|
payload.providerCtu = order.serviceLocation.zipCodeCtu;
|
||||||
|
} else {
|
||||||
|
payload.providerCtu = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Work Order Number
|
||||||
|
if (order.workOrderNumber) {
|
||||||
|
payload.orderNumber = order.workOrderNumber;
|
||||||
|
} else {
|
||||||
|
payload.orderNumber = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unverified (no price or deductible displayed)
|
||||||
|
if (!store.isVerified) {
|
||||||
|
payload.priceSubTotal = "";
|
||||||
|
payload.priceTotal = "";
|
||||||
|
}
|
||||||
|
// Deductible case (no price is displayed, only deductible)
|
||||||
|
else if (
|
||||||
|
store.isVerified &&
|
||||||
|
(typeof store.currentDeductible === 'number' && store.currentDeductible >= 0) &&
|
||||||
|
!store.isITAC &&
|
||||||
|
!store.isNoComp
|
||||||
|
) {
|
||||||
|
payload.priceSubTotal = "";
|
||||||
|
payload.priceTotal = "";
|
||||||
|
// ITAC or NoComp (where cash price is shown)
|
||||||
|
} else if (store.isVerified && (store.isITAC || store.isNoComp)) {
|
||||||
|
const subtotal = getSubtotal(order).toFixed(2);
|
||||||
|
payload.priceSubTotal = parseFloat(subtotal);
|
||||||
|
const total = getCartTotal(order).toFixed(2);
|
||||||
|
payload.priceTotal = parseFloat(total);
|
||||||
|
} else {
|
||||||
|
payload.priceSubTotal = "";
|
||||||
|
payload.priceTotal = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cash Quote or Cash Price Sub Total
|
||||||
|
payload.cashPriceSubTotal = getSubtotal(order).toString();
|
||||||
|
|
||||||
|
// Recalibration
|
||||||
|
payload.isRecalibrationOnOrder = isRecalOrder(order.lineItems);
|
||||||
|
|
||||||
|
// Appointment Type
|
||||||
|
if (isDefined(order.serviceLocation.appointmentType)) {
|
||||||
|
payload.appointmentType = order.serviceLocation.appointmentType;
|
||||||
|
} else {
|
||||||
|
payload.appointmentType = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.isInsuranceVerified = store.isVerified;
|
||||||
|
payload.insuranceCompanyName = store.issConfig.clientName ?? "";
|
||||||
|
if (!store.isVerified) {
|
||||||
|
payload.isInsuranceItac = "";
|
||||||
|
payload.isInsuranceNoComp = "";
|
||||||
|
} else {
|
||||||
|
payload.isInsuranceItac = store.isITAC ?? "";
|
||||||
|
payload.isInsuranceNoComp = store.isNoComp ?? "";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
store.isITAC ||
|
||||||
|
store.isNoComp ||
|
||||||
|
!store.isVerified
|
||||||
|
) {
|
||||||
|
payload.insuranceDeductible = "";
|
||||||
|
} else {
|
||||||
|
payload.insuranceDeductible = store.currentDeductible ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
pushToDataLayerIfDefined(payload);
|
||||||
|
},
|
||||||
|
|
||||||
pushExperimentsToDataLayer() {
|
pushExperimentsToDataLayer() {
|
||||||
const { experiments } = useMainStore().applicationUser;
|
const { experiments } = useMainStore().applicationUser;
|
||||||
experiments?.forEach((exp) => {
|
experiments?.forEach((exp) => {
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,9 @@ router.afterEach(async (to, from) => {
|
||||||
|
|
||||||
// Push values to GA
|
// Push values to GA
|
||||||
analyticsMixin.methods.pushValueToGA();
|
analyticsMixin.methods.pushValueToGA();
|
||||||
|
|
||||||
|
// Push current order status to Data Layer
|
||||||
|
analyticsMixin.methods.pushOrderToDataLayer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@ import {
|
||||||
repairWaivedForSelectedVehicle
|
repairWaivedForSelectedVehicle
|
||||||
} from '@/helpers/policy-vehicle-helper';
|
} from '@/helpers/policy-vehicle-helper';
|
||||||
import { buildURLSearchParams, getPartNumbersListForQueryString } from '@/helpers/querystring-helper';
|
import { buildURLSearchParams, getPartNumbersListForQueryString } from '@/helpers/querystring-helper';
|
||||||
import { getRecalPartNumbers, getTopLevelGlassPartsWithRecal } from '@/helpers/recal-helper';
|
import { getRecalPartNumbers, getTopLevelGlassPartsWithRecal, getHasRecalibrationPart } from '@/helpers/recal-helper';
|
||||||
import { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
|
import { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
|
||||||
import { isMobileDevice } from '@/helpers/useragent-helper';
|
import { isMobileDevice } from '@/helpers/useragent-helper';
|
||||||
import issPageValues from '@/router/router-constants/issPage-values';
|
import issPageValues from '@/router/router-constants/issPage-values';
|
||||||
import CoverageStatuses from '@/constants/coverage-statuses';
|
import CoverageStatuses from '@/constants/coverage-statuses';
|
||||||
|
import { getNonFalseValuesOfPropertyInArrayOfObjects, sortArrayOfObjectsByPropertyValue } from '@/helpers/object-helper';
|
||||||
|
|
||||||
const storeId = 'main';
|
const storeId = 'main';
|
||||||
|
|
||||||
|
|
@ -276,7 +277,7 @@ export const useMainStore = defineStore({
|
||||||
state: () => state,
|
state: () => state,
|
||||||
getters: {
|
getters: {
|
||||||
billToAccountNumber: (storeState) => storeState.issConfig.billToAccountNumber,
|
billToAccountNumber: (storeState) => storeState.issConfig.billToAccountNumber,
|
||||||
hasRecalibrationPart: (storeState) => getHasRecalibrationPart(storeState),
|
hasRecalibrationPart: (storeState) => getHasRecalibrationPartOnOrder(storeState),
|
||||||
vehicle: (storeState) => storeState.order.vehicle,
|
vehicle: (storeState) => storeState.order.vehicle,
|
||||||
damage: (storeState) => storeState.order.damage,
|
damage: (storeState) => storeState.order.damage,
|
||||||
lineItems: (state) => state.order.lineItems,
|
lineItems: (state) => state.order.lineItems,
|
||||||
|
|
@ -1348,45 +1349,6 @@ export const useMainStore = defineStore({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getServiceabilityDetails(serviceZipCode) {
|
getServiceabilityDetails(serviceZipCode) {
|
||||||
console.log('BEEP BOOP');
|
|
||||||
console.log('--ENVIRONMENT DETECTOR ROBOT ENGAGED--');
|
|
||||||
const currentEnvironment = applicationConfig.CURRENT_ENVIRONMENT;
|
|
||||||
console.log('I HAVE DETERMINED THAT THE CURRENT ENVIRONMENT IS:', currentEnvironment);
|
|
||||||
console.log('---');
|
|
||||||
console.log('---');
|
|
||||||
if (currentEnvironment === 'Localhost' || currentEnvironment === 'Dev') {
|
|
||||||
console.log('NEW SERVICEABILITY DETAILS METHOD ACTIVATED');
|
|
||||||
return this.getServiceabilityDetailsNewMethod(serviceZipCode);
|
|
||||||
} else {
|
|
||||||
console.log('OLD SERVICEABILITY DETAILS METHOD ACTIVATED');
|
|
||||||
return this.getServiceabilityDetailsOldMethod(serviceZipCode);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getServiceabilityDetailsOldMethod(serviceZipCode) {
|
|
||||||
const { vehicle, damage, parentAccountNumber, referralSequenceNumber, lineItems } = this.order;
|
|
||||||
const { carId } = vehicle;
|
|
||||||
const glassArray = convertGlassPieceNamingForApi(damage.glassToReplace);
|
|
||||||
const lineItemParts = [...(lineItems.glassParts || []), ...(lineItems.supportingItems || [])].map((part) => ({
|
|
||||||
partNumber: part.partNumber,
|
|
||||||
recalibrationType: part.recalibrationType
|
|
||||||
}));
|
|
||||||
|
|
||||||
const params = buildURLSearchParams({
|
|
||||||
applicationName: applicationConfig.APPLICATION_NAME,
|
|
||||||
parentAccountNumber,
|
|
||||||
referralSequenceNumber,
|
|
||||||
zip: serviceZipCode,
|
|
||||||
carId,
|
|
||||||
glassPieces: glassArray,
|
|
||||||
lineItems: lineItemParts
|
|
||||||
});
|
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
|
||||||
method: endpoints.GetServiceabilityDetails.method,
|
|
||||||
endpoint: `${endpoints.GetServiceabilityDetails.url}?${params.toString()}`
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getServiceabilityDetailsNewMethod(serviceZipCode) {
|
|
||||||
const { damage, lineItems, parentAccountNumber, vehicle } = this.order;
|
const { damage, lineItems, parentAccountNumber, vehicle } = this.order;
|
||||||
const { carId } = vehicle;
|
const { carId } = vehicle;
|
||||||
const flattenedGlassParts = getLineItemsFlattened(lineItems.glassParts);
|
const flattenedGlassParts = getLineItemsFlattened(lineItems.glassParts);
|
||||||
|
|
@ -3179,39 +3141,8 @@ export const useMainStore = defineStore({
|
||||||
|
|
||||||
// Private Functions
|
// Private Functions
|
||||||
|
|
||||||
function getHasRecalibrationPart(state) {
|
function getHasRecalibrationPartOnOrder(state) {
|
||||||
const hasRequiresRecalibration = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, 'requiresRecalibration')?.length > 0;
|
return getHasRecalibrationPart(state.order.lineItems);
|
||||||
const hasRecalibrationType = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, 'recalibrationType')?.length > 0;
|
|
||||||
|
|
||||||
if (hasRequiresRecalibration) {
|
|
||||||
if (hasRecalibrationType) {
|
|
||||||
// Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType'
|
|
||||||
return (
|
|
||||||
getNonFalseValuesOfPropertyInArrayOfObjects(
|
|
||||||
state.order.lineItems.glassParts,
|
|
||||||
'recalibrationType'
|
|
||||||
)[0].toLowerCase() !== 'unknown'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Has 'requiresRecalibration' but no 'recalibrationType' at all
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Does not have 'requiresRecalibration'
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
|
|
||||||
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
|
||||||
if (!arrayOfObjects) return null;
|
|
||||||
|
|
||||||
return arrayOfObjects.sort((a, b) => {
|
|
||||||
if (a[propertyName] < b[propertyName]) return -1;
|
|
||||||
if (a[propertyName] > b[propertyName]) return 1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertGlassPieceNamingForApi(glassArray) {
|
function convertGlassPieceNamingForApi(glassArray) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue