import { expect, test } from "vitest" import { addClass, classArrayToClassObject, classArrayToClassString, classObjectToClassArray, classObjectToClassString, classStringToClassArray, classStringToClassObject, containClass, formatClassToTarget, neatenClassString, prefixClassWith, removeClass, removePrefixOfClass, replaceClass, toClassArray, toClassObject, toClassString, toggleClass, } from "#Source/css/index.ts" test("neatenClassString normalizes dots and spaces", () => { expect(neatenClassString("mobius-base mobius-theme--light")).toBe( "mobius-base mobius-theme--light", ) expect(neatenClassString(".mobius-base.mobius-theme--light")).toBe( "mobius-base mobius-theme--light", ) expect(neatenClassString(" .mobius-base mobius-theme--light ")).toBe( "mobius-base mobius-theme--light", ) }) test("classStringToClassArray splits normalized class strings", () => { expect(classStringToClassArray("mobius-base mobius-theme--light")).toEqual([ "mobius-base", "mobius-theme--light", ]) expect(classStringToClassArray(".mobius-base.mobius-theme--light")).toEqual([ "mobius-base", "mobius-theme--light", ]) expect(classStringToClassArray(" .mobius-base mobius-theme--light ")).toEqual([ "mobius-base", "mobius-theme--light", ]) }) test("classArrayToClassObject marks every class as true", () => { expect(classArrayToClassObject(["mobius-base", "mobius-theme--light"])).toEqual({ "mobius-base": true, "mobius-theme--light": true, }) expect(classArrayToClassObject(["mobius-base", ""])).toEqual({ "mobius-base": true }) expect(classArrayToClassObject([])).toEqual({}) }) test("classStringToClassObject converts strings through normalized array form", () => { expect(classStringToClassObject("mobius-base mobius-theme--light")).toEqual({ "mobius-base": true, "mobius-theme--light": true, }) expect(classStringToClassObject(".mobius-base.mobius-theme--light")).toEqual({ "mobius-base": true, "mobius-theme--light": true, }) }) test("classObjectToClassArray keeps only truthy class names", () => { expect(classObjectToClassArray({ active: true, disabled: false, primary: true })).toEqual([ "active", "primary", ]) expect(classObjectToClassArray({ "": true, active: true, disabled: false })).toEqual(["active"]) expect(classObjectToClassArray({ disabled: false })).toEqual([]) }) test("classArrayToClassString joins non-empty items with spaces", () => { expect(classArrayToClassString(["mobius-base", "mobius-theme--light"])).toBe( "mobius-base mobius-theme--light", ) expect(classArrayToClassString(["mobius-base", "", "mobius-theme--light"])).toBe( "mobius-base mobius-theme--light", ) }) test("classObjectToClassString serializes only truthy keys", () => { expect(classObjectToClassString({ active: true, disabled: false, primary: true })).toBe( "active primary", ) expect(classObjectToClassString({ "": true, active: true, disabled: false })).toBe("active") expect(classObjectToClassString({ disabled: false })).toBe("") }) test("toClassString preserves string input and serializes other shapes", () => { expect(toClassString(" .button active ")).toBe(" .button active ") expect(toClassString(["button", "active"])).toBe("button active") expect(toClassString({ button: true, active: true, disabled: false })).toBe("button active") }) test("toClassArray normalizes strings and clones arrays", () => { const classArray = ["button", "", "active"] const result = toClassArray(classArray) expect(toClassArray(".button.active")).toEqual(["button", "active"]) expect(result).toEqual(["button", "active"]) expect(result).not.toBe(classArray) expect(toClassArray({ button: true, active: true, disabled: false })).toEqual([ "button", "active", ]) }) test("toClassObject normalizes strings and clones objects", () => { const classObject = { button: true, active: false, "": true } const result = toClassObject(classObject) expect(toClassObject("button active")).toEqual({ button: true, active: true }) expect(toClassObject(["button", "active"])).toEqual({ button: true, active: true }) expect(result).toEqual({ button: true, active: false }) expect(result).not.toBe(classObject) }) test("formatClassToTarget returns the same external shape as target", () => { expect(formatClassToTarget("", ["button", "active"])).toBe("button active") expect(formatClassToTarget([], "button active")).toEqual(["button", "active"]) expect(formatClassToTarget({}, ["button", "active"])).toEqual({ button: true, active: true }) }) test("prefixClassWith adds prefixes only when missing", () => { expect(prefixClassWith("pm-", "button active")).toBe("pm-button pm-active") expect(prefixClassWith("pm-", ["button", "", "pm-active"])).toEqual(["pm-button", "pm-active"]) expect(prefixClassWith("pm-", { button: true, "": true, "pm-active": false })).toEqual({ "pm-button": true, "pm-active": false, }) }) test("removePrefixOfClass removes prefixes only when present", () => { expect(removePrefixOfClass("pm-", "pm-button pm-active plain")).toBe("button active plain") expect(removePrefixOfClass("pm-", ["pm-button", "pm-", "plain"])).toEqual(["button", "plain"]) expect(removePrefixOfClass("pm-", { "pm-button": true, plain: false, "pm-": true })).toEqual({ button: true, plain: false, }) }) test("addClass merges class names while preserving target shape", () => { expect(addClass("button", "active primary")).toBe("button active primary") expect(addClass(["button", ""], { active: true, primary: true, "": false })).toEqual([ "button", "active", "primary", ]) expect(addClass({ button: true }, ["active", "primary"])).toEqual({ button: true, active: true, primary: true, }) }) test("removeClass removes selected class names while preserving target shape", () => { expect(removeClass("button active primary", "active")).toBe("button primary") expect(removeClass(["button", "active", "primary"], { active: true })).toEqual([ "button", "primary", ]) expect(removeClass({ button: true, active: true, primary: true }, ["active"])).toEqual({ button: true, active: false, primary: true, }) }) test("toggleClass flips membership for each target class", () => { expect(toggleClass("button active", "active primary")).toBe("button primary") expect(toggleClass(["button", "active"], ["active", "", "primary"])).toEqual([ "button", "primary", ]) expect(toggleClass({ button: true, active: true }, ["active", "primary"])).toEqual({ button: true, active: false, primary: true, }) }) test("replaceClass supports tuple arrays, string arrays, records, and string removals", () => { expect(replaceClass("button active", [["active", "selected"]])).toBe("button selected") expect(replaceClass("button active primary", ["active", "primary"])).toBe("button") expect(replaceClass(["button", "active"], { active: "selected" })).toEqual(["button", "selected"]) expect(replaceClass({ button: true, active: true }, "active")).toEqual({ active: false, button: true, }) expect( replaceClass({ "": true, button: true, active: false }, { "": "selected", active: "featured" }), ).toEqual({ button: true, featured: false }) expect( replaceClass("button active primary", [ ["active", ""], ["primary", "featured"], ]), ).toBe("button featured") }) test("containClass checks whether all required class names are present", () => { expect(containClass("button active", "button active primary")).toBe(true) expect(containClass(["button", "missing"], { button: true, active: true })).toBe(false) expect(containClass({ button: true }, ["button", "active"])).toBe(true) })