UNPKG

vueless

Version:

Vue Styleless UI Component Library, powered by Tailwind CSS.

258 lines (208 loc) • 6.96 kB
import { mount } from "@vue/test-utils"; import { describe, it, expect } from "vitest"; import UFile from "../UFile.vue"; import ULink from "../../ui.button-link/ULink.vue"; import UIcon from "../../ui.image-icon/UIcon.vue"; import type { ComponentPublicInstance } from "vue"; import type { Props } from "../types"; describe("UFile.vue", () => { // Props tests describe("Props", () => { // URL prop it("passes the correct url to ULink", () => { const url = "https://example.com/file.pdf"; const component = mount(UFile, { props: { url, }, }); const linkComponent = component.findComponent(ULink); expect(linkComponent.props("href")).toBe(url); }); // ImageUrl prop it("renders image when imageUrl prop is provided", () => { const imageUrl = "https://example.com/image.jpg"; const component = mount(UFile, { props: { imageUrl, }, }); const image = component.find("img"); expect(image.exists()).toBe(true); expect(image.attributes("src")).toBe(imageUrl); }); // Label prop it("renders the correct label text", () => { const label = "Example File"; const component = mount(UFile, { props: { label, }, }); const linkComponent = component.findComponent(ULink); expect(linkComponent.text()).toContain(label); }); // Size prop it("applies the correct size class", async () => { const sizeClasses = { sm: "gap-0.5", md: "gap-1", lg: "gap-1.5", }; Object.entries(sizeClasses).forEach(([size, classes]) => { const component = mount(UFile, { props: { size: size as Props["size"], }, }); expect(component.attributes("class")).toContain(classes); }); }); // ID prop it("uses provided id", () => { const id = "test-file-id"; const removable = true; const component = mount(UFile, { props: { id, removable, // Need to set removable to true to show the remove button }, }); // Directly call the onRemove method (component.vm as ComponentPublicInstance & { onRemove: () => void }).onRemove(); expect(component.emitted("remove")?.[0][0]).toBe(id); }); // Removable prop it("shows remove button when removable prop is true", () => { const removable = true; const dataTest = "test-file"; const removeIconDataTest = "test-file-remove-item"; const component = mount(UFile, { props: { removable, dataTest, }, }); // Get the remove button directly using the same approach as in the event test const removeIcon = component.findAllComponents(UIcon).find((component) => { return component.props("dataTest") === removeIconDataTest; }); expect(removeIcon).toBeDefined(); }); // DataTest prop it("applies the correct data-test attribute", () => { const dataTest = "test-file"; const component = mount(UFile, { props: { dataTest, }, }); expect(component.attributes("data-test")).toBe(dataTest); }); }); // Slots tests describe("Slots", () => { // Default slot it("renders content from default slot", () => { const slotContent = "Custom Content"; const component = mount(UFile, { slots: { default: slotContent, }, }); expect(component.text()).toContain(slotContent); }); // Default slot with bindings it("provides correct bindings to default slot", () => { const id = "test-id"; const label = "Test File"; const url = "https://example.com/file.pdf"; const imageUrl = "https://example.com/image.jpg"; // Define class names as constants instead of hardcoding them const idClass = "file-id"; const labelClass = "file-label"; const urlClass = "file-url"; const imageUrlClass = "file-image-url"; const component = mount(UFile, { props: { id, label, url, imageUrl, }, slots: { default: ` <template #default="{ id, label, url, imageUrl }"> <div class="${idClass}">{{ id }}</div> <div class="${labelClass}">{{ label }}</div> <div class="${urlClass}">{{ url }}</div> <div class="${imageUrlClass}">{{ imageUrl }}</div> </template> `, }, }); expect(component.find(`.${idClass}`).text()).toBe(id); expect(component.find(`.${labelClass}`).text()).toBe(label); expect(component.find(`.${urlClass}`).text()).toBe(url); expect(component.find(`.${imageUrlClass}`).text()).toBe(imageUrl); }); // Left slot it("renders content from left slot", () => { const slotText = "Left"; const slotClass = "left-content"; const component = mount(UFile, { slots: { left: `<span class='${slotClass}'>${slotText}</span>`, }, }); expect(component.find(`.${slotClass}`).exists()).toBe(true); expect(component.find(`.${slotClass}`).text()).toBe(slotText); }); // Right slot it("renders content from right slot", () => { const slotText = "Right"; const slotClass = "right-content"; const component = mount(UFile, { slots: { right: `<span class='${slotClass}'>${slotText}</span>`, }, }); expect(component.find(`.${slotClass}`).exists()).toBe(true); expect(component.find(`.${slotClass}`).text()).toBe(slotText); }); }); // Events tests describe("Events", () => { // Remove event it("emits remove event when remove button is clicked", async () => { const id = "test-file-id"; const removable = true; const dataTest = "test-file"; const removeIconDataTest = "test-file-remove-item"; const component = mount(UFile, { props: { id, removable, dataTest, }, }); const removeIcon = component.findAllComponents(UIcon).find((component) => { return component.props("dataTest") === removeIconDataTest; }); expect(removeIcon).toBeDefined(); // Directly call the onRemove method (component.vm as ComponentPublicInstance & { onRemove: () => void }).onRemove(); // Check if the remove event was emitted with the correct value expect(component.emitted("remove")).toBeTruthy(); expect(component.emitted("remove")?.[0][0]).toBe(id); }); }); // Exposed refs tests describe("Exposed refs", () => { // file ref it("exposes file ref", () => { const component = mount(UFile, {}); expect(component.vm.fileRef).toBeDefined(); }); }); });