feat(webui): add localized slash commands
Add a session-scoped slash command palette sourced from backend command metadata, and keep welcome-page quick actions localized across all WebUI languages. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
Xubin Ren
co-authored by
Cursor
parent
49c07aa45a
commit
ac18a8baad
@@ -1,7 +1,24 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { ThreadComposer } from "@/components/thread/ThreadComposer";
|
||||
import type { SlashCommand } from "@/lib/types";
|
||||
|
||||
const COMMANDS: SlashCommand[] = [
|
||||
{
|
||||
command: "/stop",
|
||||
title: "Stop current task",
|
||||
description: "Cancel the active agent turn.",
|
||||
icon: "square",
|
||||
},
|
||||
{
|
||||
command: "/history",
|
||||
title: "Show conversation history",
|
||||
description: "Print the last N persisted messages.",
|
||||
icon: "history",
|
||||
argHint: "[n]",
|
||||
},
|
||||
];
|
||||
|
||||
describe("ThreadComposer", () => {
|
||||
it("renders a readonly hero model composer when provided", () => {
|
||||
@@ -43,4 +60,35 @@ describe("ThreadComposer", () => {
|
||||
expect(screen.getByRole("button", { name: "Attach image" }).className).toContain("bg-card");
|
||||
expect(screen.getByRole("button", { name: "Send message" }).className).toContain("bg-foreground");
|
||||
});
|
||||
|
||||
it("opens a slash command palette and inserts the selected command", () => {
|
||||
const onSend = vi.fn();
|
||||
render(
|
||||
<ThreadComposer
|
||||
onSend={onSend}
|
||||
placeholder="Type your message..."
|
||||
slashCommands={COMMANDS}
|
||||
/>,
|
||||
);
|
||||
|
||||
const input = screen.getByLabelText("Message input");
|
||||
fireEvent.change(input, { target: { value: "/" } });
|
||||
|
||||
expect(screen.getByRole("listbox", { name: "Slash commands" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("option", { name: /\/stop/i })).toHaveAttribute(
|
||||
"aria-selected",
|
||||
"true",
|
||||
);
|
||||
|
||||
fireEvent.keyDown(input, { key: "ArrowDown" });
|
||||
expect(screen.getByRole("option", { name: /\/history/i })).toHaveAttribute(
|
||||
"aria-selected",
|
||||
"true",
|
||||
);
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(input).toHaveValue("/history ");
|
||||
expect(onSend).not.toHaveBeenCalled();
|
||||
expect(screen.queryByRole("listbox", { name: "Slash commands" })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user