From 8b5fea8d6fc7baec9007bf243ab0e948828a8cd7 Mon Sep 17 00:00:00 2001 From: Jin <22962980+JYC333@users.noreply.github.com> Date: Tue, 10 Mar 2026 00:02:22 +0000 Subject: [PATCH] test: add test for NoteAutocomplete --- .../widgets/react/NoteAutocomplete.spec.tsx | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 apps/client/src/widgets/react/NoteAutocomplete.spec.tsx diff --git a/apps/client/src/widgets/react/NoteAutocomplete.spec.tsx b/apps/client/src/widgets/react/NoteAutocomplete.spec.tsx new file mode 100644 index 0000000000..95263b30e0 --- /dev/null +++ b/apps/client/src/widgets/react/NoteAutocomplete.spec.tsx @@ -0,0 +1,135 @@ +import $ from "jquery"; +import { render } from "preact"; +import { act } from "preact/test-utils"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +const { + initNoteAutocompleteSpy, + setTextSpy, + clearTextSpy +} = vi.hoisted(() => ({ + initNoteAutocompleteSpy: vi.fn(($el) => $el), + setTextSpy: vi.fn(), + clearTextSpy: vi.fn() +})); + +vi.mock("../../services/i18n", () => ({ + t: (key: string) => key +})); + +vi.mock("../../services/note_autocomplete", () => ({ + __esModule: true, + default: { + initNoteAutocomplete: initNoteAutocompleteSpy, + setText: setTextSpy, + clearText: clearTextSpy + } +})); + +import NoteAutocomplete from "./NoteAutocomplete"; + +describe("NoteAutocomplete", () => { + let container: HTMLDivElement; + let setNoteSpy: ReturnType; + let getSelectedNoteIdSpy: ReturnType; + + beforeEach(() => { + vi.clearAllMocks(); + container = document.createElement("div"); + document.body.appendChild(container); + + setNoteSpy = vi.fn(() => Promise.resolve()); + getSelectedNoteIdSpy = vi.fn(() => "selected-note-id"); + + ($.fn as any).setNote = setNoteSpy; + ($.fn as any).getSelectedNoteId = getSelectedNoteIdSpy; + }); + + afterEach(() => { + act(() => { + render(null, container); + }); + container.remove(); + }); + + it("syncs text props through the headless helper functions", () => { + act(() => { + render(, container); + }); + + const input = container.querySelector("input") as HTMLInputElement; + + expect(initNoteAutocompleteSpy).toHaveBeenCalledTimes(1); + expect(initNoteAutocompleteSpy.mock.calls[0][0][0]).toBe(input); + expect(setTextSpy).toHaveBeenCalledTimes(1); + expect(setTextSpy.mock.calls[0][0][0]).toBe(input); + expect(setTextSpy).toHaveBeenCalledWith(expect.anything(), "hello"); + + act(() => { + render(, container); + }); + + expect(clearTextSpy).toHaveBeenCalled(); + }); + + it("syncs noteId props through the jQuery setNote extension", () => { + act(() => { + render(, container); + }); + + expect(setNoteSpy).toHaveBeenCalledWith("note-123"); + expect(clearTextSpy).not.toHaveBeenCalled(); + }); + + it("forwards autocomplete selection and clear events to consumers", () => { + const onChange = vi.fn(); + const noteIdChanged = vi.fn(); + + act(() => { + render(, container); + }); + + const input = container.querySelector("input") as HTMLInputElement; + const $input = $(input); + const suggestion = { notePath: "root/child-note", noteTitle: "Child note" }; + + $input.trigger("autocomplete:noteselected", [suggestion]); + + expect(onChange).toHaveBeenCalledWith(suggestion); + expect(noteIdChanged).toHaveBeenCalledWith("child-note"); + + input.value = ""; + $input.trigger("change"); + + expect(onChange).toHaveBeenCalledWith(null); + }); + + it("forwards onTextChange, onKeyDown and onBlur events", () => { + const onTextChange = vi.fn(); + const onKeyDown = vi.fn(); + const onBlur = vi.fn(); + + act(() => { + render( + , + container + ); + }); + + const input = container.querySelector("input") as HTMLInputElement; + const $input = $(input); + + input.value = "typed text"; + $input.trigger("input"); + $input.trigger($.Event("keydown", { originalEvent: new KeyboardEvent("keydown", { key: "Enter" }) })); + $input.trigger("blur"); + + expect(onTextChange).toHaveBeenCalledWith("typed text"); + expect(onKeyDown).toHaveBeenCalledWith(expect.any(KeyboardEvent)); + expect(onBlur).toHaveBeenCalledWith("selected-note-id"); + }); +});