Files
kandev/apps/web/components/task/chat/tiptap-slash-command-extension.test.ts
T
2026-07-02 16:45:01 +01:00

100 lines
3.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { SlashCommandNode } from "./tiptap-slash-command-extension";
import { formatSlashCommandDisplayLabel } from "./tiptap-slash-command-utils";
const SLOW_COMMAND_NAME = "slow";
const SLOW_COMMAND_LABEL = "/slow";
const SLOW_COMMAND_DESCRIPTION = "Run slowly";
type SlashCommandNodeConfig = {
addAttributes: () => Record<string, { rendered?: boolean }>;
parseHTML: () => Array<{
tag: string;
getAttrs?: (element: Element) => Record<string, unknown>;
}>;
renderHTML: (args: {
node: { attrs: Record<string, unknown> };
HTMLAttributes: Record<string, unknown>;
}) => [string, Record<string, unknown>, string];
renderText: (args: { node: { attrs: Record<string, unknown> } }) => string;
};
const config = SlashCommandNode.config as unknown as SlashCommandNodeConfig;
describe("SlashCommandNode", () => {
it("marks internal attrs as non-rendered TipTap attrs", () => {
expect(config.addAttributes()).toMatchObject({
id: { rendered: false },
label: { rendered: false },
commandName: { rendered: false },
description: { rendered: false },
});
});
it("renders text from label when present", () => {
expect(
config.renderText({
node: { attrs: { label: SLOW_COMMAND_LABEL, commandName: "fast" } },
}),
).toBe(SLOW_COMMAND_LABEL);
});
it("renders text from commandName when label is missing", () => {
expect(config.renderText({ node: { attrs: { commandName: SLOW_COMMAND_NAME } } })).toBe(
SLOW_COMMAND_LABEL,
);
});
it("renders HTML with only data attrs for slash command metadata", () => {
const html = config.renderHTML({
node: {
attrs: {
id: "cmd-1",
commandName: SLOW_COMMAND_NAME,
description: SLOW_COMMAND_DESCRIPTION,
},
},
HTMLAttributes: { class: "chip" },
});
expect(html[0]).toBe("span");
expect(html[1]).toEqual({
class: "chip",
"data-slash-command": "",
"data-id": "cmd-1",
"data-command-name": SLOW_COMMAND_NAME,
"data-description": SLOW_COMMAND_DESCRIPTION,
});
expect(html[2]).toBe(SLOW_COMMAND_LABEL);
});
it("formats the visible chip label without a leading slash", () => {
expect(
formatSlashCommandDisplayLabel({
label: SLOW_COMMAND_LABEL,
commandName: SLOW_COMMAND_NAME,
}),
).toBe(SLOW_COMMAND_NAME);
expect(formatSlashCommandDisplayLabel({ commandName: "fast" })).toBe("fast");
});
it("parses slash command attrs from HTML data attrs", () => {
const element = document.createElement("span");
element.setAttribute("data-slash-command", "");
element.setAttribute("data-id", "cmd-1");
element.setAttribute("data-label", SLOW_COMMAND_LABEL);
element.setAttribute("data-command-name", SLOW_COMMAND_NAME);
element.setAttribute("data-description", SLOW_COMMAND_DESCRIPTION);
const parser = config.parseHTML()[0];
expect(parser.tag).toBe("span[data-slash-command]");
expect(parser.getAttrs?.(element)).toEqual({
id: "cmd-1",
label: SLOW_COMMAND_LABEL,
commandName: SLOW_COMMAND_NAME,
description: SLOW_COMMAND_DESCRIPTION,
});
});
});