import { mount, shallowMount } from "@vue/test-utils"; import DSlider from "@darwin-studio/vue-ui/src/components/atoms/d-slider"; import DCaption from "@darwin-studio/vue-ui/src/components/atoms/d-caption"; import { COLOR_SCHEME } from "@darwin-studio/ui-codegen/dist/constants/color-scheme"; import { SIZE } from "@darwin-studio/ui-codegen/dist/constants/size"; import { baseClassCase, colorSchemeClassCase, controlIdAbsenceCase, controlIdAutogeneratedCase, controlIdPresenceCase, disabledAttrCase, fontSizeClassCase, elementValueAttrCase, labelAbsenceCase, propStringCase, propVNodeCase, minControlWidthCase, outlineClassCase, roundingClassCase, sizeClassCase, slotCase, tagCase, offsetCase, } from "@/utils/test-case-factories"; import config from "./config"; import sleep from "@/utils/sleep"; import { TRANSITION } from "@darwin-studio/ui-codegen/dist/constants/transition"; import prepareCssClassName from "@darwin-studio/ui-codegen/src/utils/prepareCssClassName"; import codegenConfig from "@darwin-studio/ui-codegen/config.json"; describe("DSlider", () => { const wrapper = mount(DSlider); baseClassCase(wrapper, config.class); controlIdAbsenceCase(wrapper); controlIdPresenceCase(wrapper); controlIdAutogeneratedCase(wrapper); elementValueAttrCase(wrapper, 33); // TODO: attr case factory it("Should render props.inputOptions.min to the input's min attr", async () => { const min = 13; await wrapper.setProps({ inputOptions: { min } }); const inputEl = wrapper.find(`.${config.inputOptions.class}`); expect(inputEl.attributes().min).toBe(String(min)); }); it("Should render props.max to the input's max attr", async () => { const max = 66; await wrapper.setProps({ inputOptions: { max } }); const inputEl = wrapper.find(`.${config.inputOptions.class}`); expect(inputEl.attributes().max).toBe(String(max)); }); it("Should render props.step to the input's step attr", async () => { const step = 4; await wrapper.setProps({ inputOptions: { step } }); const inputEl = wrapper.find(`.${config.inputOptions.class}`); expect(inputEl.attributes().step).toBe(String(step)); }); labelAbsenceCase(wrapper); propStringCase(wrapper, `.${config.labelOptions.class}`, "label"); propVNodeCase(wrapper, `.${config.labelOptions.class}`, "label"); slotCase(DSlider, `.${config.labelOptions.class}`, "label"); offsetCase(wrapper); colorSchemeClassCase( wrapper, `.${config.trackOptions.class}`, COLOR_SCHEME.DANGER ); slotCase(DSlider, `.${config.trackOptions.class}`, "track"); it("Shouldn't render caption element if props.caption isn't passed", async () => { await wrapper.setProps({ caption: undefined }); await sleep(0); // Should wait next event loop step for asyncComponent to be imported const captionEl = wrapper.find(`.${config.captionOptions.class}`); expect(captionEl.exists()).toBeFalsy(); await wrapper.setProps({ caption: "not empty" }); }); it("Should render caption element with props.caption content if passed", async () => { const captionContent = "some caption"; const caption =
{captionContent}
; const wrapper = mount(DSlider, { 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(DSlider, `.${config.captionOptions.class}`, "caption"); it("Should render props.captionOffset to the caption style as '--offset: props.captionOffset'", async () => { const captionOffset = 33; const wrapper = mount(DSlider, { 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}` ); }); colorSchemeClassCase( wrapper, `.${config.inputOptions.class}`, COLOR_SCHEME.DANGER ); outlineClassCase( wrapper, `.${config.inputOptions.class}`, COLOR_SCHEME.DANGER, SIZE.SMALL ); roundingClassCase(wrapper, `.${config.trackOptions.class}`); roundingClassCase(wrapper, `.${config.inputOptions.class}`); sizeClassCase(wrapper, `.${config.class}`); fontSizeClassCase(wrapper, `.${config.labelOptions.class}`); minControlWidthCase(wrapper); it(`Should render props.transition to .caption transition class`, async () => { const transition = TRANSITION.AVERAGE; const wrapper = mount(DSlider, { props: { transition, caption: "Not empty" }, }); await sleep(0); // Should wait next event loop step for asyncComponent to be imported const className = prepareCssClassName( codegenConfig.TOKENS.TRANSITION.CSS_CLASS_PREFIX, transition ); const targetEl = wrapper.find(`.${config.captionOptions.class}`); expect(targetEl.classes()).toContain(className); }); disabledAttrCase(wrapper, `.${config.inputOptions.class}`); tagCase(wrapper); it("Should emit onChange event with value payload", async () => { const value = 34; const newValue = 99; const wrapper = shallowMount(DSlider, { props: { value } }); const inputEl = wrapper.find("input"); await inputEl.setValue(newValue); await inputEl.trigger("change"); expect(wrapper.emitted("change")?.[0]).toStrictEqual([String(newValue)]); expect(wrapper.emitted("update:value")?.[0]).toStrictEqual([ String(newValue), ]); }); it("Shouldn't emit onChange if props.disabled is passed", async () => { const value = 34; const disabled = true; const wrapper = shallowMount(DSlider, { props: { value, disabled }, }); const inputEl = wrapper.find("input"); const newValue = 99; await inputEl.setValue(newValue); await inputEl.trigger("change"); expect(wrapper.emitted("change")?.[0]).toBeFalsy(); expect(wrapper.emitted("update:value")?.[0]).toBeFalsy(); }); it("Should call passed props.whenChange", async () => { const value = 33; const whenChange = jest.fn(); const wrapper = mount(DSlider, { props: { value, whenChange }, }); const inputEl = wrapper.find("input"); const newValue = 99; await inputEl.setValue(newValue); await inputEl.trigger("change"); expect(whenChange).toHaveBeenCalledWith(String(newValue)); }); it("Shouldn't call passed props.whenChange if props.disabled passed", async () => { const value = 33; const disabled = true; const whenChange = jest.fn(); const wrapper = mount(DSlider, { props: { value, disabled, whenChange }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("change"); expect(whenChange).toHaveBeenCalledTimes(0); }); it("Should emit onInput event with value payload", async () => { const value = 34; const newValue = 99; const wrapper = shallowMount(DSlider, { props: { value } }); const inputEl = wrapper.find("input"); await inputEl.setValue(newValue); await inputEl.trigger("input"); expect(wrapper.emitted("input")?.[0]).toStrictEqual([String(newValue)]); expect(wrapper.emitted("update:value")?.[0]).toStrictEqual([ String(newValue), ]); }); it("Shouldn't emit onInput if props.disabled is passed", async () => { const value = 34; const disabled = true; const wrapper = shallowMount(DSlider, { props: { value, disabled }, }); const inputEl = wrapper.find("input"); const newValue = 99; await inputEl.setValue(newValue); 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 = 33; const whenInput = jest.fn(); const wrapper = mount(DSlider, { props: { value, whenInput }, }); const inputEl = wrapper.find("input"); const newValue = 99; await inputEl.setValue(newValue); await inputEl.trigger("input"); expect(whenInput).toHaveBeenCalledWith(String(newValue)); }); it("Shouldn't call passed props.whenInput if props.disabled passed", async () => { const value = 33; const disabled = true; const whenInput = jest.fn(); const wrapper = mount(DSlider, { props: { value, disabled, whenInput }, }); const inputEl = wrapper.find("input"); await inputEl.trigger("input"); expect(whenInput).toHaveBeenCalledTimes(0); }); it("Should merge props from props.trackOptions and config.trackOptions to the track element attrs", async () => { const externalClass = "some-external-class"; const wrapper = mount(DSlider); await wrapper.setProps({ trackOptions: { class: externalClass, }, }); const trackEl = wrapper.find(`.${config.trackOptions.class}`); expect(trackEl.classes()).toContain(externalClass); }); it("Should merge props from props.inputOptions and config.inputOptions to the input element attrs", async () => { const externalClass = "some-external-class"; const wrapper = mount(DSlider); await wrapper.setProps({ inputOptions: { class: externalClass, }, }); const inputEl = wrapper.find(`.${config.inputOptions.class}`); expect(inputEl.classes()).toContain(externalClass); }); it("Should merge props from props.labelOptions and config.labelOptions to the label element attrs", async () => { const externalClass = "some-external-class"; const wrapper = mount(DSlider); await wrapper.setProps({ label: "not empty", labelOptions: { class: externalClass, }, }); const labelEl = wrapper.find(`.${config.labelOptions.class}`); expect(labelEl.classes()).toContain(externalClass); }); it("Should merge props from props.captionOptions and config.captionOptions to the caption element attrs", async () => { const externalClass = "some-external-class"; const wrapper = mount(DSlider, { props: { caption: "not empty", captionOptions: { class: externalClass, }, }, }); const caption = wrapper.findComponent(DCaption); expect(caption.classes()).toContain(externalClass); }); });