import { mount } from "@vue/test-utils";
// TODO: get @darwin-studio/ui-codegen paths from config.json
import { COLOR_SCHEME } from "@darwin-studio/ui-codegen/dist/constants/color-scheme";
import DNotification from "@/components/atoms/d-notification";
import { TYPE } from "@/components/atoms/d-notification/constants";
import {
propStringCase,
propVNodeCase,
colorSchemeClassCase,
paddingEqualClassesCase,
roundingClassCase,
sizeClassCase,
transitionClassCase,
} from "@/utils/test-case-factories";
import sleep from "@/utils/sleep";
import { POSITION } from "@/constants/position";
import config from "./config";
describe("DNotification", () => {
const content = "Some content";
const wrapper = mount(DNotification, {
props: {
enableInline: true, // Turn of the Teleport
content,
duration: 0, // Do not hide automatically
},
});
beforeEach(async () => {
// The thing is the content doesn't appear immediately due to this.show() implementation
await wrapper.vm.$nextTick();
});
it(`Renders ${config.class} class name`, async () => {
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl?.classes()).toContain(config.class);
});
propStringCase(wrapper, `.${config.class}`);
propVNodeCase(wrapper, `.${config.class}`);
it("Renders $slots.default", async () => {
const slotContent = `
Some slot content
`;
const wrapper = mount(DNotification, {
props: {
enableInline: true,
},
slots: {
default: slotContent,
},
});
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.html()).toMatch(slotContent);
});
it("Should render the position class depend on props.position", async () => {
const position = POSITION.BOTTOM_LEFT;
await wrapper.setProps({ position });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.classes()).toContain(position);
});
it("Should add min-width style if props.minWidth is set", async () => {
const minWidth = 120;
await wrapper.setProps({ minWidth });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.attributes()?.style).toContain(
"min-width: " + minWidth + "px"
);
});
it("Should add max-width style if props.maxWidth is set", async () => {
const maxWidth = "33%";
await wrapper.setProps({ maxWidth });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.attributes()?.style).toContain(
"max-width: " + maxWidth
);
});
it("Should add min-height style if props.minHeight is set", async () => {
const minHeight = 240;
await wrapper.setProps({ minHeight });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.attributes()?.style).toContain(
"min-height: " + minHeight + "px"
);
});
it("Should add max-height style if props.maxHeight is set", async () => {
const maxHeight = "10vh";
await wrapper.setProps({ maxHeight });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.attributes()?.style).toContain(
"max-height: " + maxHeight
);
});
it("Should close manually on click if props.closable is true", async () => {
const wrapper = mount(DNotification, {
props: {
enableInline: true,
closable: true,
},
});
await wrapper.vm.$nextTick();
let notificationEl = wrapper.find(`.${config.class}`);
await notificationEl.trigger("click");
notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.exists()).toBeFalsy();
});
it("Should not close manually on click if props.closable is false", async () => {
await wrapper.setProps({ closable: false });
let notificationEl = wrapper.find(`.${config.class}`);
await notificationEl.trigger("click");
notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.exists()).toBeTruthy();
});
it("Should not close automatically if props.duration is falsy", async () => {
const duration = 0;
const wrapper = mount(DNotification, {
props: {
enableInline: true,
duration,
},
});
await wrapper.vm.$nextTick();
expect(wrapper.vm.timeoutId).toBeFalsy();
});
it("Should close automatically after props.duration seconds", async () => {
const duration = 0.1;
const wrapper = mount(DNotification, {
props: {
enableInline: true,
duration,
},
});
const closeSpy = jest.spyOn(wrapper.vm, "closeHandler");
await wrapper.vm.$nextTick();
expect(wrapper.vm.timeoutId).toBeTruthy();
const delta = 0.01;
await sleep((duration + delta) * 1000);
await wrapper.vm.$nextTick();
expect(closeSpy).toBeCalled();
});
it("Should render props.notificationClass to the notification class list", async () => {
const notificationClass = "some-custom-class";
await wrapper.setProps({ notificationClass });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.classes()).toContain(notificationClass);
});
it("Should append the notification to the props.target", async () => {
const target = document.createElement("div");
target.id = "custom-target";
document.body.appendChild(target);
const wrapper = mount(DNotification, {
attachTo: document.body,
props: {
target,
},
});
await wrapper.vm.$nextTick();
expect(document.body.innerHTML).toMatchSnapshot(); // TODO: find a better way
});
it("Should props.type to the type class of the notification", async () => {
const type = TYPE.WARNING;
await wrapper.setProps({ type });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.classes()).toContain(type);
});
colorSchemeClassCase(wrapper, `.${config.class}`, COLOR_SCHEME.DANGER);
paddingEqualClassesCase(wrapper, `.${config.class}`);
roundingClassCase(wrapper, `.${config.class}`);
sizeClassCase(wrapper, `.${config.class}`);
transitionClassCase(wrapper, `.${config.class}`);
it("Should render as element passed in props.tag", async () => {
const tag = "section";
await wrapper.setProps({ tag });
const notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.element.tagName).toEqual(tag.toLocaleUpperCase());
});
it("Should emits close event on close", async () => {
const wrapper = mount(DNotification, {
props: {
enableInline: true, // Turn of the Teleport
content,
duration: 0, // Do not hide automatically
},
});
await wrapper.vm.$nextTick();
const notificationEl = wrapper.find(`.${config.class}`);
await notificationEl.trigger("click");
expect(wrapper.emitted("close")).toBeTruthy();
});
it("Should call props.whenClose when passed", async () => {
const whenClose = jest.fn();
const wrapper = mount(DNotification, {
props: {
enableInline: true, // Turn of the Teleport
content,
duration: 0, // Do not hide automatically
whenClose,
},
});
await wrapper.vm.$nextTick();
const notificationEl = wrapper.find(`.${config.class}`);
await notificationEl.trigger("click");
expect(whenClose).toBeCalled();
});
it("The content of the component should appear on nextTick when using props.content", async () => {
const wrapper = mount(DNotification, {
props: {
enableInline: true, // Turn of the Teleport
content,
duration: 0, // Do not hide automatically
},
});
let notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.exists()).toBeFalsy();
await wrapper.vm.$nextTick();
notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.exists()).toBeTruthy();
});
it("The content of the component should appear on nextTick when using default slot", async () => {
const wrapper = mount(DNotification, {
props: {
enableInline: true, // Turn of the Teleport
duration: 0, // Do not hide automatically
},
slots: {
default: content,
},
});
let notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.exists()).toBeFalsy();
await wrapper.vm.$nextTick();
notificationEl = wrapper.find(`.${config.class}`);
expect(notificationEl.exists()).toBeTruthy();
});
it("Should call clearTimeout on unmount", async () => {
window.clearTimeout = jest.fn();
const wrapper = mount(DNotification, {
props: {
enableInline: true,
},
});
await wrapper.unmount();
await wrapper.vm.$nextTick();
expect(window.clearTimeout).toBeCalled();
});
});