From 87a30200f9f30ca6bb33a731b6c7b1ee43b8d10a Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Sun, 1 Nov 2026 20:46:14 -0800 Subject: [PATCH] Debug nested template arguments (#788) --- .../TemplateFunctionDialog.test.tsx | 152 ++++++++++ .../components/TemplateFunctionDialog.tsx | 24 +- .../lib/templateFunctionArguments.test.ts | 263 ++++++++++++++++++ .../lib/templateFunctionArguments.ts | 59 ++++ apps/yaak-client/package.json | 1 + package-lock.json | 63 +++++ 6 files changed, 557 insertions(+), 5 deletions(-) create mode 100644 apps/yaak-client/components/TemplateFunctionDialog.test.tsx create mode 100644 apps/yaak-client/lib/templateFunctionArguments.test.ts create mode 100644 apps/yaak-client/lib/templateFunctionArguments.ts diff --git a/apps/yaak-client/components/TemplateFunctionDialog.test.tsx b/apps/yaak-client/components/TemplateFunctionDialog.test.tsx new file mode 100644 index 000000000..5cdbe277c --- /dev/null +++ b/apps/yaak-client/components/TemplateFunctionDialog.test.tsx @@ -0,0 +1,152 @@ +// @vitest-environment happy-dom +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { pathToFileURL } from "node:url"; +import type { Workspace } from "@yaakapp-internal/models"; +import type { TemplateFunction } from "@yaakapp-internal/plugins"; +import type { Tokens } from "@yaakapp-internal/templates"; +import { act, type ReactNode } from "react"; +import { createRoot, type Root } from "react-dom/client"; +import { afterEach, beforeAll, beforeEach, expect, test, vi } from "vite-plus/test"; +import { TemplateFunctionDialog } from "./TemplateFunctionDialog"; + +interface FormProps { + data: Record; + onChange: (values: Record) => void; +} + +const mocks = vi.hoisted(() => ({ + parse: vi.fn<(text: string) => Tokens>(), + print: vi.fn<(tokens: Tokens) => Promise>(), + serialize: vi.fn<(tokens: Tokens) => { data: string }>(), + preview: vi.fn<({ template }: { template: string }) => { data: string }>(), + form: null as FormProps | null, + config: { + name: "timestamp.format", + args: [ + { type: "text", name: "date" }, + { type: "text", name: "format" }, + ], + } as TemplateFunction, +})); + +vi.mock("@yaakapp-internal/templates", () => ({ parseTemplate: mocks.parse })); +vi.mock("@yaakapp-internal/ui", () => ({ + HStack: ({ children }: { children: ReactNode }) =>
{children}
, + InlineCode: "code", + LoadingIcon: () => null, + useDebouncedValue: (value: string) => value, +})); +vi.mock("../hooks/useActiveWorkspace", () => ({ activeWorkspaceAtom: null })); +vi.mock("../hooks/useRenderTemplate", () => ({ useRenderTemplate: mocks.preview })); +vi.mock("../hooks/useTemplateFunctionConfig", () => ({ + useTemplateFunctionConfig: () => ({ data: mocks.config }), +})); +vi.mock("../hooks/useTemplateTokensToString", () => ({ + templateTokensToString: mocks.print, + useTemplateTokensToString: mocks.serialize, +})); +vi.mock("../lib/dialog", () => ({ showDialog: vi.fn() })); +vi.mock("../lib/encryption", () => ({ convertTemplateToInsecure: vi.fn() })); +vi.mock("../lib/jotai", () => ({ jotaiStore: { get: vi.fn() } })); +vi.mock("../lib/setupOrConfigureEncryption", () => ({ setupOrConfigureEncryption: vi.fn() })); +vi.mock("./core/Dialog", () => ({ DialogFooter: () => })); +vi.mock("./core/IconButton", () => ({ IconButton: () =>