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);
});
});