From 603068f98d8221d27943ab013d2d1701a07fb419 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Fri, 10 Feb 2023 13:18:04 -0500 Subject: [PATCH] CSR-886: set up demo date picker page and beginnings of date-picker component --- .../date-picker/date-picker.spec.js | 380 ++++++++++++++++ .../date-picker/date-picker.vue | 414 +++++++++--------- .../demo-date-picker/demo-date-picker.spec.js | 19 + .../demo-date-picker/demo-date-picker.vue | 59 +++ src/router/index.js | 6 + 5 files changed, 677 insertions(+), 201 deletions(-) create mode 100644 src/common-components/date-picker/date-picker.spec.js create mode 100644 src/layouts/demo-date-picker/demo-date-picker.spec.js create mode 100644 src/layouts/demo-date-picker/demo-date-picker.vue diff --git a/src/common-components/date-picker/date-picker.spec.js b/src/common-components/date-picker/date-picker.spec.js new file mode 100644 index 000000000..de02d2f72 --- /dev/null +++ b/src/common-components/date-picker/date-picker.spec.js @@ -0,0 +1,380 @@ +import datePicker from "./date-picker"; + +// Supporting Files +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; + +describe("date-picker.vue", () => { + describe("initial setup", () => { + test("Creates a date object from today", () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const testResult = wrapper.vm.todayDateObj instanceof Date; + + // Assert + expect(testResult).toEqual(true); + + wrapper.unmount(); + }); + }); + describe("formatNumberToSetDigits", () => { + const testScenarios = [ + [0, 3, "000"], + [8, 2, "08"], + [345, 2, "345"], + [4567, 0, "4567"], + ]; + test.each(testScenarios)( + "when num is %s and digits is %s, formatNumberToSetDigits should return %s", + async (num, digits, expectedReturn) => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const fnReturn = wrapper.vm.formatNumberToSetDigits(num, digits); + + // Assert + expect(fnReturn).toEqual(expectedReturn); + } + ); + }); + describe("formatDate", () => { + test("Can format a date as MM/dd/yyyy", () => { + // Arrange + const { wrapper } = setupMocks({}); + const testDate = new Date("01-26-2023"); + + // Act + const testResult = wrapper.vm.formatDate(testDate); + + // Assert + expect(testResult).toEqual("01/26/2023"); + + wrapper.unmount(); + }); + + // test("Can get correct initialFirstDate from today", () => { + // // Arrange + // const { wrapper } = setupMocks({ + // propsData: { + // todayDate: "Thu Jan 26 2023", + // }, + // }); + + // // Act + // const testResult = wrapper.vm.initialFirstDate; + // const testResultAsDateString = testResult.toDateString(); + + // // Assert + // expect(testResultAsDateString).toEqual("Sun Jan 22 2023"); + + // wrapper.unmount(); + // }); + }); + describe("calendarData", () => { + test("should return an array", async () => { + // Arrange + const { wrapper } = setupMocks({}); + + // Act + const testResult = await wrapper.vm.calendarData; + + // Assert + expect(Array.isArray(testResult)).toBe(true); + + wrapper.unmount(); + }); + describe("for each month in calendarData, each should have keys monthLabel, yearNum, dates, startDayIndex", () => { + const testScenarios = [ + ["monthLabel", true, "string"], + ["yearNum", true, "number"], + ["dates", true, "object"], + ["startDayIndex", true, "number"], + ["monthClass", true, "string"], + ]; + + test.each(testScenarios)( + "test for %s key should return %s and be type %s", + async (label, test, type) => { + // Arrange + const { wrapper } = setupMocks({}); + const containsMonthLabel = (obj) => Object.hasOwn(obj, label); + const isCorrectType = (obj) => typeof obj[label] === type; + const isTruthyOrZero = (obj) => (obj[label] || obj[label] === 0 ? true : false); + + // Act + const calendarData = await wrapper.vm.calendarData; + console.log("calendarData: ", calendarData) + + // Assert + expect(calendarData.every(containsMonthLabel)).toBe(true); + expect(calendarData.every(isCorrectType)).toBe(true); + expect(calendarData.every(isTruthyOrZero)).toBe(true); + + wrapper.unmount(); + } + ); + }); + + test("for each month in calendarData, the dates array should have the 1st of the month", async () => { + // Arrange + const { wrapper } = setupMocks({}); + const hasAFirstInDates = (obj) => obj?.dates[0].dateNum === 1; + + // Act + const calendarData = await wrapper.vm.calendarData; + + // Assert + expect(calendarData.every(hasAFirstInDates)).toBe(true); + + wrapper.unmount(); + }); + + describe("for each month in calendarData, the dates array should have correct days of month", () => { + const testScenarios = [ + ["2022-02-05T03:00:00", 28, true], + ["2024-02-05T03:00:00", 29, true], + ["2020-01-15T03:00:00", 31, true], + ]; + + test.each(testScenarios)( + "the current month including the date %s should have %s days in its dates array", + async (dateString, noOfDays) => { + // Arrange + const { wrapper } = setupMocks({ + propsData: { + todayOverrideDateString: dateString, + }, + }); + + // Act + const calendarData = await wrapper.vm.calendarData; + const currentMonthIndex = calendarData.findIndex((month) => { + return month.monthClass === "currentMonth"; + }); + + // Assert + expect(calendarData[currentMonthIndex].dates.length === noOfDays).toBe(true); + + wrapper.unmount(); + } + ); + + // test.each(testScenarios)( + // "the date %s should have %s days in dates array", + // async (dateString, noOfDays) => { + // // Arrange + // const { wrapper } = setupMocks({ + // propsData: { + // todayOverrideDateString: dateString, + // }, + // }); + // const hasCorrectNumberOfDates = (obj) => obj?.dates.length === noOfDays; + + // // Act + // const calendarData = await wrapper.vm.calendarData; + + // // Assert + // expect(calendarData.every(hasCorrectNumberOfDates)).toBe(true); + + // wrapper.unmount(); + // } + // ); + }); + + // describe("for each object in array, the dates array should have correct days of month", () => { + // const testScenarios = [ + // ["2022-02-05T03:00:00", 28, true], + // ["2024-02-05T03:00:00", 29, true], + // ["2020-01-15T03:00:00", 31, true], + // ]; + + // test.each(testScenarios)( + // "the date %s should have %s days in dates array", + // async (dateString, noOfDays) => { + // // Arrange + // const { wrapper } = setupMocks({ + // propsData: { + // todayOverrideDateString: dateString, + // }, + // }); + // const hasCorrectNumberOfDates = (obj) => obj?.dates.length === noOfDays; + + // // Act + // const calendarData = await wrapper.vm.calendarData; + + // // Assert + // expect(calendarData.every(hasCorrectNumberOfDates)).toBe(true); + + // wrapper.unmount(); + // } + // ); + // }); + + // test.only("each object in array should have a monthLabel", () => { + // // Arrange + // const { wrapper } = setupMocks({}); + // // const testTodayDate = new Date("01-26-2023"); + + // // Act + // const testResult = wrapper.vm.calendarData; + // const containsMonthLabel = (month) => Object.hasOwn(month, 'monthLabel'); + + // // Assert + // expect(testResult.every(containsMonthLabel)).toBe(true); + + // }); + + // test.only("array should have a month object with same month as today", () => { + // // Arrange + // const { wrapper } = setupMocks({}); + // // const testTodayDate = new Date("01-26-2023"); + + // // Act + // // const testResult = wrapper.vm.calendarData; + // console.log("wrapper.vm.calendarData: ", wrapper.vm.calendarData) + + // // Assert + // // expect(wrapper.vm.calendarData).toEqual("something"); + // // expect(wrapper.vm.calendarDataOld).toEqual("something"); + + // expect(wrapper.vm.calendarData[1]).toMatchObject({ + // "dates": [ + // { + // "dateNum": 1 + // }, + // { + // "dateNum": 2 + // }, + // { + // "dateNum": 3 + // }, + // { + // "dateNum": 4 + // }, + // { + // "dateNum": 5 + // }, + // { + // "dateNum": 6 + // }, + // { + // "dateNum": 7 + // }, + // { + // "dateNum": 8 + // }, + // { + // "dateNum": 9 + // }, + // { + // "dateNum": 10 + // }, + // { + // "dateNum": 11 + // }, + // { + // "dateNum": 12 + // }, + // { + // "dateNum": 13 + // }, + // { + // "dateNum": 14 + // }, + // { + // "dateNum": 15 + // }, + // { + // "dateNum": 16 + // }, + // { + // "dateNum": 17 + // }, + // { + // "dateNum": 18 + // }, + // { + // "dateNum": 19 + // }, + // { + // "dateNum": 20 + // }, + // { + // "dateNum": 21 + // }, + // { + // "dateNum": 22 + // }, + // { + // "dateNum": 23 + // }, + // { + // "dateNum": 24 + // }, + // { + // "dateNum": 25 + // }, + // { + // "dateNum": 26 + // }, + // { + // "dateNum": 27 + // }, + // { + // "dateNum": 28 + // }, + // { + // "dateNum": 29 + // }, + // { + // "dateNum": 30 + // }, + // { + // "dateNum": 31 + // } + // ], + // "monthLabel": "January", + // "yearNum": 2023 + // }); + + // wrapper.unmount(); + // }); + }); +}); + +function setupMocks(mountOptionsMockData = {}) { + const initialMountOptionsMockData = { + // router: { + // navigate: jest.fn(), + // navigateWithSaving: jest.fn(), + // navigateWithoutSaving: jest.fn(), + // }, + // actionList: [ + // // { + // // actionName: storeActions.SAVE_PART_QUESTION_ANSWERS, + // // data: {}, + // // }, + // // { + // // actionName: storeActions.GET_PARTS, + // // data: {}, + // // }, + // ], + // store: { + // // getters: store.getters, + // // commit: store.commit, + // }, + }; + + const mountOptions = getMountOptions( + Object.assign(initialMountOptionsMockData, mountOptionsMockData) + ); + + // console.log("mountOptions: ", mountOptions) + + const wrapper = shallowMount(datePicker, mountOptions); + + return { wrapper }; +} diff --git a/src/common-components/date-picker/date-picker.vue b/src/common-components/date-picker/date-picker.vue index 1c83c0a4e..95e89c005 100644 --- a/src/common-components/date-picker/date-picker.vue +++ b/src/common-components/date-picker/date-picker.vue @@ -1,205 +1,50 @@ @@ -209,16 +54,160 @@ export default { name: "datePicker", data() { return { - currentMonth: "October", - currentYear: "2022", + currentMonth: "February", + currentYear: "2023", isFirstDayOfMonth: true, isCurrentDay: true, + // calendarData: [], + monthsBeforeToLoadOffset: -1, + monthsAfterToLoadOffset: 1, }; }, + props: { + todayOverrideDateString: { // only used for unit tests to override today's date + type: String, + default: null, + }, + }, + computed: { + todayDateObj() { + return this.todayOverrideDateString ? new Date(this.todayOverrideDateString) : new Date(); + }, + calendarData() { + return this.setCalendarData(); + }, + // initialFirstDate() { + // return startOfWeek(this.todayDateObj); + // }, + }, + // mounted() { + // this.setCalendarData(); + // }, + methods: { + formatDate(date) { + // return format(date, "MM/dd/yyyy"); + // console.log("date: ", date) + const dateArr = date.toDateString().split(" "); + // console.log("dateArr: ", dateArr) + const dayIndex = date.getDay(); + // console.log("dayIndex: ", dayIndex) + const dateIndex = date.getDate(); + // console.log("dateIndex: ", dateIndex) + const yearIndex = date.getFullYear(); + // console.log("yearIndex: ", yearIndex) + const monthIndex = date.getMonth(); + // console.log("monthIndex: ", monthIndex) + const monthIndexStr = this.formatNumberToSetDigits(monthIndex + 1, 2); + const dateIndexStr = this.formatNumberToSetDigits(dateIndex, 2); + + return monthIndexStr + "/" + dateIndexStr + "/" + yearIndex.toString(); + }, + formatNumberToSetDigits(num, digits) { + let numStr = num.toString(); + // const strLength = numStr.length; + while (numStr.length < digits) { + numStr = "0" + numStr; + } + return numStr; + }, + setCalendarData() { + const monthsOfYear = [ // TODO: MOVE THIS TO A CONSTANT + "January", // 0 // -12 // 12 + "February", // 1 // -11 // 13 + "March", // 2 // -10 // 14 + "April", // 3 // -9 // 15 + "May", // 4 // -8 // 16 + "June", // 5 // -7 // 17 + "July", // 6 // -6 // 18 + "August", // 7 // -5 // 19 + "September", // 8 // -4 // 20 + "October", // 9 // -3 // 21 + "November", // 10 // -2 // 22 + "December", // 11 // -1 // 23 + ]; + const todayDateObj = this.todayDateObj; + const todayMonth = todayDateObj.getMonth(); // returns zero index of months + const todayYear = todayDateObj.getFullYear(); // returns # of year + + // const todayDate = todayDateObj.getDate(); // returns # of date + // const todayMonthFirstDate = new Date(todayYear, todayMonth, 1); // returns date object + // const todayMonthLastDate = new Date(todayYear, todayMonth + 1, 0); // returns date object + // const todayMonthLastDateNum = todayMonthLastDate.getDate(); // returns # of date + // const todayStartDayIndex = todayMonthFirstDate.getDay(); // returns zero index of weekdays + + function getMonthData(offset) { + let monthClass = ""; + let yearNum = todayYear; + let adjustedMonthIndex = todayMonth + offset; + + // console.log("111... todayMonth: ", todayMonth, " / yearNum: ", yearNum, " / offset: ", offset); + + if (offset === 0) { + monthClass = "currentMonth"; + } else if (offset > 0) { + monthClass = "futureMonth"; + while (adjustedMonthIndex > 11) { + adjustedMonthIndex = adjustedMonthIndex - 12; + yearNum++; + } + } else { + monthClass = "pastMonth"; + while (adjustedMonthIndex < 0) { + adjustedMonthIndex = 12 + adjustedMonthIndex; + yearNum--; + } + } + + // console.log("adjustedMonthIndex: ", adjustedMonthIndex, " / yearNum: ", yearNum); + + const monthEndDate = new Date(yearNum, adjustedMonthIndex + 1, 0); + const datesArray = []; + for (let i = 1; i <= monthEndDate.getDate(); i++) { + datesArray.push({ dateNum: i }); + } + const monthFirstDate = new Date(yearNum, adjustedMonthIndex, 1); // returns date object + const startDayIndex = monthFirstDate.getDay(); + console.log("startDayIndex: ", startDayIndex) + + const monthToAdd = { + monthLabel: monthsOfYear[adjustedMonthIndex], + yearNum: yearNum, + dates: datesArray, + startDayIndex: startDayIndex, + monthClass: monthClass, + }; + // console.log("monthToAdd: ", monthToAdd) + return monthToAdd; + } + + // this.monthsBeforeToLoadOffset, this.monthsAfterToLoadOffset (DATA VARS) + const months = []; + for (let i = this.monthsBeforeToLoadOffset; i <= this.monthsAfterToLoadOffset; i++) { + months.push(getMonthData(i)); + } + return months; + }, + + + + + + + + + + getTodayDate() { + const todayDate = new Date(); + return todayDate; + }, + }, }; -