UNPKG

vueless

Version:

Vue Styleless UI Component Library, powered by Tailwind CSS.

373 lines (286 loc) 10 kB
import { flushPromises, mount } from "@vue/test-utils"; import { describe, it, expect, vi } from "vitest"; import UInputSearch from "../UInputSearch.vue"; import UInput from "../../ui.form-input/UInput.vue"; import UIcon from "../../ui.image-icon/UIcon.vue"; import UButton from "../../ui.button/UButton.vue"; import type { Props } from "../types.ts"; describe("UInputSearch.vue", () => { describe("props", () => { it("Mode lValue – set initial value correctly", () => { const initialValue = "Test input"; const component = mount(UInputSearch, { props: { modelValue: initialValue, }, }); expect(component.get("input").element.value).toBe(initialValue); }); it("Model Value – updates value on input", async () => { vi.useFakeTimers(); const updatedValue = "Test input 2"; const component = mount(UInputSearch, { props: { modelValue: "Test input", debounce: 0, }, }); await component.get("input").setValue(updatedValue); vi.advanceTimersByTime(0); await flushPromises(); expect(component.emitted("update:modelValue")).toBeDefined(); expect(component.emitted("update:modelValue")![0][0]).toBe(updatedValue); vi.useRealTimers(); }); it("Label – passes label to UInput", () => { const label = "Test Label"; const component = mount(UInputSearch, { props: { label, }, }); expect(component.getComponent(UInput).props("label")).toBe(label); }); it("Size – passes size to UInput", () => { const size = "lg"; const component = mount(UInputSearch, { props: { size: size as Props["size"], }, }); expect(component.getComponent(UInput).props("size")).toBe(size); }); it("Placeholder – passes placeholder to UInput", () => { const placeholder = "Search here..."; const component = mount(UInputSearch, { props: { placeholder, }, }); expect(component.getComponent(UInput).props("placeholder")).toBe(placeholder); }); it("Label Align – passes labelAlign to UInput", () => { const labelAlign = "top"; const component = mount(UInputSearch, { props: { labelAlign: labelAlign as Props["labelAlign"], }, }); expect(component.getComponent(UInput).props("labelAlign")).toBe(labelAlign); }); it("Description – passes description to UInput", () => { const description = "This is a description"; const component = mount(UInputSearch, { props: { description, }, }); expect(component.getComponent(UInput).props("description")).toBe(description); }); it("Error – passes error to UInput", () => { const error = "This is an error message"; const component = mount(UInputSearch, { props: { error, }, }); expect(component.getComponent(UInput).props("error")).toBe(error); }); it("Min Length – don't emit value if it has less length than minLength", async () => { const minLength = 5; const shortValue = "Test"; const component = mount(UInputSearch, { props: { modelValue: "", minLength, debounce: 0, }, }); await component.get("input").setValue(shortValue); await flushPromises(); expect(component.emitted("update:modelValue")).toBeUndefined(); }); it("Search Button Label – renders search button with label", () => { const searchButtonLabel = "Search"; const component = mount(UInputSearch, { props: { searchButtonLabel, }, }); expect(component.getComponent(UButton).props("label")).toBe(searchButtonLabel); }); it("Search Button Label – hides search icon when provided", async () => { const component = mount(UInputSearch, { props: { modelValue: "Test input", searchButtonLabel: "Search", }, }); expect(component.find("[vl-key='searchIcon']").exists()).toBe(false); }); it("Debounce – sets debounce time for input", async () => { vi.useFakeTimers(); const debounceTime = 300; const updatedValue = "Debounced input"; const component = mount(UInputSearch, { props: { modelValue: "Test input", debounce: debounceTime, }, }); await component.get("input").setValue(updatedValue); vi.advanceTimersByTime(debounceTime); await flushPromises(); expect(component.emitted("update:modelValue")).toBeDefined(); expect(component.emitted("update:modelValue")![0][0]).toBe(updatedValue); vi.useRealTimers(); }); it("Left Icon – passes leftIcon to UInput", () => { const leftIcon = "search"; const component = mount(UInputSearch, { props: { leftIcon, }, }); expect(component.getComponent(UInput).props("leftIcon")).toBe(leftIcon); expect(component.getComponent(UIcon).props("name")).toBe(leftIcon); }); it("Right Icon – passes rightIcon to search icon component", () => { const rightIcon = "close"; const component = mount(UInputSearch, { props: { rightIcon, }, }); expect(component.findComponent(UIcon).props("name")).toBe(rightIcon); }); it("Readonly – sets readonly state on UInput", () => { const component = mount(UInputSearch, { props: { modelValue: "Test input", readonly: true, }, }); expect(component.get("input").attributes("readonly")).toBeDefined(); }); it("Disabled – passes disabled state to UInput", () => { const component = mount(UInputSearch, { props: { modelValue: "Test input", disabled: true, }, }); expect(component.get("input").attributes("disabled")).toBeDefined(); }); it("Data Test – applies the correct data-test attribute", async () => { const testCases = [ { testCase: "search-icon" }, { testCase: "clear" }, { testCase: "search-button", searchButtonLabel: "Search" }, ]; testCases.forEach(async ({ testCase, searchButtonLabel }) => { const dataTest = "test"; const resolvedDataTest = `test-${testCase}`; const component = mount(UInputSearch, { props: { dataTest, modelValue: "Test input", searchButtonLabel, }, }); await flushPromises(); component.get(`[data-test='${resolvedDataTest}']`); }); }); }); describe("Slots", () => { it("Left – renders left slot content", () => { const slotContent = "Left Slot Content"; const component = mount(UInputSearch, { slots: { left: slotContent, }, }); expect(component.html()).toContain(slotContent); }); it("Right – renders right slot content", () => { const slotContent = "Right Slot Content"; const component = mount(UInputSearch, { slots: { right: slotContent, }, }); expect(component.html()).toContain(slotContent); }); it("Right – exposes right icon name", () => { const rightIcon = "close"; const component = mount(UInputSearch, { props: { rightIcon, }, }); expect(component.getComponent(UIcon).props("name")).toBe(rightIcon); }); it("Right – exposes Search Button Label", () => { const searchButtonLabel = "Search"; const component = mount(UInputSearch, { props: { searchButtonLabel, }, }); expect(component.getComponent(UButton).props("label")).toBe(searchButtonLabel); }); }); describe("Events", () => { it("Clear – emits clear event when clear icon is clicked", async () => { const component = mount(UInputSearch, { props: { modelValue: "Test input", dataTest: "test", }, }); await flushPromises(); await component.get("[vl-key='clearIcon']").trigger("click"); expect(component.emitted("clear")).toBeDefined(); expect(component.emitted("update:modelValue")).toBeDefined(); expect(component.emitted("update:modelValue")![0][0]).toBe(""); }); it("Search – emits search event when search button is clicked", async () => { const initialValue = "Test input"; const component = mount(UInputSearch, { props: { modelValue: initialValue, searchButtonLabel: "Search", }, }); await component.getComponent(UButton).trigger("click"); expect(component.emitted("search")).toBeDefined(); expect(component.emitted("search")![0][0]).toBe(initialValue); }); it("Search – emits search event when search icon is clicked", async () => { const initialValue = "Test input"; const component = mount(UInputSearch, { props: { modelValue: initialValue, }, }); await flushPromises(); await component.get("[vl-key='searchIcon']").trigger("click"); expect(component.emitted("search")).toBeDefined(); expect(component.emitted("search")![0][0]).toBe(initialValue); }); }); describe("Exposed Properties", () => { it("Input – exposes input element ref", () => { const component = mount(UInputSearch, { props: { modelValue: "test search", }, }); expect(component.vm.input).toBeDefined(); expect(component.vm.input!.tagName).toBe("INPUT"); expect(component.vm.input!.value).toBe("test search"); expect(component.vm.input!.getAttribute("inputmode")).toBe("search"); }); }); });