Skip to content

Commit

Permalink
test(command box): select and execute command, prevent the combobox f…
Browse files Browse the repository at this point in the history
…rom blocking requests
  • Loading branch information
MarcMcIntosh committed Feb 20, 2024
1 parent d563dbc commit 3fa0760
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 23 deletions.
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
[x] combobox undo / redo
[x] list display in response has a large margin/padding
[ ] tidy up combobox
[x] bug @ast_definition blocks sending requests

### EVENTS TODO FOR IDEs

Expand Down
35 changes: 24 additions & 11 deletions src/components/ComboBox/ComboBox.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { describe, test, vi, expect, afterEach } from "vitest";
import { render, cleanup, waitFor } from "../../utils/test-utils";
import { render, cleanup } from "../../utils/test-utils";
import { ComboBox, ComboBoxProps } from "./ComboBox";
import { TextArea, type TextAreaProps } from "../TextArea";

Expand All @@ -9,14 +9,13 @@ const App = (props: Partial<ComboBoxProps>) => {
const [selectedCommand, setSelectedCommand] = React.useState<string>("");

const requestCompletionSpy = vi.fn();
const onSubmitSpy = vi.fn();
const defaultProps: ComboBoxProps = {
commands: ["@file", "@workspace"],
requestCommandsCompletion: requestCompletionSpy,
commandArguments: ["/foo", "/bar"],
value: value,
onChange: setValue,
onSubmit: onSubmitSpy,
onSubmit: () => ({}),
placeholder: "Type @ for commands",
render: (props: TextAreaProps) => <TextArea {...props} />,
selectedCommand,
Expand Down Expand Up @@ -91,11 +90,9 @@ describe("ComboBox", () => {
const { user, ...app } = render(<App />);
const textarea = app.getByRole("combobox");
await user.type(textarea, "@f");
await waitFor(() => app.getByText("@file"));
await user.keyboard("{Enter}");
expect(app.getByRole("combobox").textContent).toEqual("@file ");
await waitFor(() => app.getByText("/foo"));
await user.type(textarea, "/f{Enter}");
await user.keyboard("{Enter}");
expect(app.getByRole("combobox").textContent).toEqual("@file /foo");
});

Expand Down Expand Up @@ -195,17 +192,33 @@ describe("ComboBox", () => {
expect(event.target.value).toEqual("hello\n");
});

test("select and execute command", async () => {
const onSubmitSpy = vi.fn();
const { user, ...app } = render(<App onSubmit={onSubmitSpy} />);
const textarea = app.getByRole("combobox");
await user.type(textarea, "@");
await user.keyboard("{Enter}");
await user.keyboard("{Enter}");
expect(textarea.textContent).toEqual("@file /foo");
await user.keyboard("{Enter}");
expect(onSubmitSpy).toHaveBeenCalled();
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
expect(onSubmitSpy.mock.lastCall[0]?.target.value).toEqual("@file /foo\n");
});

test("select command, type / and then delete", async () => {
const { user, ...app } = render(<App />);
const textarea = app.getByRole("combobox");
await user.type(textarea, "@fi{Enter}");
expect(app.getByRole("combobox").textContent).toEqual("@file ");
await user.type(textarea, "/");
expect(app.queryByText("/foo")).not.toBeNull();
expect(app.queryByText("/bar")).not.toBeNull();
await user.type(textarea, "{Backspace}");
expect(textarea.textContent).toEqual("@file ");
await user.keyboard("/");
expect(app.queryByText("/foo")).not.toBeNull();
expect(app.queryByText("/bar")).not.toBeNull();
await user.keyboard("{Backspace}");
await user.keyboard("{Backspace}");
expect(app.queryByText("/foo")).toBeNull();
expect(app.queryByText("/bar")).toBeNull();
expect(app.queryByText("@workspace")).not.toBeNull();
});

test("change a command after typing", async () => {
Expand Down
24 changes: 12 additions & 12 deletions src/components/ComboBox/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -264,19 +264,19 @@ export const ComboBox: React.FC<ComboBoxProps> = ({
};

const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
const maybeTrigger = event.target.value
.substring(
startPosition ?? event.target.selectionStart - trigger.length,
event.target.selectionStart,
)
.trim();

onChange(event.target.value);

if (trigger && maybeTrigger) {
combobox.setValue(maybeTrigger);
setTrigger(maybeTrigger);
combobox.show();
const maybeCommand = detectCommand(event.target);
if (maybeCommand) {
setTrigger(maybeCommand.command);
setStartPosition(maybeCommand.startPosition);
const [command, ...args] = maybeCommand.command
.split(" ")
.filter((d) => d);
setSelectedCommand(args.length > 0 ? command + " " : "");
} else {
setTrigger("");
setSelectedCommand("");
setStartPosition(null);
}
};

Expand Down

0 comments on commit 3fa0760

Please sign in to comment.