import { mount, shallowMount } from "@vue/test-utils"; import DCheckbox from "@/components/atoms/d-checkbox"; import config from "@/components/atoms/d-checkbox/config"; import { COLOR_SCHEME } from "@darwin-studio/ui-codegen/dist/constants/color-scheme"; import { SIZE } from "@darwin-studio/ui-codegen/dist/constants/size"; import colorSchemeStyles from "@darwin-studio/ui-codegen/dist/styles/color-scheme.css"; // TODO: shorter path, default export ??? TODO: make it module ??? import { baseClassCase, borderClassCase, colorSchemeClassCase, controlIdAbsenceCase, controlIdAutogeneratedCase, controlIdPresenceCase, defaultCheckMarkCase, disabledAttrCase, disabledClassCase, propVNodeCase, propStringCase, iconSlotCase, inputAttrsCase, inputClassCase, elementValueAttrCase, labelClassCase, labelFontCase, minControlWidthCase, outlineClassCase, paddingEqualClassesCase, roundingClassCase, sizeClassCase, slotCase, tagCase, transitionClassCase, } from "@/utils/test-case-factories"; import sleep from "@/utils/sleep"; import prepareCssClassName from "@darwin-studio/ui-codegen/src/utils/prepareCssClassName"; import codegenConfig from "@darwin-studio/ui-codegen/config.json"; import DCaption from "@/components/atoms/d-caption"; describe("DCheckbox", () => { const wrapper = shallowMount(DCheckbox, { props: { checked: true, caption: "Not empty" }, }); baseClassCase(wrapper, config.class); it("Should render input element with checkbox type", () => { const inputEl = wrapper.find("input"); expect(inputEl.exists()).toBeTruthy(); expect(inputEl.attributes().type).toBe("checkbox"); }); elementValueAttrCase(wrapper); inputClassCase(wrapper); inputAttrsCase(wrapper); minControlWidthCase(wrapper); defaultCheckMarkCase(wrapper, config); iconSlotCase(DCheckbox, `.${config.iconContainerClass}`); // TODO: make check target class ?? it("Icon container classes should contain props.iconContainerClass if passed", async () => { const iconContainerClass = "iconContainerCustomClass"; await wrapper.setProps({ iconContainerClass }); const iconContainerEl = wrapper.find(`.${config.iconContainerClass}`); expect(iconContainerEl.classes()).toContain(iconContainerClass); }); // TODO: make check target class ?? it("Icon container classes should contain colorSchemeStyles.__disabled if props.disabled passed", async () => { await wrapper.setProps({ disabled: true }); const iconContainerEl = wrapper.find(`.${config.iconContainerClass}`); expect(iconContainerEl.classes()).toContain(colorSchemeStyles.__disabled); }); labelClassCase(wrapper); labelFontCase(wrapper); propStringCase(wrapper, `.${config.labelInnerClass}`, "label"); propVNodeCase(wrapper, `.${config.labelInnerClass}`, "label"); slotCase(DCheckbox, `.${config.labelInnerClass}`, "label"); disabledClassCase(wrapper, `.${config.labelClass}`); disabledAttrCase(wrapper, `.${config.inputClass}`); controlIdPresenceCase(wrapper); controlIdAbsenceCase(wrapper); controlIdAutogeneratedCase(wrapper); borderClassCase( wrapper, `.${config.iconContainerClass}`, COLOR_SCHEME.SECONDARY ); colorSchemeClassCase( wrapper, `.${config.iconContainerClass}`, COLOR_SCHEME.DANGER ); outlineClassCase(wrapper, "input", COLOR_SCHEME.ALTERNATIVE, SIZE.LARGE); paddingEqualClassesCase(wrapper, `.${config.iconContainerClass}`); roundingClassCase(wrapper, `.${config.iconContainerClass}`); sizeClassCase(wrapper, "input"); sizeClassCase(wrapper, `.${config.iconContainerClass}`); sizeClassCase(wrapper, `.${config.iconContainerBackdropClass}`); transitionClassCase(wrapper, `.${config.iconContainerClass}`); // TODO: combine all Caption cases in one factory or just test composition??? it("Shouldn't render caption element if props.caption isn't passed", async () => { const wrapper = await mount(DCheckbox); const captionEl = wrapper.find(`.${config.captionOptions.class}`); expect(captionEl.exists()).toBeFalsy(); }); it("Should render caption element with props.caption content if passed", async () => { const captionContent = "some caption"; const caption =
{captionContent}
; const wrapper = await mount(DCheckbox, { props: { caption } }); await sleep(0); // Should wait next event loop step for asyncComponent to be imported const captionEl = wrapper.find(`.${config.captionOptions.class}`); expect(captionEl.exists()).toBeTruthy(); expect(captionEl.text()).toBe(captionContent); }); slotCase(DCheckbox, `.${config.captionOptions.class}`, "caption"); it("Should render props.captionOffset to the caption style as '--offset: props.captionOffset'", async () => { const captionOffset = 33; const wrapper = await mount(DCheckbox, { props: { captionOffset, caption: "Not empty" }, }); await sleep(0); // Should wait next event loop step for asyncComponent to be imported const captionEl = wrapper.find(`.${config.captionOptions.class}`); expect(captionEl.attributes("style")).toContain( `--offset: ${captionOffset}` ); }); transitionClassCase(wrapper, `.${config.captionOptions.class}`, { caption: "not empty", }); it("Should merge props from props.captionOptions and config.CaptionOptions to the caption element attrs", async () => { const externalClass = "some-external-class"; const wrapper = mount(DCheckbox, { props: { caption: "not empty", captionOptions: { class: externalClass, }, }, }); const caption = wrapper.findComponent(DCaption); expect(caption.classes()).toContain(externalClass); }); it("Shouldn render props.size into props.font of the DCaption", async () => { const size = SIZE.HUGE; const wrapper = await mount(DCheckbox, { props: { size, caption: "Not empty" }, }); await sleep(0); // Should wait next event loop step for asyncComponent to be imported const captionEl = wrapper.find(`.${config.captionOptions.class}`); const className = prepareCssClassName( codegenConfig.TOKENS.FONT.CSS_CLASS_PREFIX, size ); expect(captionEl.classes()).toContain(className); }); it("Should emit onChange event with checked and value payload", async () => { const value = "some value"; const checked = true; const wrapper = shallowMount(DCheckbox, { props: { value, checked } }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("change"); expect(wrapper.emitted("change")?.[0]).toStrictEqual([ !checked, !checked ? value : undefined, ]); expect(wrapper.emitted("update:checked")?.[0]).toStrictEqual([!checked]); expect(wrapper.emitted("update:value")?.[0]).toStrictEqual([ !checked ? value : undefined, ]); }); it("Shouldn't emit onChange if props.disabled is passed", async () => { const value = "some value"; const checked = true; const disabled = true; const wrapper = shallowMount(DCheckbox, { props: { value, checked, disabled }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("change"); expect(wrapper.emitted("change")?.[0]).toBeFalsy(); expect(wrapper.emitted("update:checked")?.[0]).toBeFalsy(); expect(wrapper.emitted("update:value")?.[0]).toBeFalsy(); }); it("Should call passed props.whenChange", async () => { const value = "some value"; const checked = true; const whenChange = jest.fn(); const wrapper = shallowMount(DCheckbox, { props: { value, checked, whenChange }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("change"); expect(whenChange).toHaveBeenCalledWith( !checked, !checked ? value : undefined ); }); it("Shouldn't call passed props.whenChange if props.disabled passed", async () => { const value = "some value"; const checked = true; const disabled = true; const whenChange = jest.fn(); const wrapper = shallowMount(DCheckbox, { props: { value, checked, disabled, whenChange }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("change"); expect(whenChange).toHaveBeenCalledTimes(0); }); it("Should emit onInput event with value payload", async () => { const value = "some value"; const checked = true; const disabled = false; const wrapper = shallowMount(DCheckbox, { props: { value, checked, disabled }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("input"); expect(wrapper.emitted("input")?.[0]).toStrictEqual([ !checked ? value : undefined, ]); expect(wrapper.emitted("update:value")?.[0]?.[0]).toStrictEqual( !checked ? value : undefined ); }); it("Shouldn't emit onInput if props.disabled is passed", async () => { const value = "some value"; const checked = true; const disabled = true; const wrapper = shallowMount(DCheckbox, { props: { value, checked, disabled }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("input"); expect(wrapper.emitted("input")?.[0]).toBeFalsy(); expect(wrapper.emitted("update:value")?.[0]).toBeFalsy(); }); it("Should call passed props.whenInput", async () => { const value = "some value"; const checked = true; const whenInput = jest.fn(); const wrapper = shallowMount(DCheckbox, { props: { value, checked, whenInput }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("input"); expect(whenInput).toHaveBeenCalledWith(!checked ? value : undefined); }); it("Shouldn't call passed props.whenInput if props.disabled passed", async () => { const value = "some value"; const checked = true; const disabled = true; const whenInput = jest.fn(); const wrapper = shallowMount(DCheckbox, { props: { value, checked, disabled, whenInput }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("click"); await inputEl.trigger("input"); expect(whenInput).toHaveBeenCalledTimes(0); }); tagCase(wrapper); });