summaryrefslogtreecommitdiffstats
path: root/packages/excalidraw/tests/search.test.tsx
diff options
context:
space:
mode:
authorkj_sh6042026-03-15 16:19:35 -0400
committerkj_sh6042026-03-15 16:19:35 -0400
commit6ec259a0e71174651bae95d4628138bf6fd68742 (patch)
tree5e33c6a5ec091ecabfcb257fdc7b6a88ed8754ac /packages/excalidraw/tests/search.test.tsx
parent16c8578b15c727f22921f8a80a56ee4d4e7f2272 (diff)
refactor: packages/
Diffstat (limited to 'packages/excalidraw/tests/search.test.tsx')
-rw-r--r--packages/excalidraw/tests/search.test.tsx148
1 files changed, 148 insertions, 0 deletions
diff --git a/packages/excalidraw/tests/search.test.tsx b/packages/excalidraw/tests/search.test.tsx
new file mode 100644
index 0000000..68ad658
--- /dev/null
+++ b/packages/excalidraw/tests/search.test.tsx
@@ -0,0 +1,148 @@
+import React from "react";
+import { act, render, waitFor } from "./test-utils";
+import { Excalidraw } from "../index";
+import { CANVAS_SEARCH_TAB, CLASSES, DEFAULT_SIDEBAR } from "../constants";
+import { Keyboard } from "./helpers/ui";
+import { KEYS } from "../keys";
+import { updateTextEditor } from "./queries/dom";
+import { API } from "./helpers/api";
+import type { ExcalidrawTextElement } from "../element/types";
+
+const { h } = window;
+
+const querySearchInput = async () => {
+ const input =
+ h.app.excalidrawContainerValue.container?.querySelector<HTMLInputElement>(
+ `.${CLASSES.SEARCH_MENU_INPUT_WRAPPER} input`,
+ )!;
+ await waitFor(() => expect(input).not.toBeNull());
+ return input;
+};
+
+describe("search", () => {
+ beforeEach(async () => {
+ await render(<Excalidraw handleKeyboardGlobally />);
+ API.setAppState({
+ openSidebar: null,
+ });
+ });
+
+ it("should toggle search on cmd+f", async () => {
+ expect(h.app.state.openSidebar).toBeNull();
+
+ Keyboard.withModifierKeys({ ctrl: true }, () => {
+ Keyboard.keyPress(KEYS.F);
+ });
+ expect(h.app.state.openSidebar).not.toBeNull();
+ expect(h.app.state.openSidebar?.name).toBe(DEFAULT_SIDEBAR.name);
+ expect(h.app.state.openSidebar?.tab).toBe(CANVAS_SEARCH_TAB);
+
+ const searchInput = await querySearchInput();
+ expect(searchInput.matches(":focus")).toBe(true);
+ });
+
+ it("should refocus search input with cmd+f when search sidebar is still open", async () => {
+ Keyboard.withModifierKeys({ ctrl: true }, () => {
+ Keyboard.keyPress(KEYS.F);
+ });
+
+ const searchInput =
+ h.app.excalidrawContainerValue.container?.querySelector<HTMLInputElement>(
+ `.${CLASSES.SEARCH_MENU_INPUT_WRAPPER} input`,
+ );
+
+ act(() => {
+ searchInput?.blur();
+ });
+
+ expect(h.app.state.openSidebar).not.toBeNull();
+ expect(searchInput?.matches(":focus")).toBe(false);
+
+ Keyboard.withModifierKeys({ ctrl: true }, () => {
+ Keyboard.keyPress(KEYS.F);
+ });
+ expect(searchInput?.matches(":focus")).toBe(true);
+ });
+
+ it("should match text and cycle through matches on Enter", async () => {
+ const scrollIntoViewMock = jest.fn();
+ window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
+
+ API.setElements([
+ API.createElement({ type: "text", text: "test one" }),
+ API.createElement({ type: "text", text: "test two" }),
+ ]);
+
+ expect(h.app.state.openSidebar).toBeNull();
+
+ Keyboard.withModifierKeys({ ctrl: true }, () => {
+ Keyboard.keyPress(KEYS.F);
+ });
+ expect(h.app.state.openSidebar).not.toBeNull();
+ expect(h.app.state.openSidebar?.name).toBe(DEFAULT_SIDEBAR.name);
+ expect(h.app.state.openSidebar?.tab).toBe(CANVAS_SEARCH_TAB);
+
+ const searchInput = await querySearchInput();
+
+ expect(searchInput.matches(":focus")).toBe(true);
+
+ updateTextEditor(searchInput, "test");
+
+ await waitFor(() => {
+ expect(h.app.state.searchMatches.length).toBe(2);
+ expect(h.app.state.searchMatches[0].focus).toBe(true);
+ });
+
+ Keyboard.keyPress(KEYS.ENTER, searchInput);
+ expect(h.app.state.searchMatches[0].focus).toBe(false);
+ expect(h.app.state.searchMatches[1].focus).toBe(true);
+
+ Keyboard.keyPress(KEYS.ENTER, searchInput);
+ expect(h.app.state.searchMatches[0].focus).toBe(true);
+ expect(h.app.state.searchMatches[1].focus).toBe(false);
+ });
+
+ it("should match text split across multiple lines", async () => {
+ const scrollIntoViewMock = jest.fn();
+ window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
+
+ API.setElements([
+ API.createElement({
+ type: "text",
+ text: "",
+ }),
+ ]);
+
+ API.updateElement(h.elements[0] as ExcalidrawTextElement, {
+ text: "t\ne\ns\nt \nt\ne\nx\nt \ns\np\nli\nt \ni\nn\nt\no\nm\nu\nlt\ni\np\nl\ne \nli\nn\ne\ns",
+ originalText: "test text split into multiple lines",
+ });
+
+ expect(h.app.state.openSidebar).toBeNull();
+
+ Keyboard.withModifierKeys({ ctrl: true }, () => {
+ Keyboard.keyPress(KEYS.F);
+ });
+ expect(h.app.state.openSidebar).not.toBeNull();
+ expect(h.app.state.openSidebar?.name).toBe(DEFAULT_SIDEBAR.name);
+ expect(h.app.state.openSidebar?.tab).toBe(CANVAS_SEARCH_TAB);
+
+ const searchInput = await querySearchInput();
+
+ expect(searchInput.matches(":focus")).toBe(true);
+
+ updateTextEditor(searchInput, "test");
+
+ await waitFor(() => {
+ expect(h.app.state.searchMatches.length).toBe(1);
+ expect(h.app.state.searchMatches[0]?.matchedLines?.length).toBe(4);
+ });
+
+ updateTextEditor(searchInput, "ext spli");
+
+ await waitFor(() => {
+ expect(h.app.state.searchMatches.length).toBe(1);
+ expect(h.app.state.searchMatches[0]?.matchedLines?.length).toBe(6);
+ });
+ });
+});