@@ -94,22 +108,20 @@ 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 customerReview from "@/layouts/review/review-sections/customer-review/customer-review";
+
+import { AppointmentTypeStrings } from "@/constants/schedule-constants";
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";
+import store from "@/store";
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();
@@ -138,7 +150,75 @@ export default {
},
methods: {
arePagePrerequisitesValid() {
- return true;
+ // Vehicle
+ const vehicle = store.getters.order.vehicle;
+ const vehicleReqs = !!(vehicle.year && vehicle.make && vehicle.model && vehicle.style);
+
+ // Damage
+ const damage = store.getters.order.damage;
+ const damageReqs = !!(
+ (damage.isRepair && damage.numberOfChips) ||
+ (!damage.isRepair && damage.glassToReplace?.length)
+ );
+
+ // Service Package
+ const lineItems = store.getters.order.lineItems;
+ // damageReqs handles checking for damage, even though it is also required for this section.
+ const packageReqs = !!(
+ (damage.isRepair || lineItems.glassParts) &&
+ lineItems.supportingItems &&
+ lineItems.vaps
+ );
+
+ // Service Location
+ const serviceLocation = store.getters.order.serviceLocation;
+ const mobileReqs = !!(
+ serviceLocation.address &&
+ serviceLocation.city &&
+ serviceLocation.state &&
+ serviceLocation.zipCode
+ );
+
+ const providerLocation = serviceLocation.provider.address;
+ const dropOffInshopReqs = !!(
+ providerLocation.streetAddress &&
+ providerLocation.city &&
+ providerLocation.state &&
+ providerLocation.zipCode
+ );
+
+ const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
+
+ const serviceLocationReqs =
+ (isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
+
+ // Schedule
+ const schedule = store.getters.order.schedule;
+ const scheduleReqs = !!(
+ schedule.date &&
+ schedule.startTime &&
+ schedule.endTime &&
+ schedule.jobMaxMinutes &&
+ schedule.jobMinMinutes
+ );
+
+ // Customer
+ const customer = store.getters.order.customer;
+ const customerReqs = !!(
+ customer.firstName &&
+ customer.lastName &&
+ customer.phoneNumber &&
+ customer.emailAddress
+ );
+
+ return (
+ vehicleReqs &&
+ damageReqs &&
+ packageReqs &&
+ serviceLocationReqs &&
+ scheduleReqs &&
+ customerReqs
+ );
},
backButtonAction() {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
@@ -168,6 +248,18 @@ export default {
this.$route
);
},
+ editSchedule() {
+ this.$router.navigateWithoutSaving(
+ this.navigationScenarios.CLICKED_SCHEDULE_EDIT,
+ this.$route
+ );
+ },
+ editCustomerDetails() {
+ this.$router.navigateWithoutSaving(
+ this.navigationScenarios.CLICKED_CUSTOMER_EDIT,
+ this.$route
+ );
+ },
},
computed: {
subHeaderTitle() {
@@ -191,6 +283,12 @@ export default {
serviceLocationInfo() {
return this.$store.getters.order.serviceLocation;
},
+ appointmentType() {
+ return this.$store.getters.order.serviceLocation.appointmentType;
+ },
+ customerInfo() {
+ return this.$store.getters.order.customer;
+ },
},
components: {
funnelHeader,
@@ -202,6 +300,8 @@ export default {
damageReview,
servicePackageReview,
serviceLocationReview,
+ scheduleReview,
+ customerReview,
},
};
diff --git a/src/layouts/schedule/helpers/schedule-helper.js b/src/layouts/schedule/helpers/schedule-helper.js
index 82c756b5b..0f595b435 100644
--- a/src/layouts/schedule/helpers/schedule-helper.js
+++ b/src/layouts/schedule/helpers/schedule-helper.js
@@ -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}`;
+}
diff --git a/src/layouts/schedule/schedule.spec.js b/src/layouts/schedule/schedule.spec.js
index 2c4bafc33..b47036c10 100644
--- a/src/layouts/schedule/schedule.spec.js
+++ b/src/layouts/schedule/schedule.spec.js
@@ -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 };
}
diff --git a/src/layouts/schedule/schedule.spec.js1 b/src/layouts/schedule/schedule.spec.js1
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue
index 5bebe26fb..00b3e796b 100644
--- a/src/layouts/schedule/schedule.vue
+++ b/src/layouts/schedule/schedule.vue
@@ -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,
};
}
},
diff --git a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js
index 43d997892..93f8cfe01 100644
--- a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js
+++ b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js
@@ -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: [
diff --git a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue
index 724facf6c..cce2c0503 100644
--- a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue
+++ b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue
@@ -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,
};
},
},
diff --git a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
index 31c415a2d..9a0fb063e 100644
--- a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
+++ b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
@@ -88,7 +88,7 @@ export default {
if (this.availabilityRating == null) {
return "gray";
} else {
- return this.availabilityRating == "high" ? "green" : "red";
+ return this.availabilityRating == "high" ? "green" : "Orange";
}
},
badgeText() {
diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js
index 30e144310..b26b5e31c 100644
--- a/src/layouts/vehicle-damage/vehicle-damage.spec.js
+++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js
@@ -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" } },
},
},
};
diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue
index 6ea4fe81d..c03fabda1 100644
--- a/src/layouts/vehicle-damage/vehicle-damage.vue
+++ b/src/layouts/vehicle-damage/vehicle-damage.vue
@@ -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() {
diff --git a/src/layouts/vehicle-make/make-question/make-question.spec.js b/src/layouts/vehicle-make/make-question/make-question.spec.js
deleted file mode 100644
index 7025c118c..000000000
--- a/src/layouts/vehicle-make/make-question/make-question.spec.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
-import { shallowMount } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import store from "@/store";
-jest.mock(
- "@/store",
- () => {
- return {};
- },
- { virtual: true }
-);
-
-describe("make-question.vue", () => {
- test("Selected make is emitted upon selection.", async () => {
- //Arrange
- const { wrapper } = setupMocks({ modelValueProp: "honda" });
- const makeToSelect = "ford";
-
- //Act
- wrapper.setValue({ selectedMake: makeToSelect });
- await wrapper.vm.$nextTick();
-
- //Assert
- expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ selectedMake: "ford" }]);
- });
-});
-
-describe("make-question.vue", () => {
- test("Data from store api are used as radio question answers.", async () => {
- //Arrange
- const { wrapper, cmsContent } = setupMocks({
- dataFromStoreApi: ["honda", "ford", "dodge"],
- });
-
- //Act
- const initialData = makeQuestion.methods.loadInitialData.call(wrapper.vm);
- makeQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
-
- //Assert
- const buttonQuestionComponent = await wrapper.findComponent({
- name: "buttonQuestion",
- });
- expect(buttonQuestionComponent.attributes("answers")).toBe("honda,ford,dodge");
- });
-});
-
-function setupMocks({
- modelValueProp = "1900",
- cmsQuestionText = "CMS text goes here",
- dataFromStoreApi = [],
-}) {
- //Mock store
- store.dispatch = jest.fn(() => dataFromStoreApi);
- store.getters = { vehicle: { year: 2019 } };
- const mountOptions = getMountOptions({
- store: {
- dispatch: store.dispatch,
- getters: store.getters,
- },
- });
-
- //Mock props
- const mockMixin = {
- methods: {
- getCmsContent: jest.fn(),
- },
- };
- mountOptions.propsData = {
- modelValue: modelValueProp,
- };
- mountOptions.mixins = [mockMixin];
- const wrapper = shallowMount(makeQuestion, mountOptions);
-
- //Mock CMS content
- const cmsContent = {
- QuestionText: cmsQuestionText,
- };
- return { wrapper, cmsContent };
-}
diff --git a/src/layouts/vehicle-make/make-question/make-question.vue b/src/layouts/vehicle-make/make-question/make-question.vue
deleted file mode 100644
index 2d3551c53..000000000
--- a/src/layouts/vehicle-make/make-question/make-question.vue
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle-make/vehicle-make.spec.js b/src/layouts/vehicle-make/vehicle-make.spec.js
deleted file mode 100644
index 3b169a9b9..000000000
--- a/src/layouts/vehicle-make/vehicle-make.spec.js
+++ /dev/null
@@ -1,228 +0,0 @@
-// Supporting Files
-import { shallowMount } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import { settleAllPromises } from "@/helpers/layout-helper.js";
-import { nextTick } from "vue";
-import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
-import baseMixin from "@/mixins/base-mixin.js";
-import store from "@/store";
-
-// Components
-import vehicleMake from "@/layouts/vehicle-make/vehicle-make.vue";
-import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
-
-jest.mock("@/store", () => ({
- commit: jest.fn(),
- dispatch: jest.fn(),
- // getters: jest.fn().mockImplementation(() => ({
- // vehicle: {
- // year: 2019,
- // },
- // })),
-}));
-
-// Mock fetchCmsContentForPage
-jest.mock("@/helpers/cms-content-helper", () => ({
- fetchCmsContentForPage: jest.fn(),
-}));
-
-// Mock our module for promises.
-jest.mock("@/helpers/layout-helper.js", () => ({
- settleAllPromises: jest.fn(),
-}));
-
-describe("vehicle-make.vue", () => {
- test("Make question component is initized with api data", async (done) => {
- //Arrange
- const makeQuestionInitialData = ["honda", "ford", "dodge"];
- const { wrapper, apiPromise } = setupMocks({
- makeQuestionInitialData: makeQuestionInitialData,
- });
-
- //Act
- vehicleMake.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-make" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- //Assert
- apiPromise.finally(() => {
- expect(makeQuestion.methods.initializeComponent).toHaveBeenCalledWith(
- makeQuestionInitialData
- );
- done();
- });
- });
-});
-
-describe("vehicle-make.vue", () => {
- test("BackButtonAction triggers a router.navigateWithoutSaving change", async (done) => {
- //Arrange
- const { wrapper, apiPromise } = setupMocks({
- pageHeaderWidgetHeaderText: "Select a make to get started",
- mountOptionsMockData: {
- router: {
- navigate: jest.fn(),
- navigateWithoutSaving: jest.fn(),
- },
- },
- });
-
- //Act
- vehicleMake.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-make" } },
- undefined,
- (c) => c(wrapper.vm)
- );
- wrapper.vm.backButtonAction();
- await nextTick();
-
- //Assert
- apiPromise.finally(() => {
- expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
- done();
- });
- });
-});
-
-describe("vehicle-make.vue", () => {
- describe("arePagePrerequisitesValue", () => {
- test("Year set, arePagePrerequisitesValid should be true", async () => {
- //Arrange
- const { wrapper } = setupMocks({
- vehicleData: {
- year: 2019,
- },
- });
-
- //Act
- vehicleMake.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-make" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
-
- //Assert
- expect(arePagePrerequisitesValid).toBe(true);
- });
-
- test("Year not set, arePagePrerequisitesValid should be false", async () => {
- //Arrange
- store.getters.vehicle.year = jest.fn().mockReturnValueOnce(undefined);
- const { wrapper } = setupMocks({});
-
- //Act
- let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
-
- //Assert
- expect(arePagePrerequisitesValid).toBe(false);
- });
- });
-
- test("selectedMake changes => save make in store", async () => {
- //Arrange
- const { wrapper } = setupMocks({
- mountOptionsMockData: {
- router: {
- navigate: jest.fn(),
- navigateWithSaving: jest.fn(),
- },
- },
- });
-
- // Act
- await wrapper.setData({
- selectedMake: "Make",
- });
- await wrapper.vm.$nextTick();
-
- // Assert
- expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalledWith(
- "saveVehicleMake",
- "Make",
- false
- );
- });
-
- test("selectedMake changes => navigate with saving", async () => {
- //Arrange
- const { wrapper } = setupMocks({
- mountOptionsMockData: {
- router: {
- navigate: jest.fn(),
- navigateWithSaving: jest.fn(),
- },
- route: {
- fmgPage: "test",
- },
- },
- });
-
- // Act
- await wrapper.setData({
- selectedMake: "Make",
- });
-
- // Assert
- expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
- "SELECTED_MAKE",
- expect.anything()
- );
- });
-});
-
-function setupMocks({
- vehicleMakeQuestionCmsContent = {},
- makeQuestionInitialData = {},
- pageHeaderWidgetHeaderText = {},
- mountOptionsMockData = {},
- vehicleData = {},
-}) {
- //Mock api responses
- const apiResponses = {
- cmsContent: {
- FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
- VehicleMakeQuestion: vehicleMakeQuestionCmsContent,
- VehicleBannerWidget: {
- GenericVehicleImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
- },
- FunnelHeaderWidget: {
- LogoImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
- },
- },
- makeQuestionInitialData: makeQuestionInitialData,
- };
-
- const apiPromise = Promise.resolve(apiResponses);
-
- store.getters = {
- vehicle: vehicleData,
- };
-
- fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
- settleAllPromises.mockImplementation(() => apiPromise);
-
- //Mock make question methods
- makeQuestion.methods = {
- loadInitialData: jest.fn(),
- initializeComponent: jest.fn(),
- };
-
- const mountOptions = getMountOptions(mountOptionsMockData);
- const wrapper = shallowMount(vehicleMake, mountOptions);
- const makeQuestionWrapper = wrapper.findComponent({ name: "makeQuestion" });
- makeQuestionWrapper.vm.initializeComponent = makeQuestion.methods.initializeComponent;
- wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
-
- return { wrapper, apiPromise };
-}
diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue
deleted file mode 100644
index a50440e35..000000000
--- a/src/layouts/vehicle-make/vehicle-make.vue
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle-model/model-question/model-question.spec.js b/src/layouts/vehicle-model/model-question/model-question.spec.js
deleted file mode 100644
index 16ca638d9..000000000
--- a/src/layouts/vehicle-model/model-question/model-question.spec.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import modelQuestion from "@/layouts/vehicle-model/model-question/model-question";
-import { shallowMount } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import store from "@/store";
-jest.mock(
- "@/store",
- () => {
- return {};
- },
- { virtual: true }
-);
-
-describe("model-question.vue", () => {
- test("Selected model is emitted upon selection.", async () => {
- //Arrange
- const { wrapper } = setupMocks({ modelValueProp: "Accord" });
- const modelToSelect = "Civic";
-
- //Act
- wrapper.setValue({ selectedModel: modelToSelect });
- await wrapper.vm.$nextTick();
-
- //Assert
- expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ selectedModel: "Civic" }]);
- });
-});
-
-describe("model-question.vue", () => {
- test("Data from store api are used as radio question answers.", async () => {
- //Arrange
- const { wrapper, cmsContent } = setupMocks({
- dataFromStoreApi: ["accord", "civic", "insight"],
- });
-
- //Act
- const initialData = modelQuestion.methods.loadInitialData.call(wrapper.vm);
- modelQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
-
- //Assert
- const buttonQuestionComponent = await wrapper.findComponent({
- name: "buttonQuestion",
- });
- expect(buttonQuestionComponent.attributes("answers")).toBe("accord,civic,insight");
- });
-});
-
-function setupMocks({
- modelValueProp = "1900",
- cmsQuestionText = "CMS text goes here",
- dataFromStoreApi = [],
-}) {
- //Mock store
- store.dispatch = jest.fn(() => dataFromStoreApi);
- store.getters = { vehicle: { year: 2019, make: "honda" } };
- const mountOptions = getMountOptions({
- store: {
- dispatch: store.dispatch,
- getters: store.getters,
- },
- });
-
- //Mock props
- const mockMixin = {
- methods: {
- getCmsContent: jest.fn(),
- },
- };
- mountOptions.propsData = {
- modelValue: modelValueProp,
- };
- mountOptions.mixins = [mockMixin];
- const wrapper = shallowMount(modelQuestion, mountOptions);
-
- //Mock CMS content
- const cmsContent = {
- QuestionText: cmsQuestionText,
- };
- return { wrapper, cmsContent };
-}
diff --git a/src/layouts/vehicle-model/model-question/model-question.vue b/src/layouts/vehicle-model/model-question/model-question.vue
deleted file mode 100644
index 5ca926abc..000000000
--- a/src/layouts/vehicle-model/model-question/model-question.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle-model/vehicle-model.spec.js b/src/layouts/vehicle-model/vehicle-model.spec.js
deleted file mode 100644
index 33b74482d..000000000
--- a/src/layouts/vehicle-model/vehicle-model.spec.js
+++ /dev/null
@@ -1,147 +0,0 @@
-// Components
-import vehicleModel from "@/layouts/vehicle-model/vehicle-model.vue";
-import modelQuestion from "@/layouts/vehicle-model/model-question/model-question";
-
-// Supporting files
-import { settleAllPromises } from "@/helpers/layout-helper.js";
-import { shallowMount } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import { nextTick } from "vue";
-import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
-import baseMixin from "@/mixins/base-mixin.js";
-
-// Mock our module for promises.
-jest.mock("@/helpers/layout-helper.js", () => ({
- settleAllPromises: jest.fn(),
-}));
-
-// Mock fetchCmsContentForPage
-jest.mock("@/helpers/cms-content-helper", () => ({
- fetchCmsContentForPage: jest.fn(),
-}));
-
-// Mock Store
-jest.mock("@/store", () => ({
- commit: jest.fn(),
- dispatch: jest.fn(),
- getters: {
- vehicle: {
- make: "Acura",
- },
- },
-}));
-
-describe("vehicle-model.vue", () => {
- test("Model question component is initized with api data", async (done) => {
- //Arange
- const modelQuestionInitialData = ["accord", "civic", "insight"];
- const { wrapper, apiPromise } = setupMocks({
- modelQuestionInitialData: modelQuestionInitialData,
- });
- //Act
- vehicleModel.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-model" } },
- undefined,
- (c) => c(wrapper.vm)
- );
- //Assert
- apiPromise.finally(() => {
- expect(modelQuestion.methods.initializeComponent).toHaveBeenCalledWith(
- modelQuestionInitialData
- );
- done();
- });
- });
-});
-
-describe("vehicle-model.vue", () => {
- test("BackButtonAction triggers a router.navigateWithoutSaving change", async (done) => {
- //Arrange
- const { wrapper, apiPromise } = setupMocks({
- pageHeaderWidgetHeaderText: "Select a model to get started",
- mountOptionsMockData: {
- router: {
- navigate: jest.fn(),
- navigateWithoutSaving: jest.fn(),
- },
- },
- });
- //Act
- vehicleModel.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-model" } },
- undefined,
- (c) => c(wrapper.vm)
- );
- wrapper.vm.backButtonAction();
- await nextTick();
- //Assert
- apiPromise.finally(() => {
- expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
- done();
- });
- });
-});
-describe("vehicle-model.vue", () => {
- test("Make set, arePagePrerequisitesValid should be true ", async () => {
- //Arrange
- const { wrapper } = setupMocks({});
-
- //Act
- vehicleModel.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-model" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
- await nextTick();
-
- //Assert
- expect(arePagePrerequisitesValid).toBe(true);
- });
-});
-
-function setupMocks({
- buttonQuestionContent = {},
- modelQuestionInitialData = {},
- pageHeaderWidgetHeaderText = {},
- mountOptionsMockData = {},
-}) {
- //Mock api responses
- const apiResponses = {
- cmsContent: {
- FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
- VehicleModelQuestion: buttonQuestionContent,
- VehicleBannerWidget: {
- GenericVehicleImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
- },
- FunnelHeaderWidget: {
- LogoImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
- },
- },
- modelQuestionInitialData: modelQuestionInitialData,
- };
- const apiPromise = Promise.resolve(apiResponses);
-
- settleAllPromises.mockImplementation(() => apiPromise);
- fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
-
- //Mock model question methods
- modelQuestion.methods = {
- loadInitialData: jest.fn(),
- initializeComponent: jest.fn(),
- };
- const mountOptions = getMountOptions(mountOptionsMockData);
- const wrapper = shallowMount(vehicleModel, mountOptions);
- wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
-
- const modelQuestionWrapper = wrapper.findComponent({ name: "modelQuestion" });
- modelQuestionWrapper.vm.initializeComponent = modelQuestion.methods.initializeComponent;
-
- return { wrapper, apiPromise };
-}
diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue
deleted file mode 100644
index d15c170c6..000000000
--- a/src/layouts/vehicle-model/vehicle-model.vue
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle-style/style-question/style-question.spec.js b/src/layouts/vehicle-style/style-question/style-question.spec.js
deleted file mode 100644
index c02301316..000000000
--- a/src/layouts/vehicle-style/style-question/style-question.spec.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import styleQuestion from "@/layouts/vehicle-style/style-question/style-question";
-import { shallowMount } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import store from "@/store";
-jest.mock(
- "@/store",
- () => {
- return {};
- },
- { virtual: true }
-);
-
-describe("style-question.vue", () => {
- test("Selected style is emitted upon selection.", async () => {
- //Arrange
- const { wrapper } = setupMocks({ modelValueProp: "2 Door" });
- const styleToSelect = "4 Door";
-
- //Act
- wrapper.setValue({ selectedStyle: styleToSelect });
- await wrapper.vm.$nextTick();
-
- //Assert
- expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ selectedStyle: "4 Door" }]);
- });
-});
-
-describe("style-question.vue", () => {
- test("Data from store api are used as radio question answers.", async () => {
- //Arrange
- const { wrapper, cmsContent } = setupMocks({
- dataFromStoreApi: ["2 Door", "4 Door"],
- });
-
- //Act
- const initialData = styleQuestion.methods.loadInitialData.call(wrapper.vm);
- styleQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
-
- //Assert
- const buttonQuestionComponent = await wrapper.findComponent({
- name: "buttonQuestion",
- });
- expect(buttonQuestionComponent.attributes("answers")).toBe("2 Door,4 Door");
- });
-});
-
-function setupMocks({
- modelValueProp = "1900",
- cmsQuestionText = "CMS text goes here",
- dataFromStoreApi = [],
-}) {
- //Mock store
- store.dispatch = jest.fn(() => dataFromStoreApi);
- store.getters = { vehicle: { year: 2019, make: "honda", model: "civc" } };
- const mountOptions = getMountOptions({
- store: {
- dispatch: store.dispatch,
- getters: store.getters,
- },
- });
-
- //Mock props
- const mockMixin = {
- methods: {
- getCmsContent: jest.fn(),
- },
- };
- mountOptions.propsData = {
- modelValue: modelValueProp,
- };
- mountOptions.mixins = [mockMixin];
- const wrapper = shallowMount(styleQuestion, mountOptions);
-
- //Mock CMS content
- const cmsContent = {
- QuestionText: cmsQuestionText,
- };
- return { wrapper, cmsContent };
-}
diff --git a/src/layouts/vehicle-style/style-question/style-question.vue b/src/layouts/vehicle-style/style-question/style-question.vue
deleted file mode 100644
index 0bfd00f7c..000000000
--- a/src/layouts/vehicle-style/style-question/style-question.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle-style/vehicle-style.spec.js b/src/layouts/vehicle-style/vehicle-style.spec.js
deleted file mode 100644
index f7dacb6b4..000000000
--- a/src/layouts/vehicle-style/vehicle-style.spec.js
+++ /dev/null
@@ -1,256 +0,0 @@
-// Components
-import vehicleStyle from "@/layouts/vehicle-style/vehicle-style.vue";
-import styleQuestion from "@/layouts/vehicle-style/style-question/style-question";
-
-// Supporting files
-import { settleAllPromises } from "@/helpers/layout-helper.js";
-import { nextTick } from "vue";
-import { shallowMount } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import { storeActions } from "@/constants/store-actions";
-import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
-import baseMixin from "@/mixins/base-mixin.js";
-import router from "@/router";
-import store from "@/store";
-import { storeMutations } from "@/constants/store-mutations";
-
-// Mock our module for promises.
-jest.mock("@/helpers/layout-helper.js", () => ({
- settleAllPromises: jest.fn(),
-}));
-
-// Mock fetchCmsContentForPage
-jest.mock("@/helpers/cms-content-helper", () => ({
- fetchCmsContentForPage: jest.fn(),
-}));
-
-// Mock fetchCmsContentForPage
-jest.mock("@/router", () => ({
- overrideNavigation: jest.fn(),
-}));
-
-describe("vehicle-style.vue", () => {
- beforeEach(() => {
- jest.clearAllMocks();
- });
-
- test("Style question component is initized with api data", async (done) => {
- //Arrange
- const styleQuestionInitialData = ["2 Door", "4 Door"];
- const { wrapper, apiPromise } = setupMocks({
- styleQuestionInitialData: styleQuestionInitialData,
- });
-
- //Act
- vehicleStyle.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-style" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- //Assert
- apiPromise.finally(() => {
- expect(styleQuestion.methods.initializeComponent).toHaveBeenCalledWith(
- styleQuestionInitialData
- );
- done();
- });
- });
-
- test("BackButtonAction triggers a router.navigateWithoutSaving change", async (done) => {
- //Arrange
- const { wrapper, apiPromise } = setupMocks({
- pageHeaderWidgetHeaderText: "Select a style to get started",
- mountOptionsMockData: {
- router: {
- navigate: jest.fn(),
- navigateWithSaving: jest.fn(),
- navigateWithoutSaving: jest.fn(),
- },
- },
- });
-
- //Act
- vehicleStyle.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-style" } },
- undefined,
- (c) => c(wrapper.vm)
- );
- wrapper.vm.backButtonAction();
- await nextTick();
-
- //Assert
- apiPromise.finally(() => {
- expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
- done();
- });
- });
-
- test("setVehicle triggers a dispatchStoreAction commit", async (done) => {
- //Arrange
- const { wrapper, apiPromise } = setupMocks({
- pageHeaderWidgetHeaderText: "Select a style to get started",
- mountOptionsMockData: {
- actionList: [
- {
- actionName: storeActions.SET_VEHICLE,
- data: "mockData",
- },
- ],
- },
- });
-
- //Act
- vehicleStyle.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-style" } },
- undefined,
- (c) => c(wrapper.vm)
- );
- wrapper.vm.setVehicle();
- await nextTick();
-
- //Assert
- apiPromise.finally(() => {
- expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
- done();
- });
- });
-
- test("Model set, arePagePrerequisitesValid should be true ", async () => {
- //Arrange
- const { wrapper } = setupMocks({});
-
- //Act
- vehicleStyle.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-style" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
- await nextTick();
-
- //Assert
- expect(arePagePrerequisitesValid).toBe(true);
- });
-
- test("there is only one vehicle style => autoselect and move to vehicle damage", async () => {
- //Arrange
- const { wrapper } = setupMocks({
- styleQuestionInitialData: ["2 door sedan"],
- });
-
- // Act
- await vehicleStyle.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-style" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- // Assert
- expect(store.commit).toHaveBeenCalledWith(storeMutations.UPDATE_STYLE, "2 door sedan");
- expect(router.overrideNavigation).toHaveBeenCalled();
- });
-
- test("there is only one vehicle style and vehicle-damage was visited => don't autoselect or move to vehicle damage", async () => {
- //Arrange
- const { wrapper } = setupMocks({
- styleQuestionInitialData: ["2 door sedan"],
- mountOptionsMockData: {
- store: {
- getters: {
- applicationUser: {
- pageData: {
- "part-questions": null,
- "vehicle-make": {},
- "vehicle-model": {},
- "vehicle-style": {},
- "vehicle-damage": {},
- },
- },
- },
- },
- },
- });
-
- // Act
- await vehicleStyle.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-style" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- // Assert
- expect(store.commit).not.toHaveBeenCalledWith(storeMutations.UPDATE_STYLE, "2 door sedan");
- expect(router.overrideNavigation).not.toHaveBeenCalled();
- });
-});
-
-function setupMocks({
- vehicleStyleQuestionCmsContent = {},
- styleQuestionInitialData = {},
- pageHeaderWidgetHeaderText = {},
- mountOptionsMockData = {},
-}) {
- //Mock api responses
- const apiResponses = {
- cmsContent: {
- FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
- VehicleStyleQuestion: vehicleStyleQuestionCmsContent,
- VehicleBannerWidget: {
- GenericVehicleImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
- },
- FunnelHeaderWidget: {
- LogoImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
- },
- },
- styleQuestionInitialData: styleQuestionInitialData,
- };
-
- const apiPromise = Promise.resolve(apiResponses);
-
- settleAllPromises.mockImplementation(() => apiPromise);
- fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
-
- //Mock style question methods
- styleQuestion.methods = {
- loadInitialData: jest.fn(),
- initializeComponent: jest.fn(),
- };
-
- store.commit = jest.fn();
- store.dispatch = jest.fn();
- store.getters = mountOptionsMockData.store?.getters ?? {
- vehicle: {
- model: "TL",
- },
- applicationUser: {
- pageData: {
- "part-questions": null,
- "vehicle-make": {},
- "vehicle-model": {},
- "vehicle-style": {},
- },
- },
- };
-
- const mountOptions = getMountOptions({
- ...mountOptionsMockData,
- store,
- });
- const wrapper = shallowMount(vehicleStyle, mountOptions);
- wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
-
- const styleQuestionWrapper = wrapper.findComponent({ name: "styleQuestion" });
- styleQuestionWrapper.vm.initializeComponent = styleQuestion.methods.initializeComponent;
-
- return { wrapper, apiPromise };
-}
diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue
deleted file mode 100644
index 2d2a4a534..000000000
--- a/src/layouts/vehicle-style/vehicle-style.vue
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle-year/vehicle-year.spec.js b/src/layouts/vehicle-year/vehicle-year.spec.js
deleted file mode 100644
index ad024f131..000000000
--- a/src/layouts/vehicle-year/vehicle-year.spec.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import { shallowMount, flushPromises } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import { settleAllPromises } from "@/helpers/layout-helper.js";
-import { nextTick } from "vue";
-import { storeMutations } from "@/constants/store-mutations";
-import { storeActions } from "@/constants/store-actions";
-import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
-import baseMixin from "@/mixins/base-mixin.js";
-
-import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue";
-import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
-
-import store from "@/store";
-
-jest.mock("@/store", () => ({
- commit: jest.fn(),
- dispatch: jest.fn(),
- getters: {
- applicationUser: {
- experiments: [],
- },
- },
-}));
-
-// Mock our module for promises.
-jest.mock("@/helpers/layout-helper.js", () => ({
- settleAllPromises: jest.fn(),
-}));
-
-// Mock fetchCmsContentForPage
-jest.mock("@/helpers/cms-content-helper", () => ({
- fetchCmsContentForPage: jest.fn(),
-}));
-
-describe("vehicle-year.vue", () => {
- test("Year question component is initized with api data", async (done) => {
- //Arrange
- const yearQuestionInitialData = ["2023", "2022", "2021"];
- const { wrapper, apiPromise } = setupMocks({
- yearQuestionInitialData: yearQuestionInitialData,
- });
-
- //Act
- vehicleYear.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-year" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- //Assert
- apiPromise.finally(() => {
- expect(yearQuestion.methods.initializeComponent).toHaveBeenCalledWith(
- yearQuestionInitialData
- );
- done();
- });
- });
-});
-
-describe("vehicle-year.vue", () => {
- test("arePagePrerequisitesValid should be true ", async () => {
- //Arrange
- const { wrapper } = setupMocks({});
-
- //Act
- vehicleYear.beforeRouteEnter.call(
- wrapper.vm,
- { query: { fmgPage: "vehicle-make" } },
- undefined,
- (c) => c(wrapper.vm)
- );
-
- let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
- await nextTick();
-
- //Assert
- expect(arePagePrerequisitesValid).toBe(true);
- });
-});
-
-function setupMocks({
- vehicleYearQuestionCmsContent = {},
- yearQuestionInitialData = {},
- pageHeaderWidgetHeaderText = {},
- mountOptionsMockData = {},
-}) {
- //Mock api responses
- const apiResponses = {
- cmsContent: {
- FunnelSubHeaderWidget: { HeaderText: pageHeaderWidgetHeaderText },
- VehicleYearQuestion: vehicleYearQuestionCmsContent,
- VehicleBannerWidget: {
- GenericVehicleImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
- },
- FunnelHeaderWidget: {
- LogoImage:
- "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
- },
- },
- yearQuestionInitialData: yearQuestionInitialData,
- };
- const apiPromise = Promise.resolve(apiResponses);
-
- settleAllPromises.mockImplementation(() => apiPromise);
- fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
-
- //Mock year question methods
- yearQuestion.methods = {
- loadInitialData: jest.fn(),
- initializeComponent: jest.fn(),
- };
-
- const mountOptions = getMountOptions(mountOptionsMockData);
- const wrapper = shallowMount(vehicleYear, mountOptions);
- const yearQuestionWrapper = wrapper.findComponent({ name: "yearQuestion" });
- yearQuestionWrapper.vm.initializeComponent = yearQuestion.methods.initializeComponent;
- wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
-
- return { wrapper, apiPromise };
-}
diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue
deleted file mode 100644
index 5b166151a..000000000
--- a/src/layouts/vehicle-year/vehicle-year.vue
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle-year/year-question/year-question.spec.js b/src/layouts/vehicle-year/year-question/year-question.spec.js
deleted file mode 100644
index f6a1e5e71..000000000
--- a/src/layouts/vehicle-year/year-question/year-question.spec.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
-import { shallowMount } from "@vue/test-utils";
-import { getMountOptions } from "@/helpers/unit-test-helper.js";
-import store from "@/store";
-jest.mock(
- "@/store",
- () => {
- return {};
- },
- { virtual: true }
-);
-
-describe("year-question.vue", () => {
- test("Selected year is emitted upon selection.", async () => {
- //Arrange
- const { wrapper } = setupMocks({ modelValueProp: "2020" });
- const yearToSelect = "2021";
-
- //Act
- wrapper.setValue({ modelValue: yearToSelect });
- await wrapper.vm.$nextTick();
-
- //Assert
- expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ modelValue: "2021" }]);
- });
-});
-
-describe("year-question.vue", () => {
- test("Data from store api are used as radio question answers.", async () => {
- //Arrange
- const { wrapper, cmsContent } = setupMocks({
- dataFromStoreApi: ["2023", "2022", "2021"],
- });
-
- //Act
- const initialData = yearQuestion.methods.loadInitialData.call(wrapper.vm);
- yearQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
-
- //Assert
- const buttonQuestionComponent = await wrapper.findComponent({
- name: "buttonQuestion",
- });
- expect(buttonQuestionComponent.attributes("answers")).toBe("2023,2022,2021");
- });
-});
-
-function setupMocks({
- modelValueProp = "1900",
- cmsQuestionText = "CMS text goes here",
- dataFromStoreApi = [],
-}) {
- //Mock store
- store.dispatch = jest.fn(() => dataFromStoreApi);
- const mountOptions = getMountOptions({
- store: {
- dispatch: store.dispatch,
- },
- });
-
- //Mock props
- const mockMixin = {
- methods: {
- getCmsContent: jest.fn(),
- },
- };
- mountOptions.propsData = {
- modelValue: modelValueProp,
- };
- mountOptions.mixins = [mockMixin];
-
- const wrapper = shallowMount(yearQuestion, mountOptions);
-
- //Mock CMS content
- const cmsContent = {
- QuestionText: cmsQuestionText,
- };
- return { wrapper, cmsContent };
-}
diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue
deleted file mode 100644
index 6d8110216..000000000
--- a/src/layouts/vehicle-year/year-question/year-question.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
diff --git a/src/layouts/vehicle/vehicle.vue b/src/layouts/vehicle/vehicle.vue
index 13001e2fd..37e813bed 100644
--- a/src/layouts/vehicle/vehicle.vue
+++ b/src/layouts/vehicle/vehicle.vue
@@ -58,7 +58,9 @@
@@ -110,17 +112,17 @@ export default {
selectedMake: this.selectedMakefromStore(),
selectedModel: this.selectedModelfromStore(),
selectedStyle: this.selectedStylefromStore(),
- vehicle: {
- carId: null,
- category: null,
- imageUrl: null,
- imageVifNumber: null,
- imageVifColor: null,
- },
+ carId: null,
+ category: null,
+ imageUrl: null,
+ imageVifNumber: null,
+ imageVifColor: null,
yearOptions: [],
makeOptions: [],
modelOptions: [],
styleOptions: [],
+ displayGeneric: this.displayGenericFromStore(),
+ unmatchedVehicleIcon: false,
};
},
@@ -279,7 +281,18 @@ export default {
this.selectedModel,
style
);
- this.vehicle = result?.data;
+ this.carId = result?.data.carId;
+ this.category = result?.data.category;
+ this.imageUrl = result?.data.imageUrl;
+ this.imageVifNumber = result?.data.imageVifNumber;
+ this.imageVifColor = result?.data.imageVifColor;
+ if (this.imageUrl == null) {
+ this.displayGeneric = false;
+ this.unmatchedVehicleIcon = true;
+ } else this.unmatchedVehicleIcon = false;
+ } else {
+ this.imageUrl = null;
+ this.displayGeneric = true;
}
},
},
@@ -293,6 +306,15 @@ export default {
style: style,
});
},
+ displayGenericFromStore() {
+ if (store.getters.vehicle.imageUrl !== null) return false;
+ else if (
+ store.getters.vehicle.imageUrl === null &&
+ store.getters.vehicle.carId !== null
+ )
+ return false;
+ else return true;
+ },
arePagePrerequisitesValid() {
return true;
},
@@ -305,7 +327,11 @@ export default {
make: this.selectedMake,
model: this.selectedModel,
style: this.selectedStyle,
- vehicle: this.vehicle,
+ carId: this.carId,
+ category: this.category,
+ imageUrl: this.imageUrl,
+ imageVifNumber: this.imageVifNumber,
+ imageVifColor: this.imageVifColor,
},
false
);
@@ -353,12 +379,6 @@ export default {
},
},
- computed: {
- displayGeneric() {
- return !this.selectedStyle;
- },
- },
-
components: {
funnelHeader,
funnelFooter,
diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js
index 88b4772f8..37615f68b 100644
--- a/src/mixins/analytics-mixin.js
+++ b/src/mixins/analytics-mixin.js
@@ -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);
diff --git a/src/router/index.js b/src/router/index.js
index 6d812f847..e8fbf4d26 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -31,11 +31,6 @@ 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",
diff --git a/src/router/router-constants/fmgPage-values.js b/src/router/router-constants/fmgPage-values.js
index fc8841c13..ba931f77d 100644
--- a/src/router/router-constants/fmgPage-values.js
+++ b/src/router/router-constants/fmgPage-values.js
@@ -1,8 +1,4 @@
const fmgPageValues = {
- VEHICLE_YEAR: "vehicle-year",
- VEHICLE_MAKE: "vehicle-make",
- VEHICLE_MODEL: "vehicle-model",
- VEHICLE_STYLE: "vehicle-style",
VEHICLE: "vehicle",
VEHICLE_DAMAGE: "vehicle-damage",
ADDRESS_LOOKUP: "address-lookup",
diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js
index ae1c880ae..30f7d0341 100644
--- a/src/router/router-constants/navigation-scenarios.js
+++ b/src/router/router-constants/navigation-scenarios.js
@@ -12,12 +12,6 @@ const navigationScenarios = {
CLICKED_FORWARD: "CLICKED_FORWARD",
CLICKED_FORWARD_WITH_CASH: "CLICKED_FORWARD_WITH_CASH",
- // YMMS
- SELECTED_YEAR: "SELECTED_YEAR",
- SELECTED_MODEL: "SELECTED_MODEL",
- SELECTED_MAKE: "SELECTED_MAKE",
- SELECTED_STYLE: "SELECTED_STYLE",
-
// Vin selection
CLICKED_BACK_WITH_VIN: "CLICKED_BACK_WITH_VIN",
CLICKED_FORWARD_WITH_VIN: "CLICKED_FORWARD_WITH_VIN",
@@ -51,6 +45,8 @@ 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",
+ CLICKED_CUSTOMER_EDIT: "CLICKED_CUSTOMER_EDIT",
};
export { navigationScenarios };
diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js
index 017e1372a..91fd47229 100644
--- a/src/router/router-constants/routing-table.js
+++ b/src/router/router-constants/routing-table.js
@@ -13,54 +13,7 @@ const routingTable = function (store) {
},
],
},
- {
- fmgPageValue: fmgPageValues.VEHICLE_YEAR,
- maps: [
- {
- scenario: navigationScenarios.SELECTED_YEAR,
- destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE,
- },
- ],
- },
- {
- fmgPageValue: fmgPageValues.VEHICLE_MAKE,
- maps: [
- {
- scenario: navigationScenarios.SELECTED_MAKE,
- destinationFmgPageValue: fmgPageValues.VEHICLE_MODEL,
- },
- {
- scenario: navigationScenarios.CLICKED_BACK,
- destinationFmgPageValue: fmgPageValues.VEHICLE_YEAR,
- },
- ],
- },
- {
- fmgPageValue: fmgPageValues.VEHICLE_MODEL,
- maps: [
- {
- scenario: navigationScenarios.SELECTED_MODEL,
- destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
- },
- {
- scenario: navigationScenarios.CLICKED_BACK,
- destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE,
- },
- ],
- },
- {
- fmgPageValue: fmgPageValues.VEHICLE_STYLE,
- maps: [
- {
- scenario: navigationScenarios.SELECTED_STYLE,
- destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
- },
- {
- scenario: navigationScenarios.CLICKED_BACK,
- destinationFmgPageValue: fmgPageValues.VEHICLE_MODEL,
- },
- ],
- },
+
{
fmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
maps: [
@@ -484,6 +437,14 @@ const routingTable = function (store) {
scenario: navigationScenarios.CLICKED_SERVICE_LOCATION_EDIT,
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
},
+ {
+ scenario: navigationScenarios.CLICKED_SCHEDULE_EDIT,
+ destinationFmgPageValue: fmgPageValues.SCHEDULE,
+ },
+ {
+ scenario: navigationScenarios.CLICKED_CUSTOMER_EDIT,
+ destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
+ },
],
},
];
diff --git a/src/store/index.js b/src/store/index.js
index 7d1caf59a..e9e19973a 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -13,11 +13,19 @@ 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 = () => {
return {
+ submitAfterSave: false,
order: {
vehicle: {
year: null,
@@ -32,12 +40,6 @@ const getDefaultState = () => {
imageColor: null,
registration: {
licensePlate: null,
- address: null,
- city: null,
- state: null,
- zipCode: null,
- firstName: null,
- lastName: null,
},
},
serviceLocation: {
@@ -96,8 +98,10 @@ const getDefaultState = () => {
endTime: null,
routeCode: null,
jobMaxMinutes: null,
+ jobMinMinutes: null,
},
referralNumber: null,
+ referralSequenceNumber: null,
referralDate: null,
referralCorrelationId: null,
eon: null,
@@ -120,6 +124,10 @@ export const state = getDefaultState();
// Export Mutations
export const mutations = {
+ updateWorkOrderFlag(state, submitAfterSave) {
+ state.submitAfterSave = submitAfterSave;
+ },
+
// VEHICLE MUTATIONS
updateYear(state, year) {
state.order.vehicle.year = year;
@@ -190,6 +198,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;
},
@@ -205,27 +216,6 @@ export const mutations = {
updateInsuranceVerifiedStatus(state, isVerified) {
state.order.payment.insuranceCoverage.isVerified = isVerified;
},
- updateRegistrationLicensePlate(state, licensePlate) {
- state.order.vehicle.registration.licensePlate = licensePlate;
- },
- updateRegistrationAddress(state, registrationAddress) {
- state.order.vehicle.registration.address = registrationAddress;
- },
- updateRegistrationCity(state, registrationCity) {
- state.order.vehicle.registration.city = registrationCity;
- },
- updateRegistrationState(state, registrationState) {
- state.order.vehicle.registration.state = registrationState;
- },
- updateRegistrationZipCode(state, registrationZipCode) {
- state.order.vehicle.registration.zipCode = registrationZipCode;
- },
- updateRegistrationFirstName(state, firstName) {
- state.order.vehicle.registration.firstName = firstName;
- },
- updateRegistrationLastName(state, lastName) {
- state.order.vehicle.registration.lastName = lastName;
- },
updateCustomerEmailAddress(state, customerEmailAddress) {
state.order.customer.emailAddress = customerEmailAddress;
},
@@ -283,6 +273,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) {
@@ -345,12 +336,8 @@ export const mutations = {
},
resetRegistrationState(state) {
state.order.vehicle.registration.licensePlate = null;
- state.order.vehicle.registration.address = null;
- state.order.vehicle.registration.city = null;
- state.order.vehicle.registration.state = null;
- state.order.vehicle.registration.zipCode = null;
- state.order.vehicle.registration.firstName = null;
- state.order.vehicle.registration.lastName = null;
+ state.order.customer.firstName = null;
+ state.order.customer.lastName = null;
},
resetGlassPartsState(state) {
state.order.lineItems.glassParts = null;
@@ -368,6 +355,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 +399,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;
@@ -492,7 +481,7 @@ export const mutations = {
state.order.customer.emailAddress = sessionInformation.order.customer.emailAddress;
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.phoneNumber = sessionInformation.order.customer.servicePhoneNumber;
state.order.customer.isSmsOptIn = sessionInformation.order.customer.isSmsOptIn;
state.order.existingPromoCode = sessionInformation.order.existingPromoCode;
@@ -506,6 +495,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 +530,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 +541,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];
@@ -751,12 +768,13 @@ export const actions = {
});
},
- 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),
});
},
@@ -872,6 +890,7 @@ export const actions = {
context,
{
referralNumber,
+ referralSequenceNumber,
referralDate,
referralCorrelationId,
eon,
@@ -881,6 +900,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);
@@ -900,6 +920,8 @@ export const actions = {
event,
shouldUseSessionId,
experimentsForUser,
+ referralSequenceNumber,
+ parentAccountNumber,
}
) {
var payload = {
@@ -912,6 +934,8 @@ export const actions = {
event: event,
shouldUseSessionId: shouldUseSessionId,
experimentsForUser: experimentsForUser,
+ referralSequenceNumber: referralSequenceNumber,
+ parentAccountNumber: parentAccountNumber,
};
return globalMethods
@@ -944,6 +968,8 @@ export const actions = {
value,
shouldUseSessionId,
experimentsForUser,
+ referralSequenceNumber,
+ parentAccountNumber,
}
) {
var payload = {
@@ -958,6 +984,8 @@ export const actions = {
value: value,
shouldUseSessionId: shouldUseSessionId,
experimentsForUser: experimentsForUser,
+ referralSequenceNumber: referralSequenceNumber,
+ parentAccountNumber: parentAccountNumber,
};
return globalMethods
@@ -1377,6 +1405,7 @@ export const actions = {
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url,
payload: {
+ submitAfterSave: context.state.submitAfterSave,
applicationUser: {
crmCustomerId: applicationUser.crmCustomerId,
experiments: applicationUser.experiments,
@@ -1407,7 +1436,7 @@ export const actions = {
firstName: order.customer.firstName,
lastName: order.customer.lastName,
isSmsOptIn: order.customer.isSmsOptIn,
- phoneNumber: order.customer.phoneNumber,
+ servicePhoneNumber: order.customer.phoneNumber,
},
damage: {
numberOfChips: damage.numberOfChips,
@@ -1427,7 +1456,7 @@ export const actions = {
InsuranceCoverage: {
isVerified: order.payment.insuranceCoverage.isVerified ?? false,
},
- isInsurance: order.payment.isInsurance ?? false,
+ isInsurance: order.payment.isInsurance,
parentAccountNumber: order.payment.parentAccountNumber,
},
serviceLocation: {
@@ -1458,12 +1487,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,
},
},
@@ -1528,93 +1558,19 @@ export const actions = {
);
},
+ saveWorkOrderFlag(context, submitAfterSave) {
+ context.commit(storeMutations.UPDATE_WORK_ORDER_FLAG, submitAfterSave);
+ },
+
// Business domain actions
// Vehicle
- saveVehicleYear(context, year) {
- //Reset dependent state when changing
- if (context.state.order.vehicle.year !== year) {
- context.commit(storeMutations.UPDATE_MAKE, null);
- context.commit(storeMutations.UPDATE_MODEL, null);
- context.commit(storeMutations.UPDATE_STYLE, null);
- context.commit(storeMutations.UPDATE_CAR_ID, null);
- context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
-
- context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
-
- //Save new values
- context.commit(storeMutations.UPDATE_YEAR, year);
- }
- },
-
- saveVehicleMake(context, make) {
- //Reset dependent state when changing
- if (context.state.order.vehicle.make !== make) {
- context.commit(storeMutations.UPDATE_MODEL, null);
- context.commit(storeMutations.UPDATE_STYLE, null);
- context.commit(storeMutations.UPDATE_CAR_ID, null);
- context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
-
- context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
-
- //Save new values
- context.commit(storeMutations.UPDATE_MAKE, make);
- }
- },
-
- saveVehicleModel(context, model) {
- //Reset dependent state when changing
- if (context.state.order.vehicle.model !== model) {
- context.commit(storeMutations.UPDATE_STYLE, null);
- context.commit(storeMutations.UPDATE_CAR_ID, null);
- context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
-
- context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
-
- //Save new values
- context.commit(storeMutations.UPDATE_MODEL, model);
- }
- },
-
- saveVehicleStyle(context, style) {
- //Reset dependent state when changing
- if (context.state.order.vehicle.style !== style) {
- context.commit(storeMutations.UPDATE_CAR_ID, null);
- context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
-
- context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
- context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
-
- //Save new values
- context.commit(storeMutations.UPDATE_STYLE, style);
- }
- },
-
- saveVehicle(context, { year, make, model, style, vehicle }) {
- context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
+ saveVehicle(
+ context,
+ { year, make, model, style, carId, category, imageUrl, imageVifNumber, imageVifColor }
+ ) {
+ context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
+ context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
if (context.state.order.vehicle.year !== year) {
context.commit(storeMutations.UPDATE_YEAR, year);
@@ -1628,11 +1584,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);
+ context.commit(storeMutations.UPDATE_CAR_ID, carId);
+ context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, category);
+ context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, imageUrl);
+ context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, imageVifNumber);
+ context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, imageVifColor);
},
saveVehicleDamage(
@@ -1720,12 +1676,8 @@ export const actions = {
) {
//Reset dependent state when changing
if (
- registrationInfo?.address !== context.state.order.vehicle.registration?.address ||
- registrationInfo?.city !== context.state.order.vehicle.registration?.city ||
- registrationInfo?.state !== context.state.order.vehicle.registration?.state ||
- registrationInfo?.zipCode !== context.state.order.vehicle.registration?.zipCode ||
- registrationInfo?.firstName !== context.state.order.vehicle.registration?.firstName ||
- registrationInfo?.lastName !== context.state.order.vehicle.registration?.lastName
+ registrationInfo?.firstName !== context.state.order.customer?.firstName ||
+ registrationInfo?.lastName !== context.state.order.customer?.lastName
) {
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
@@ -2056,12 +2008,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
diff --git a/src/store/store.spec.js b/src/store/store.spec.js
index e072eb164..ded194ba8 100644
--- a/src/store/store.spec.js
+++ b/src/store/store.spec.js
@@ -819,6 +819,7 @@ describe("Actions", () => {
// Act
actions.updateStoreWithSaveSessionResponse(context, {
referralNumber: "123",
+ referralSequenceNumber: 123,
referralDate: new Date().toUTCString(),
referralCorrelationId: "xxx-xxx-xxx",
parentAccountNumber: "167132",
@@ -1551,7 +1552,7 @@ describe("Actions", () => {
isCarIdDifferent: true,
isSelectedGlassAvailableForVehicle: false,
vehicleInfo: { carId: "C010101", vin: "XXXXX" },
- registrationInfo: { zipCode: "80020", address: "123 Marys Ave" },
+ registrationInfo: { firstName: "abc", lastName: "123" },
serviceLocationInfo: { state: "CO" },
customerEmail: "test@safelite.com",
};
@@ -1572,168 +1573,6 @@ describe("Actions", () => {
expect(commit).toBeCalledWith(storeMutations.UPDATE_REGISTRATION, payload.registrationInfo);
});
- it("saveVehicleYear, should wipe out vehicle info if year changes", () => {
- // Arrange
- const context = state;
-
- context.state = {
- order: {
- vehicle: {
- year: "2015",
- },
- },
- };
-
- const commit = jest.fn();
- const dispatch = jest.fn();
-
- context.commit = commit;
- context.dispatch = dispatch;
-
- // Act
- actions.saveVehicleYear(context, "2016");
-
- // Assert
- expect(dispatch).toHaveBeenNthCalledWith(
- 1,
- storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
- );
- expect(dispatch).toHaveBeenNthCalledWith(
- 2,
- storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
- );
-
- expect(commit).toBeCalledWith(storeMutations.UPDATE_MAKE, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
- });
-
- it("saveVehicleMake, should wipe out vehicle info if make changes", () => {
- // Arrange
- const context = state;
-
- context.state = {
- order: {
- vehicle: {
- make: "Honda",
- },
- },
- };
-
- const commit = jest.fn();
- const dispatch = jest.fn();
-
- context.commit = commit;
- context.dispatch = dispatch;
-
- // Act
- actions.saveVehicleMake(context, "Toyota");
-
- // Assert
- expect(dispatch).toHaveBeenNthCalledWith(
- 1,
- storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
- );
- expect(dispatch).toHaveBeenNthCalledWith(
- 2,
- storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
- );
-
- expect(commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
- });
-
- it("saveVehicle model, should wipe out vehicle info if model changes", () => {
- // Arrange
- const context = state;
-
- context.state = {
- order: {
- vehicle: {
- model: "Civic",
- },
- },
- };
-
- const commit = jest.fn();
- const dispatch = jest.fn();
-
- context.commit = commit;
- context.dispatch = dispatch;
-
- // Act
- actions.saveVehicleModel(context, "Accord");
-
- // Assert
- expect(dispatch).toHaveBeenNthCalledWith(
- 1,
- storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
- );
- expect(dispatch).toHaveBeenNthCalledWith(
- 2,
- storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
- );
-
- expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
- });
-
- it("saveVehicleStyle, should wipe out vehicle info if style changes", () => {
- // Arrange
- const context = state;
-
- context.state = {
- order: {
- vehicle: {
- style: "Sedan",
- },
- },
- };
-
- const commit = jest.fn();
- const dispatch = jest.fn();
-
- context.commit = commit;
- context.dispatch = dispatch;
-
- // Act
- actions.saveVehicleStyle(context, "SUV");
-
- // Assert
- expect(dispatch).toHaveBeenNthCalledWith(
- 1,
- storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
- );
- expect(dispatch).toHaveBeenNthCalledWith(
- 2,
- storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
- );
-
- expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
- expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
- });
-
it("saveVehicle, should save vehicle info", () => {
// Arrange
const context = state;
@@ -1761,14 +1600,20 @@ describe("Actions", () => {
make: "Honda",
model: "Civic",
style: "Sedan",
- vehicle: {
- carId: "C00000000",
- category: "CAR",
- },
+ 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);
}
@@ -1781,8 +1626,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);
+ context.commit(storeMutations.UPDATE_CAR_ID, payload.carId);
+ context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, payload.category);
});
it("saveVehicleDamage, should wipe out damage if different", () => {
@@ -3321,8 +3166,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],