diff --git a/jest.config.js b/jest.config.js
index aaf2d9ff8..0a6fbc048 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -26,8 +26,7 @@ module.exports = {
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
coverageThreshold: {
global: {
- statements: 75,
- // Got the go ahead from Mark to temporarily lower this. Taking out initialize component made the year,make,model and style coverage drop a bit. Once unit tests for license plate lookup, vin lookup and address lookup are in the coverage should go back up to 90
+ statements: 80,
},
},
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js
index 9d7d3ea6a..fc0daf323 100644
--- a/src/constants/store-actions.js
+++ b/src/constants/store-actions.js
@@ -62,6 +62,7 @@ const storeActions = {
SAVE_VEHICLE_MAKE: "saveVehicleMake",
SAVE_VEHICLE_MODEL: "saveVehicleModel",
SAVE_VEHICLE_STYLE: "saveVehicleStyle",
+ SAVE_VEHICLE: "saveVehicle",
SAVE_VEHICLE_DAMAGE: "saveVehicleDamage",
SAVE_VIN_LOOKUP: "saveVinLookup",
SAVE_SERVICE_ZIP_CODE_INFO: "saveServiceZipCodeInfo",
@@ -85,6 +86,7 @@ const storeActions = {
"saveSupportingItemsSuppressingStateResetting",
SAVE_VAPS: "saveVaps",
SAVE_CUSTOMER_DETAILS: "saveCustomerDetails",
+ SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes",
};
export { storeActions };
diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js
index 76d510507..7b57187c2 100644
--- a/src/constants/store-mutations.js
+++ b/src/constants/store-mutations.js
@@ -34,11 +34,13 @@ const storeMutations = {
UPDATE_SERVICE_ZIP: "updateServiceZip",
UPDATE_SERVICE_LOCATION: "updateServiceLocation",
+ UPDATE_SERVICE_LOCATION_TECH_NOTES: "updateServiceLocationTechNotes",
+ UPDATE_TECH_NOTES: "updateTechNotes",
UPDATE_SCHEDULE: "updateSchedule",
UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress",
- //CUSTOMER MUTATIONS
+ // CUSTOMER MUTATIONS
UPDATE_CUSTOMER_DETAILS: "updateCustomerDetails",
// ORDER MUTATIONS
diff --git a/src/digital-components/dropdown-question/dropdown-question.vue b/src/digital-components/dropdown-question/dropdown-question.vue
index 7c0dd0d3b..6c032b740 100644
--- a/src/digital-components/dropdown-question/dropdown-question.vue
+++ b/src/digital-components/dropdown-question/dropdown-question.vue
@@ -16,9 +16,13 @@
:disabled="isDisabled"
:aria-required="isRequired"
:validationRules="validationRules"
- :placeHolderText="placeHolderText">
+ :placeHolderText="placeHolderText"
+ :valueAsKey="valueAsKey">
-
@@ -47,6 +51,11 @@ export default {
placeHolderText: String,
cmsWidgetName: String,
hasError: Boolean,
+ valueAsKey: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
setup(props) {
const uuid = uuidv4();
diff --git a/src/digital-components/textarea-question/textarea-question.vue b/src/digital-components/textarea-question/textarea-question.vue
index 0ffe5ec0a..83d718976 100644
--- a/src/digital-components/textarea-question/textarea-question.vue
+++ b/src/digital-components/textarea-question/textarea-question.vue
@@ -54,7 +54,7 @@ export default {
},
},
remainingCount() {
- return this.maxLength - this.value.length;
+ return this.maxLength - (this.value?.length ?? 0);
},
urgentCountdown() {
return this.remainingCount <= this.maxLength * 0.1 ? true : false;
diff --git a/src/layouts/customer-details/customer-details.vue b/src/layouts/customer-details/customer-details.vue
index 753bf8fc1..be533117f 100644
--- a/src/layouts/customer-details/customer-details.vue
+++ b/src/layouts/customer-details/customer-details.vue
@@ -32,7 +32,7 @@
+ v-model="isSmsOptin" />
({
+ commit: jest.fn(),
+ dispatch: jest.fn(),
+}));
+
+// Mock fetchCmsContentForPage
+jest.mock("@/helpers/cms-content-helper", () => ({
+ fetchCmsContentForPage: () => Promise.resolve("content"),
+ splitCopyOnCMSPlaceHolder: jest.fn(() => ["A", "B"]),
+}));
+
+jest.mock(
+ "@/store",
+ () => {
+ return {};
+ },
+ { virtual: true }
+);
+
+store.getters = {
+ order: {
+ schedule: {
+ date: "2020-01-01",
+ },
+ lineItems: {
+ glassParts: [],
+ supportingItems: [],
+ },
+ serviceLocation: {
+ appointmentType: "Inshop",
+ },
+ },
+ lineItems: {
+ glassParts: [],
+ supportingItems: [],
+ },
+};
+
+describe("schedule.vue", () => {
+ test("Should navigateWithoutSaving", async () => {
+ //Arrange
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ router: {
+ navigateWithoutSaving: jest.fn(),
+ },
+ route: { schedule },
+ },
+ });
+
+ wrapper.vm.dispatchStoreAction = jest.fn(() => {
+ return {
+ data: [],
+ };
+ });
+
+ //Act
+ await wrapper.vm.forwardButtonAction();
+
+ //Assert
+ expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
+ });
+ test("should pass arePagePrerequisitesValid with a mobile order and no providerNumber", () => {
+ //Arrange
+ const { wrapper } = setupMocks({});
+ store.getters = {
+ order: {
+ schedule: {
+ date: "2020-01-01",
+ },
+ serviceLocation: {
+ zipCode: "12345",
+ zipCodeCtu: "value",
+ appointmentType: "Mobile",
+ },
+ damage: {
+ isRepair: true,
+ },
+ referralNumber: "1234567",
+ },
+ payment: {
+ isInsurance: true,
+ },
+ lineItems: {
+ supportingItems: [],
+ },
+ };
+
+ let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
+
+ expect(arePagePrerequisitesValid).toBe(true);
+ });
+ test("should pass arePagePrerequisitesValid with a inshop order and providerNumber", () => {
+ //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: true,
+ },
+ lineItems: {
+ supportingItems: [],
+ },
+ };
+
+ let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
+
+ expect(arePagePrerequisitesValid).toBe(true);
+ });
+ test("should fail arePagePrerequisitesValid with a replace with no glass parts", () => {
+ //Arrange
+ 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",
+ },
+ payment: {
+ isInsurance: true,
+ },
+ lineItems: {
+ supportingItems: [],
+ glassParts: [],
+ },
+ };
+
+ let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
+
+ 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);
+ });
+});
+
+const mockCmsContent = {};
+
+function setupMocks({ customMountOptions }) {
+ const mountOptions = getMountOptions({
+ ...customMountOptions,
+ });
+
+ mountOptions.global.mocks["$store"] = store;
+ mountOptions["attachTo"] = document.body;
+ mountOptions.mixins = [
+ {
+ methods: {
+ getCmsContent: jest.fn().mockImplementation((widgetName, fieldName) => {
+ if (mockCmsContent[widgetName] && mockCmsContent[widgetName][fieldName])
+ return mockCmsContent[widgetName][fieldName];
+ }),
+ },
+ },
+ ];
+
+ const wrapper = shallowMount(schedule, mountOptions);
+ wrapper.vm.setCmsContent = jest.fn();
+ return { wrapper };
+}
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
new file mode 100644
index 000000000..43d997892
--- /dev/null
+++ b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js
@@ -0,0 +1,712 @@
+import { shallowMount, flushPromises } from "@vue/test-utils";
+import { getMountOptions } from "@/helpers/unit-test-helper.js";
+import timeSlotModalQuestion from "@/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue";
+import store from "@/store";
+import {
+ RouteCodeFlags,
+ PREMIUM_TIME_SLOT_ID_FLAG,
+ PREMIUM_FEE_PART_TYPE,
+} from "@/constants/schedule-constants";
+
+describe("time-slot-modal-list-button-question.vue", () => {
+ test("When selected time slot is changed, a correctly formatted selectedTimeSlot should be emitted", async () => {
+ //Arrange
+ const date = "2023-07-01";
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00 AM";
+ const endTime = "8:30 AM";
+ const jobMaxMinutes = 100;
+ const expectedEmit = [
+ [
+ {
+ date: date,
+ routeCode: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ jobMaxMinutes: jobMaxMinutes.toString(),
+ },
+ ],
+ ];
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ },
+ },
+ });
+
+ wrapper.vm.$refs.timeSlots.closeModal = jest.fn();
+ wrapper.vm.selectedTimeSlotId = timeSlotId;
+
+ //Act
+ wrapper.vm.setSelectedTimeSlot();
+
+ //Assert
+ expect(wrapper.emitted()["update:modelValue"]).toEqual(expectedEmit);
+ });
+});
+describe("time-slot-modal-list-button-question.vue Supplemental information", () => {
+ test("The correct supplemental information should be obtained from CMS - Mobile - Not Premium ", async () => {
+ //Arrange
+ const mobileCmsWidgetName = "MobileNotPremium";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "test" },
+ appointmentType: "Mobile",
+ mobileCmsWidgetName: mobileCmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.supplementalInformationBlock).toEqual(
+ mockCmsContent[mobileCmsWidgetName]["BodyText"]
+ );
+ });
+ test("The correct supplemental information should be obtained from CMS - Mobile - Premium", async () => {
+ //Arrange
+ const mobileCmsWidgetName = "MobilePremium";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "test" + PREMIUM_TIME_SLOT_ID_FLAG },
+ appointmentType: "Mobile",
+ mobileCmsWidgetName: mobileCmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.supplementalInformationBlock).toEqual(
+ mockCmsContent[mobileCmsWidgetName]["BodyText"]
+ );
+ });
+ test("No supplemental information should be obtained from CMS - Inshop", async () => {
+ //Arrange
+ const inshopWidgetName = "Inshop";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "test" },
+ appointmentType: "Inshop",
+ cmsWidgetName: inshopWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.supplementalInformationBlock).toBeNull();
+ });
+ test("No supplemental information should be obtained from CMS - Drop off, nothing selected", async () => {
+ //Arrange
+ const dropOffWidgetName = "Dropoff";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: null,
+ appointmentType: "Dropoff",
+ cmsWidgetName: dropOffWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.supplementalInformationBlock).toBeNull();
+ });
+ test("Correct supplemental information should be retrieved, Dropoff regular", async () => {
+ //Arrange
+ const dropOffWidgetName = "Dropoff";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF },
+ appointmentType: "Dropoff",
+ dropoffCmsWidgetName: dropOffWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.supplementalInformationBlock).toEqual(
+ mockCmsContent[dropOffWidgetName]["BodyText"]
+ );
+ });
+ test("Correct supplemental information should be retrieved, Dropoff Overnight", async () => {
+ //Arrange
+ const overnightDropOffCmsWidgetName = "Overnight";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "Test" + RouteCodeFlags.OVERNIGHT_DROP_OFF },
+ appointmentType: "Dropoff",
+ overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.supplementalInformationBlock).toEqual(
+ mockCmsContent[overnightDropOffCmsWidgetName]["BodyText"]
+ );
+ });
+ test("Correct supplemental information should be retrieved, Dropoff Sameday", async () => {
+ //Arrange
+ const sameDayDropOffCmsWidgetName = "Sameday";
+ const date = new Date().toISOString().split("T")[0];
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00 AM";
+ const endTime = "8:30 AM";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF },
+ appointmentType: "Dropoff",
+ sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ expect(wrapper.vm.supplementalInformationBlock).toEqual(
+ mockCmsContent[sameDayDropOffCmsWidgetName]["BodyText"]
+ );
+ });
+});
+
+describe("time-slot-modal-list-button-question.vue Disclaimer", () => {
+ test("The correct disclaimer information should be obtained from CMS - Dropoff - Sameday ", async () => {
+ //Arrange
+ const sameDayDropOffCmsWidgetName = "Sameday";
+ const date = new Date().toISOString().split("T")[0];
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00 AM";
+ const endTime = "8:30 AM";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF },
+ appointmentType: "Dropoff",
+ sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ expect(wrapper.vm.disclaimerTextBlockCopy).toEqual(
+ mockCmsContent[sameDayDropOffCmsWidgetName]["FooterText"]
+ );
+ });
+ test("Correct disclaimer information should be retrieved, Dropoff regular", async () => {
+ //Arrange
+ const dropOffWidgetName = "Dropoff";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF },
+ appointmentType: "Dropoff",
+ dropoffCmsWidgetName: dropOffWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.disclaimerTextBlockCopy).toEqual(
+ mockCmsContent[dropOffWidgetName]["FooterText"]
+ );
+ });
+ test("Correct disclaimer information should be retrieved, Dropoff overnight", async () => {
+ //Arrange
+ const overnightDropOffCmsWidgetName = "Overnight";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "Test" + RouteCodeFlags.OVERNIGHT_DROP_OFF },
+ appointmentType: "Dropoff",
+ overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.disclaimerTextBlockCopy).toEqual(
+ mockCmsContent[overnightDropOffCmsWidgetName]["FooterText"]
+ );
+ });
+ test("No disclaimer information should be retrieved, non-dropoff", async () => {
+ //Arrange
+ const inshopWidgetName = "Inshop";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "test" },
+ appointmentType: "Inshop",
+ cmsWidgetName: inshopWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.disclaimerTextBlockCopy).toBeNull();
+ });
+});
+
+describe("time-slot-modal-list-button-question.vue Duration", () => {
+ test("The correct duration information should be displayed - Dropoff - Sameday ", async () => {
+ //Arrange
+ const sameDayDropOffCmsWidgetName = "Sameday";
+ const date = new Date().toISOString().split("T")[0];
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00 AM";
+ const endTime = "8:30 AM";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF },
+ appointmentType: "Dropoff",
+ sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ expect(wrapper.vm.durationTextBlockCopy).toEqual(
+ mockCmsContent[sameDayDropOffCmsWidgetName]["SubheaderText"]
+ );
+ });
+ test("Correct duration information should be retrieved, Dropoff overnight", async () => {
+ //Arrange
+ const overnightDropOffCmsWidgetName = "Overnight";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "Test" + RouteCodeFlags.OVERNIGHT_DROP_OFF },
+ appointmentType: "Dropoff",
+ overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.durationTextBlockCopy).toEqual(
+ mockCmsContent[overnightDropOffCmsWidgetName]["SubheaderText"]
+ );
+ });
+ test("Correct duration information should be retrieved, Dropoff", async () => {
+ //Arrange
+ const dropoffCmsWidgetName = "Dropoff";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF },
+ appointmentType: "Dropoff",
+ dropoffCmsWidgetName: dropoffCmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.durationTextBlockCopy).toEqual(
+ mockCmsContent[dropoffCmsWidgetName]["SubheaderText"]
+ );
+ });
+ test("Correct duration information should be retrieved, Inshop - convert to hours", async () => {
+ //Arrange
+ const cmsWidgetName = "Inshop";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: 180,
+ estimatedServiceMinutesMinimum: 120,
+ modelValue: { routeCode: "Test" },
+ appointmentType: "Inshop",
+ cmsWidgetName: cmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.durationTextBlockCopy).toEqual(
+ mockCmsContent[cmsWidgetName]["SubheaderText"] + " 2 - 3 hours"
+ );
+ });
+ test("Correct duration information should be retrieved, Inshop - convert to minutes", async () => {
+ //Arrange
+ const cmsWidgetName = "Inshop";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: 90,
+ estimatedServiceMinutesMinimum: 60,
+ modelValue: { routeCode: "Test" },
+ appointmentType: "Inshop",
+ cmsWidgetName: cmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.durationTextBlockCopy).toEqual(
+ mockCmsContent[cmsWidgetName]["SubheaderText"] + " 60 - 90 minutes"
+ );
+ });
+ test("Correct duration information should be retrieved, Inshop - min = maximum time", async () => {
+ //Arrange
+ const cmsWidgetName = "Inshop";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: 240,
+ estimatedServiceMinutesMinimum: 240,
+ modelValue: { routeCode: "Test" },
+ appointmentType: "Inshop",
+ cmsWidgetName: cmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.durationTextBlockCopy).toEqual(
+ mockCmsContent[cmsWidgetName]["SubheaderText"] + " 4 hours"
+ );
+ });
+ test("No duration information should be displayed, Mobile", async () => {
+ //Arrange
+ const mobileCmsWidgetName = "Mobile";
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: 240,
+ estimatedServiceMinutesMinimum: 240,
+ modelValue: { routeCode: "Test" },
+ appointmentType: "Mobile",
+ mobileCmsWidgetName: mobileCmsWidgetName,
+ },
+ },
+ });
+ //Assert
+ expect(wrapper.vm.durationTextBlockCopy).toBeNull();
+ });
+});
+
+describe("time-slot-modal-list-button-question.vue Available Timeslots", () => {
+ test("Available Timeslots should be formatted correctly - Dropoff - Sameday ", async () => {
+ //Arrange
+ const sameDayDropOffCmsWidgetName = "Sameday";
+ const date = new Date().toISOString().split("T")[0];
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00 AM";
+ const endTime = "8:30 AM";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ appointmentType: "Dropoff",
+ sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ const expectedTimeSlotObject = {
+ buttonLabel: mockCmsContent[sameDayDropOffCmsWidgetName]["HeaderText"],
+ value: timeSlotId,
+ };
+ expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject);
+ });
+ test("Available Timeslots should be formatted correctly - Dropoff - Overnight ", async () => {
+ //Arrange
+ const overnightDropOffCmsWidgetName = "Overnight";
+ const date = new Date().toISOString().split("T")[0];
+ const timeSlotId = "testRouteCodeId" + RouteCodeFlags.OVERNIGHT_DROP_OFF;
+ const startTime = "8:00 AM";
+ const endTime = "8:30 AM";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ appointmentType: "Dropoff",
+ overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ const expectedTimeSlotObject = {
+ buttonLabel: mockCmsContent[overnightDropOffCmsWidgetName]["HeaderText"],
+ value: timeSlotId,
+ };
+ expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject);
+ });
+ test("Available Timeslots should be formatted correctly - Dropoff", async () => {
+ //Arrange
+ const dropoffCmsWidgetName = "Dropoff";
+ const date = "2020-01-01";
+ const timeSlotId = "testRouteCodeId" + RouteCodeFlags.ALL_DAY_DROP_OFF;
+ const startTime = "8:00 AM";
+ const endTime = "8:30 AM";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ appointmentType: "Dropoff",
+ dropoffCmsWidgetName: dropoffCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ const expectedTimeSlotObject = {
+ buttonLabel: mockCmsContent[dropoffCmsWidgetName]["HeaderText"],
+ value: timeSlotId,
+ };
+ expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject);
+ });
+ test("Available Timeslots should be formatted correctly - Mobile not premium", async () => {
+ //Arrange
+ const mobileCmsWidgetName = "MobileNotPremium";
+ const date = "2020-01-01";
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00";
+ const endTime = "8:30";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ appointmentType: "Mobile",
+ mobileCmsWidgetName: mobileCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ const expectedTimeSlotObject = {
+ buttonLabel: startTime + " AM - " + endTime + " AM",
+ value: timeSlotId,
+ };
+ expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject);
+ });
+ test("Available Timeslots should be formatted correctly - Mobile with premium", async () => {
+ //Arrange
+ const mobilePremiumCmsWidgetName = "MobilePremium";
+ const date = "2020-01-01";
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00";
+ const endTime = "8:30";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ premiumAppointmentFee: {
+ partType: PREMIUM_FEE_PART_TYPE,
+ },
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ offerPremium: true,
+ },
+ ],
+ },
+ appointmentType: "Mobile",
+ mobilePremiumCmsWidgetName: mobilePremiumCmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ const expectedTimeSlotObject = {
+ additionalButtonData: {
+ isPremiumAppointment: true,
+ },
+ buttonLabel: mockCmsContent[mobilePremiumCmsWidgetName]["HeaderText"],
+ buttonLabelSubCopy: "+$15.99",
+ value: timeSlotId + PREMIUM_TIME_SLOT_ID_FLAG,
+ };
+ expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject);
+ });
+ test("Available Timeslots should be formatted correctly - Inshop", async () => {
+ //Arrange
+ const cmsWidgetName = "Inshop";
+ const date = "2020-01-01";
+ const timeSlotId = "testRouteCodeId";
+ const startTime = "8:00";
+ const endTime = "8:30";
+ const jobMaxMinutes = 100;
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ estimatedServiceMinutesMaximum: jobMaxMinutes,
+ dateAndTimeSlotData: {
+ date: date,
+ timeSlots: [
+ {
+ id: timeSlotId,
+ startTime: startTime,
+ endTime: endTime,
+ },
+ ],
+ },
+ appointmentType: "Inshop",
+ cmsWidgetName: cmsWidgetName,
+ },
+ },
+ });
+
+ //Assert
+ const expectedTimeSlotObject = { buttonLabel: startTime + " AM", value: timeSlotId };
+ expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject);
+ });
+});
+
+const mockCmsContent = {
+ MobileNotPremium: {
+ BodyText: "Mobile, not premium BodyText",
+ FooterText: "Mobile, not premium FooterText",
+ SubheaderText: "Mobile, not premium SubheaderText",
+ HeaderText: "Mobile, not premium HeaderText",
+ },
+ MobilePremium: {
+ "BodyText:": "Mobile, with premium BodyText",
+ FooterText: "Mobile, with premium FooterText",
+ SubheaderText: "Mobile, with premium SubheaderText",
+ HeaderText: "Mobile, with premium HeaderText",
+ },
+ Inshop: {
+ BodyText: "Inshop BodyText",
+ FooterText: "Inshop FooterText",
+ SubheaderText: "Inshop SubheaderText",
+ HeaderText: "Inshop HeaderText",
+ },
+ Dropoff: {
+ BodyText: "Dropoff BodyText",
+ FooterText: "Dropoff FooterText",
+ SubheaderText: "Dropoff SubheaderText",
+ HeaderText: "Dropoff HeaderText",
+ },
+ Overnight: {
+ BodyText: "Dropoff Overnight",
+ FooterText: "Dropoff, Overnight FooterText",
+ SubheaderText: "Dropoff, Overnight SubheaderText",
+ HeaderText: "Dropoff, Overnight HeaderText",
+ },
+ Sameday: {
+ BodyText: "Dropoff Sameday",
+ FooterText: "Dropoff, Sameday FooterText",
+ SubheaderText: "Dropoff, Sameday SubheaderText",
+ HeaderText: "Dropoff, Sameday HeaderText",
+ },
+};
+
+function setupMocks({ customMountOptions }) {
+ const mountOptions = getMountOptions({
+ ...customMountOptions,
+ });
+ mountOptions.global.mocks["$store"] = store;
+ mountOptions["attachTo"] = document.body;
+ mountOptions.mixins = [
+ {
+ methods: {
+ getCmsContent: jest.fn().mockImplementation((widgetName, fieldName) => {
+ if (mockCmsContent[widgetName] && mockCmsContent[widgetName][fieldName])
+ return mockCmsContent[widgetName][fieldName];
+ }),
+ getTotalLineItemPrice: jest.fn().mockImplementation(() => 15.99),
+ },
+ },
+ ];
+
+ const wrapper = shallowMount(timeSlotModalQuestion, mountOptions);
+ wrapper.vm.setCmsContent = jest.fn();
+ return { wrapper };
+}
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 13f33ae05..724facf6c 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
@@ -150,7 +150,7 @@ export default {
return this.modelValue?.routeCode;
},
set: function (newValue) {
- // Button Question only supports Number, or String data types so we must get the full object to emit
+ // Button Question only supports Number, or String data types so we must convert to the full object before emitting
this.selectedValue = this.getSelectedTimeSlotObject(newValue);
},
},
@@ -326,7 +326,7 @@ export default {
}
},
modal() {
- return this.$refs["timeSlots"];
+ return this.$refs[this.modalName];
},
},
methods: {
diff --git a/src/layouts/vehicle/vehicle-question/vehicle-question.vue b/src/layouts/vehicle/vehicle-question/vehicle-question.vue
index 283f26811..79b58bfaa 100644
--- a/src/layouts/vehicle/vehicle-question/vehicle-question.vue
+++ b/src/layouts/vehicle/vehicle-question/vehicle-question.vue
@@ -1,9 +1,5 @@
-
+
diff --git a/src/layouts/vehicle/vehicle.vue b/src/layouts/vehicle/vehicle.vue
index bea1fdd8e..24ae0d215 100644
--- a/src/layouts/vehicle/vehicle.vue
+++ b/src/layouts/vehicle/vehicle.vue
@@ -15,8 +15,9 @@
ref="vehicleYearQuestion"
class="mb-2 mt-4"
v-model="selectedYear"
+ :isDisabled="!yearOptions.length"
+ :options="yearOptions"
cmsWidgetName="VehicleYearQuestion"
- :updateValues="updateYearValues"
validationRules="year-required"
placeHolderText="Select year"
inputId="yearQuestionField" />
@@ -25,8 +26,9 @@
ref="vehicleMakeQuestion"
class="mb-2 mt-4"
v-model="selectedMake"
+ :isDisabled="!makeOptions.length"
+ :options="makeOptions"
cmsWidgetName="VehicleMakeQuestion"
- :updateValues="updateMakeValues"
validationRules="make-required"
placeHolderText="Select make"
inputId="makeQuestionField" />
@@ -36,7 +38,8 @@
class="mb-2 mt-4"
v-model="selectedModel"
cmsWidgetName="VehicleModelQuestion"
- :updateValues="updateModelValues"
+ :isDisabled="!modelOptions.length"
+ :options="modelOptions"
validationRules="model-required"
placeHolderText="Select model"
inputId="modelQuestionField" />
@@ -46,7 +49,8 @@
class="mb-2 mt-4"
v-model="selectedStyle"
cmsWidgetName="VehicleStyleQuestion"
- :updateValues="updateStyleValues"
+ :isDisabled="!styleOptions.length"
+ :options="styleOptions"
validationRules="style-required"
placeHolderText="Select style"
inputId="styleQuestionField" />
@@ -101,10 +105,14 @@ export default {
name: "vehicle",
data() {
return {
- selectedYear: null,
- selectedMake: null,
- selectedModel: null,
- selectedStyle: null,
+ selectedYear: this.selectedYearfromStore(),
+ selectedMake: this.selectedMakefromStore(),
+ selectedModel: this.selectedModelfromStore(),
+ selectedStyle: this.selectedStylefromStore(),
+ yearOptions: [],
+ makeOptions: [],
+ modelOptions: [],
+ styleOptions: [],
};
},
@@ -113,10 +121,6 @@ export default {
validationRules: String,
},
- mounted() {
- this.$refs["vehicleYearQuestion"].getNewValues(this.selectedYearfromStore);
- },
-
async beforeRouteEnter(to, from, next) {
// Call APIs
@@ -124,6 +128,43 @@ export default {
const experimentForLogging = store.getters.applicationUser.experiments.find(
(e) => e.universeName === experimentUniverses.CONCEPT_FUNNEL
);
+ const yearQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
+ storeActions.GET_VEHICLE_YEARS,
+ {}
+ );
+ var makeQuestionInitialDataPromise = null;
+ var modelQuestionInitialDataPromise = null;
+ var styleQuestionInitialDataPromise = null;
+
+ if (
+ store.getters.order.vehicle.make &&
+ store.getters.order.vehicle.model &&
+ store.getters.order.vehicle.style
+ ) {
+ makeQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
+ storeActions.GET_VEHICLE_MAKES,
+ {
+ year: store.getters.order.vehicle.year,
+ }
+ );
+
+ modelQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
+ storeActions.GET_VEHICLE_MODELS,
+ {
+ year: store.getters.order.vehicle.year,
+ make: store.getters.order.vehicle.make,
+ }
+ );
+
+ styleQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
+ storeActions.GET_VEHICLE_STYLES,
+ {
+ year: store.getters.order.vehicle.year,
+ make: store.getters.order.vehicle.make,
+ model: store.getters.order.vehicle.model,
+ }
+ );
+ }
// If the concept funnel experiment is found, as it should be when coming from safelite.com, then log the experiment exposure.
if (experimentForLogging !== undefined) {
@@ -146,6 +187,22 @@ export default {
resultKey: "cmsContent",
promise: cmsContentPromise,
},
+ {
+ resultKey: "yearQuestionInitialData",
+ promise: yearQuestionInitialDataPromise,
+ },
+ {
+ resultKey: "makeQuestionInitialData",
+ promise: makeQuestionInitialDataPromise,
+ },
+ {
+ resultKey: "modelQuestionInitialData",
+ promise: modelQuestionInitialDataPromise,
+ },
+ {
+ resultKey: "styleQuestionInitialData",
+ promise: styleQuestionInitialDataPromise,
+ },
];
let resultMap = await settleAllPromises(promiseResultMap);
@@ -153,48 +210,74 @@ export default {
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
+ vm.initializeYearComponent(resultMap.yearQuestionInitialData);
+
+ if (
+ makeQuestionInitialDataPromise &&
+ modelQuestionInitialDataPromise &&
+ styleQuestionInitialDataPromise
+ )
+ vm.initializeMMSComponent(
+ resultMap.makeQuestionInitialData,
+ resultMap.modelQuestionInitialData,
+ resultMap.styleQuestionInitialData
+ );
});
},
watch: {
- selectedYear(year) {
- const parsedYear = parseInt(year);
- this.dispatchStoreAction(storeActions.SAVE_VEHICLE_YEAR, parsedYear);
+ async selectedYear(year) {
if (year) {
- this.$refs["vehicleMakeQuestion"].getNewValues(this.selectedMakefromStore);
+ const result = await this.getMakeOptions(year);
+ this.makeOptions = result?.data;
+ if (this.selectedYearfromStore() !== year) {
+ this.selectedMake = null;
+ this.selectedModel = null;
+ this.selectedStyle = null;
+ }
} else {
- this.$refs["vehicleMakeQuestion"].clearValues();
+ this.makeOptions = [];
}
},
- selectedMake(make) {
- this.dispatchStoreAction(storeActions.SAVE_VEHICLE_MAKE, make, false);
+ async selectedMake(make) {
if (make) {
- this.$refs["vehicleModelQuestion"].getNewValues(this.selectedModelfromStore);
+ const result = await this.getModelOptions(this.selectedYear, make);
+ this.modelOptions = result?.data;
+ if (this.selectedMakefromStore() !== make) {
+ this.selectedModel = null;
+ this.selectedStyle = null;
+ }
} else {
- this.$refs["vehicleModelQuestion"].clearValues();
+ this.modelOptions = [];
}
},
- selectedModel(model) {
- this.dispatchStoreAction(storeActions.SAVE_VEHICLE_MODEL, model, false);
+ async selectedModel(model) {
if (model) {
- this.$refs["vehicleStyleQuestion"].getNewValues(this.selectedStylefromStore);
+ const result = await this.getStyleOptions(
+ this.selectedYear,
+ this.selectedMake,
+ model
+ );
+ this.styleOptions = result?.data;
+ if (this.selectedModelfromStore() !== model) {
+ this.selectedStyle = null;
+ }
} else {
- this.$refs["vehicleStyleQuestion"].clearValues();
+ this.styleOptions = [];
}
},
selectedStyle(style) {
- this.dispatchStoreAction(storeActions.SAVE_VEHICLE_STYLE, style, false);
- this.setVehicle();
+ this.setVehicle(this.selectedYear, this.selectedMake, this.selectedModel, style);
},
},
methods: {
- setVehicle() {
+ setVehicle(year, make, model, style) {
return this.dispatchStoreAction(this.storeActions.SET_VEHICLE, {
- year: this.$store.getters.vehicle.year,
- make: this.$store.getters.vehicle.make,
- model: this.$store.getters.vehicle.model,
- style: this.$store.getters.vehicle.style,
+ year: year,
+ make: make,
+ model: model,
+ style: style,
});
},
@@ -207,42 +290,29 @@ export default {
},
navigateForward() {
+ this.dispatchStoreAction(
+ storeActions.SAVE_VEHICLE,
+ {
+ year: this.selectedYear,
+ make: this.selectedMake,
+ model: this.selectedModel,
+ style: this.selectedStyle,
+ },
+ false
+ );
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
- async updateYearValues() {
- return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_YEARS, {});
+ initializeYearComponent(initialData) {
+ this.yearOptions = initialData;
},
-
- async updateMakeValues() {
- return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MAKES, {
- year: store.getters.vehicle.year,
- });
- },
-
- async updateModelValues() {
- return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MODELS, {
- year: store.getters.vehicle.year,
-
- make: store.getters.vehicle.make,
- });
- },
-
- async updateStyleValues() {
- return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_STYLES, {
- year: store.getters.vehicle.year,
- make: store.getters.vehicle.make,
- model: store.getters.vehicle.model,
- });
- },
- },
-
- computed: {
- displayGeneric() {
- return !this.selectedStyle;
+ initializeMMSComponent(makeOptions, modelOptions, styleOptions) {
+ this.makeOptions = makeOptions;
+ this.modelOptions = modelOptions;
+ this.styleOptions = styleOptions;
},
selectedYearfromStore() {
- return store.getters.vehicle.year;
+ return store.getters.vehicle.year?.toString();
},
selectedMakefromStore() {
return store.getters.vehicle.make;
@@ -253,6 +323,32 @@ export default {
selectedStylefromStore() {
return store.getters.vehicle.style;
},
+ async getMakeOptions(year) {
+ return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MAKES, {
+ year: year,
+ });
+ },
+
+ async getModelOptions(year, make) {
+ return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MODELS, {
+ year: year,
+ make: make,
+ });
+ },
+
+ async getStyleOptions(year, make, model) {
+ return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_STYLES, {
+ year: year,
+ make: make,
+ model: model,
+ });
+ },
+ },
+
+ computed: {
+ displayGeneric() {
+ return !this.selectedStyle;
+ },
},
components: {
diff --git a/src/store/index.js b/src/store/index.js
index fb86b61c3..4bdc53977 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -59,9 +59,14 @@ const getDefaultState = () => {
zipCodeCtu: null,
},
},
+ techNotes: null,
},
customer: {
+ firstName: null,
+ lastName: null,
emailAddress: null,
+ phoneNumber: null,
+ isSmsOptin: null,
},
damage: {
isRepair: null,
@@ -272,6 +277,9 @@ export const mutations = {
},
};
},
+ updateServiceLocationTechNotes(state, techNotes) {
+ state.order.serviceLocation.techNotes = techNotes;
+ },
updateSchedule(state, scheduleInfo) {
if (scheduleInfo) {
state.order.schedule.date = scheduleInfo.date;
@@ -281,14 +289,13 @@ export const mutations = {
state.order.schedule.jobMaxMinutes = scheduleInfo.jobMaxMinutes;
}
},
- updateCustomerDetails(state, detailsInfo) {
- if (detailsInfo) {
- state.order.customerDetails.firstName = detailsInfo.firstName;
- state.order.customerDetails.lastName = detailsInfo.lastName;
- state.order.customerDetails.email = detailsInfo.email;
- state.order.customerDetails.telephone = detailsInfo.telephone;
- state.order.customerDetails.textUpdates = detailsInfo.textUpdates;
- state.order.customerDetails.techNotes = detailsInfo.techNotes;
+ updateCustomerDetails(state, customerDetails) {
+ if (customerDetails) {
+ state.order.customer.firstName = customerDetails.firstName;
+ state.order.customer.lastName = customerDetails.lastName;
+ state.order.customer.emailAddress = customerDetails.emailAddress;
+ state.order.customer.phoneNumber = customerDetails.phoneNumber;
+ state.order.customer.isSmsOptin = customerDetails.isSmsOptin;
}
},
@@ -1619,6 +1626,25 @@ export const actions = {
}
},
+ saveVehicle(context, { year, make, model, style }) {
+ context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
+ context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
+ context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
+
+ if (context.state.order.vehicle.year !== year) {
+ context.commit(storeMutations.UPDATE_YEAR, year);
+ }
+ if (context.state.order.vehicle.make !== make) {
+ context.commit(storeMutations.UPDATE_MAKE, make);
+ }
+ if (context.state.order.vehicle.model !== model) {
+ context.commit(storeMutations.UPDATE_MODEL, model);
+ }
+ if (context.state.order.vehicle.style !== style) {
+ context.commit(storeMutations.UPDATE_STYLE, style);
+ }
+ },
+
saveVehicleDamage(
context,
{ isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }
@@ -1947,8 +1973,8 @@ export const actions = {
context.commit(storeMutations.UPDATE_SCHEDULE, scheduleInfo);
},
- saveDetails(context, scheduleInfo) {
- context.commit(storeMutations.UPDATE_DETAILS, scheduleInfo);
+ saveCustomerDetails(context, customerDetails) {
+ context.commit(storeMutations.UPDATE_CUSTOMER_DETAILS, customerDetails);
},
saveServiceZipCodeInfo(context, serviceZipCodeInfo) {
@@ -1982,6 +2008,10 @@ export const actions = {
context.commit(storeMutations.UPDATE_SERVICE_LOCATION, serviceLocationInfo);
},
+ saveServiceLocationTechNotes(context, techNotesInfo) {
+ context.commit(storeMutations.UPDATE_SERVICE_LOCATION_TECH_NOTES, techNotesInfo);
+ },
+
saveEmail(context, email) {
context.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, email === "" ? null : email);
},
diff --git a/src/store/store.spec.js b/src/store/store.spec.js
index 4a6788433..08aa406c9 100644
--- a/src/store/store.spec.js
+++ b/src/store/store.spec.js
@@ -1702,6 +1702,59 @@ describe("Actions", () => {
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
});
+ it("saveVehicle, should save vehicle info", () => {
+ // Arrange
+ const context = state;
+
+ context.state = {
+ order: {
+ vehicle: {
+ year: "2016",
+ make: "Toyota",
+ model: "Accord",
+ style: "SUV",
+ },
+ },
+ };
+
+ const commit = jest.fn();
+ const dispatch = jest.fn();
+
+ context.commit = commit;
+ context.dispatch = dispatch;
+
+ //Act
+ const payload = {
+ year: "2015",
+ make: "Honda",
+ model: "Civic",
+ style: "Sedan",
+ };
+ 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);
+ }
+ if (context.state.order.vehicle.make !== payload.make) {
+ expect(commit).toBeCalledWith(storeMutations.UPDATE_MAKE, payload.make);
+ }
+ if (context.state.order.vehicle.model !== payload.model) {
+ expect(commit).toBeCalledWith(storeMutations.UPDATE_MODEL, payload.model);
+ }
+ if (context.state.order.vehicle.style !== payload.style) {
+ expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, payload.style);
+ }
+ });
+
it("saveVehicleDamage, should wipe out damage if different", () => {
// Arrange
const context = state;