From c29fb598e53e4a1651bf8705fd4a1e4aec135d1f Mon Sep 17 00:00:00 2001 From: Jacobtread Date: Sat, 4 Apr 2026 10:09:24 +1300 Subject: [PATCH] tests: obsidian icon tests --- src/components/obsidianIcon.test.ts | 61 +++++++++++++++++++++++++++++ src/components/obsidianIcon.ts | 13 ++---- src/styles.css | 7 ++++ 3 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 src/components/obsidianIcon.test.ts diff --git a/src/components/obsidianIcon.test.ts b/src/components/obsidianIcon.test.ts new file mode 100644 index 0000000..283afbf --- /dev/null +++ b/src/components/obsidianIcon.test.ts @@ -0,0 +1,61 @@ +// @vitest-environment happy-dom + +import { setIcon } from "obsidian"; +import { describe, it, expect, vi, beforeEach } from "vitest"; + +import { createMockContainer } from "@/__mocks__/obsidian"; + +import { createObsidianIcon } from "./obsidianIcon"; + +vi.mock("obsidian", () => ({ + setIcon: vi.fn((containerEl: HTMLElement, icon: string) => { + containerEl.innerHTML += ``; + }), +})); + +describe("createObsidianIcon", () => { + let container: HTMLElement; + + beforeEach(() => { + vi.clearAllMocks(); + + container = createMockContainer(); + }); + + it("should create a wrapper div and set its class", () => { + const wrapper = createObsidianIcon(container, "star"); + + expect(wrapper).toBeInstanceOf(HTMLDivElement); + expect(wrapper.classList.length).toBe(1); + expect(wrapper.classList.contains("timekeep-icon-wrapper")).toBe(true); + }); + + it("should call setIcon with wrapper and icon name", () => { + const wrapper = createObsidianIcon(container, "star"); + + expect(setIcon).toHaveBeenCalledTimes(1); + expect(setIcon).toHaveBeenCalledWith(wrapper, "star"); + }); + + it("should add class to the first child if className is a string", () => { + const wrapper = createObsidianIcon(container, "star", "my-class"); + const firstChild = wrapper.firstElementChild as SVGElement; + + expect(firstChild.classList.length).toBe(1); + expect(firstChild.classList.contains("my-class")).toBe(true); + }); + + it("should add multiple classes if className is an array", () => { + const wrapper = createObsidianIcon(container, "star", ["class1", "class2"]); + const firstChild = wrapper.firstElementChild as SVGElement; + expect(firstChild.classList.length).toBe(2); + expect(firstChild.classList.contains("class1")).toBe(true); + expect(firstChild.classList.contains("class2")).toBe(true); + }); + + it("should not call addClass if no className is provided", () => { + const wrapper = createObsidianIcon(container, "star"); + const firstChild = wrapper.firstElementChild as SVGElement; + expect(firstChild.classList.length).toBe(0); + }); +}); diff --git a/src/components/obsidianIcon.ts b/src/components/obsidianIcon.ts index 4691595..6e51a1d 100644 --- a/src/components/obsidianIcon.ts +++ b/src/components/obsidianIcon.ts @@ -13,14 +13,7 @@ export function createObsidianIcon( icon: string, className?: string | string[] ): HTMLDivElement { - const wrapperEl = containerEl.createDiv(); - wrapperEl.setCssStyles({ - display: "inline-block", - lineHeight: "1", - padding: "0", - margin: "0", - }); - + const wrapperEl = containerEl.createDiv({ cls: "timekeep-icon-wrapper" }); setIcon(wrapperEl, icon); // Get the created icon child element @@ -29,9 +22,9 @@ export function createObsidianIcon( // Assign the custom class if available if (firstChild && className) { if (Array.isArray(className)) { - firstChild.addClass(...className); + firstChild.classList.add(...className); } else { - firstChild.addClass(className); + firstChild.classList.add(className); } } diff --git a/src/styles.css b/src/styles.css index db4d3c5..cb712ae 100644 --- a/src/styles.css +++ b/src/styles.css @@ -365,3 +365,10 @@ gap: 1rem; flex-flow: column; } + +.timekeep-icon-wrapper { + display: inline-block; + line-height: 1; + padding: 0px; + margin: 0px; +}