157 lines
5.0 KiB
TypeScript
157 lines
5.0 KiB
TypeScript
import { useState } from "react";
|
|
|
|
import { render, screen, waitFor } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import { Button } from "./button";
|
|
import {
|
|
Command,
|
|
CommandDialog,
|
|
CommandEmpty,
|
|
CommandGroup,
|
|
CommandInput,
|
|
CommandItem,
|
|
CommandList,
|
|
CommandSeparator,
|
|
CommandShortcut
|
|
} from "./command";
|
|
|
|
describe("Command", () => {
|
|
it("renders root, input, list, item, and shortcut slots", async () => {
|
|
const user = userEvent.setup();
|
|
|
|
render(
|
|
<Command label="Quick actions">
|
|
<CommandInput placeholder="Search actions" />
|
|
<CommandList>
|
|
<CommandEmpty>No results.</CommandEmpty>
|
|
<CommandGroup heading="Actions">
|
|
<CommandItem value="launch-release">Launch release</CommandItem>
|
|
<CommandItem value="open-legal">
|
|
Open legal review
|
|
<CommandShortcut>G L</CommandShortcut>
|
|
</CommandItem>
|
|
</CommandGroup>
|
|
<CommandSeparator />
|
|
</CommandList>
|
|
</Command>
|
|
);
|
|
|
|
const root = document.querySelector('[data-slot="root"]');
|
|
const input = screen.getByPlaceholderText("Search actions");
|
|
|
|
expect(root).toHaveAttribute("data-slot", "root");
|
|
expect(input).toHaveAttribute("data-slot", "input");
|
|
expect(document.querySelector('[data-slot="list"]')).toBeInTheDocument();
|
|
expect(screen.getByText("Open legal review").closest('[data-slot="item"]')).toBeInTheDocument();
|
|
expect(screen.getByText("G L")).toHaveAttribute("data-slot", "shortcut");
|
|
|
|
await user.type(input, "zzz");
|
|
expect(await screen.findByText("No results.")).toHaveAttribute("data-slot", "empty");
|
|
});
|
|
|
|
it("calls onSelect when a command item is chosen", async () => {
|
|
const user = userEvent.setup();
|
|
const onSelect = vi.fn();
|
|
|
|
render(
|
|
<Command>
|
|
<CommandInput placeholder="Search actions" />
|
|
<CommandList>
|
|
<CommandItem onSelect={onSelect} value="launch-release">
|
|
Launch release
|
|
</CommandItem>
|
|
</CommandList>
|
|
</Command>
|
|
);
|
|
|
|
await user.click(screen.getByText("Launch release"));
|
|
|
|
expect(onSelect).toHaveBeenCalledWith("launch-release");
|
|
});
|
|
|
|
it("renders inside a dialog and closes through the default close control", async () => {
|
|
const user = userEvent.setup();
|
|
|
|
function CommandDialogExample() {
|
|
const [open, setOpen] = useState(true);
|
|
|
|
return (
|
|
<CommandDialog onOpenChange={setOpen} open={open}>
|
|
<CommandInput placeholder="Search across workspace" />
|
|
<CommandList>
|
|
<CommandItem value="open-docs">Open docs</CommandItem>
|
|
</CommandList>
|
|
</CommandDialog>
|
|
);
|
|
}
|
|
|
|
render(<CommandDialogExample />);
|
|
|
|
expect(screen.getByPlaceholderText("Search across workspace")).toBeInTheDocument();
|
|
|
|
await user.click(screen.getByRole("button", { name: "Close dialog" }));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByPlaceholderText("Search across workspace")).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it("supports loading and footer content on the root command surface", async () => {
|
|
render(
|
|
<Command
|
|
footer={<Button size="sm">Manage commands</Button>}
|
|
label="Workspace palette"
|
|
loading
|
|
loadingMessage="Searching workspace…"
|
|
>
|
|
<CommandInput placeholder="Search workspace" />
|
|
<CommandList>
|
|
<CommandEmpty>No matching items.</CommandEmpty>
|
|
</CommandList>
|
|
</Command>
|
|
);
|
|
|
|
expect(screen.getByText("Searching workspace…")).toHaveAttribute("data-slot", "loading");
|
|
expect(screen.getByText("Manage commands")).toBeInTheDocument();
|
|
});
|
|
|
|
it("supports dialog title, description, and footer actions for a practical palette shell", async () => {
|
|
const user = userEvent.setup();
|
|
|
|
function CommandDialogExample() {
|
|
const [open, setOpen] = useState(true);
|
|
|
|
return (
|
|
<CommandDialog
|
|
description="Jump to docs, recent launches, and operational shortcuts."
|
|
footer={<Button size="sm">Manage shortcuts</Button>}
|
|
onOpenChange={setOpen}
|
|
open={open}
|
|
title="Workspace command palette"
|
|
>
|
|
<CommandInput placeholder="Search across workspace" />
|
|
<CommandList>
|
|
<CommandGroup heading="Recent">
|
|
<CommandItem value="recent-release">Recent release brief</CommandItem>
|
|
</CommandGroup>
|
|
</CommandList>
|
|
</CommandDialog>
|
|
);
|
|
}
|
|
|
|
render(<CommandDialogExample />);
|
|
|
|
expect(screen.getByText("Workspace command palette")).toBeInTheDocument();
|
|
expect(screen.getByText("Jump to docs, recent launches, and operational shortcuts.")).toBeInTheDocument();
|
|
expect(screen.getByText("Manage shortcuts")).toBeInTheDocument();
|
|
|
|
await user.click(screen.getByRole("button", { name: "Close dialog" }));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByText("Workspace command palette")).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|