UNPKG

vueless

Version:

Vue Styleless UI Component Library, powered by Tailwind CSS.

423 lines (343 loc) 11.5 kB
import { mount } from "@vue/test-utils"; import { describe, it, expect, beforeAll } from "vitest"; import UNumber from "../UNumber.vue"; import { MATH_SIGN, MATH_SIGN_TYPE } from "../utilNumber"; import type { Props } from "../types"; describe("UNumber.vue", () => { let value: number; beforeAll(() => { value = 1234.56; }); describe("Props", () => { it("Size – applies the correct size class", async () => { const sizeClasses = { xs: "text-tiny", sm: "text-small", md: "text-medium", lg: "text-large", }; Object.entries(sizeClasses).forEach(([size, classes]) => { const component = mount(UNumber, { props: { size: size as Props["size"], }, }); expect(component.attributes("class")).toContain(classes); }); }); it("Color – applies the correct color class", async () => { const colors = [ "primary", "secondary", "error", "warning", "success", "info", "notice", "neutral", "grayscale", ]; colors.forEach((color) => { const component = mount(UNumber, { props: { color: color as Props["color"], }, }); expect(component.attributes("class")).toContain(color); }); }); it("Value – renders the correct number value", () => { const expectedFormattedNumber = "1 234,56"; const component = mount(UNumber, { props: { value, }, }); expect(component.text()).toContain(expectedFormattedNumber); }); it("Sign – renders the correct sign based on sign prop", () => { const testNegativeValue = -123; // Auto sign (negative value) // Should show minus sign for negative values const autoComponent = mount(UNumber, { props: { value: testNegativeValue, sign: MATH_SIGN_TYPE.auto as Props["sign"], }, }); expect(autoComponent.text()).toContain(MATH_SIGN.MINUS); // Auto sign (positive value) // Should not show any sign for positive values const autoPositiveComponent = mount(UNumber, { props: { value, sign: MATH_SIGN_TYPE.auto as Props["sign"], }, }); expect(autoPositiveComponent.text()).not.toContain(MATH_SIGN.MINUS); expect(autoPositiveComponent.text()).not.toContain(MATH_SIGN.PLUS); // Positive sign // Should show plus sign regardless of value const positiveComponent = mount(UNumber, { props: { value, sign: MATH_SIGN_TYPE.positive as Props["sign"], }, }); expect(positiveComponent.text()).toContain(MATH_SIGN.PLUS); // Negative sign // Should show minus sign regardless of value const negativeComponent = mount(UNumber, { props: { value, sign: MATH_SIGN_TYPE.negative as Props["sign"], }, }); expect(negativeComponent.text()).toContain(MATH_SIGN.MINUS); // Unsigned // Should not show any sign regardless of value const unsignedComponent = mount(UNumber, { props: { value: testNegativeValue, sign: MATH_SIGN_TYPE.unsigned as Props["sign"], }, }); expect(unsignedComponent.text()).not.toContain(MATH_SIGN.MINUS); expect(unsignedComponent.text()).not.toContain(MATH_SIGN.PLUS); }); it("Currency – renders the currency symbol", () => { const currency = "$"; const component = mount(UNumber, { props: { value, currency, }, }); expect(component.text()).toContain(currency); }); it("CurrencyAlign – aligns currency correctly based on currencyAlign prop", () => { const currency = "$"; const alignTests = [ { align: "left", expectation: (text: string) => text.startsWith(currency) }, { align: "right", expectation: (text: string) => text.endsWith(currency) }, ]; alignTests.forEach(({ align, expectation }) => { const component = mount(UNumber, { props: { value, currency, currencyAlign: align as Props["currencyAlign"], }, }); expect(expectation(component.text())).toBe(true); }); }); it("CurrencySpace – adds space between currency and number when currencySpace is true", () => { const currency = "$"; const spaceTests = [ { space: true, align: "left" }, { space: false, align: "left" }, { space: true, align: "right" }, { space: false, align: "right" }, ]; spaceTests.forEach(({ space, align }) => { const component = mount(UNumber, { props: { value, currency, currencySpace: space, currencyAlign: align as Props["currencyAlign"], }, }); expect(component.html()).toContain(currency); // Visual inspection of spacing would be done in a real browser // Here we just verify the component renders with the given props expect(component.props().currencySpace).toBe(space); expect(component.props().currencyAlign).toBe(align); }); }); it("Raw – renders formatted number as plain text without HTML elements when raw is true", () => { const component = mount(UNumber, { props: { value, raw: true, }, }); // Should render plain text without the number div structure expect(component.find("[vl-key='number']").exists()).toBe(false); expect(component.text()).toContain("1 234,56"); }); it("Raw – renders with currency when raw is true and currency is set", () => { const currency = "$"; const component = mount(UNumber, { props: { value, currency, currencyAlign: "left", raw: true, }, }); expect(component.text()).toBe("$1 234,56"); }); it("Raw – renders with currency and space when raw is true, currency is set, and currencySpace is true", () => { const currency = "$"; const component = mount(UNumber, { props: { value, currency, currencyAlign: "left", currencySpace: true, raw: true, }, }); expect(component.text()).toBe("$ 1 234,56"); }); it("Raw – renders with currency on right when raw is true and currencyAlign is right", () => { const currency = "$"; const component = mount(UNumber, { props: { value, currency, currencyAlign: "right", raw: true, }, }); expect(component.text()).toBe("1 234,56$"); }); // eslint-disable-next-line vue/max-len it("Raw – renders with currency on right and space when raw is true, currencyAlign is right, and currencySpace is true", () => { const currency = "$"; const component = mount(UNumber, { props: { value, currency, currencyAlign: "right", currencySpace: true, raw: true, }, }); expect(component.text()).toBe("1 234,56 $"); }); it("Raw – renders with sign when raw is true and sign is set", () => { const testNegativeValue = -123; const component = mount(UNumber, { props: { value: testNegativeValue, sign: MATH_SIGN_TYPE.auto as Props["sign"], raw: true, }, }); expect(component.text()).toContain(MATH_SIGN.MINUS); }); it("MinFractionDigits – adds zeros to meet the minimum fraction digits requirement", () => { const value = 123; const minFractionDigits = 2; const expectedMinFractionResult = "123,00"; const component = mount(UNumber, { props: { value, minFractionDigits, }, }); expect(component.text()).toContain(expectedMinFractionResult); }); it("MaxFractionDigits – rounds the fraction to the maximum number of digits", () => { const value = 123.456789; const maxFractionDigits = 2; const expectedMaxFractionResult = "123,46"; // Rounded from .456789 to 2 digits const component = mount(UNumber, { props: { value, maxFractionDigits, }, }); expect(component.text()).toContain(expectedMaxFractionResult); // Original decimal part should not be present const originalDecimalPart = value.toString().split(".")[1]; expect(component.text()).not.toContain(originalDecimalPart); }); it("DecimalSeparator – uses the correct decimal separator", () => { const value = 123.45; const decimalSeparator = ","; const expectedFormattedNumber = "123,45"; const component = mount(UNumber, { props: { value, decimalSeparator, }, }); expect(component.text()).toContain(expectedFormattedNumber); }); it("ThousandsSeparator – uses the correct thousands separator", () => { const value = 1234567.89; const thousandsSeparator = " "; const expectedFormattedInteger = "1 234 567"; const component = mount(UNumber, { props: { value, thousandsSeparator, }, }); expect(component.text()).toContain(expectedFormattedInteger); }); it("Align – applies the correct align class", () => { const alignClasses = { left: "justify-start", right: "justify-end", }; Object.entries(alignClasses).forEach(([align, classes]) => { const component = mount(UNumber, { props: { align: align as Props["align"], }, }); expect(component.attributes("class")).toContain(classes); }); }); it("DataTest – applies the correct data-test attribute", () => { const testDataTest = "test-number"; const component = mount(UNumber, { props: { dataTest: testDataTest, }, }); expect(component.find("[vl-key='number']").attributes("data-test")).toBe(testDataTest); }); }); describe("Slots", () => { it("Left – renders content from left slot", () => { const slotText = "Left"; const slotClass = "left-content"; const component = mount(UNumber, { props: { value, }, slots: { left: `<span class='${slotClass}'>${slotText}</span>`, }, }); expect(component.find(`.${slotClass}`).exists()).toBe(true); expect(component.find(`.${slotClass}`).text()).toBe(slotText); }); it("Right – renders content from right slot", () => { const slotText = "Right"; const slotClass = "right-content"; const component = mount(UNumber, { props: { value, }, slots: { right: `<span class='${slotClass}'>${slotText}</span>`, }, }); expect(component.find(`.${slotClass}`).exists()).toBe(true); expect(component.find(`.${slotClass}`).text()).toBe(slotText); }); }); describe("Exposed refs", () => { it("wrapperRef – exposes wrapperRef", () => { const component = mount(UNumber, {}); expect(component.vm.wrapperRef).toBeDefined(); }); }); });