Files
paseo/packages/app/src/screens/new-workspace-empty.test.ts
T
Mohamed BoudraandGitHub c34fb26359 feat(app): create empty workspace without a prompt (#834)
* feat(app): create empty workspace from new-workspace composer

Pressing Create with an empty composer (no text, no attachments) on the
new-workspace screen now creates the workspace without an agent and
lands the user on the empty-state, where they can open a terminal or
start an agent on their own. Dispatching submit handler routes to a
named runCreateEmptyWorkspace sibling of runCreateChatAgent so empty
creation is a first-class action, not a hidden branch in the chat path.

* refactor(app): extract empty-workspace helpers into own module

Gives the empty-workspace dispatch a real home, shrinks the test mock
graph from ~20 modules to one.

* test(app): type prompt in new-workspace e2e to exercise chat path

Empty-submission now creates a bare workspace (no agent), so tests that
assert agent-tab/optimistic-draft behavior must type a prompt to take
the chat path.
2026-05-09 18:44:40 +08:00

56 lines
2.1 KiB
TypeScript

import { beforeAll, describe, expect, it, vi } from "vitest";
import type { ComposerAttachment } from "@/attachments/types";
import type { MessagePayload } from "@/components/message-input";
const navigateToWorkspace = vi.hoisted(() => vi.fn());
vi.mock("@/hooks/use-workspace-navigation", () => ({ navigateToWorkspace }));
let isEmptyWorkspaceSubmission: typeof import("./new-workspace-empty").isEmptyWorkspaceSubmission;
let runCreateEmptyWorkspace: typeof import("./new-workspace-empty").runCreateEmptyWorkspace;
beforeAll(async () => {
({ isEmptyWorkspaceSubmission, runCreateEmptyWorkspace } = await import("./new-workspace-empty"));
});
function payload(
input: { text?: string; attachments?: ComposerAttachment[] } = {},
): MessagePayload {
return { text: input.text ?? "", attachments: input.attachments ?? [], cwd: "/sample/repo" };
}
describe("runCreateEmptyWorkspace", () => {
it("creates a workspace without prompt or attachments and navigates to it", async () => {
const workspace = { id: "workspace-123" };
const ensureWorkspace = vi.fn().mockResolvedValue(workspace);
await runCreateEmptyWorkspace({ payload: payload(), ensureWorkspace, serverId: "server-abc" });
expect(ensureWorkspace).toHaveBeenCalledOnce();
expect(ensureWorkspace).toHaveBeenCalledWith({
cwd: "/sample/repo",
prompt: "",
attachments: [],
});
expect(navigateToWorkspace).toHaveBeenCalledOnce();
expect(navigateToWorkspace).toHaveBeenCalledWith("server-abc", workspace.id);
});
});
describe("isEmptyWorkspaceSubmission", () => {
it("treats whitespace-only text with no attachments as empty, but any attachment as non-empty", () => {
const attachment: ComposerAttachment = {
kind: "image",
metadata: {
id: "image-1",
mimeType: "image/png",
storageType: "web-indexeddb",
storageKey: "image-1",
createdAt: 0,
},
};
expect(isEmptyWorkspaceSubmission(payload({ text: " \n\t " }))).toBe(true);
expect(isEmptyWorkspaceSubmission(payload({ attachments: [attachment] }))).toBe(false);
});
});