From 2e9754f107ad3138158e34aac476e4d920a4a2cf Mon Sep 17 00:00:00 2001 From: Jaya Singh Date: Fri, 3 May 2024 16:05:44 -0500 Subject: [PATCH 1/9] added unit test for date time picker --- .../activity/tests/dateTimePicker.spec.ts | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts diff --git a/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts b/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts new file mode 100644 index 00000000000..31d7f27176a --- /dev/null +++ b/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts @@ -0,0 +1,83 @@ +import { shallowMount } from "@vue/test-utils"; +import DateTimePicker from "../dateTimePicker.vue"; +import moment from "moment"; + +describe("DateTimePicker.vue", () => { + let wrapper; + let now; + + beforeEach(() => { + now = moment(); + wrapper = shallowMount(DateTimePicker, { + propsData: { + modelValue: moment().format(), + dateClass: "date-class", + timeClass: "time-class", + }, + }); + }); + it("sets initial data correctly", () => { + expect(wrapper.vm.dateString).toBe(now.format("YYYY-MM-DD")); + expect(wrapper.vm.time).toBeInstanceOf(Date); + }); + + // it("emits update:modelValue when time changes", async () => { + // const newTime = new Date(); + // const newTimeFormatted = moment(newTime).format(); + // await wrapper.setData({ time: newTime }); + // + // expect(wrapper.emitted("update:modelValue")).toBeTruthy(); + // expect(wrapper.emitted("update:modelValue")[0]).toEqual([newTimeFormatted]); + // }); + it("renders date-picker and time-picker", () => { + expect(wrapper.find(".bs-date-picker").exists()).toBe(true); + expect(wrapper.find(".time-class").exists()).toBe(true); + }); + + it("sets initial data correctly", () => { + expect(wrapper.vm.dateString).toBe(moment().format("YYYY-MM-DD")); + expect(wrapper.vm.time).toBeInstanceOf(Date); + }); + + it("emits update:modelValue when time changes", async () => { + const newTime = new Date(); + await wrapper.setData({ time: newTime }); + + expect(wrapper.emitted("update:modelValue")).toBeTruthy(); + expect(wrapper.emitted("update:modelValue")[0]).toEqual([ + moment(newTime).format(), + ]); + }); + + it("updates time and dateString when modelValue changes", async () => { + const newModelValue = moment().add(1, "days").format(); + await wrapper.setProps({ modelValue: newModelValue }); + + expect(wrapper.vm.dateString).toBe( + moment(newModelValue).format("YYYY-MM-DD"), + ); + expect(wrapper.vm.time).toEqual(moment(newModelValue).toDate()); + }); + it("recalculates date when dateString changes", async () => { + const newDateString = moment().add(1, "days").format("YYYY-MM-DD"); + await wrapper.setData({ dateString: newDateString }); + + expect(moment(wrapper.vm.time).format("YYYY-MM-DD")).toBe(newDateString); + }); + + it("sets time and dateString from modelValue when modelValue changes", async () => { + const newModelValue = moment().add(1, "days").format(); + await wrapper.setProps({ modelValue: newModelValue }); + + expect(wrapper.vm.time).toEqual(moment(newModelValue).toDate()); + expect(wrapper.vm.dateString).toBe( + moment(newModelValue).format("YYYY-MM-DD"), + ); + }); + it("binds v-model and class correctly to date-picker and time-picker", () => { + expect(typeof wrapper.vm.dateString).toBe("string"); + expect(wrapper.vm.time).toBeInstanceOf(Date); + expect(wrapper.vm.dateClass).toBe("date-class"); + expect(wrapper.vm.timeClass).toBe("time-class"); + }); +}); From d735221c5b314fd51f4f940a5aa41e49ed6db73e Mon Sep 17 00:00:00 2001 From: Jaya Singh Date: Mon, 13 May 2024 18:16:20 -0500 Subject: [PATCH 2/9] Refactor: Clean up DateTimePicker tests and add new cases --- .../activity/tests/dateTimePicker.spec.ts | 162 +++++++++++++----- 1 file changed, 121 insertions(+), 41 deletions(-) diff --git a/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts b/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts index 31d7f27176a..78193238d0a 100644 --- a/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts +++ b/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/tests/dateTimePicker.spec.ts @@ -1,83 +1,163 @@ -import { shallowMount } from "@vue/test-utils"; +import { mount } from "@vue/test-utils"; import DateTimePicker from "../dateTimePicker.vue"; import moment from "moment"; +const mountDateTimePicker = async (props = {}) => { + return mount(DateTimePicker, { + props: { + modelValue: moment().format(), + dateClass: "date-class", + timeClass: "time-class", + ...props, + }, + global: { + stubs: { + "date-picker": true, + "time-picker": true, + }, + }, + }); +}; + describe("DateTimePicker.vue", () => { - let wrapper; let now; beforeEach(() => { now = moment(); - wrapper = shallowMount(DateTimePicker, { - propsData: { - modelValue: moment().format(), - dateClass: "date-class", - timeClass: "time-class", - }, - }); }); - it("sets initial data correctly", () => { - expect(wrapper.vm.dateString).toBe(now.format("YYYY-MM-DD")); - expect(wrapper.vm.time).toBeInstanceOf(Date); + afterEach(() => { + jest.clearAllMocks(); }); - // it("emits update:modelValue when time changes", async () => { - // const newTime = new Date(); - // const newTimeFormatted = moment(newTime).format(); - // await wrapper.setData({ time: newTime }); - // - // expect(wrapper.emitted("update:modelValue")).toBeTruthy(); - // expect(wrapper.emitted("update:modelValue")[0]).toEqual([newTimeFormatted]); - // }); - it("renders date-picker and time-picker", () => { - expect(wrapper.find(".bs-date-picker").exists()).toBe(true); - expect(wrapper.find(".time-class").exists()).toBe(true); - }); - - it("sets initial data correctly", () => { - expect(wrapper.vm.dateString).toBe(moment().format("YYYY-MM-DD")); + it("sets initial data correctly", async () => { + const wrapper = await mountDateTimePicker(); + expect(wrapper.vm.dateString).toBe(now.format("YYYY-MM-DD")); expect(wrapper.vm.time).toBeInstanceOf(Date); }); it("emits update:modelValue when time changes", async () => { + const wrapper = await mountDateTimePicker(); const newTime = new Date(); + const newTimeFormatted = moment(newTime).format(); await wrapper.setData({ time: newTime }); expect(wrapper.emitted("update:modelValue")).toBeTruthy(); - expect(wrapper.emitted("update:modelValue")[0]).toEqual([ - moment(newTime).format(), - ]); + expect(wrapper.emitted("update:modelValue")[0]).toEqual([newTimeFormatted]); + }); + + it("renders date-picker and time-picker", async () => { + const wrapper = await mountDateTimePicker(); + expect(wrapper.find(".bs-date-picker").exists()).toBe(true); + expect(wrapper.find(".time-class").exists()).toBe(true); }); it("updates time and dateString when modelValue changes", async () => { + const wrapper = await mountDateTimePicker(); const newModelValue = moment().add(1, "days").format(); await wrapper.setProps({ modelValue: newModelValue }); expect(wrapper.vm.dateString).toBe( - moment(newModelValue).format("YYYY-MM-DD"), + moment(newModelValue).format("YYYY-MM-DD") ); expect(wrapper.vm.time).toEqual(moment(newModelValue).toDate()); }); + it("recalculates date when dateString changes", async () => { + const wrapper = await mountDateTimePicker(); const newDateString = moment().add(1, "days").format("YYYY-MM-DD"); await wrapper.setData({ dateString: newDateString }); expect(moment(wrapper.vm.time).format("YYYY-MM-DD")).toBe(newDateString); }); - it("sets time and dateString from modelValue when modelValue changes", async () => { - const newModelValue = moment().add(1, "days").format(); - await wrapper.setProps({ modelValue: newModelValue }); - - expect(wrapper.vm.time).toEqual(moment(newModelValue).toDate()); - expect(wrapper.vm.dateString).toBe( - moment(newModelValue).format("YYYY-MM-DD"), - ); - }); - it("binds v-model and class correctly to date-picker and time-picker", () => { + it("binds v-model and class correctly to date-picker and time-picker", async () => { + const wrapper = await mountDateTimePicker(); expect(typeof wrapper.vm.dateString).toBe("string"); expect(wrapper.vm.time).toBeInstanceOf(Date); expect(wrapper.vm.dateClass).toBe("date-class"); expect(wrapper.vm.timeClass).toBe("time-class"); }); + + it("applies dateClass and timeClass props correctly", async () => { + const wrapper = await mountDateTimePicker(); + expect(wrapper.find(".date-class").exists()).toBe(true); + expect(wrapper.find(".time-class").exists()).toBe(true); + }); + + it("passes clear-btn prop correctly to date-picker", async () => { + const wrapper = await mountDateTimePicker(); + const datePicker = wrapper.find(".bs-date-picker"); + + expect(datePicker.attributes("clear-btn")).toBe("false"); + }); + + it("computes datetime correctly", async () => { + const wrapper = await mountDateTimePicker(); + expect(wrapper.vm.datetime).toBe(moment(wrapper.vm.time).format()); + }); + + it("applies CSS classes correctly", async () => { + const wrapper = await mountDateTimePicker(); + expect(wrapper.find(".bs-date-picker").exists()).toBe(true); + }); + + it("renders date-picker and time-picker", async () => { + const wrapper = await mountDateTimePicker(); + const datePicker = wrapper.findComponent({ name: "date-picker" }); + const timePicker = wrapper.findComponent({ name: "time-picker" }); + + expect(datePicker.exists()).toBe(true); + expect(timePicker.exists()).toBe(true); + }); + + it("passes correct props to date-picker and time-picker", async () => { + const wrapper = await mountDateTimePicker(); + const datePicker = wrapper.findComponent({ name: "date-picker" }); + const timePicker = wrapper.findComponent({ name: "time-picker" }); + + expect(datePicker.attributes("modelvalue")).toBe(wrapper.vm.dateString); + expect(datePicker.attributes("class")).toContain(wrapper.vm.dateClass); + expect(datePicker.attributes("clear-btn")).toBe("false"); + + // Convert both values to ISO string format before comparing them + const receivedTime = new Date( + timePicker.attributes("modelvalue") + ).toISOString(); + const expectedTime = new Date(wrapper.vm.time).toISOString(); + + expect(receivedTime).toBe(expectedTime); + expect(timePicker.attributes("class")).toContain(wrapper.vm.timeClass); + }); + + it("emits update:modelValue when time changes", async () => { + const wrapper = await mountDateTimePicker(); + wrapper.vm.time = new Date(); + + await wrapper.vm.$nextTick(); + + expect(wrapper.emitted("update:modelValue")).toBeTruthy(); + }); + + it("recalculates date when dateString changes", async () => { + const wrapper = await mountDateTimePicker(); + const originalTime = wrapper.vm.time; + wrapper.vm.dateString = "2022-01-01"; + + await wrapper.vm.$nextTick(); + + expect(wrapper.vm.time).not.toEqual(originalTime); + }); + + it("sets time and dateString from modelValue", async () => { + const wrapper = await mountDateTimePicker(); + const newModelValue = moment().format(); + wrapper.setProps({ modelValue: newModelValue }); + + await wrapper.vm.$nextTick(); + + expect(wrapper.vm.time).toEqual(moment(newModelValue).toDate()); + expect(wrapper.vm.dateString).toEqual( + moment(newModelValue).format("YYYY-MM-DD") + ); + }); }); From 044ce2b4b8c6dabe3a4efe1df1c0aef8b44e15e2 Mon Sep 17 00:00:00 2001 From: Jaya Singh Date: Wed, 15 May 2024 10:45:54 -0500 Subject: [PATCH 3/9] cleaned and added more tests --- .../components/activity/dateTimePicker.vue | 18 ++++++- .../activity/tests/dateTimePicker.spec.ts | 52 ++++++++----------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/dateTimePicker.vue b/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/dateTimePicker.vue index c0e56c86e6a..3094d639687 100644 --- a/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/dateTimePicker.vue +++ b/rundeckapp/grails-spa/packages/ui-trellis/src/app/components/activity/dateTimePicker.vue @@ -5,8 +5,9 @@ :class="dateClass" :clear-btn="false" class="bs-date-picker" + role="combobox" /> - +