UNPKG

vueless

Version:

Vue Styleless UI Component Library, powered by Tailwind CSS.

572 lines (468 loc) 14.8 kB
import { mount, flushPromises } from "@vue/test-utils"; import { describe, it, expect } from "vitest"; import { nextTick, ref } from "vue"; import UCollapsible from "../UCollapsible.vue"; import type { Props } from "../types"; import type { UnknownObject } from "../../types"; function mountCollapsible(options: UnknownObject = {}) { return mount(UCollapsible, options); } describe("UCollapsible.vue", () => { describe("Props", () => { it("Model Value – controls opened state when provided", async () => { const open = ref(false); const component = mountCollapsible({ props: { open: open.value, dataTest: "test", "onUpdate:open": (value: boolean) => { open.value = value; component.setProps({ open: value }); }, }, slots: { default: "Trigger", content: "Content", }, }); expect(component.find('[data-test="test-content"]').exists()).toBe(false); await component.find('[data-test="test"]').trigger("click"); await nextTick(); expect(component.emitted("update:open")).toBeTruthy(); expect(component.emitted("update:open")![0][0]).toBe(true); await component.setProps({ open: true }); await nextTick(); expect(component.find('[data-test="test-content"]').exists()).toBe(true); }); it("Model Value – works independently when not provided", async () => { const component = mountCollapsible({ props: { dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); expect(component.find('[data-test="test-content"]').exists()).toBe(false); await component.find('[data-test="test"]').trigger("click"); await nextTick(); await flushPromises(); expect(component.find('[data-test="test-content"]').exists()).toBe(true); }); it("YPosition – applies correct position class for top", () => { const component = mountCollapsible({ props: { yPosition: "top" as Props["yPosition"], open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const content = component.find('[data-test="test-content"]'); expect(content.attributes("class")).toContain("bottom-full"); expect(content.attributes("class")).toContain("mb-1"); }); it("YPosition – applies correct position class for bottom", () => { const component = mountCollapsible({ props: { yPosition: "bottom" as Props["yPosition"], open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const content = component.find('[data-test="test-content"]'); expect(content.attributes("class")).toContain("top-full"); expect(content.attributes("class")).toContain("mt-1"); }); it("XPosition – applies correct position class for left", () => { const component = mountCollapsible({ props: { xPosition: "left" as Props["xPosition"], open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const content = component.find('[data-test="test-content"]'); expect(content.attributes("class")).toContain("left-0"); }); it("XPosition – applies correct position class for right", () => { const component = mountCollapsible({ props: { xPosition: "right" as Props["xPosition"], open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const content = component.find('[data-test="test-content"]'); expect(content.attributes("class")).toContain("right-0"); }); it("Absolute – applies absolute positioning when true", () => { const component = mountCollapsible({ props: { absolute: true, open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const content = component.find('[data-test="test-content"]'); expect(content.attributes("class")).toContain("absolute"); }); it("Absolute – does not apply absolute positioning when false", () => { const component = mountCollapsible({ props: { absolute: false, open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const content = component.find('[data-test="test-content"]'); expect(content.attributes("class")).not.toContain("absolute"); }); it("Disabled – prevents opening when disabled", async () => { const component = mountCollapsible({ props: { disabled: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); await component.find('[data-test="test"]').trigger("click"); await nextTick(); expect(component.find('[data-test="test-content"]').exists()).toBe(false); }); it("Disabled – applies cursor-not-allowed class", () => { const component = mountCollapsible({ props: { disabled: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const wrapper = component.find('[data-test="test"]'); expect(wrapper.attributes("class")).toContain("cursor-not-allowed"); }); it("CloseOnOutside – closes when clicking outside", async () => { const component = mountCollapsible({ props: { closeOnOutside: true, open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, attachTo: document.body, }); expect(component.find('[data-test="test-content"]').exists()).toBe(true); document.body.click(); await nextTick(); expect(component.emitted("close")).toBeTruthy(); component.unmount(); }); it("CloseOnContent – closes when clicking content", async () => { const component = mountCollapsible({ props: { closeOnContent: true, open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); await component.find('[data-test="test-content"]').trigger("click"); await nextTick(); expect(component.emitted("close")).toBeTruthy(); }); it("CloseOnContent – does not close when false", async () => { const component = mountCollapsible({ props: { closeOnContent: false, open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); await component.find('[data-test="test-content"]').trigger("click"); await nextTick(); expect(component.find('[data-test="test-content"]').exists()).toBe(true); }); it("Id – applies custom id when provided", () => { const customId = "custom-collapsible-id"; const component = mountCollapsible({ props: { id: customId, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); const wrapper = component.find('[data-test="test"]'); expect(wrapper.attributes("id")).toBe(customId); }); it("DataTest – applies custom data-test attribute", () => { const dataTest = "custom-test"; const component = mountCollapsible({ props: { dataTest, }, slots: { default: "Trigger", content: "Content", }, }); expect(component.find(`[data-test="${dataTest}"]`).exists()).toBe(true); }); }); describe("Slots", () => { it("Default – renders trigger content", () => { const triggerContent = "Click Me"; const component = mountCollapsible({ slots: { default: triggerContent, }, }); expect(component.text()).toContain(triggerContent); }); it("Default – exposes opened state to slot", async () => { const component = mountCollapsible({ props: { dataTest: "test", }, slots: { default: `<template #default="{ opened }"> <div class="trigger">{{ opened ? 'Opened' : 'Closed' }}</div> </template>`, }, }); expect(component.find(".trigger").text()).toBe("Closed"); await component.find('[data-test="test"]').trigger("click"); await nextTick(); await flushPromises(); expect(component.find(".trigger").text()).toBe("Opened"); }); it("Content – renders collapsible content when opened", () => { const contentText = "Collapsible Content"; const component = mountCollapsible({ props: { open: true, }, slots: { default: "Trigger", content: contentText, }, }); expect(component.text()).toContain(contentText); }); it("Content – exposes opened state to slot", () => { const component = mountCollapsible({ props: { open: true, }, slots: { default: "Trigger", content: `<template #content="{ opened }"> <div class="content-state">{{ opened ? 'Open' : 'Closed' }}</div> </template>`, }, }); expect(component.find(".content-state").text()).toBe("Open"); }); }); describe("Events", () => { it("Update:open – emits when toggling", async () => { const component = mountCollapsible({ props: { open: false, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); await component.find('[data-test="test"]').trigger("click"); await nextTick(); expect(component.emitted("update:open")).toBeTruthy(); expect(component.emitted("update:open")![0][0]).toBe(true); }); it("Open – emits when collapsible opens", async () => { const component = mountCollapsible({ props: { dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); await component.find('[data-test="test"]').trigger("click"); await nextTick(); await flushPromises(); expect(component.emitted("open")).toBeTruthy(); }); it("Close – emits when collapsible closes", async () => { const component = mountCollapsible({ props: { open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); await component.find('[data-test="test"]').trigger("click"); await nextTick(); await flushPromises(); expect(component.emitted("close")).toBeTruthy(); }); }); describe("Exposed Methods", () => { it("wrapperRef – exposes wrapper element reference", () => { const component = mountCollapsible({ slots: { default: "Trigger", content: "Content", }, }); expect(component.vm.wrapperRef).toBeDefined(); expect(component.vm.wrapperRef).toBeInstanceOf(HTMLDivElement); }); it("show – opens the collapsible", async () => { const component = mountCollapsible({ props: { dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); component.vm.show(); await nextTick(); await flushPromises(); expect(component.find('[data-test="test-content"]').exists()).toBe(true); expect(component.emitted("open")).toBeTruthy(); }); it("show – does not open when disabled", async () => { const component = mountCollapsible({ props: { disabled: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); component.vm.show(); await nextTick(); expect(component.find('[data-test="test-content"]').exists()).toBe(false); }); it("hide – closes the collapsible", async () => { const component = mountCollapsible({ props: { open: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); expect(component.find('[data-test="test-content"]').exists()).toBe(true); component.vm.hide(); await nextTick(); expect(component.emitted("close")).toBeTruthy(); }); it("toggle – toggles the collapsible state", async () => { const component = mountCollapsible({ props: { dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); component.vm.toggle(); await nextTick(); await flushPromises(); expect(component.find('[data-test="test-content"]').exists()).toBe(true); component.vm.toggle(); await nextTick(); await flushPromises(); expect(component.find('[data-test="test-content"]').exists()).toBe(false); }); it("toggle – does not toggle when disabled", async () => { const component = mountCollapsible({ props: { disabled: true, dataTest: "test", }, slots: { default: "Trigger", content: "Content", }, }); component.vm.toggle(); await nextTick(); expect(component.find('[data-test="test-content"]').exists()).toBe(false); }); it("isOpened – reflects the current opened state", async () => { const component = mountCollapsible({ slots: { default: "Trigger", content: "Content", }, }); expect(component.vm.isOpened).toBe(false); component.vm.show(); await nextTick(); await flushPromises(); expect(component.vm.isOpened).toBe(true); component.vm.hide(); await nextTick(); await flushPromises(); expect(component.vm.isOpened).toBe(false); }); }); });