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