import { mount, shallowMount } from "@vue/test-utils";
import { INPUT_TYPE } from "@/components/atoms/d-input/constants";
import { FONT } from "@darwin-studio/ui-codegen/dist/constants/font";
import { COLOR_SCHEME } from "@darwin-studio/ui-codegen/dist/constants/color-scheme";
import { SIZE } from "@darwin-studio/ui-codegen/dist/constants/size";
import codegenConfig from "@darwin-studio/ui-codegen/config.json";
import prepareCssClassName from "@darwin-studio/ui-codegen/src/utils/prepareCssClassName";
import DInput from "@/components/atoms/d-input";
import config from "./config";
import {
baseClassCase,
borderClassCase,
controlIdAbsenceCase,
controlIdAutogeneratedCase,
controlIdPresenceCase,
propVNodeCase,
propStringCase,
fontSizeClassCase,
inputAttrsCase,
inputClassCase,
elementValueAttrCase,
labelAbsenceCase,
labelClassCase,
labelFontCase,
minControlWidthCase,
outlineClassCase,
paddingEqualClassesCase,
roundingClassCase,
sizeClassCase,
slotCase,
tagCase,
transitionClassCase,
} from "@/utils/test-case-factories";
import sleep from "@/utils/sleep";
import DCaption from "@/components/atoms/d-caption";
describe("DInput", () => {
const wrapper = mount(DInput, { props: { caption: "Not empty" } });
baseClassCase(wrapper, config.class);
minControlWidthCase(wrapper);
elementValueAttrCase(wrapper);
inputClassCase(wrapper);
it("Should render props.placeholder to the input element placeholder attr", async () => {
const placeholder = "Some placeholder";
await wrapper.setProps({ placeholder });
const inputEl = wrapper.find("input");
expect(inputEl.attributes().placeholder).toBe(placeholder);
});
it("Should render props.inputType to the input element type attr", async () => {
const inputType = INPUT_TYPE.PASSWORD;
await wrapper.setProps({ inputType });
const inputEl = wrapper.find("input");
expect(inputEl.attributes().type).toBe(inputType);
});
it("Should render props.inputSize to the input element size attr", async () => {
const inputSize = 5;
await wrapper.setProps({ inputSize });
const inputEl = wrapper.find("input");
expect(inputEl.attributes().size).toBe(String(inputSize));
});
inputAttrsCase(wrapper);
labelAbsenceCase(wrapper);
labelClassCase(wrapper);
labelFontCase(wrapper);
propStringCase(wrapper, `.${config.labelClass}`, "label");
propVNodeCase(wrapper, `.${config.labelClass}`, "label");
slotCase(DInput, `.${config.labelClass}`, "label");
controlIdPresenceCase(wrapper);
controlIdAbsenceCase(wrapper);
controlIdAutogeneratedCase(wrapper);
borderClassCase(wrapper, "input", COLOR_SCHEME.SECONDARY);
it("Should render props.inputFont to input font class", async () => {
const inputFont = FONT.LARGE;
const className = prepareCssClassName(
codegenConfig.TOKENS.FONT.CSS_CLASS_PREFIX,
inputFont
);
await wrapper.setProps({ inputFont });
const inputEl = wrapper.find("input");
expect(inputEl.classes()).toContain(className);
await wrapper.setProps({ inputFont: undefined });
});
// TODO: fix
fontSizeClassCase(wrapper, "input");
outlineClassCase(wrapper, "input", COLOR_SCHEME.SECONDARY, SIZE.LARGE);
paddingEqualClassesCase(wrapper, "input");
roundingClassCase(wrapper, "input");
sizeClassCase(wrapper, "input");
transitionClassCase(wrapper, "input");
// TODO: combine all Caption cases in one factory or just test composition???
it("Shouldn render props.size into props.font of the DCaption", async () => {
const size = SIZE.HUGE;
const wrapper = await mount(DInput, {
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("Shouldn't render caption element if props.caption isn't passed", async () => {
const wrapper = await mount(DInput);
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();
});
it("Should render caption element with props.caption content if passed", async () => {
const captionContent = "some caption";
const caption =
{captionContent}
;
const wrapper = await mount(DInput, { 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(DInput, `.${config.captionOptions.class}`, "caption");
it("Should render props.captionOffset to the caption style as '--offset: props.captionOffset'", async () => {
const captionOffset = 33;
await wrapper.setProps({
caption: "Caption string",
captionOffset,
});
const captionEl = wrapper.find(`.${config.captionOptions.class}`);
expect(captionEl.attributes("style")).toContain(
`--offset: ${captionOffset}`
);
});
transitionClassCase(wrapper, `.${config.captionOptions.class}`);
it("Should merge props from props.captionOptions and config.captionOption to the caption element attrs", async () => {
const externalClass = "some-external-class";
const wrapper = mount(DInput, {
props: {
caption: "not empty",
captionOptions: {
class: externalClass,
},
},
});
const caption = wrapper.findComponent(DCaption);
expect(caption.classes()).toContain(externalClass);
});
it("Should emit onChange event with checked and value payload", async () => {
const value = "some value";
const checked = false;
const wrapper = shallowMount(DInput, { props: { name, value, checked } });
const inputEl = wrapper.find("input");
await inputEl.trigger("click");
await inputEl.trigger("change");
expect(wrapper.emitted("change")?.[0]).toStrictEqual([value]);
expect(wrapper.emitted("update:value")?.[0]).toStrictEqual([value]);
});
// TODO: case factory
it("Should emit onChange event with value payload", async () => {
const wrapper = shallowMount(DInput);
const inputEl = wrapper.find("input");
const newValue = "new value";
await inputEl.setValue(newValue);
await inputEl.trigger("change");
expect(wrapper.emitted("change")?.[0]).toStrictEqual([newValue]);
expect(wrapper.emitted("update:value")?.[0]).toStrictEqual([newValue]);
});
// TODO: case factory
it("Shouldn't emit onChange event if is disable", async () => {
const wrapper = shallowMount(DInput, {
props: { disabled: true },
});
const inputEl = wrapper.find("input");
await inputEl.trigger("change");
expect(wrapper.emitted("change")).toBeFalsy();
});
// TODO: case factory
it("Should call passed props.whenChange", async () => {
const whenChange = jest.fn();
const wrapper = shallowMount(DInput, {
props: { whenChange, disabled: false },
});
const inputEl = wrapper.find("input");
const newValue = "new value";
await inputEl.setValue(newValue);
expect(whenChange).toHaveBeenCalledWith(newValue);
});
// TODO: case factory
it("Shouldn't call passed props.whenChange if is disabled", async () => {
const whenChange = jest.fn();
const wrapper = shallowMount(DInput, {
props: { whenChange, disabled: true },
});
const inputEl = wrapper.find("input");
await inputEl.trigger("change");
expect(whenChange).toHaveBeenCalledTimes(0);
});
// TODO: case factory
it("Should emit onInput event", async () => {
const wrapper = shallowMount(DInput);
const inputEl = wrapper.find("input");
const newValue = "new value";
await inputEl.setValue(newValue);
expect(wrapper.emitted("input")?.[0]).toStrictEqual([newValue]);
});
// TODO: case factory
it("Shouldn't emit onInput event if is disable", async () => {
const wrapper = shallowMount(DInput, {
props: { disabled: true },
});
const inputEl = wrapper.find("input");
await inputEl.trigger("input");
expect(wrapper.emitted("input")).toBeFalsy();
});
// TODO: case factory
it("Should call passed props.whenInput", async () => {
const whenInput = jest.fn();
const wrapper = shallowMount(DInput, {
props: { whenInput, disabled: false },
});
const inputEl = wrapper.find("input");
const newValue = "new value";
await inputEl.setValue(newValue);
expect(whenInput).toHaveBeenCalledWith(newValue);
});
// TODO: case factory
it("Shouldn't call passed props.whenInput if is disabled", async () => {
const whenInput = jest.fn();
const wrapper = shallowMount(DInput, {
props: { whenInput, disabled: true },
});
const inputEl = wrapper.find("input");
await inputEl.trigger("input");
expect(whenInput).toHaveBeenCalledTimes(0);
});
// TODO: case factory
it("Should emit onSubmit event", async () => {
const wrapper = shallowMount(DInput);
const inputEl = wrapper.find("input");
const newValue = "new value";
await inputEl.setValue(newValue);
await inputEl.trigger("keyup", { key: "Enter" });
expect(wrapper.emitted("submit")?.[0]).toStrictEqual([newValue]);
});
// TODO: case factory
it("Shouldn't emit onSubmit event if is disable", async () => {
const wrapper = shallowMount(DInput, {
props: { disabled: true },
});
const inputEl = wrapper.find("input");
await inputEl.trigger("keyup", { key: "Enter" });
expect(wrapper.emitted("submit")).toBeFalsy();
});
// TODO: case factory
it("Should call passed props.whenSubmit", async () => {
const whenSubmit = jest.fn();
const wrapper = shallowMount(DInput, {
props: { whenSubmit, disabled: false },
});
const inputEl = wrapper.find("input");
const newValue = "new value";
await inputEl.setValue(newValue);
await inputEl.trigger("keyup", { key: "Enter" });
expect(whenSubmit).toHaveBeenCalledWith(newValue);
});
// TODO: case factory
it("Shouldn't call passed props.whenSubmit if is disabled", async () => {
const whenSubmit = jest.fn();
const wrapper = shallowMount(DInput, {
props: { whenSubmit, disabled: true },
});
const inputEl = wrapper.find("input");
await inputEl.trigger("keyup", { key: "Enter" });
expect(whenSubmit).toHaveBeenCalledTimes(0);
});
it("Should should render before slot", () => {
const slotBeforeClass = "slotBefore";
const slotBefore = `before slot content
`;
const wrapper = shallowMount(DInput, {
slots: {
before: slotBefore,
},
});
const slotBeforeContainerEl = wrapper.find(
`.${config.beforeContainerClass}`
);
expect(slotBeforeContainerEl.exists()).toBeTruthy();
const slotBeforeEl = wrapper.find(`.${slotBeforeClass}`);
expect(slotBeforeEl.exists()).toBeTruthy();
});
it("Should should render after slot", () => {
const slotAfterClass = "slotAfter";
const slotAfter = `after slot content
`;
const wrapper = shallowMount(DInput, {
slots: {
after: slotAfter,
},
});
const slotAfterContainerEl = wrapper.find(`.${config.afterContainerClass}`);
expect(slotAfterContainerEl.exists()).toBeTruthy();
const slotAfterEl = wrapper.find(`.${slotAfterClass}`);
expect(slotAfterEl.exists()).toBeTruthy();
});
tagCase(wrapper);
});