diff --git a/src/layouts/schedule/schedule-june-2025.vue b/src/layouts/schedule/schedule-june-2025.vue
deleted file mode 100644
index 0464b2914..000000000
--- a/src/layouts/schedule/schedule-june-2025.vue
+++ /dev/null
@@ -1,782 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/layouts/schedule/schedule.specDISABLED.js b/src/layouts/schedule/schedule.specDISABLED.js
deleted file mode 100644
index 9d25152c8..000000000
--- a/src/layouts/schedule/schedule.specDISABLED.js
+++ /dev/null
@@ -1,616 +0,0 @@
-// 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 store from "@/store";
-import router from "@/router";
-import baseMixin from "../../mixins/base-mixin";
-
-// Mock basemixin
-jest.mock("@/mixins/base-mixin.js", () => ({
- methods: {
- dispatchStoreAction: jest.fn().mockImplementation((storeAction) => {
- if (storeAction === "getShopTimeSlots" || storeAction === "getMobileTimeSlots") {
- 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,
- },
- ]);
- }
- }),
- dispatchStoreActionWithLogging: jest.fn().mockImplementation((storeAction) => {
- if (storeAction === "getShopTimeSlots" || storeAction === "getMobileTimeSlots") {
- 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,
- },
- ]);
- }
- }),
- filterOutCertainPartTypesOrNumbers: jest.fn(),
- hasSubmittedOrder: jest.fn(),
- getTotalPriceOfAllLineItemsAndChildParts: jest.fn(),
- getTotalLineItemPrice: jest.fn(),
- },
-}));
-
-// Mock fetchCmsContentForPage
-jest.mock("@/helpers/cms-content-helper", () => ({
- fetchCmsContentForPage: () => Promise.resolve("content"),
- splitCopyOnCMSPlaceHolder: jest.fn(() => ["A", "B"]),
-}));
-
-beforeEach(() => {
- jest.restoreAllMocks();
- jest.clearAllMocks();
- store.getters = {
- applicationUser: {
- experiments: [],
- },
- 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",
- policy: {
- policyNumber: "123",
- },
- },
- payment: {
- isInsurance: true,
- },
- lineItems: {
- glassParts: [],
- supportingItems: [],
- },
- experimentSettings: {},
- vehicle: {
- carId: "123",
- },
- };
-});
-afterEach(() => {
- store.getters = {};
- jest.restoreAllMocks();
- jest.clearAllMocks();
-});
-
-describe("schedule.vue...", () => {
- describe("initial load", () => {
- test("should pass arePagePrerequisitesValid with a mobile CASH order and no providerNumber", () => {
- // Arrange
- const { wrapper } = setupMocks({});
- store.getters.order.serviceLocation.appointmentType = "Mobile";
- store.getters.order.serviceLocation.provider.policyNumber = null;
- store.getters.payment.isInsurance = false;
-
- // Act
- const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
-
- // Assert
- expect(arePagePrerequisitesValid).toBe(true);
- });
-
- test("should pass arePagePrerequisitesValid with an 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 timeslots when getMoreScheduleData is called", async () => {
- // Arrange
- const { wrapper } = setupMocks({});
- wrapper.vm.selectableDatesInshop = {
- days: [],
- };
- wrapper.vm.selectableDatesMobile = {
- days: [],
- };
-
- // Act
- const newShopTimeSlots = await wrapper.vm.getMoreScheduleData(
- "2023-01-01",
- "2023-01-31"
- );
-
- // Assert
- expect(newShopTimeSlots).toStrictEqual({
- inshopTimeSlotsData: {
- 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,
- },
- mobileTimeSlotsData: {
- 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 getMoreScheduleData is called with large date ranges", async () => {
- // Arrange
- const { wrapper } = setupMocks({});
- wrapper.vm.selectableDatesInshop = {
- days: [],
- };
- wrapper.vm.selectableDatesMobile = {
- days: [],
- };
-
- // Act
- await wrapper.vm.getMoreScheduleData.call(
- wrapper.vm,
- "2023-01-01",
- "2023-03-31",
- "Inshop",
- "123"
- );
-
- // Assert
- expect(baseMixin.methods.dispatchStoreActionWithLogging).toHaveBeenCalledTimes(6);
- expect(baseMixin.methods.dispatchStoreActionWithLogging).toHaveBeenCalledWith(
- "getShopTimeSlots",
- expect.anything(),
- expect.anything(),
- expect.anything()
- );
- });
-
- describe("beforeRouteEnter function... ", () => {
- // TODO: restore this test (temporarily removed it until CASH-845 is in QA then looping back)
- xtest("should call next() and call all functions within next", async () => {
- // Arrange
- const { wrapper } = setupMocks({});
- wrapper.vm.selectableDatesInshop = {
- days: [],
- };
- wrapper.vm.updateFooterButtonText = jest.fn();
- wrapper.vm.setDisplayWaitList = 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.selectableDatesInshop).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();
- expect(wrapper.vm.setDisplayWaitList).toHaveBeenCalled();
- });
- });
-
- describe("computed properties...", () => {
- test("timeSlotsForSelectedDate should return timeslots if selected date is available", () => {
- // Arrange
- const { wrapper } = setupMocks({});
- wrapper.vm.selectableDatesInshop = {
- 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.selectableDatesInshop = {
- 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.selectableDatesInshop = {
- days: [],
- };
-
- // Act
- const testValue = wrapper.vm.getServiceZipCtuCodeFromStore();
-
- // Assert
- expect(testValue).toStrictEqual("01234");
- });
-
- test("getDisplayTextForMilitaryTime should return the correctly formatted string", () => {
- // Arrange
- const { wrapper } = setupMocks({});
- wrapper.vm.selectableDatesInshop = {
- 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("Clicking back should fire correct navigation", () => {
- // Arrange
- const { wrapper } = setupMocks({});
- wrapper.vm.selectableDatesInshop = {
- days: [],
- };
- wrapper.vm.$router.navigateWithoutSaving = jest.fn();
-
- // Act
- wrapper.vm.backButtonAction();
-
- // Assert
- expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
- "CLICKED_BACK",
- "schedule"
- );
- });
- });
-
- // TODO: restore this test (temporarily removed it until CASH-845 is in QA then looping back)
- xtest("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();
-
- // Assert
- expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
- });
-
- 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({});
- 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,
- },
- });
-
- // Act
- await wrapper.vm.updateSupportingItems();
-
- // Assert
- expect(wrapper.vm.dispatchStoreAction).toBeCalledWith(
- "saveSupportingItemsSuppressingStateResetting",
- expect.not.arrayContaining([
- expect.objectContaining({
- partType: "EARLY BIRD",
- }),
- ]),
- expect.anything()
- );
- });
-});
-
-const mockCmsContent = {};
-
-function setupMocks({ customMountOptions }) {
- const mountOptions = getMountOptions({
- ...customMountOptions,
- route: { name: "schedule" },
- });
-
- mountOptions.global.mocks["$store"] = store;
- mountOptions.global.mocks["$router"] = router;
- mountOptions["attachTo"] = document.body;
- mountOptions.mixins = [
- {
- methods: {
- getCmsContent: jest.fn().mockImplementation((widgetName, fieldName) => {
- if (mockCmsContent[widgetName] && mockCmsContent[widgetName][fieldName])
- return mockCmsContent[widgetName][fieldName];
- }),
- },
- },
- ];
- mountOptions.global.mocks.pageName = "schedule";
-
- const wrapper = shallowMount(schedule, mountOptions);
-
- wrapper.vm.setCmsContent = jest.fn();
- wrapper.vm.$refs.datePicker.initializeComponent = jest.fn();
- wrapper.vm.$refs.datePicker.loadInitialData = jest.fn();
- wrapper.vm.$refs.locationAlerts.initializeComponent = jest.fn();
- wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
-
- return { wrapper };
-}
diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue
index 7c9d9f444..0a0a78d68 100644
--- a/src/layouts/schedule/schedule.vue
+++ b/src/layouts/schedule/schedule.vue
@@ -579,7 +579,7 @@ export default {
vm.showPricingByDay = false; // Pricing By Day is not used in this version
vm.preSelectedDate = preSelectedDate;
vm.appointmentType = appointmentType;
- vm.setData(
+ vm.setDataOnLoad(
zipCodeData,
resultMap.serviceabilityDetails,
pricedMobileFeePart,
@@ -921,7 +921,7 @@ export default {
}
},
- setData(zipCodeData, serviceabilityDetails, mobileFeePart, shopProviderData) {
+ setDataOnLoad(zipCodeData, serviceabilityDetails, mobileFeePart, shopProviderData) {
if (zipCodeData) {
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
this.zipCodeCtu = zipCodeData.zipCodeCtu;
@@ -1133,6 +1133,7 @@ export default {
this.resetWaitlist();
this.preSelectedDate = null;
this.shopProviderData = shopQuestionPopUpData.shopProviderData;
+ const oldProvider = this.selectedProvider;
const selectedProvider = this.shopProviderData.shopProviders.find((shopProvider) => {
return shopProvider.providerNumber === shopQuestionPopUpData.selectedProviderNumber;
});
@@ -1144,7 +1145,12 @@ export default {
selectedProvider
);
} else {
- this.updateSelectedProvider(selectedProvider);
+ const didProviderNumberChange =
+ oldProvider?.providerNumber !== selectedProvider.providerNumber;
+ if (didProviderNumberChange) {
+ this.updateSelectedProvider(selectedProvider);
+ this.initializeDatePicker();
+ }
}
},
async getMoreScheduleData(startDate, endDate) {
@@ -1172,6 +1178,8 @@ export default {
async initializeDatePicker() {
this.selectedDate = null;
+ const includeMobileTimeSlots = this.isServiceableMobile;
+ const includeInshopTimeSlots = this.isServiceableInshop || this.isServiceableDropoff;
const datePickerInitialData = await this.$refs.datePicker.loadInitialData({
// setup config options for date-picker
selectableDatesSetting: "custom",
@@ -1180,8 +1188,8 @@ export default {
preSelectedDate: this.preSelectedDate,
providerNumber: this.selectedProvider?.providerNumber,
zipCode: this.zipCode,
- includeMobileTimeSlots: this.isServiceableMobile,
- includeInshopTimeSlots: this.isServiceableInshop || this.isServiceableDropoff,
+ includeMobileTimeSlots: includeMobileTimeSlots,
+ includeInshopTimeSlots: includeInshopTimeSlots,
});
datePickerInitialData.pricingByDayBasePrice = this.pricingByDayBasePrice;
datePickerInitialData.pricingByDayUpcharge = this.pricingByDayUpcharge;
@@ -1197,8 +1205,8 @@ export default {
} else {
// if no date is preselected on load, make sure there are some dates available
if (
- this.selectableDatesInshop.days.length < 1 ||
- this.selectableDatesMobile.days.length < 1
+ (includeInshopTimeSlots && this.selectableDatesInshop.days.length < 1) ||
+ (includeMobileTimeSlots && this.selectableDatesMobile.days.length < 1)
) {
await this.$nextTick();
await this.$refs.datePicker.showAnotherMonth();
@@ -1622,15 +1630,9 @@ export default {
this.selectedProvider = new Provider();
this.updateSelectedProvider();
},
- updateSelectedProvider(newProvider) {
- if (newProvider) {
- const didProviderNumberChange =
- this.selectedProvider.providerNumber !== newProvider.providerNumber;
- this.selectedProvider = newProvider;
-
- if (didProviderNumberChange) {
- this.initializeDatePicker();
- }
+ updateSelectedProvider(newShopProvider) {
+ if (newShopProvider) {
+ this.selectedProvider = newShopProvider;
} else if (this.appointmentType === this.appointmentTypeStrings.MOBILE) {
this.selectedProvider = {
providerNumber: this.shopProviderData.mobileProviderNumber.toString(),
@@ -1710,7 +1712,6 @@ export default {
} else {
this.appointmentType = AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF;
}
-
// make sure a selectedProvider exists
this.updateSelectedProvider(this.lastSelectedInshopOrDropoffProvider);
} else {