Merge branch 'develop' into feature/CSR-1564
This commit is contained in:
commit
4307b67988
39 changed files with 2374 additions and 873 deletions
|
|
@ -15,10 +15,8 @@ module.exports = {
|
|||
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
||||
"!src/layouts/reveal/**/*.vue",
|
||||
"!src/ux-components/text-link/**/*.vue",
|
||||
"!src/digital-components/date-picker/**/*.vue", // Temp until unit tests completed
|
||||
"!src/layouts/vin-lookup/**/*.vue", //Temporary for Quote page testing
|
||||
"!src/common-components/funnel-header/menu-modal/**/*.vue",
|
||||
"!src/layouts/schedule/*.vue", // Temp test exclusion while in development
|
||||
"!src/layouts/schedule/helpers/schedule-helper.js", // Temp test exclusion while in development
|
||||
"!src/layouts/review/*.vue", // Temp test exclusion while in development
|
||||
// END
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ const GaEvents = {
|
|||
const GaCategories = {
|
||||
API_RESPONSE: "Api_Response",
|
||||
EVOX: "Evox",
|
||||
FUNNEL_ENTRY: "funnel_entry",
|
||||
};
|
||||
|
||||
const GaActions = {
|
||||
|
|
@ -21,7 +20,6 @@ const GaActions = {
|
|||
VIF: "vif",
|
||||
SUBMITTED: "Submitted",
|
||||
DISPLAYED: "Displayed",
|
||||
ZIP_CODE_PROVIDED: "zip_code_provided",
|
||||
};
|
||||
|
||||
const GaLabels = {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const storeActions = {
|
|||
GET_VEHICLE_MAKES: "getVehicleMakes",
|
||||
GET_VEHICLE_MODELS: "getVehicleModels",
|
||||
GET_VEHICLE_STYLES: "getVehicleStyles",
|
||||
SET_VEHICLE: "setVehicle",
|
||||
GET_VEHICLE: "getVehicle",
|
||||
GET_DAMAGE_OPTIONS: "getDamageOptions",
|
||||
GET_EVOX_IMAGE: "getEvoxImage",
|
||||
IS_VIN_OPTIONAL_VEHICLE: "isVinOptionalVehicle",
|
||||
|
|
|
|||
|
|
@ -35,16 +35,15 @@ const storeMutations = {
|
|||
UPDATE_SERVICE_ZIP: "updateServiceZip",
|
||||
UPDATE_SERVICE_LOCATION: "updateServiceLocation",
|
||||
UPDATE_SERVICE_LOCATION_TECH_NOTES: "updateServiceLocationTechNotes",
|
||||
UPDATE_TECH_NOTES: "updateTechNotes",
|
||||
UPDATE_SCHEDULE: "updateSchedule",
|
||||
|
||||
UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress",
|
||||
|
||||
// CUSTOMER MUTATIONS
|
||||
UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress",
|
||||
UPDATE_CUSTOMER_DETAILS: "updateCustomerDetails",
|
||||
|
||||
// ORDER MUTATIONS
|
||||
UPDATE_REFERRAL_NUMBER: "updateReferralNumber",
|
||||
UPDATE_REFERRAL_SEQUENCE_NUMBER: "updateReferralSequenceNumber",
|
||||
UPDATE_REFERRAL_DATE: "updateReferralDate",
|
||||
UPDATE_REFERRAL_CORRELATION_ID: "updateReferralCorrelationId",
|
||||
UPDATE_PARENT_ACCT_NUMBER: "updateParentAcctNumber",
|
||||
|
|
|
|||
1348
src/digital-components/date-picker/date-picker.spec.js
Normal file
1348
src/digital-components/date-picker/date-picker.spec.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,477 +0,0 @@
|
|||
import datePicker from "./date-picker";
|
||||
|
||||
// Supporting Files
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
|
||||
describe("date-picker.vue", () => {
|
||||
describe("initial setup", () => {
|
||||
test("Creates a date object from today", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = await setupMocks({
|
||||
propsData: {
|
||||
selectableDatesSetting: "custom"
|
||||
},
|
||||
});
|
||||
|
||||
wrapper.vm.loadInitialData = jest.fn().mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve, reject) => {
|
||||
resolve({
|
||||
data: [responseValue],
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.vm.loadInitialData).toHaveBeenCalled();
|
||||
|
||||
// console.log("wrapper.vm.today: ", wrapper.vm.today)
|
||||
|
||||
// // Act
|
||||
// const testResult = wrapper.vm.today instanceof Date;
|
||||
// console.log("testResult: ", testResult)
|
||||
|
||||
// // Assert
|
||||
// expect(testResult).toEqual(true);
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
// describe("formatNumberToSetDigits", () => {
|
||||
// const testScenarios = [
|
||||
// [0, 3, "000"],
|
||||
// [8, 2, "08"],
|
||||
// [345, 2, "345"],
|
||||
// [4567, 0, "4567"],
|
||||
// ];
|
||||
// test.each(testScenarios)(
|
||||
// "when num is %s and digits is %s, formatNumberToSetDigits should return %s",
|
||||
// async (num, digits, expectedReturn) => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({});
|
||||
|
||||
// // Act
|
||||
// const fnReturn = wrapper.vm.formatNumberToSetDigits(num, digits);
|
||||
|
||||
// // Assert
|
||||
// expect(fnReturn).toEqual(expectedReturn);
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// describe("formatDate", () => {
|
||||
// test("Can format a date as MM/dd/yyyy", () => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({});
|
||||
// const testDate = new Date("01-26-2023");
|
||||
|
||||
// // Act
|
||||
// const testResult = wrapper.vm.formatDate(testDate);
|
||||
|
||||
// // Assert
|
||||
// expect(testResult).toEqual("01/26/2023");
|
||||
|
||||
// wrapper.unmount();
|
||||
// });
|
||||
|
||||
// // test("Can get correct initialFirstDate from today", () => {
|
||||
// // // Arrange
|
||||
// // const { wrapper } = setupMocks({
|
||||
// // propsData: {
|
||||
// // todayDate: "Thu Jan 26 2023",
|
||||
// // },
|
||||
// // });
|
||||
|
||||
// // // Act
|
||||
// // const testResult = wrapper.vm.initialFirstDate;
|
||||
// // const testResultAsDateString = testResult.toDateString();
|
||||
|
||||
// // // Assert
|
||||
// // expect(testResultAsDateString).toEqual("Sun Jan 22 2023");
|
||||
|
||||
// // wrapper.unmount();
|
||||
// // });
|
||||
// });
|
||||
// describe("calendarData", () => {
|
||||
// test("should return an array", async () => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({});
|
||||
|
||||
// // Act
|
||||
// const testResult = await wrapper.vm.calendarData;
|
||||
|
||||
// // Assert
|
||||
// expect(Array.isArray(testResult)).toBe(true);
|
||||
|
||||
// wrapper.unmount();
|
||||
// });
|
||||
// describe("each month should have keys monthLabel, yearNum, dates, firstDateDayIndex", () => {
|
||||
// const testScenarios = [
|
||||
// ["monthLabel", true, "string"],
|
||||
// ["yearNum", true, "number"],
|
||||
// ["dates", true, "object"],
|
||||
// ["firstDateDayIndex", true, "number"],
|
||||
// ["monthClass", true, "string"],
|
||||
// ];
|
||||
|
||||
// test.each(testScenarios)(
|
||||
// "test for %s key should return %s and be type %s",
|
||||
// async (label, test, type) => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({});
|
||||
// const containsMonthLabel = (obj) => Object.hasOwn(obj, label);
|
||||
// const isCorrectType = (obj) => typeof obj[label] === type;
|
||||
// const isTruthyOrZero = (obj) => (obj[label] || obj[label] === 0 ? true : false);
|
||||
|
||||
// // Act
|
||||
// const calendarData = await wrapper.vm.calendarData;
|
||||
// // console.log("calendarData: ", calendarData);
|
||||
|
||||
// // Assert
|
||||
// expect(calendarData.every(containsMonthLabel)).toBe(true);
|
||||
// expect(calendarData.every(isCorrectType)).toBe(true);
|
||||
// expect(calendarData.every(isTruthyOrZero)).toBe(true);
|
||||
|
||||
// wrapper.unmount();
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
|
||||
// describe("the current month's week which includes today", () => {
|
||||
// const testScenarios = [
|
||||
// ["2022-02-05T03:00:00", 1, 2, true],
|
||||
// ["2024-02-05T03:00:00", 4, 0, true],
|
||||
// ["2020-01-15T03:00:00", 12, 0, true],
|
||||
// ];
|
||||
|
||||
// test.each(testScenarios)(
|
||||
// "the first date of the week including the date %s should be the date number %s and be day index %s",
|
||||
// async (todayDateString, startDate, dayOfWeekIndex) => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({
|
||||
// propsData: {
|
||||
// todayOverrideDateString: todayDateString,
|
||||
// },
|
||||
// });
|
||||
|
||||
// // Act
|
||||
// const calendarData = await wrapper.vm.calendarData;
|
||||
// const currentMonthIndex = calendarData.findIndex((month) => {
|
||||
// console.log("month: ", month);
|
||||
// return month.monthClass === "currentMonth";
|
||||
// });
|
||||
// console.log("calendarData ", calendarData);
|
||||
// console.log("currentMonthIndex ", currentMonthIndex);
|
||||
|
||||
// // Assert
|
||||
// expect(calendarData[currentMonthIndex].dates[0].dateNum === startDate).toBe(
|
||||
// true
|
||||
// );
|
||||
// expect(
|
||||
// calendarData[currentMonthIndex].dates[0].firstDateDayIndex ===
|
||||
// dayOfWeekIndex
|
||||
// ).toBe(true);
|
||||
|
||||
// wrapper.unmount();
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
|
||||
// test("the current month's dates array should start with the first day of the week which includes today", async () => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({});
|
||||
// const hasAFirstInDates = (obj) => obj?.dates[0].dateNum === 1;
|
||||
|
||||
// // Act
|
||||
// const calendarData = await wrapper.vm.calendarData;
|
||||
// const currentMonthIndex = calendarData.findIndex((month) => {
|
||||
// return month.monthClass === "currentMonth";
|
||||
// });
|
||||
|
||||
// // Assert
|
||||
// expect(calendarData[currentMonthIndex].dates[0].dateNum === 1).toBe(true);
|
||||
|
||||
// wrapper.unmount();
|
||||
// });
|
||||
|
||||
// test("for each month (other than current month), the dates array should have the 1st of the month", async () => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({});
|
||||
// const hasAFirstInDates = (obj) => obj?.dates[0].dateNum === 1;
|
||||
|
||||
// // Act
|
||||
// const calendarData = await wrapper.vm.calendarData;
|
||||
|
||||
// // Assert
|
||||
// expect(calendarData.every(hasAFirstInDates)).toBe(true);
|
||||
|
||||
// wrapper.unmount();
|
||||
// });
|
||||
|
||||
// describe("for the current month in calendarData, the dates array should have correct days of month", () => {
|
||||
// const testScenarios = [
|
||||
// ["2022-02-05T03:00:00", 28, true],
|
||||
// ["2024-02-05T03:00:00", 29, true],
|
||||
// ["2020-01-15T03:00:00", 31, true],
|
||||
// ];
|
||||
|
||||
// test.each(testScenarios)(
|
||||
// "the current month including the date %s should have %s days in its dates array",
|
||||
// async (dateString, noOfDays) => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({
|
||||
// propsData: {
|
||||
// todayOverrideDateString: dateString,
|
||||
// },
|
||||
// });
|
||||
|
||||
// // Act
|
||||
// const calendarData = await wrapper.vm.calendarData;
|
||||
// const currentMonthIndex = calendarData.findIndex((month) => {
|
||||
// return month.monthClass === "currentMonth";
|
||||
// });
|
||||
|
||||
// // Assert
|
||||
// expect(calendarData[currentMonthIndex].dates.length === noOfDays).toBe(true);
|
||||
|
||||
// wrapper.unmount();
|
||||
// }
|
||||
// );
|
||||
|
||||
// // test.each(testScenarios)(
|
||||
// // "the date %s should have %s days in dates array",
|
||||
// // async (dateString, noOfDays) => {
|
||||
// // // Arrange
|
||||
// // const { wrapper } = setupMocks({
|
||||
// // propsData: {
|
||||
// // todayOverrideDateString: dateString,
|
||||
// // },
|
||||
// // });
|
||||
// // const hasCorrectNumberOfDates = (obj) => obj?.dates.length === noOfDays;
|
||||
|
||||
// // // Act
|
||||
// // const calendarData = await wrapper.vm.calendarData;
|
||||
|
||||
// // // Assert
|
||||
// // expect(calendarData.every(hasCorrectNumberOfDates)).toBe(true);
|
||||
|
||||
// // wrapper.unmount();
|
||||
// // }
|
||||
// // );
|
||||
// });
|
||||
|
||||
// // describe("for each object in array, the dates array should have correct days of month", () => {
|
||||
// // const testScenarios = [
|
||||
// // ["2022-02-05T03:00:00", 28, true],
|
||||
// // ["2024-02-05T03:00:00", 29, true],
|
||||
// // ["2020-01-15T03:00:00", 31, true],
|
||||
// // ];
|
||||
|
||||
// // test.each(testScenarios)(
|
||||
// // "the date %s should have %s days in dates array",
|
||||
// // async (dateString, noOfDays) => {
|
||||
// // // Arrange
|
||||
// // const { wrapper } = setupMocks({
|
||||
// // propsData: {
|
||||
// // todayOverrideDateString: dateString,
|
||||
// // },
|
||||
// // });
|
||||
// // const hasCorrectNumberOfDates = (obj) => obj?.dates.length === noOfDays;
|
||||
|
||||
// // // Act
|
||||
// // const calendarData = await wrapper.vm.calendarData;
|
||||
|
||||
// // // Assert
|
||||
// // expect(calendarData.every(hasCorrectNumberOfDates)).toBe(true);
|
||||
|
||||
// // wrapper.unmount();
|
||||
// // }
|
||||
// // );
|
||||
// // });
|
||||
|
||||
// // test.only("each object in array should have a monthLabel", () => {
|
||||
// // // Arrange
|
||||
// // const { wrapper } = setupMocks({});
|
||||
// // // const testTodayDate = new Date("01-26-2023");
|
||||
|
||||
// // // Act
|
||||
// // const testResult = wrapper.vm.calendarData;
|
||||
// // const containsMonthLabel = (month) => Object.hasOwn(month, 'monthLabel');
|
||||
|
||||
// // // Assert
|
||||
// // expect(testResult.every(containsMonthLabel)).toBe(true);
|
||||
|
||||
// // });
|
||||
|
||||
// // test.only("array should have a month object with same month as today", () => {
|
||||
// // // Arrange
|
||||
// // const { wrapper } = setupMocks({});
|
||||
// // // const testTodayDate = new Date("01-26-2023");
|
||||
|
||||
// // // Act
|
||||
// // // const testResult = wrapper.vm.calendarData;
|
||||
// // console.log("wrapper.vm.calendarData: ", wrapper.vm.calendarData)
|
||||
|
||||
// // // Assert
|
||||
// // // expect(wrapper.vm.calendarData).toEqual("something");
|
||||
// // // expect(wrapper.vm.calendarDataOld).toEqual("something");
|
||||
|
||||
// // expect(wrapper.vm.calendarData[1]).toMatchObject({
|
||||
// // "dates": [
|
||||
// // {
|
||||
// // "dateNum": 1
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 2
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 3
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 4
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 5
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 6
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 7
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 8
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 9
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 10
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 11
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 12
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 13
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 14
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 15
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 16
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 17
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 18
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 19
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 20
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 21
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 22
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 23
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 24
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 25
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 26
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 27
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 28
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 29
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 30
|
||||
// // },
|
||||
// // {
|
||||
// // "dateNum": 31
|
||||
// // }
|
||||
// // ],
|
||||
// // "monthLabel": "January",
|
||||
// // "yearNum": 2023
|
||||
// // });
|
||||
|
||||
// // wrapper.unmount();
|
||||
// // });
|
||||
// });
|
||||
});
|
||||
|
||||
function setupMocks(mountOptionsMockData = {}) {
|
||||
const initialMountOptionsMockData = {
|
||||
// router: {
|
||||
// navigate: jest.fn(),
|
||||
// navigateWithSaving: jest.fn(),
|
||||
// navigateWithoutSaving: jest.fn(),
|
||||
// },
|
||||
// actionList: [
|
||||
// // {
|
||||
// // actionName: storeActions.SAVE_PART_QUESTION_ANSWERS,
|
||||
// // data: {},
|
||||
// // },
|
||||
// // {
|
||||
// // actionName: storeActions.GET_PARTS,
|
||||
// // data: {},
|
||||
// // },
|
||||
// ],
|
||||
// store: {
|
||||
// // getters: store.getters,
|
||||
// // commit: store.commit,
|
||||
// },
|
||||
};
|
||||
|
||||
const mountOptions = getMountOptions(
|
||||
Object.assign(initialMountOptionsMockData, mountOptionsMockData)
|
||||
);
|
||||
|
||||
// console.log("mountOptions: ", mountOptions)
|
||||
|
||||
const wrapper = shallowMount(datePicker, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
@ -174,9 +174,8 @@ export default {
|
|||
return this.todayDateNum + (6 - this.todayDayIndex);
|
||||
},
|
||||
calendarViewDirection() {
|
||||
if (this.selectableDatesSetting === "past") return "past";
|
||||
if (this.selectableDatesSetting === "custom") return "future";
|
||||
return "none";
|
||||
return "past";
|
||||
},
|
||||
selectedDate: {
|
||||
get() {
|
||||
|
|
@ -428,7 +427,7 @@ export default {
|
|||
} else if (direction === "past") {
|
||||
// first 0, then -1
|
||||
for (let i = 0; i >= 0 - monthsBeforeToLoadOffset; i--) {
|
||||
months.unshift(this.getMonthData(i, options));
|
||||
months.unshift(await this.getMonthData(i, options));
|
||||
}
|
||||
} else {
|
||||
// TODO - IF A CALENDAR WITH BOTH PAST AND FUTURE WAS EVER NEEDED
|
||||
|
|
@ -610,7 +609,7 @@ export default {
|
|||
// find the first day-hidden to become the next api call start date
|
||||
monthStartDateNum =
|
||||
monthToShow.dates.find(({ dayClasses }) => dayClasses.includes("day-hidden"))
|
||||
.dateNum - 1; // TRY 2
|
||||
.dateNum - 1;
|
||||
} else {
|
||||
if (this.calendarViewDirection === "future") {
|
||||
monthToShow = this.months.find((month) =>
|
||||
|
|
@ -646,11 +645,12 @@ export default {
|
|||
this.$store.getters.order.serviceLocation.appointmentType,
|
||||
this.$store.getters.order.serviceLocation.provider.providerNumber
|
||||
);
|
||||
|
||||
moreSelectableDates.days.forEach((selectableDate) => {
|
||||
const index = this.selectableDatesData.findIndex(
|
||||
(dateObj) => dateObj.date === selectableDate.date
|
||||
);
|
||||
if (index === -1) this.selectableDatesData.push(selectableDate.date);
|
||||
if (index === -1) this.selectableDatesData.push(selectableDate);
|
||||
this.months.forEach((month) => {
|
||||
// TODO: avoid checking all calendar dates; maybe only ones between monthStart and monthEnd as defined above?
|
||||
month.dates.forEach((date) => {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
<textLink
|
||||
linkType="text"
|
||||
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
||||
href="#!"
|
||||
:href="getExternalLink(copy)"
|
||||
@click-event="$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))"
|
||||
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)" />
|
||||
</span>
|
||||
|
|
@ -34,6 +34,7 @@ import {
|
|||
splitCopyOnCMSPlaceHolder,
|
||||
getRouterLinkRouteFromCopy,
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
getExternalLink,
|
||||
} from "@/helpers/cms-content-helper";
|
||||
import { applicationConfig } from "@/constants/application-config";
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ export default {
|
|||
splitCopyOnCMSPlaceHolder,
|
||||
getRouterLinkRouteFromCopy,
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
getExternalLink,
|
||||
},
|
||||
computed: {
|
||||
pageQueryString() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<div class="funnel-sub-header">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center container-fluid overflow-hidden">
|
||||
class="d-flex align-items-center container-fluid overflow-hidden"
|
||||
:class="[textAlignment]">
|
||||
<h5 class="text-center fw-normal mb-0" :class="headerColor">
|
||||
<span>
|
||||
{{ text }}
|
||||
|
|
@ -36,6 +37,10 @@ export default {
|
|||
type: String,
|
||||
default: "dark-header",
|
||||
},
|
||||
leftAlignHeader: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
buttonBack,
|
||||
|
|
@ -44,6 +49,9 @@ export default {
|
|||
text() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
|
||||
},
|
||||
textAlignment() {
|
||||
return this.leftAlignHeader ? "justify-content-start" : "justify-content-center";
|
||||
},
|
||||
subText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "HeaderSubText");
|
||||
},
|
||||
|
|
@ -82,4 +90,8 @@ p.small {
|
|||
.sub-text {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.justify-content-start {
|
||||
padding-left: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -13,13 +13,20 @@ export default {
|
|||
required: true,
|
||||
},
|
||||
cmsWidgetName: String,
|
||||
displayVehicleImage: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
vehicleImageToDisplay() {
|
||||
if (this.displayVehicleImage !== null) {
|
||||
return this.displayVehicleImage;
|
||||
}
|
||||
if (this.displayGenericVehicleImage) {
|
||||
return this.genericVehicleImage;
|
||||
}
|
||||
|
||||
if (
|
||||
this.$store.getters.vehicle.imageUrl === null ||
|
||||
this.$store.getters.vehicle.imageUrl === "NULL"
|
||||
|
|
|
|||
|
|
@ -310,6 +310,16 @@ export function getRouterLinkRouteFromCopy(copy) {
|
|||
return copy.split(":")[1].split(",")[0];
|
||||
}
|
||||
|
||||
export function getExternalLink(copy) {
|
||||
let url = copy.split(":")[1].split(",")[0];
|
||||
if (url.includes("https-")) {
|
||||
const prefixAdded = url.replace("https-", "https://");
|
||||
return prefixAdded;
|
||||
}
|
||||
|
||||
return "#!";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string3 of input following this pattern: {string1:string2,string3}
|
||||
* @returns string
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ async function saveSessionHelper() {
|
|||
storeActions.UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE,
|
||||
{
|
||||
referralNumber: savedSessionInfo.data.referralNumber?.toString(),
|
||||
referralSequenceNumber: savedSessionInfo.data.referralSequenceNumber,
|
||||
referralCorrelationId: savedSessionInfo.data.referralCorrelationId,
|
||||
referralDate: savedSessionInfo.data.referralDate,
|
||||
parentAccountNumber: savedSessionInfo.data.parentAccountNumber?.toString(),
|
||||
|
|
|
|||
10
src/helpers/querystring-helper.js
Normal file
10
src/helpers/querystring-helper.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export function getQuerystringParameter(key) {
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const lowerCaseParams = new URLSearchParams();
|
||||
for (const [name, value] of urlParams) {
|
||||
lowerCaseParams.append(name.toLowerCase(), value);
|
||||
}
|
||||
|
||||
return lowerCaseParams.get(key) ? lowerCaseParams.get(key) : null;
|
||||
}
|
||||
|
|
@ -681,7 +681,6 @@ function setupMocks({
|
|||
},
|
||||
],
|
||||
router: {
|
||||
navigate: jest.fn(),
|
||||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<checkboxQuestion
|
||||
class="mb-5"
|
||||
cmsWidgetName="TextMeQuestionWidget"
|
||||
v-model="isSmsOptin" />
|
||||
v-model="isSmsOptIn" />
|
||||
<textareaQuestion
|
||||
class="mb-4"
|
||||
v-model="techNotes"
|
||||
|
|
@ -110,7 +110,7 @@ export default {
|
|||
lastName: this.getLastNameFromStore(),
|
||||
emailAddress: this.getEmailAddressFromStore(),
|
||||
phoneNumber: this.getPhoneNumberFromStore(),
|
||||
isSmsOptin: this.getIsSmsOptinFromStore(),
|
||||
isSmsOptIn: this.getIsSmsOptInFromStore(),
|
||||
techNotes: this.getTechNotesFromStore(),
|
||||
};
|
||||
},
|
||||
|
|
@ -135,8 +135,8 @@ export default {
|
|||
getPhoneNumberFromStore() {
|
||||
return store.getters.order.customer.phoneNumber;
|
||||
},
|
||||
getIsSmsOptinFromStore() {
|
||||
return store.getters.order.customer.isSmsOptin;
|
||||
getIsSmsOptInFromStore() {
|
||||
return store.getters.order.customer.isSmsOptIn;
|
||||
},
|
||||
getTechNotesFromStore() {
|
||||
return store.getters.order.serviceLocation.techNotes;
|
||||
|
|
@ -152,7 +152,7 @@ export default {
|
|||
lastName: this.lastName,
|
||||
emailAddress: this.emailAddress,
|
||||
phoneNumber: this.phoneNumber,
|
||||
isSmsOptin: this.isSmsOptin,
|
||||
isSmsOptIn: this.isSmsOptIn,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
|
|||
|
|
@ -356,8 +356,12 @@ export default {
|
|||
|
||||
<style lang="scss">
|
||||
.vinLookupMethodHeading p {
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: $black;
|
||||
strong {
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
1
src/layouts/payment-method/payment-method.spec.js
Normal file
1
src/layouts/payment-method/payment-method.spec.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
test.todo("some test to be written in the future");
|
||||
73
src/layouts/payment-method/payment-method.vue
Normal file
73
src/layouts/payment-method/payment-method.vue
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||
<div class="page-container-grouped-styles">
|
||||
<loadingModal ref="loadingModal" />
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" leftAlignHeader />
|
||||
<hr class="mt-0" />
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
:isBackButtonHidden="shouldHideBackButton"
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
|
||||
// Validation
|
||||
import { Form } from "vee-validate";
|
||||
|
||||
export default {
|
||||
name: "payment-method",
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
// TODO: Data fetching Promise declarations
|
||||
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// TODO
|
||||
return true;
|
||||
},
|
||||
backButtonAction() {},
|
||||
forwardButtonAction() {},
|
||||
},
|
||||
components: {
|
||||
funnelHeader,
|
||||
funnelFooter,
|
||||
funnelSubHeader,
|
||||
Form,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
<div class="d-flex">
|
||||
<textBlock
|
||||
:cmsWidgetName="headerCmsWidgetName"
|
||||
:customText="customHeaderText"
|
||||
typeStyle="body small bold dark"
|
||||
marginTopSizeOverride="0" />
|
||||
<textLink
|
||||
|
|
@ -26,9 +27,10 @@ import textBlock from "@/digital-components/text-block/text-block";
|
|||
import textLink from "@/ux-components/text-link/text-link";
|
||||
|
||||
export default {
|
||||
name: "vehicle-review",
|
||||
name: "review-block",
|
||||
props: {
|
||||
headerCmsWidgetName: String,
|
||||
customHeaderText: String,
|
||||
// Specifically an array of strings.
|
||||
content: Array,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<reviewBlock
|
||||
:customHeaderText="headerText"
|
||||
:content="displayContent"
|
||||
@edit-clicked="editClicked" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import reviewBlock from "@/layouts/review/review-block/review-block";
|
||||
|
||||
export default {
|
||||
name: "schedule-review",
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
appointmentType: String,
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
editClicked() {
|
||||
this.$emit("edit-clicked");
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
displayContent() {
|
||||
return [
|
||||
this.getCmsContent(this.cmsWidgetName, "BodyText"),
|
||||
this.getCmsContent(this.cmsWidgetName, "BodyText2"),
|
||||
];
|
||||
},
|
||||
headerText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
|
||||
},
|
||||
},
|
||||
components: {
|
||||
reviewBlock,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -10,7 +10,7 @@ import reviewBlock from "@/layouts/review/review-block/review-block";
|
|||
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||
|
||||
export default {
|
||||
name: "service-package-review",
|
||||
name: "service-location-review",
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
serviceLocation: Object,
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@
|
|||
<textBlock
|
||||
:customText="subHeaderTitle"
|
||||
typeStyle="h5"
|
||||
justifyText="justify-content-center"
|
||||
justifyText="center"
|
||||
margin="mt-1"
|
||||
class="dark-header" />
|
||||
<textBlock
|
||||
:customText="subHeaderBody"
|
||||
typeStyle="body"
|
||||
justifyText="justify-content-left"
|
||||
justifyText="left"
|
||||
margin="mt-0 mb-2" />
|
||||
|
||||
<buttonMain
|
||||
|
|
@ -69,6 +69,13 @@
|
|||
cmsWidgetName="ServiceLocationTitleWidget"
|
||||
:serviceLocation="serviceLocationInfo"
|
||||
@edit-clicked="editServiceLocation" />
|
||||
|
||||
<hr class="my-0" />
|
||||
|
||||
<scheduleReview
|
||||
cmsWidgetName="ScheduleWidget"
|
||||
:appointmentType="appointmentType"
|
||||
@edit-clicked="editSchedule" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -94,22 +101,16 @@ import vehicleReview from "@/layouts/review/review-sections/vehicle-review/vehic
|
|||
import damageReview from "@/layouts/review/review-sections/damage-review/damage-review";
|
||||
import servicePackageReview from "@/layouts/review/review-sections/service-package-review/service-package-review";
|
||||
import serviceLocationReview from "@/layouts/review/review-sections/service-location-review/service-location-review";
|
||||
import scheduleReview from "@/layouts/review/review-sections/schedule-review/schedule-review";
|
||||
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
|
||||
export default {
|
||||
name: "review",
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
// Get rain defense and wiper availability for package review section.
|
||||
const wipersPromise = baseMixin.methods.dispatchStoreAction(storeActions.GET_WIPERS);
|
||||
const rainDefensePromise = baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.GET_RAIN_DEFENSE
|
||||
);
|
||||
|
||||
const servicePackageInitialDataPromise = servicePackageReview.methods.loadInitialData();
|
||||
|
||||
|
|
@ -168,6 +169,12 @@ export default {
|
|||
this.$route
|
||||
);
|
||||
},
|
||||
editSchedule() {
|
||||
this.$router.navigateWithoutSaving(
|
||||
this.navigationScenarios.CLICKED_SCHEDULE_EDIT,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
subHeaderTitle() {
|
||||
|
|
@ -191,6 +198,12 @@ export default {
|
|||
serviceLocationInfo() {
|
||||
return this.$store.getters.order.serviceLocation;
|
||||
},
|
||||
appointmentType() {
|
||||
return this.$store.getters.order.serviceLocation.appointmentType;
|
||||
},
|
||||
exposeCms() {
|
||||
return this.$root.cmsContentByWidget;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
funnelHeader,
|
||||
|
|
@ -202,6 +215,7 @@ export default {
|
|||
damageReview,
|
||||
servicePackageReview,
|
||||
serviceLocationReview,
|
||||
scheduleReview,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -45,3 +45,33 @@ export function sumDateString(dateString, daysToAdd) {
|
|||
date.setDate(date.getDate() + daysToAdd);
|
||||
return convertDateToDateString(date);
|
||||
}
|
||||
|
||||
export function militaryToTwelveHourTime(timeString) {
|
||||
// Expected input: "HH:MM"
|
||||
if (typeof timeString !== "string") return;
|
||||
let hours = parseInt(timeString.split(":")[0]);
|
||||
const minutes = timeString.split(":")[1];
|
||||
const meridianNotation = hours > 11 ? "PM" : "AM";
|
||||
|
||||
if (hours > 12) {
|
||||
hours -= 12;
|
||||
}
|
||||
|
||||
return `${hours}:${minutes} ${meridianNotation}`;
|
||||
}
|
||||
|
||||
export function getDisplayTextForDurationLength(durationMinimum, durationMaximum) {
|
||||
const isLongAppointment = durationMaximum >= 120;
|
||||
const isDurationRange = durationMinimum !== durationMaximum;
|
||||
|
||||
const adjustedMinimum = isLongAppointment ? durationMinimum / 60 : durationMinimum;
|
||||
const adjustedMaximum = isLongAppointment ? durationMaximum / 60 : durationMaximum;
|
||||
|
||||
const durationText = isDurationRange
|
||||
? `${adjustedMinimum} - ${adjustedMaximum}`
|
||||
: adjustedMinimum;
|
||||
|
||||
const unitText = isLongAppointment ? "hours" : "minutes";
|
||||
|
||||
return `${durationText} ${unitText}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,77 @@
|
|||
// Components
|
||||
import schedule from "@/layouts/schedule/schedule.vue";
|
||||
|
||||
// Supporting Files
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import { applicationConfig } from "@/constants/application-config";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import schedule from "@/layouts/schedule/schedule.vue";
|
||||
import store from "@/store";
|
||||
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
||||
import router from "@/router";
|
||||
import { nextTick } from "vue";
|
||||
import baseMixin from "../../mixins/base-mixin";
|
||||
|
||||
jest.mock("@/store", () => ({
|
||||
commit: jest.fn(),
|
||||
dispatch: jest.fn(),
|
||||
// Mock basemixin
|
||||
jest.mock("@/mixins/base-mixin.js", () => ({
|
||||
methods: {
|
||||
dispatchStoreAction: jest.fn().mockImplementation((storeAction) => {
|
||||
if (storeAction === "getShopTimeSlots") {
|
||||
return {
|
||||
data: {
|
||||
estimatedServiceMinutesMinimum: 90,
|
||||
estimatedServiceMinutesMaximum: 120,
|
||||
days: [
|
||||
{
|
||||
date: "2023-12-01",
|
||||
timeSlots: [
|
||||
{
|
||||
id: "06747-01820-S-B*20424*7 AM",
|
||||
startTime: "07:00",
|
||||
endTime: "08:00",
|
||||
offerPremium: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
if (storeAction === "getMobilePremiumFee") {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
partNumber: "EARLY BIRD",
|
||||
description: null,
|
||||
partType: "EARLY BIRD",
|
||||
laborAmount: 0,
|
||||
sellingPrice: 14.99,
|
||||
kitPrice: 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (storeAction === "priceOrderItemsAndSaveServerData") {
|
||||
return Promise.resolve([
|
||||
{
|
||||
partNumber: "EARLY BIRD",
|
||||
description: null,
|
||||
partType: "EARLY BIRD",
|
||||
laborAmount: 0,
|
||||
sellingPrice: 14.99,
|
||||
kitPrice: 0,
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (storeAction === "saveSupportingItemsSuppressingStateResetting") {
|
||||
return Promise.resolve([
|
||||
{
|
||||
partNumber: "EARLY BIRD",
|
||||
description: null,
|
||||
partType: "EARLY BIRD",
|
||||
laborAmount: 0,
|
||||
sellingPrice: 14.99,
|
||||
kitPrice: 0,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock fetchCmsContentForPage
|
||||
|
|
@ -18,50 +80,402 @@ jest.mock("@/helpers/cms-content-helper", () => ({
|
|||
splitCopyOnCMSPlaceHolder: jest.fn(() => ["A", "B"]),
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
"@/store",
|
||||
() => {
|
||||
return {};
|
||||
},
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
store.getters = {
|
||||
order: {
|
||||
schedule: {
|
||||
date: "2020-01-01",
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
jest.clearAllMocks();
|
||||
store.getters = {
|
||||
order: {
|
||||
schedule: {
|
||||
date: "2019-01-01",
|
||||
startTime: "09:00",
|
||||
endTime: "10:00",
|
||||
routeCode: "000",
|
||||
},
|
||||
lineItems: {
|
||||
glassParts: [
|
||||
{
|
||||
partNumber: "ABC123",
|
||||
},
|
||||
],
|
||||
supportingItems: [],
|
||||
},
|
||||
serviceLocation: {
|
||||
appointmentType: "Inshop",
|
||||
zipCode: "12345",
|
||||
zipCodeCtu: "01234",
|
||||
provider: {
|
||||
providerNumber: "123",
|
||||
},
|
||||
},
|
||||
damage: {
|
||||
isRepair: false,
|
||||
},
|
||||
referralNumber: "1234567",
|
||||
},
|
||||
payment: {
|
||||
isInsurance: true,
|
||||
},
|
||||
lineItems: {
|
||||
glassParts: [],
|
||||
supportingItems: [],
|
||||
},
|
||||
serviceLocation: {
|
||||
appointmentType: "Inshop",
|
||||
},
|
||||
},
|
||||
lineItems: {
|
||||
glassParts: [],
|
||||
supportingItems: [],
|
||||
},
|
||||
};
|
||||
};
|
||||
});
|
||||
afterEach(() => {
|
||||
store.getters = {};
|
||||
jest.restoreAllMocks();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("schedule.vue", () => {
|
||||
test("Should navigateWithoutSaving", async () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
router: {
|
||||
navigateWithSaving: jest.fn(),
|
||||
},
|
||||
route: { schedule },
|
||||
},
|
||||
describe("schedule.vue...", () => {
|
||||
describe("initial load", () => {
|
||||
test("should pass arePagePrerequisitesValid with a mobile order and no providerNumber", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
store.getters.order.serviceLocation.appointmentType = "Mobile";
|
||||
store.getters.order.serviceLocation.provider = null;
|
||||
|
||||
//Act
|
||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
||||
//Assert
|
||||
expect(arePagePrerequisitesValid).toBe(true);
|
||||
});
|
||||
test("should pass arePagePrerequisitesValid with a inshop order and providerNumber", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
||||
//Assert
|
||||
expect(arePagePrerequisitesValid).toBe(true);
|
||||
});
|
||||
test("should fail arePagePrerequisitesValid with a replace with no glass parts", async () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
store.getters.order.lineItems.glassParts = [];
|
||||
|
||||
//Act
|
||||
const arePagePrerequisitesValid2 = await wrapper.vm.arePagePrerequisitesValid();
|
||||
|
||||
//Assert
|
||||
expect(arePagePrerequisitesValid2).toBe(false);
|
||||
});
|
||||
test("should fail arePagePrerequisitesValid without isInsurance", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
store.getters.payment.isInsurance = null;
|
||||
|
||||
//Act
|
||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
||||
//Assert
|
||||
expect(arePagePrerequisitesValid).toBe(false);
|
||||
});
|
||||
|
||||
test("should return newShopTimeSlots when getAvailableDatesMethod is called", async () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
|
||||
//Act
|
||||
const newShopTimeSlots = await wrapper.vm.getAvailableDatesMethod(
|
||||
"2023-01-01",
|
||||
"2023-01-31"
|
||||
);
|
||||
|
||||
//Assert
|
||||
expect(newShopTimeSlots).toStrictEqual({
|
||||
days: [
|
||||
{
|
||||
date: "2023-12-01",
|
||||
timeSlots: [
|
||||
{
|
||||
endTime: "08:00",
|
||||
id: "06747-01820-S-B*20424*7 AM",
|
||||
offerPremium: false,
|
||||
startTime: "07:00",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
estimatedServiceMinutesMinimum: 90,
|
||||
estimatedServiceMinutesMaximum: 120,
|
||||
});
|
||||
});
|
||||
|
||||
test("should call API service in day ranges of 34 or less when getAvailableDatesMethod is called with large date ranges", async () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
|
||||
//Act
|
||||
await wrapper.vm.getAvailableDates.call(
|
||||
wrapper.vm,
|
||||
"2023-01-01",
|
||||
"2023-03-31",
|
||||
"Inshop",
|
||||
"123"
|
||||
);
|
||||
|
||||
//Assert
|
||||
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalledTimes(3);
|
||||
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(
|
||||
"getShopTimeSlots",
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
||||
describe("beforeRouteEnter function... ", () => {
|
||||
test("should call next() and call all functions within next", async () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
wrapper.vm.updateFooterButtonText = jest.fn();
|
||||
const nextFunction = jest.fn((c) => {
|
||||
c(wrapper.vm);
|
||||
});
|
||||
|
||||
//Act
|
||||
await schedule.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "schedule" } },
|
||||
undefined,
|
||||
nextFunction
|
||||
);
|
||||
|
||||
//Assert
|
||||
expect(nextFunction).toHaveBeenCalled();
|
||||
expect(wrapper.vm.setCmsContent).toHaveBeenCalledWith("content");
|
||||
expect(wrapper.vm.$refs.datePicker.initializeComponent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
calendarViewDirection: "future",
|
||||
})
|
||||
);
|
||||
expect(wrapper.vm.$refs.locationAlerts.initializeComponent).toHaveBeenCalled();
|
||||
expect(wrapper.vm.selectableDatesData).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
days: expect.any(Array),
|
||||
estimatedServiceMinutesMaximum: expect.any(Number),
|
||||
estimatedServiceMinutesMinimum: expect.any(Number),
|
||||
})
|
||||
);
|
||||
expect(wrapper.vm.mobilePremiumAppointmentFee).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
partNumber: expect.any(String),
|
||||
})
|
||||
);
|
||||
expect(wrapper.vm.updateFooterButtonText).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("computed properties...", () => {
|
||||
test("timeSlotsForSelectedDate should return timeslots if selected date is available", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [
|
||||
{
|
||||
date: "2022-11-11",
|
||||
timeSlots: [
|
||||
{
|
||||
id: "1820I-01820-M-I*20425*AM",
|
||||
startTime: "08:00",
|
||||
endTime: "12:00",
|
||||
offerPremium: true,
|
||||
},
|
||||
{
|
||||
id: "1820I-01820-M-I*20425*PM",
|
||||
startTime: "12:00",
|
||||
endTime: "17:00",
|
||||
offerPremium: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
wrapper.setData({
|
||||
selectedDate: "2022-11-11",
|
||||
});
|
||||
|
||||
//Act
|
||||
const testValue = wrapper.vm.timeSlotsForSelectedDate;
|
||||
|
||||
//Assert
|
||||
expect(testValue).toStrictEqual(
|
||||
expect.objectContaining({
|
||||
date: "2022-11-11",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("timeSlotsForSelectedDate should be null if no date has been selected", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [
|
||||
{
|
||||
date: "2022-11-11",
|
||||
timeSlots: [
|
||||
{
|
||||
id: "1820I-01820-M-I*20425*AM",
|
||||
startTime: "08:00",
|
||||
endTime: "12:00",
|
||||
offerPremium: true,
|
||||
},
|
||||
{
|
||||
id: "1820I-01820-M-I*20425*PM",
|
||||
startTime: "12:00",
|
||||
endTime: "17:00",
|
||||
offerPremium: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
wrapper.setData({
|
||||
selectedDate: undefined,
|
||||
});
|
||||
|
||||
//Act
|
||||
const testValue = wrapper.vm.timeSlotsForSelectedDate;
|
||||
|
||||
//Assert
|
||||
expect(testValue).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("schedule page methods...", () => {
|
||||
test("getServiceZipCtuCodeFromStore should return zipCodeCtu", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
|
||||
//Act
|
||||
const testValue = wrapper.vm.getServiceZipCtuCodeFromStore();
|
||||
|
||||
//Assert
|
||||
expect(testValue).toStrictEqual("01234");
|
||||
});
|
||||
|
||||
test("openInshopTimeSlotsModal should trigger openModal method", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
|
||||
//Act
|
||||
wrapper.vm.openInshopTimeSlotsModal();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$refs.timeSlotModalQuestion.openModal).toBeCalled();
|
||||
});
|
||||
|
||||
test("getSelectedRouteCode should return schedule routeCode", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
|
||||
//Act
|
||||
const testValue = wrapper.vm.getSelectedRouteCode();
|
||||
|
||||
//Assert
|
||||
expect(testValue).toStrictEqual("000");
|
||||
});
|
||||
|
||||
test("timeSlotModalClosed should null any selected date when there's no route code", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
wrapper.setData({
|
||||
selectedDate: "1980-05-05",
|
||||
});
|
||||
wrapper.setData({
|
||||
selectedTimeSlot: {
|
||||
date: "2019-01-01",
|
||||
startTime: "09:00",
|
||||
endTime: "10:00",
|
||||
routeCode: null,
|
||||
},
|
||||
});
|
||||
|
||||
//Act
|
||||
wrapper.vm.timeSlotModalClosed();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.selectedDate).toBe(null);
|
||||
});
|
||||
|
||||
test("getDisplayTextForMilitaryTime should return the correctly formatted string", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
const timeInput1 = "15:00";
|
||||
const timeInput2 = "15:30";
|
||||
|
||||
//Act
|
||||
const testOutput1 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput1);
|
||||
const testOutput2 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput2);
|
||||
const testOutput3 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput1, true);
|
||||
const testOutput4 = wrapper.vm.getDisplayTextForMilitaryTime(timeInput2, true);
|
||||
|
||||
//Assert
|
||||
expect(testOutput1).toBe("3:00 PM");
|
||||
expect(testOutput2).toBe("3:30 PM");
|
||||
expect(testOutput3).toBe("3 PM");
|
||||
expect(testOutput4).toBe("3:30 PM");
|
||||
});
|
||||
|
||||
test("getDisplayTextForMilitaryTime should return the correctly formatted string", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
wrapper.vm.$router.navigateWithoutSaving = jest.fn();
|
||||
wrapper.vm.$route = "testRoute";
|
||||
|
||||
//Act
|
||||
wrapper.vm.backButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
|
||||
"CLICKED_BACK",
|
||||
"testRoute"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("forwardButtonAction should call route method navigateWithoutSaving", async () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||
return {
|
||||
data: [],
|
||||
};
|
||||
});
|
||||
wrapper.vm.$router.navigateWithSaving = jest.fn(() => {
|
||||
return {};
|
||||
});
|
||||
|
||||
//Act
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
|
@ -69,136 +483,123 @@ describe("schedule.vue", () => {
|
|||
//Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
||||
});
|
||||
test("should pass arePagePrerequisitesValid with a mobile order and no providerNumber", () => {
|
||||
|
||||
test("for mobile appts, updateSupportingItems should call store action to save supporting items", async () => {
|
||||
//Arrange
|
||||
store.getters.order.serviceLocation.appointmentType = "Mobile";
|
||||
store.getters.lineItems.supportingItems = [
|
||||
{
|
||||
partNumber: "EARLY BIRD",
|
||||
description: null,
|
||||
partType: "EARLY BIRD",
|
||||
laborAmount: 0,
|
||||
sellingPrice: 0,
|
||||
kitPrice: 0,
|
||||
},
|
||||
];
|
||||
const { wrapper } = setupMocks({});
|
||||
store.getters = {
|
||||
order: {
|
||||
schedule: {
|
||||
date: "2020-01-01",
|
||||
},
|
||||
serviceLocation: {
|
||||
zipCode: "12345",
|
||||
zipCodeCtu: "value",
|
||||
appointmentType: "Mobile",
|
||||
},
|
||||
damage: {
|
||||
isRepair: true,
|
||||
},
|
||||
referralNumber: "1234567",
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||
return {
|
||||
data: [],
|
||||
};
|
||||
});
|
||||
wrapper.vm.mobilePremiumAppointmentFee = 14.99;
|
||||
wrapper.setData({
|
||||
selectedTimeSlot: {
|
||||
date: "2019-01-01",
|
||||
startTime: "09:00",
|
||||
endTime: "10:00",
|
||||
routeCode: null,
|
||||
isPremiumAppointment: true,
|
||||
},
|
||||
payment: {
|
||||
isInsurance: true,
|
||||
},
|
||||
lineItems: {
|
||||
supportingItems: [],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
//Act
|
||||
await wrapper.vm.updateSupportingItems();
|
||||
|
||||
expect(arePagePrerequisitesValid).toBe(true);
|
||||
//Assert
|
||||
expect(wrapper.vm.dispatchStoreAction).toBeCalledWith(
|
||||
"saveSupportingItemsSuppressingStateResetting",
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
partType: "EARLY BIRD",
|
||||
}),
|
||||
]),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
test("should pass arePagePrerequisitesValid with a inshop order and providerNumber", () => {
|
||||
|
||||
test("for Inshop appts, updateSupportingItems should call store action to save supporting items WITHOUT the EARLY BIRD supporting item", async () => {
|
||||
//Arrange
|
||||
store.getters.order.serviceLocation.appointmentType = "Inshop";
|
||||
store.getters.lineItems.supportingItems = [
|
||||
{
|
||||
partNumber: "EARLY BIRD",
|
||||
description: null,
|
||||
partType: "EARLY BIRD",
|
||||
laborAmount: 0,
|
||||
sellingPrice: 0,
|
||||
kitPrice: 0,
|
||||
},
|
||||
];
|
||||
const { wrapper } = setupMocks({});
|
||||
store.getters = {
|
||||
order: {
|
||||
schedule: {
|
||||
date: "2020-01-01",
|
||||
},
|
||||
serviceLocation: {
|
||||
zipCode: "12345",
|
||||
zipCodeCtu: "value",
|
||||
appointmentType: "Inshop",
|
||||
provider: {
|
||||
providerNumber: "5",
|
||||
},
|
||||
},
|
||||
damage: {
|
||||
isRepair: true,
|
||||
},
|
||||
referralNumber: "1234567",
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||
return {
|
||||
data: [],
|
||||
};
|
||||
});
|
||||
wrapper.vm.mobilePremiumAppointmentFee = 14.99;
|
||||
wrapper.setData({
|
||||
selectedTimeSlot: {
|
||||
date: "2019-01-01",
|
||||
startTime: "09:00",
|
||||
endTime: "10:00",
|
||||
routeCode: null,
|
||||
isPremiumAppointment: true,
|
||||
},
|
||||
payment: {
|
||||
isInsurance: true,
|
||||
},
|
||||
lineItems: {
|
||||
supportingItems: [],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
//Act
|
||||
await wrapper.vm.updateSupportingItems();
|
||||
|
||||
expect(arePagePrerequisitesValid).toBe(true);
|
||||
//Assert
|
||||
expect(wrapper.vm.dispatchStoreAction).toBeCalledWith(
|
||||
"saveSupportingItemsSuppressingStateResetting",
|
||||
expect.not.arrayContaining([
|
||||
expect.objectContaining({
|
||||
partType: "EARLY BIRD",
|
||||
}),
|
||||
]),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
test("should fail arePagePrerequisitesValid with a replace with no glass parts", () => {
|
||||
|
||||
test("if no EARLY BIRD supporting item, then updateSupportingItems should NOT call store action", async () => {
|
||||
//Arrange
|
||||
store.getters.order.serviceLocation.appointmentType = "Mobile";
|
||||
store.getters.lineItems.supportingItems = [];
|
||||
const { wrapper } = setupMocks({});
|
||||
store.getters = {
|
||||
order: {
|
||||
schedule: {
|
||||
date: "2020-01-01",
|
||||
},
|
||||
serviceLocation: {
|
||||
zipCode: "12345",
|
||||
zipCodeCtu: "value",
|
||||
appointmentType: "Inshop",
|
||||
provider: {
|
||||
providerNumber: "5",
|
||||
},
|
||||
},
|
||||
damage: {
|
||||
isRepair: false,
|
||||
},
|
||||
referralNumber: "1234567",
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||
return {
|
||||
data: [],
|
||||
};
|
||||
});
|
||||
wrapper.vm.mobilePremiumAppointmentFee = 14.99;
|
||||
wrapper.setData({
|
||||
selectedTimeSlot: {
|
||||
date: "2019-01-01",
|
||||
startTime: "09:00",
|
||||
endTime: "10:00",
|
||||
routeCode: null,
|
||||
isPremiumAppointment: false,
|
||||
},
|
||||
payment: {
|
||||
isInsurance: true,
|
||||
},
|
||||
lineItems: {
|
||||
supportingItems: [],
|
||||
glassParts: [],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
//Act
|
||||
await wrapper.vm.updateSupportingItems();
|
||||
|
||||
expect(arePagePrerequisitesValid).toBe(false);
|
||||
});
|
||||
test("should fail arePagePrerequisitesValid without isInsurance", () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
store.getters = {
|
||||
order: {
|
||||
schedule: {
|
||||
date: "2020-01-01",
|
||||
},
|
||||
serviceLocation: {
|
||||
zipCode: "12345",
|
||||
zipCodeCtu: "value",
|
||||
appointmentType: "Inshop",
|
||||
provider: {
|
||||
providerNumber: "5",
|
||||
},
|
||||
},
|
||||
damage: {
|
||||
isRepair: true,
|
||||
},
|
||||
referralNumber: "1234567",
|
||||
},
|
||||
payment: {
|
||||
isInsurance: null,
|
||||
},
|
||||
lineItems: {
|
||||
supportingItems: [],
|
||||
glassParts: [],
|
||||
},
|
||||
};
|
||||
|
||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
||||
expect(arePagePrerequisitesValid).toBe(false);
|
||||
//Assert
|
||||
expect(wrapper.vm.dispatchStoreAction).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -210,6 +611,7 @@ function setupMocks({ customMountOptions }) {
|
|||
});
|
||||
|
||||
mountOptions.global.mocks["$store"] = store;
|
||||
mountOptions.global.mocks["$router"] = router;
|
||||
mountOptions["attachTo"] = document.body;
|
||||
mountOptions.mixins = [
|
||||
{
|
||||
|
|
@ -223,6 +625,12 @@ function setupMocks({ customMountOptions }) {
|
|||
];
|
||||
|
||||
const wrapper = shallowMount(schedule, mountOptions);
|
||||
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.datePicker.initializeComponent = jest.fn();
|
||||
wrapper.vm.$refs.locationAlerts.initializeComponent = jest.fn();
|
||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||
wrapper.vm.$refs.timeSlotModalQuestion.openModal = jest.fn();
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
0
src/layouts/schedule/schedule.spec.js1
Normal file
0
src/layouts/schedule/schedule.spec.js1
Normal file
|
|
@ -320,6 +320,7 @@ export default {
|
|||
);
|
||||
return newShopTimeSlots;
|
||||
},
|
||||
getAvailableDates,
|
||||
getServiceZipCtuCodeFromStore() {
|
||||
return store.getters.order.serviceLocation.zipCodeCtu;
|
||||
},
|
||||
|
|
@ -338,12 +339,6 @@ export default {
|
|||
getSupportingItems() {
|
||||
return store.getters.lineItems.supportingItems;
|
||||
},
|
||||
isMobilePremiumFeeOnOrderInVuex() {
|
||||
const supportingItemsFromVuex = store.getters.lineItems.supportingItems;
|
||||
return !!supportingItemsFromVuex.filter(
|
||||
(lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE
|
||||
).length;
|
||||
},
|
||||
timeSlotModalClosed() {
|
||||
// Clear the selectedDate if no timeSlot has been selected
|
||||
if (this.selectedTimeSlot.routeCode == null) {
|
||||
|
|
@ -459,6 +454,7 @@ export default {
|
|||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ describe("time-slot-modal-list-button-question.vue", () => {
|
|||
const startTime = "8:00 AM";
|
||||
const endTime = "8:30 AM";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
const expectedEmit = [
|
||||
[
|
||||
{
|
||||
|
|
@ -24,6 +25,7 @@ describe("time-slot-modal-list-button-question.vue", () => {
|
|||
startTime: startTime,
|
||||
endTime: endTime,
|
||||
jobMaxMinutes: jobMaxMinutes.toString(),
|
||||
jobMinMinutes: jobMinMinutes.toString(),
|
||||
},
|
||||
],
|
||||
];
|
||||
|
|
@ -32,6 +34,7 @@ describe("time-slot-modal-list-button-question.vue", () => {
|
|||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -163,11 +166,13 @@ describe("time-slot-modal-list-button-question.vue Supplemental information", ()
|
|||
const startTime = "8:00 AM";
|
||||
const endTime = "8:30 AM";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -201,11 +206,13 @@ describe("time-slot-modal-list-button-question.vue Disclaimer", () => {
|
|||
const startTime = "8:00 AM";
|
||||
const endTime = "8:30 AM";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -288,11 +295,13 @@ describe("time-slot-modal-list-button-question.vue Duration", () => {
|
|||
const startTime = "8:00 AM";
|
||||
const endTime = "8:30 AM";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -434,11 +443,13 @@ describe("time-slot-modal-list-button-question.vue Available Timeslots", () => {
|
|||
const startTime = "8:00 AM";
|
||||
const endTime = "8:30 AM";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -470,11 +481,13 @@ describe("time-slot-modal-list-button-question.vue Available Timeslots", () => {
|
|||
const startTime = "8:00 AM";
|
||||
const endTime = "8:30 AM";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -506,11 +519,13 @@ describe("time-slot-modal-list-button-question.vue Available Timeslots", () => {
|
|||
const startTime = "8:00 AM";
|
||||
const endTime = "8:30 AM";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -542,11 +557,13 @@ describe("time-slot-modal-list-button-question.vue Available Timeslots", () => {
|
|||
const startTime = "8:00";
|
||||
const endTime = "8:30";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
@ -578,11 +595,13 @@ describe("time-slot-modal-list-button-question.vue Available Timeslots", () => {
|
|||
const startTime = "8:00";
|
||||
const endTime = "8:30";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
premiumAppointmentFee: {
|
||||
partType: PREMIUM_FEE_PART_TYPE,
|
||||
},
|
||||
|
|
@ -622,11 +641,13 @@ describe("time-slot-modal-list-button-question.vue Available Timeslots", () => {
|
|||
const startTime = "8:00";
|
||||
const endTime = "8:30";
|
||||
const jobMaxMinutes = 100;
|
||||
const jobMinMinutes = 50;
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
propsData: {
|
||||
estimatedServiceMinutesMaximum: jobMaxMinutes,
|
||||
estimatedServiceMinutesMinimum: jobMinMinutes,
|
||||
dateAndTimeSlotData: {
|
||||
date: date,
|
||||
timeSlots: [
|
||||
|
|
|
|||
|
|
@ -47,7 +47,11 @@ import buttonQuestion from "@/digital-components/button-question/button-question
|
|||
import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button";
|
||||
|
||||
// Helpers
|
||||
import { convertDateStringToDate } from "@/layouts/schedule/helpers/schedule-helper";
|
||||
import {
|
||||
convertDateStringToDate,
|
||||
militaryToTwelveHourTime,
|
||||
getDisplayTextForDurationLength,
|
||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||
import { deepClone } from "@/helpers/object-helper";
|
||||
|
||||
// Validation - TODO: Move this somewhere more global?
|
||||
|
|
@ -88,6 +92,7 @@ export default {
|
|||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
}),
|
||||
},
|
||||
cmsWidgetName: String,
|
||||
|
|
@ -263,7 +268,7 @@ export default {
|
|||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
|
||||
const inshopDurationTime = this.getDisplayTextForDurationLength(
|
||||
const inshopDurationTime = getDisplayTextForDurationLength(
|
||||
this.estimatedServiceMinutesMinimum,
|
||||
this.estimatedServiceMinutesMaximum
|
||||
);
|
||||
|
|
@ -346,33 +351,6 @@ export default {
|
|||
this.$emit("update:modelValue", this.selectedValue);
|
||||
this.closeModal();
|
||||
},
|
||||
getDisplayTextForMilitaryTime(militaryTimeInput) {
|
||||
// Expected input: "HH:MM"
|
||||
let hours = parseInt(militaryTimeInput.split(":")[0]);
|
||||
const minutes = militaryTimeInput.split(":")[1];
|
||||
const meridianNotation = hours > 11 ? "PM" : "AM";
|
||||
|
||||
if (hours > 12) {
|
||||
hours -= 12;
|
||||
}
|
||||
|
||||
return `${hours}:${minutes} ${meridianNotation}`;
|
||||
},
|
||||
getDisplayTextForDurationLength(durationMinimum, durationMaximum) {
|
||||
const isLongAppointment = durationMaximum >= 120;
|
||||
const isDurationRange = durationMinimum !== durationMaximum;
|
||||
|
||||
const adjustedMinimum = isLongAppointment ? durationMinimum / 60 : durationMinimum;
|
||||
const adjustedMaximum = isLongAppointment ? durationMaximum / 60 : durationMaximum;
|
||||
|
||||
const durationText = isDurationRange
|
||||
? `${adjustedMinimum} - ${adjustedMaximum}`
|
||||
: adjustedMinimum;
|
||||
|
||||
const unitText = isLongAppointment ? "hours" : "minutes";
|
||||
|
||||
return `${durationText} ${unitText}`;
|
||||
},
|
||||
getRelevantDropOffCmsWidgetNameForSelectedTimeSlot(
|
||||
selectedTimeSlotId,
|
||||
isSameDayRelevant = false
|
||||
|
|
@ -387,7 +365,7 @@ export default {
|
|||
},
|
||||
getAvailableTimeSlotsForInshop(timeSlotsForSelectedDate) {
|
||||
return timeSlotsForSelectedDate.map((timeSlot) => {
|
||||
const readableTime = this.getDisplayTextForMilitaryTime(timeSlot.startTime);
|
||||
const readableTime = militaryToTwelveHourTime(timeSlot.startTime);
|
||||
return {
|
||||
value: timeSlot.id,
|
||||
buttonLabel: readableTime,
|
||||
|
|
@ -415,9 +393,9 @@ export default {
|
|||
},
|
||||
getAvailableTimeSlotsForMobile(timeSlotsForSelectedDate) {
|
||||
const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => {
|
||||
const readableTime = `${this.getDisplayTextForMilitaryTime(
|
||||
const readableTime = `${militaryToTwelveHourTime(
|
||||
timeSlot.startTime
|
||||
)} - ${this.getDisplayTextForMilitaryTime(timeSlot.endTime)}`;
|
||||
)} - ${militaryToTwelveHourTime(timeSlot.endTime)}`;
|
||||
return {
|
||||
value: timeSlot.id,
|
||||
buttonLabel: readableTime,
|
||||
|
|
@ -472,6 +450,7 @@ export default {
|
|||
startTime: timeSlot.startTime,
|
||||
endTime: timeSlot.endTime,
|
||||
jobMaxMinutes: this.estimatedServiceMinutesMaximum.toString(),
|
||||
jobMinMinutes: this.estimatedServiceMinutesMinimum.toString(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -481,6 +460,7 @@ export default {
|
|||
endTime: null,
|
||||
routeCode: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ jest.mock("@/store", () => ({
|
|||
damage: {
|
||||
glassToReplace: [],
|
||||
},
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
},
|
||||
}));
|
||||
|
||||
|
|
@ -134,7 +133,6 @@ describe("vehicle-damage.vue", () => {
|
|||
getters: {
|
||||
vehicle: {},
|
||||
payment: { insuranceCoverage: { isVerified: false } },
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -177,7 +175,7 @@ describe("vehicle-damage.vue", () => {
|
|||
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(
|
||||
storeActions.GET_DAMAGE_OPTIONS,
|
||||
{ carId: "C00000000", zipCode: "11111" }
|
||||
{ carId: "C00000000" }
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -243,7 +241,6 @@ describe("vehicle-damage.vue", () => {
|
|||
getters: {
|
||||
vehicle: {},
|
||||
payment: { insuranceCoverage: { isVerified: false } },
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -273,7 +270,7 @@ describe("vehicle-damage.vue", () => {
|
|||
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(
|
||||
storeActions.GET_DAMAGE_OPTIONS,
|
||||
{ carId: "C00000000", zipCode: "11111" }
|
||||
{ carId: "C00000000" }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -526,7 +523,6 @@ describe("vehicle-damage.vue", () => {
|
|||
eventBusItem: jest.fn(),
|
||||
damage: { glassToReplace: [{ glassLocation: damageLocation }] },
|
||||
isRepair: true,
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
};
|
||||
|
||||
var glassSelections = wrapper.vm.getDamageLocationsFromStore();
|
||||
|
|
@ -604,7 +600,6 @@ describe("vehicle-damage.vue", () => {
|
|||
isRepair: isRepair,
|
||||
numberOfChips: 2,
|
||||
},
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
};
|
||||
|
||||
var windshieldSelections = wrapper.vm.getWindshieldOptionsFromStore();
|
||||
|
|
@ -641,7 +636,6 @@ describe("vehicle-damage.vue", () => {
|
|||
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
||||
},
|
||||
isRepair: true,
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
};
|
||||
|
||||
var glassSelections = wrapper.vm.getDriverSideReplaceOptionsFromStore();
|
||||
|
|
@ -678,7 +672,6 @@ describe("vehicle-damage.vue", () => {
|
|||
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
||||
},
|
||||
isRepair: true,
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
};
|
||||
|
||||
var glassSelections = wrapper.vm.getPassengerSideReplaceOptionsFromStore();
|
||||
|
|
@ -713,7 +706,6 @@ describe("vehicle-damage.vue", () => {
|
|||
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
|
||||
},
|
||||
isRepair: true,
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
};
|
||||
|
||||
var glassSelections = wrapper.vm.getRearReplaceOptionsFromStore();
|
||||
|
|
@ -746,7 +738,6 @@ describe("vehicle-damage.vue", () => {
|
|||
getters: {
|
||||
vehicle: {},
|
||||
payment: { insuranceCoverage: { isVerified: true } },
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -787,7 +778,6 @@ function setupMocks({ pageHeaderWidgetHeaderText, mountOptionsMockData, funnelCo
|
|||
isVerified: false,
|
||||
},
|
||||
},
|
||||
order: { serviceLocation: { zipCode: "11111" } },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
|||
|
||||
import store from "@/store";
|
||||
import baseMixin from "@/mixins/base-mixin";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule("replace-options-required", required(errorMessages.REPLACE_OPTIONS_REQUIRED));
|
||||
|
||||
|
|
@ -90,20 +89,10 @@ export default {
|
|||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const lowerCaseParams = new URLSearchParams();
|
||||
for (const [name, value] of urlParams) {
|
||||
lowerCaseParams.append(name.toLowerCase(), value);
|
||||
}
|
||||
|
||||
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE)
|
||||
? lowerCaseParams.get(queryStrings.ZIP_CODE)
|
||||
: store.getters.order.serviceLocation.zipCode;
|
||||
|
||||
const damageOptionsPromise = baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.GET_DAMAGE_OPTIONS,
|
||||
{ carId: store.getters.vehicle.carId, zipCode: zip }
|
||||
{ carId: store.getters.vehicle.carId }
|
||||
);
|
||||
|
||||
// Settle promises and get results
|
||||
|
|
@ -146,7 +135,6 @@ export default {
|
|||
},
|
||||
selectedWindshieldOptions: this.getWindshieldOptionsFromStore(),
|
||||
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore(),
|
||||
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -169,18 +157,6 @@ export default {
|
|||
true
|
||||
);
|
||||
}
|
||||
if (this.serviceZipCode) {
|
||||
this.pushEventToGA(
|
||||
this.GaCategories.FUNNEL_ENTRY,
|
||||
this.GaActions.ZIP_CODE_PROVIDED,
|
||||
this.serviceZipCode,
|
||||
true
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
getZipFromStore() {
|
||||
return this.$store.getters.order.serviceLocation.zipCode;
|
||||
},
|
||||
|
||||
backButtonAction() {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
// Components
|
||||
import vehicle from "@/layouts/vehicle/vehicle.vue";
|
||||
|
||||
// Supporting files
|
||||
// Supporting Files
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import { nextTick } from "vue";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||
settleAllPromises: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("vehicle.vue", () => {
|
||||
test('"Continue" button is enabled after YMMS is selected.', async () => {
|
||||
const { wrapper } = setupMocks();
|
||||
|
||||
const continueButton = wrapper.get('[data-test-id="funnel-footer-main-button"]');
|
||||
|
||||
expect(continueButton.attributes()["aria-disabled"]).toBe("false");
|
||||
});
|
||||
|
||||
test("arePagePrerequisitesValid should be true ", async () => {
|
||||
//Arrange
|
||||
const { wrapper } = setupMocks();
|
||||
|
|
@ -26,66 +24,33 @@ describe("vehicle.vue", () => {
|
|||
expect(arePagePrerequisitesValid).toBe(true);
|
||||
});
|
||||
});
|
||||
describe("vehicle.vue", () => {
|
||||
describe("navigation", () => {
|
||||
test("if the continue button is clicked, navigate forward", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks();
|
||||
|
||||
describe("navigation", () => {
|
||||
test("forwardButtonAction should trigger navigateForward", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks();
|
||||
wrapper.vm.navigateForward = jest.fn();
|
||||
// Act
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Act
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const FunnelFooterWidgetMockData = {
|
||||
ForwardButtonText: "Continue",
|
||||
};
|
||||
|
||||
function setupMocks() {
|
||||
const mockRoute = {
|
||||
query: {
|
||||
fmgPage: "vehicle",
|
||||
},
|
||||
};
|
||||
|
||||
const mockRouter = {
|
||||
navigate: jest.fn(),
|
||||
};
|
||||
|
||||
const wrapper = mount(vehicle, {
|
||||
global: {
|
||||
mixins: [
|
||||
{
|
||||
methods: {
|
||||
getCmsContent: jest.fn((cmsWidgetName, fieldName) => {
|
||||
if (cmsWidgetName === "FunnelFooterWidget") {
|
||||
if (fieldName === "ForwardButtonText") {
|
||||
return FunnelFooterWidgetMockData.ForwardButtonText;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}),
|
||||
getFooterInfoBoxHeight: jest.fn(() => 80),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
mocks: {
|
||||
$route: mockRoute,
|
||||
$router: mockRouter,
|
||||
const wrapper = shallowMount(
|
||||
vehicle,
|
||||
getMountOptions({
|
||||
router: {
|
||||
navigate: jest.fn(),
|
||||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
stubs: {
|
||||
FunnelHeader: true,
|
||||
FunnelSubHeader: true,
|
||||
VehicleBanner: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return { mockRoute, mockRouter, wrapper };
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
<vehicleBanner
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
:displayVehicleImage="vehicle.imageUrl"
|
||||
class="mt-5 mb-3"
|
||||
ref="banner" />
|
||||
|
||||
|
|
@ -109,6 +110,13 @@ export default {
|
|||
selectedMake: this.selectedMakefromStore(),
|
||||
selectedModel: this.selectedModelfromStore(),
|
||||
selectedStyle: this.selectedStylefromStore(),
|
||||
vehicle: {
|
||||
carId: null,
|
||||
category: null,
|
||||
imageUrl: null,
|
||||
imageVifNumber: null,
|
||||
imageVifColor: null,
|
||||
},
|
||||
yearOptions: [],
|
||||
makeOptions: [],
|
||||
modelOptions: [],
|
||||
|
|
@ -116,11 +124,6 @@ export default {
|
|||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
validationRules: String,
|
||||
},
|
||||
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
||||
|
|
@ -244,7 +247,8 @@ export default {
|
|||
const result = await this.getModelOptions(this.selectedYear, make);
|
||||
this.modelOptions = result?.data;
|
||||
if (this.selectedMakefromStore() !== make) {
|
||||
this.selectedModel = null;
|
||||
if (this.modelOptions.length === 1) this.selectedModel = this.modelOptions[0];
|
||||
else this.selectedModel = null;
|
||||
this.selectedStyle = null;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -260,36 +264,40 @@ export default {
|
|||
);
|
||||
this.styleOptions = result?.data;
|
||||
if (this.selectedModelfromStore() !== model) {
|
||||
this.selectedStyle = null;
|
||||
if (this.styleOptions.length === 1) this.selectedStyle = this.styleOptions[0];
|
||||
else this.selectedStyle = null;
|
||||
}
|
||||
} else {
|
||||
this.styleOptions = [];
|
||||
}
|
||||
},
|
||||
selectedStyle(style) {
|
||||
this.setVehicle(this.selectedYear, this.selectedMake, this.selectedModel, style);
|
||||
async selectedStyle(style) {
|
||||
if (style) {
|
||||
const result = await this.getVehicle(
|
||||
this.selectedYear,
|
||||
this.selectedMake,
|
||||
this.selectedModel,
|
||||
style
|
||||
);
|
||||
this.vehicle = result?.data;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
setVehicle(year, make, model, style) {
|
||||
return this.dispatchStoreAction(this.storeActions.SET_VEHICLE, {
|
||||
getVehicle(year, make, model, style) {
|
||||
return this.dispatchStoreAction(this.storeActions.GET_VEHICLE, {
|
||||
year: year,
|
||||
make: make,
|
||||
model: model,
|
||||
style: style,
|
||||
});
|
||||
},
|
||||
|
||||
arePagePrerequisitesValid() {
|
||||
return true;
|
||||
},
|
||||
|
||||
async forwardButtonAction() {
|
||||
return this.navigateForward();
|
||||
},
|
||||
|
||||
navigateForward() {
|
||||
this.dispatchStoreAction(
|
||||
storeActions.SAVE_VEHICLE,
|
||||
{
|
||||
|
|
@ -297,12 +305,12 @@ export default {
|
|||
make: this.selectedMake,
|
||||
model: this.selectedModel,
|
||||
style: this.selectedStyle,
|
||||
vehicle: this.vehicle,
|
||||
},
|
||||
false
|
||||
);
|
||||
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||
},
|
||||
|
||||
initializeYearComponent(initialData) {
|
||||
this.yearOptions = initialData;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ export default {
|
|||
event: pageEvent,
|
||||
shouldUseSessionId: false,
|
||||
experimentsForUser: store.getters.applicationUser.experiments,
|
||||
referralSequenceNumber: store.getters.order.referralSequenceNumber,
|
||||
parentAccountNumber: store.getters.order.payment.parentAccountNumber,
|
||||
};
|
||||
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false);
|
||||
|
|
@ -57,6 +59,8 @@ export default {
|
|||
value: value,
|
||||
shouldUseSessionId: false,
|
||||
experimentsForUser: store.getters.applicationUser.experiments,
|
||||
referralSequenceNumber: store.getters.order.referralSequenceNumber,
|
||||
parentAccountNumber: store.getters.order.payment.parentAccountNumber,
|
||||
};
|
||||
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.LOG_CUSTOM_EVENT, payload, false);
|
||||
|
|
|
|||
|
|
@ -29,12 +29,18 @@ import { experimentTriggers } from "../constants/experiments";
|
|||
import { applicationConfig } from "../constants/application-config";
|
||||
|
||||
import review from "@/layouts/review/review";
|
||||
import paymentMethod from "@/layouts/payment-method/payment-method";
|
||||
const routes = [
|
||||
{
|
||||
path: "/review", // This is a temporary route for testing.
|
||||
name: "review",
|
||||
component: review,
|
||||
},
|
||||
{
|
||||
path: "/payment-method", // This is a temporary route for testing.
|
||||
name: "payment-method",
|
||||
component: paymentMethod,
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
name: "root",
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ const fmgPageValues = {
|
|||
SCHEDULE: "schedule",
|
||||
CUSTOMER_DETAILS: "customer-details",
|
||||
REVIEW: "review",
|
||||
PAYMENT_METHOD: "payment-method",
|
||||
};
|
||||
|
||||
export { fmgPageValues };
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ const navigationScenarios = {
|
|||
CLICKED_DAMAGE_EDIT: "CLICKED_DAMAGE_EDIT",
|
||||
CLICKED_SERVICE_PACKAGE_EDIT: "CLICKED_SERVICE_PACKAGE_EDIT",
|
||||
CLICKED_SERVICE_LOCATION_EDIT: "CLICKED_SERVICE_LOCATION_EDIT",
|
||||
CLICKED_SCHEDULE_EDIT: "CLICKED_SCHEDULE_EDIT",
|
||||
};
|
||||
|
||||
export { navigationScenarios };
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@ const routingTable = function (store) {
|
|||
scenario: navigationScenarios.CLICKED_SERVICE_LOCATION_EDIT,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_SCHEDULE_EDIT,
|
||||
destinationFmgPageValue: fmgPageValues.SCHEDULE,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -13,7 +13,14 @@ import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
|||
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
|
||||
import { deepEqual } from "@/helpers/object-helper";
|
||||
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
|
||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||
import {
|
||||
convertDateStringToDate,
|
||||
militaryToTwelveHourTime,
|
||||
getDisplayTextForDurationLength,
|
||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||
|
||||
// Export State
|
||||
const getDefaultState = () => {
|
||||
|
|
@ -66,7 +73,7 @@ const getDefaultState = () => {
|
|||
lastName: null,
|
||||
emailAddress: null,
|
||||
phoneNumber: null,
|
||||
isSmsOptin: null,
|
||||
isSmsOptIn: null,
|
||||
},
|
||||
damage: {
|
||||
isRepair: null,
|
||||
|
|
@ -96,8 +103,10 @@ const getDefaultState = () => {
|
|||
endTime: null,
|
||||
routeCode: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
},
|
||||
referralNumber: null,
|
||||
referralSequenceNumber: null,
|
||||
referralDate: null,
|
||||
referralCorrelationId: null,
|
||||
eon: null,
|
||||
|
|
@ -190,6 +199,9 @@ export const mutations = {
|
|||
updateReferralNumber(state, referralNumber) {
|
||||
state.order.referralNumber = referralNumber;
|
||||
},
|
||||
updateReferralSequenceNumber(state, referralSequenceNumber) {
|
||||
state.order.referralSequenceNumber = referralSequenceNumber;
|
||||
},
|
||||
updateReferralDate(state, referralDate) {
|
||||
state.order.referralDate = referralDate;
|
||||
},
|
||||
|
|
@ -283,6 +295,7 @@ export const mutations = {
|
|||
state.order.schedule.endTime = scheduleInfo.endTime;
|
||||
state.order.schedule.routeCode = scheduleInfo.routeCode;
|
||||
state.order.schedule.jobMaxMinutes = scheduleInfo.jobMaxMinutes;
|
||||
state.order.schedule.jobMinMinutes = scheduleInfo.jobMinMinutes;
|
||||
}
|
||||
},
|
||||
updateCustomerDetails(state, customerDetails) {
|
||||
|
|
@ -291,7 +304,7 @@ export const mutations = {
|
|||
state.order.customer.lastName = customerDetails.lastName;
|
||||
state.order.customer.emailAddress = customerDetails.emailAddress;
|
||||
state.order.customer.phoneNumber = customerDetails.phoneNumber;
|
||||
state.order.customer.isSmsOptin = customerDetails.isSmsOptin;
|
||||
state.order.customer.isSmsOptIn = customerDetails.isSmsOptIn;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -368,6 +381,7 @@ export const mutations = {
|
|||
state.order.schedule.endTime = null;
|
||||
state.order.schedule.routeCode = null;
|
||||
state.order.schedule.jobMaxMinutes = null;
|
||||
state.order.schedule.jobMinMinutes = null;
|
||||
|
||||
//premium appointment fee used on schedule page also needs reset when schedule is reset
|
||||
const supportingItems = state.order.lineItems.supportingItems;
|
||||
|
|
@ -411,6 +425,7 @@ export const mutations = {
|
|||
// Misc Mutations
|
||||
updateStateWithOrderInformation(state, sessionInformation) {
|
||||
state.order.referralNumber = sessionInformation.order.referralNumber;
|
||||
state.order.referralSequenceNumber = sessionInformation.order.referralSequenceNumber;
|
||||
state.order.referralDate = sessionInformation.order.referralDate;
|
||||
state.order.referralCorrelationId = sessionInformation.order.referralCorrelationId;
|
||||
state.order.eon = sessionInformation.order.eon;
|
||||
|
|
@ -493,7 +508,7 @@ export const mutations = {
|
|||
state.order.customer.firstName = sessionInformation.order.customer.firstName;
|
||||
state.order.customer.lastName = sessionInformation.order.customer.lastName;
|
||||
state.order.customer.phoneNumber = sessionInformation.order.customer.phoneNumber;
|
||||
state.order.customer.isSmsOptin = sessionInformation.order.customer.isSmsOptin;
|
||||
state.order.customer.isSmsOptIn = sessionInformation.order.customer.isSmsOptIn;
|
||||
|
||||
state.order.existingPromoCode = sessionInformation.order.existingPromoCode;
|
||||
state.applicationUser.experiments = sessionInformation.applicationUser.experiments;
|
||||
|
|
@ -506,6 +521,7 @@ export const mutations = {
|
|||
state.order.schedule.endTime = sessionInformation.order.schedule?.endTime;
|
||||
state.order.schedule.routeCode = sessionInformation.order.schedule?.routeCode;
|
||||
state.order.schedule.jobMaxMinutes = sessionInformation.order.schedule?.jobMaxMinutes;
|
||||
state.order.schedule.jobMinMinutes = sessionInformation.order.schedule?.jobMinMinutes;
|
||||
},
|
||||
updateExperiments(state, experiments) {
|
||||
state.applicationUser.experiments = experiments;
|
||||
|
|
@ -540,6 +556,9 @@ export const getters = {
|
|||
isMobileAppointment: (state) => {
|
||||
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
||||
},
|
||||
isDropOffAppointment: (state) => {
|
||||
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF;
|
||||
},
|
||||
isRecalibrationOnOrder: (state) => {
|
||||
return getHasRecalibrationPart(state);
|
||||
},
|
||||
|
|
@ -548,6 +567,30 @@ export const getters = {
|
|||
(vap) => vap.partType.toUpperCase() === partTypeStrings.REAR_WIPER.toUpperCase()
|
||||
);
|
||||
},
|
||||
scheduleDisplayText: (state) => {
|
||||
const dateModel = convertDateStringToDate(state.order.schedule.date);
|
||||
const readableDate = dateModel?.toLocaleDateString("en-us", {
|
||||
weekday: "long",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
});
|
||||
|
||||
const readableStartTime = militaryToTwelveHourTime(state.order.schedule.startTime);
|
||||
const readableEndTime = militaryToTwelveHourTime(state.order.schedule.endTime);
|
||||
|
||||
const readableDuration = getDisplayTextForDurationLength(
|
||||
state.order.schedule.jobMinMinutes,
|
||||
state.order.schedule.jobMaxMinutes
|
||||
);
|
||||
|
||||
return {
|
||||
date: readableDate,
|
||||
startTime: readableStartTime,
|
||||
endTime: readableEndTime,
|
||||
duration: readableDuration,
|
||||
};
|
||||
},
|
||||
lineItems: (state) => state.order.lineItems,
|
||||
pageData: (state) => (page) => {
|
||||
return state.applicationUser.pageData[page];
|
||||
|
|
@ -739,7 +782,7 @@ export const actions = {
|
|||
});
|
||||
},
|
||||
|
||||
setVehicle(context, { year, make, model, style }) {
|
||||
getVehicle(context, { year, make, model, style }) {
|
||||
return globalMethods
|
||||
.callHttpClient({
|
||||
methods: endpoints.GetVehicle.method,
|
||||
|
|
@ -747,27 +790,17 @@ export const actions = {
|
|||
payload: {},
|
||||
})
|
||||
.then((response) => {
|
||||
context.commit(storeMutations.UPDATE_CAR_ID, response.data.carId);
|
||||
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, response.data.category);
|
||||
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, response.data.imageUrl);
|
||||
context.commit(
|
||||
storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER,
|
||||
response.data.imageVifNumber
|
||||
);
|
||||
context.commit(
|
||||
storeMutations.UPDATE_VEHICLE_IMAGE_COLOR,
|
||||
response.data.imageVifColor
|
||||
);
|
||||
return response;
|
||||
});
|
||||
},
|
||||
|
||||
getDamageOptions(context, { carId, zipCode }) {
|
||||
getDamageOptions(context, { carId }) {
|
||||
return globalMethods.callHttpClient({
|
||||
methods: endpoints.GetDamageOptions.method,
|
||||
endpoint: `${endpoints.GetDamageOptions.url}/${carId}`,
|
||||
payload: {},
|
||||
additionalSuccessEventDataHandler: (response) => "QueryStringZip: " + zipCode,
|
||||
additionalSuccessEventDataHandler: (response) =>
|
||||
"QueryStringZip: " + getQuerystringParameter(queryStrings.ZIP_CODE),
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -883,6 +916,7 @@ export const actions = {
|
|||
context,
|
||||
{
|
||||
referralNumber,
|
||||
referralSequenceNumber,
|
||||
referralDate,
|
||||
referralCorrelationId,
|
||||
eon,
|
||||
|
|
@ -892,6 +926,7 @@ export const actions = {
|
|||
}
|
||||
) {
|
||||
context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
|
||||
context.commit(storeMutations.UPDATE_REFERRAL_SEQUENCE_NUMBER, referralSequenceNumber);
|
||||
context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate);
|
||||
context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId);
|
||||
context.commit(storeMutations.UPDATE_EON, eon);
|
||||
|
|
@ -911,6 +946,8 @@ export const actions = {
|
|||
event,
|
||||
shouldUseSessionId,
|
||||
experimentsForUser,
|
||||
referralSequenceNumber,
|
||||
parentAccountNumber,
|
||||
}
|
||||
) {
|
||||
var payload = {
|
||||
|
|
@ -923,6 +960,8 @@ export const actions = {
|
|||
event: event,
|
||||
shouldUseSessionId: shouldUseSessionId,
|
||||
experimentsForUser: experimentsForUser,
|
||||
referralSequenceNumber: referralSequenceNumber,
|
||||
parentAccountNumber: parentAccountNumber,
|
||||
};
|
||||
|
||||
return globalMethods
|
||||
|
|
@ -955,6 +994,8 @@ export const actions = {
|
|||
value,
|
||||
shouldUseSessionId,
|
||||
experimentsForUser,
|
||||
referralSequenceNumber,
|
||||
parentAccountNumber,
|
||||
}
|
||||
) {
|
||||
var payload = {
|
||||
|
|
@ -969,6 +1010,8 @@ export const actions = {
|
|||
value: value,
|
||||
shouldUseSessionId: shouldUseSessionId,
|
||||
experimentsForUser: experimentsForUser,
|
||||
referralSequenceNumber: referralSequenceNumber,
|
||||
parentAccountNumber: parentAccountNumber,
|
||||
};
|
||||
|
||||
return globalMethods
|
||||
|
|
@ -1417,7 +1460,7 @@ export const actions = {
|
|||
emailAddress: order.customer.emailAddress,
|
||||
firstName: order.customer.firstName,
|
||||
lastName: order.customer.lastName,
|
||||
isSmsOptin: order.customer.isSmsOptin,
|
||||
isSmsOptIn: order.customer.isSmsOptIn,
|
||||
phoneNumber: order.customer.phoneNumber,
|
||||
},
|
||||
damage: {
|
||||
|
|
@ -1469,12 +1512,13 @@ export const actions = {
|
|||
endTime: order.schedule?.endTime,
|
||||
routeCode: order.schedule?.routeCode,
|
||||
jobMaxMinutes: order.schedule?.jobMaxMinutes,
|
||||
jobMinMinutes: order.schedule?.jobMinMinutes,
|
||||
},
|
||||
existingPromoCode: null,
|
||||
referralCorrelationId: order.referralCorrelationId,
|
||||
referralDate: order.referralDate,
|
||||
referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place
|
||||
referralSequenceNumber: order.referralNumber?.toString(), // TODO Pass the referralSequence number once insurance flow creates it
|
||||
referralNumber: order.referralNumber?.toString(),
|
||||
referralSequenceNumber: order.referralSequenceNumber,
|
||||
eon: order.eon,
|
||||
},
|
||||
},
|
||||
|
|
@ -1624,9 +1668,7 @@ export const actions = {
|
|||
}
|
||||
},
|
||||
|
||||
saveVehicle(context, { year, make, model, style }) {
|
||||
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
||||
saveVehicle(context, { year, make, model, style, vehicle }) {
|
||||
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||
|
||||
if (context.state.order.vehicle.year !== year) {
|
||||
|
|
@ -1641,6 +1683,11 @@ export const actions = {
|
|||
if (context.state.order.vehicle.style !== style) {
|
||||
context.commit(storeMutations.UPDATE_STYLE, style);
|
||||
}
|
||||
context.commit(storeMutations.UPDATE_CAR_ID, vehicle.carId);
|
||||
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicle.category);
|
||||
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicle.imageUrl);
|
||||
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicle.imageVifNumber);
|
||||
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicle.imageVifColor);
|
||||
},
|
||||
|
||||
saveVehicleDamage(
|
||||
|
|
@ -2064,12 +2111,6 @@ export const actions = {
|
|||
return true;
|
||||
default:
|
||||
}
|
||||
if (
|
||||
context.state.order.vehicle.make.toLowerCase() === "ford" &&
|
||||
context.state.order.vehicle.year >= 2018
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
context.state.order.vehicle.make.toLowerCase() === "bmw" &&
|
||||
context.state.order.vehicle.year <= 2017
|
||||
|
|
|
|||
|
|
@ -335,6 +335,28 @@ describe("Mutations", () => {
|
|||
expect(storeState.order.serviceLocation.state).toEqual("OH");
|
||||
expect(storeState.order.serviceLocation.zipCodeCtu).toEqual("01820");
|
||||
});
|
||||
|
||||
it("updateCustomerDetails, should set customer details in state", () => {
|
||||
// Arrange
|
||||
const storeState = state;
|
||||
const customerDetails = {
|
||||
firstName: "foo",
|
||||
lastName: "bar",
|
||||
emailAddress: "foo@bar.com",
|
||||
phoneNumber: "555-555-5555",
|
||||
isSmsOptIn: true,
|
||||
};
|
||||
|
||||
// Act
|
||||
mutations.updateCustomerDetails(storeState, customerDetails);
|
||||
|
||||
// Assert
|
||||
expect(state.order.customer.firstName).toEqual("foo");
|
||||
expect(state.order.customer.lastName).toEqual("bar");
|
||||
expect(state.order.customer.emailAddress).toEqual("foo@bar.com");
|
||||
expect(state.order.customer.phoneNumber).toEqual("555-555-5555");
|
||||
expect(state.order.customer.isSmsOptIn).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Actions", () => {
|
||||
|
|
@ -484,12 +506,9 @@ describe("Actions", () => {
|
|||
expect(response.data).toEqual({ style: "4 DOOR SEDAN" });
|
||||
});
|
||||
|
||||
it("setVehicle action, should get vehicle data and set carId and vehicle category", async () => {
|
||||
it("getVehicle action, should get vehicle data ", async () => {
|
||||
// Arrange
|
||||
const context = state;
|
||||
const commit = jest.fn();
|
||||
|
||||
context.commit = commit;
|
||||
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
|
|
@ -497,10 +516,8 @@ describe("Actions", () => {
|
|||
});
|
||||
|
||||
// Assert
|
||||
const response = await actions.setVehicle(context, "C00000000");
|
||||
const response = await actions.getVehicle(context, "C00000000");
|
||||
|
||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, "C00000000");
|
||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, "CAR");
|
||||
expect(response.data).toEqual({ carId: "C00000000", category: "CAR" });
|
||||
});
|
||||
|
||||
|
|
@ -802,6 +819,7 @@ describe("Actions", () => {
|
|||
// Act
|
||||
actions.updateStoreWithSaveSessionResponse(context, {
|
||||
referralNumber: "123",
|
||||
referralSequenceNumber: 123,
|
||||
referralDate: new Date().toUTCString(),
|
||||
referralCorrelationId: "xxx-xxx-xxx",
|
||||
parentAccountNumber: "167132",
|
||||
|
|
@ -943,7 +961,7 @@ describe("Actions", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("saveServiceZipCodeInfo, should call mutation and save zip code to state", () => {
|
||||
it("saveServiceZipCodeInfo, should call mutation", () => {
|
||||
// Arrange
|
||||
const context = state;
|
||||
const commit = jest.fn();
|
||||
|
|
@ -958,7 +976,6 @@ describe("Actions", () => {
|
|||
|
||||
// Assert
|
||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_SERVICE_LOCATION, serviceZipCodeInfo);
|
||||
expect(state.order.serviceLocation.zipCode).toEqual("43212");
|
||||
});
|
||||
|
||||
it("saveServiceZipCodeInfo, should reset if zip code is different", () => {
|
||||
|
|
@ -1027,7 +1044,7 @@ describe("Actions", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("saveServiceLocation, should call mutation and save service address to state", () => {
|
||||
it("saveServiceLocation, should call mutation", () => {
|
||||
// Arrange
|
||||
const context = state;
|
||||
const commit = jest.fn();
|
||||
|
|
@ -1046,11 +1063,6 @@ describe("Actions", () => {
|
|||
|
||||
// Assert
|
||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_SERVICE_LOCATION, serviceLocation);
|
||||
expect(state.order.serviceLocation.address).toEqual("123 Test Lane");
|
||||
expect(state.order.serviceLocation.city).toEqual("Columbus");
|
||||
expect(state.order.serviceLocation.zipCode).toEqual("43212");
|
||||
expect(state.order.serviceLocation.state).toEqual("OH");
|
||||
expect(state.order.serviceLocation.zipCodeCtu).toEqual("01820");
|
||||
});
|
||||
|
||||
it("saveServiceLocation, should reset if zipcode is different", () => {
|
||||
|
|
@ -1297,6 +1309,27 @@ describe("Actions", () => {
|
|||
expect(commit).not.toHaveBeenCalledWith(storeMutations.RESET_SCHEDULE);
|
||||
});
|
||||
|
||||
it("saveCustomerDetails, should call mutation", () => {
|
||||
// Arrange
|
||||
const context = state;
|
||||
const commit = jest.fn();
|
||||
context.commit = commit;
|
||||
|
||||
const customerDetails = {
|
||||
firstName: "foo",
|
||||
lastName: "bar",
|
||||
emailAddress: "foo@bar.com",
|
||||
phoneNumber: "555-555-5555",
|
||||
isSmsOptIn: true,
|
||||
};
|
||||
|
||||
// Act
|
||||
actions.saveCustomerDetails(context, customerDetails);
|
||||
|
||||
// Assert
|
||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_CUSTOMER_DETAILS, customerDetails);
|
||||
});
|
||||
|
||||
it("saveGlassParts, should call mutation", () => {
|
||||
// Arrange
|
||||
const context = {
|
||||
|
|
@ -1729,18 +1762,14 @@ describe("Actions", () => {
|
|||
make: "Honda",
|
||||
model: "Civic",
|
||||
style: "Sedan",
|
||||
vehicle: {
|
||||
carId: "C00000000",
|
||||
category: "CAR",
|
||||
},
|
||||
};
|
||||
actions.saveVehicle(context, payload);
|
||||
|
||||
//Assert
|
||||
expect(dispatch).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
|
||||
);
|
||||
expect(dispatch).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
|
||||
);
|
||||
if (context.state.order.vehicle.year !== payload.year) {
|
||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_YEAR, payload.year);
|
||||
}
|
||||
|
|
@ -1753,6 +1782,8 @@ describe("Actions", () => {
|
|||
if (context.state.order.vehicle.style !== payload.style) {
|
||||
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, payload.style);
|
||||
}
|
||||
context.commit(storeMutations.UPDATE_CAR_ID, payload.vehicle.carId);
|
||||
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, payload.vehicle.category);
|
||||
});
|
||||
|
||||
it("saveVehicleDamage, should wipe out damage if different", () => {
|
||||
|
|
@ -3291,8 +3322,6 @@ describe("Getters", () => {
|
|||
describe("isVinOptionalVehicle", () => {
|
||||
const testVehicles = [
|
||||
["2017", "acura", false],
|
||||
["2017", "ford", false],
|
||||
["2018", "ford", true],
|
||||
["2018", "bmw", false],
|
||||
["2017", "bmw", true],
|
||||
["2016", "bmw", true],
|
||||
|
|
|
|||
Loading…
Reference in a new issue