CASH-2572 | Add in empty dates logic

It wasn't possible to display 15 days that had no actual available dates
Changed initialization logic to no longer assume an empty availableDates meant we hadn't loaded yet
Updated unit tests
Fixed a styling bug for 2571
This commit is contained in:
scottkiener-at-safelite 2026-06-05 10:19:31 -04:00
parent f1e6d125fc
commit 85e28701f3
4 changed files with 29 additions and 19 deletions

View file

@ -112,8 +112,8 @@ describe("date-picker.vue", () => {
wrapper.unmount();
});
test("returns empty array when availableDates is empty", () => {
const wrapper = mountDesktop({ availableDates: [] });
test("returns empty array when availableDates is null", () => {
const wrapper = mountDesktop({ availableDates: null });
expect(wrapper.vm.allDates).toEqual([]);
wrapper.unmount();
});
@ -427,7 +427,7 @@ describe("date-picker.vue", () => {
describe("initializeWindow", () => {
test("sets the initialized flag to true", async () => {
const wrapper = mountDesktop({ availableDates: [] });
const wrapper = mountDesktop({ availableDates: null });
expect(wrapper.vm.initialized).toBe(false);
await wrapper.setProps({ availableDates: AVAILABLE_DATES });
expect(wrapper.vm.initialized).toBe(true);
@ -436,7 +436,7 @@ describe("date-picker.vue", () => {
test("positions windowStart to the window containing the first available date", async () => {
const wrapper = mountDesktop({
availableDates: [],
availableDates: null,
startDate: "2026-01-01",
endDate: "2026-01-10",
});
@ -447,7 +447,7 @@ describe("date-picker.vue", () => {
});
test("emits update:modelValue with the first available date", async () => {
const wrapper = mountDesktop({ availableDates: [] });
const wrapper = mountDesktop({ availableDates: null });
await wrapper.setProps({ availableDates: AVAILABLE_DATES });
expect(wrapper.emitted("update:modelValue")[0][0]).toBe("2026-01-21");
wrapper.unmount();
@ -455,7 +455,7 @@ describe("date-picker.vue", () => {
test("positions windowStart to the last window and does not emit when no dates are available", async () => {
const wrapper = mountDesktop({
availableDates: [],
availableDates: null,
startDate: "2026-01-01",
endDate: "2026-01-10",
});
@ -468,7 +468,7 @@ describe("date-picker.vue", () => {
});
test("does not re-run after initialized flag is set", async () => {
const wrapper = mountDesktop({ availableDates: [] });
const wrapper = mountDesktop({ availableDates: null });
await wrapper.setProps({ availableDates: AVAILABLE_DATES });
const emissionCount = wrapper.emitted("update:modelValue").length;
// Add a newly available date within the range to trigger the watcher again
@ -481,8 +481,8 @@ describe("date-picker.vue", () => {
describe("allDates watcher", () => {
test("calls initializeWindow when dates first arrive with no modelValue set", async () => {
const wrapper = mountDesktop({ availableDates: [] });
// No dates → mounted() does nothing; initialized stays false
const wrapper = mountDesktop({ availableDates: null });
// null availableDates → allDates=[] → mounted() does nothing; initialized stays false
expect(wrapper.vm.initialized).toBe(false);
await wrapper.setProps({ availableDates: AVAILABLE_DATES });
expect(wrapper.vm.initialized).toBe(true);
@ -492,7 +492,7 @@ describe("date-picker.vue", () => {
test("clears pendingAutoSelect and advances the window when pendingAutoSelect is true", async () => {
const wrapper = mountDesktop({
availableDates: [],
availableDates: null,
startDate: "2026-01-01",
endDate: "2026-01-10",
});
@ -506,11 +506,11 @@ describe("date-picker.vue", () => {
wrapper.unmount();
});
test("takes no action when allDates becomes empty", async () => {
test("takes no action when availableDates becomes null", async () => {
const wrapper = mountDesktop({ availableDates: AVAILABLE_DATES });
// mounted() calls initializeWindow() → emits; record count
const emissionCount = wrapper.emitted("update:modelValue").length;
await wrapper.setProps({ availableDates: [] });
await wrapper.setProps({ availableDates: null });
// watcher fires with newDates=[] → early return, nothing changes
expect(wrapper.emitted("update:modelValue").length).toBe(emissionCount);
wrapper.unmount();

View file

@ -80,8 +80,8 @@ export default {
name: "datePicker",
props: {
availableDates: {
type: Array,
default: () => [],
default: null,
validator: (v) => v === null || Array.isArray(v),
},
startDate: {
type: String,
@ -111,9 +111,11 @@ export default {
},
computed: {
allDates() {
if (this.availableDates === null) return [];
const availableSet = new Set(this.availableDates);
if (!this.availableDates.length || !this.startDate || !this.endDate) return [];
if (!this.startDate || !this.endDate) return [];
const first = parseLocalDate(this.startDate);
const last = parseLocalDate(this.endDate);

View file

@ -122,6 +122,7 @@ export default {
timeSlots: resultMap.mobileTimeSlots ?? null,
}
: null;
vm.datesLoaded = true;
});
},
computed: {
@ -129,6 +130,7 @@ export default {
return this.getCmsContent("ServiceLocationText", "Text");
},
availableDates() {
if (!this.datesLoaded) return null;
const inshopDates = this.inShopProvidersAndTimeslots.flatMap(({ timeSlots }) =>
(timeSlots?.days ?? []).map((d) => d.date)
);
@ -142,6 +144,7 @@ export default {
return {
selectedDate: null,
isLoadingDates: false,
datesLoaded: false,
datePickerStartDate: toDateString(0),
datePickerEndDate: toDateString(SCHEDULE_FETCH_DAYS - 1),
inShopProvidersAndTimeslots: [],
@ -220,4 +223,8 @@ export default {
.dark-header {
color: $black;
}
h5 {
line-height: 32px;
font-size: 1.25rem;
}
</style>

View file

@ -3,10 +3,11 @@ import { experimentSettings } from "@/constants/experiments";
import { routeData } from "@/router/constants/routes";
export async function scheduleBeforeEnter(to, from) {
const isSchedulingEnabled = experimentMixin.methods.hasSettingEqualTo(
experimentSettings.USE_SCHEDULING_PAGE,
"true"
);
const isSchedulingEnabled = true;
// experimentMixin.methods.hasSettingEqualTo(
// experimentSettings.USE_SCHEDULING_PAGE,
// "true"
// );
if (isSchedulingEnabled) {
return {