UNPKG

vueless

Version:

Vue Styleless UI Component Library, powered by Tailwind CSS.

412 lines (330 loc) 11.1 kB
import { mount } from "@vue/test-utils"; import { describe, it, expect, vi, beforeAll } from "vitest"; import UToggle from "../UToggle.vue"; import UButton from "../../ui.button/UButton.vue"; import type { Props, UToggleOption } from "../types.ts"; describe("UToggle.vue", () => { let name: string; let options: UToggleOption[]; beforeAll(() => { name = "toggle-test"; options = [ { value: "option1", label: "Option 1" }, { value: "option2", label: "Option 2" }, { value: "option3", label: "Option 3" }, ]; }); describe("Props", () => { it("Size – applies the correct size class", async () => { const size = { "2xs": "text-small", xs: "text-small", sm: "text-medium", md: "text-medium", lg: "text-large", xl: "text-large", }; Object.entries(size).forEach(([size, classes]) => { const component = mount(UToggle, { props: { size: size as Props["size"], name, options, }, }); const buttons = component.findAllComponents(UButton); expect(buttons[0].attributes("class")).toContain(classes); }); }); it("Options – renders the correct number of options", () => { const component = mount(UToggle, { props: { options, name, }, }); const buttons = component.findAllComponents(UButton); expect(buttons.length).toBe(options.length); }); it("Options – disables individual option when option disabled prop is true", () => { const customOptions: UToggleOption[] = [ { value: "option1", label: "Option 1" }, { value: "option2", label: "Option 2", disabled: true }, ]; const component = mount(UToggle, { props: { options: customOptions, name, }, }); const buttons = component.findAllComponents(UButton); expect(buttons[0].attributes("disabled")).toBeUndefined(); expect(buttons[1].attributes("disabled")).toBeDefined(); }); it("Options – set icon for individual options", () => { const iconOptions: UToggleOption[] = [ { value: "option1", label: "Option 1", icon: "star" }, { value: "option2", label: "Option 2", leftIcon: "check" }, { value: "option3", label: "Option 3", rightIcon: "close" }, ]; const component = mount(UToggle, { props: { options: iconOptions, name, }, }); const buttons = component.findAllComponents(UButton); expect(buttons[0].props("icon")).toBe("star"); expect(buttons[1].props("leftIcon")).toBe("check"); expect(buttons[2].props("rightIcon")).toBe("close"); }); it("Model Value – correctly selects option based on modelValue for single selection", async () => { const selectedClass = "bg-primary"; const selectedValue = "option2"; const component = mount(UToggle, { props: { modelValue: selectedValue, options, name, }, }); const buttons = component.findAllComponents(UButton); expect(buttons[1].attributes("class")).toContain(selectedClass); }); it("Model Value – correctly selects options based on modelValue for multiple selection", async () => { const selectedClass = "bg-primary"; const selectedValues = ["option1", "option3"]; const multiComponent = mount(UToggle, { props: { options, modelValue: selectedValues, multiple: true, name, }, }); const multiButtons = multiComponent.findAllComponents(UButton); expect(multiButtons[0].attributes("class")).toContain(selectedClass); expect(multiButtons[2].attributes("class")).toContain(selectedClass); }); it("Multiple – allows multiple selections when multiple prop is true", async () => { const component = mount(UToggle, { props: { options, modelValue: ["option1"], multiple: true, name, }, }); await component.findAllComponents(UButton)[1].trigger("click"); const emittedValue = component.emitted("update:modelValue")?.[0][0]; // Verify both options are now selected (original + clicked) expect(emittedValue).toEqual(["option1", "option2"]); }); it("Split – applies split class when split prop is true", () => { const split = true; const splitClasses = "flex-wrap"; const component = mount(UToggle, { props: { split, name, }, }); expect(component.attributes("class")).toContain(splitClasses); }); it("Split – applies unsplit class when split prop is false", () => { const split = false; const unsplitClasses = "gap-px"; const component = mount(UToggle, { props: { split, name, }, }); expect(component.attributes("class")).toContain(unsplitClasses); }); it("Disabled – disables all options when disabled prop is true", () => { const disabled = true; const component = mount(UToggle, { props: { options, disabled, name, }, }); const buttons = component.findAllComponents(UButton); buttons.forEach((button) => { expect(button.attributes("disabled")).toBeDefined(); }); }); it("Block – applies block class when block prop is true", () => { const block = true; const blockClasses = "w-full"; const component = mount(UToggle, { props: { block, options, name, }, }); expect(component.attributes("class")).toContain(blockClasses); }); it("Round – applies round class to buttons when round prop is true", () => { const round = true; const roundClasses = "rounded-full"; const component = mount(UToggle, { props: { round, options, name, }, }); const button = component.findComponent(UButton); expect(button.attributes("class")).toContain(roundClasses); }); it("Square – applies square class to buttons when square prop is true", () => { const square = true; const component = mount(UToggle, { props: { options, square, name, }, }); const button = component.findComponent(UButton); // Square buttons have equal padding on all sides expect(button.attributes("class")).toContain("p-"); }); it("Id – applies the correct id attribute", () => { const id = "test-toggle-id"; const component = mount(UToggle, { props: { id, name, }, }); expect(component.attributes("id")).toBe(id); }); it("Data Test – applies the correct data-test attribute", () => { const dataTest = "test-toggle"; const component = mount(UToggle, { props: { dataTest, name, }, }); expect(component.attributes("data-test")).toBe(dataTest); }); }); describe("Slots", () => { it("Left – renders content from left slot", () => { const slotText = "Left"; const slotClass = "left-content"; const component = mount(UToggle, { props: { options, name, }, slots: { left: `<span class='${slotClass}'>${slotText}</span>`, }, }); expect(component.find(`.${slotClass}`).text()).toBe(slotText); }); it("Option – renders content from option slot", () => { const slotText = "Custom Option"; const slotClass = "option-content"; const component = mount(UToggle, { props: { options, name, }, slots: { option: `<span class='${slotClass}'>${slotText}</span>`, }, }); expect(component.find(`.${slotClass}`).text()).toBe(slotText); }); it("Option – provides correct bindings to slots", () => { const optionIndex = "0"; const bindingOptions: UToggleOption[] = [ { value: "option1", label: "Option 1", icon: "star" }, ]; const valueClass = "option-value"; const labelClass = "option-label"; const iconClass = "option-icon"; const indexClass = "option-index"; const component = mount(UToggle, { props: { options: bindingOptions, name, }, slots: { option: ` <template #option="{ option, label, iconName, index }"> <span class="${valueClass}">{{ option.value }}</span> <span class="${labelClass}">{{ label }}</span> <span class="${iconClass}">{{ iconName }}</span> <span class="${indexClass}">{{ index }}</span> </template> `, }, }); expect(component.find(`.${valueClass}`).text()).toBe(bindingOptions[0].value); expect(component.find(`.${labelClass}`).text()).toBe(bindingOptions[0].label); expect(component.find(`.${iconClass}`).text()).toBe(bindingOptions[0].icon); expect(component.find(`.${indexClass}`).text()).toBe(optionIndex); }); it("Right – renders content from right slot", () => { const slotText = "Right"; const slotClass = "right-content"; const component = mount(UToggle, { props: { options, name, }, slots: { right: `<span class='${slotClass}'>${slotText}</span>`, }, }); expect(component.find(`.${slotClass}`).text()).toBe(slotText); }); }); describe("Events", () => { it("Model Value – emits update:modelValue event when option is clicked", async () => { const component = mount(UToggle, { props: { options, name, }, }); await component.findAllComponents(UButton)[0].trigger("click"); const emittedValue = component.emitted("update:modelValue")?.[0][0]; expect(emittedValue).toBe(options[0].value); }); it("Option Click – calls option onClick callback when option is clicked", async () => { const onClick = vi.fn(); const callbackOptions: UToggleOption[] = [{ value: "option1", label: "Option 1", onClick }]; const component = mount(UToggle, { props: { options: callbackOptions, name, }, }); await component.findComponent(UButton).trigger("click"); expect(onClick).toHaveBeenCalled(); expect(onClick).toHaveBeenCalledWith( expect.objectContaining({ value: "option1", label: "Option 1" }), ); }); }); describe("Exposed refs", () => { it("Options – exposes optionsRef", () => { const component = mount(UToggle, { props: { name, }, }); expect(component.vm.optionsRef).toBeDefined(); }); }); });