mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-28 04:03:05 +00:00
fix(app): return to chat after fullscreen submission (#6987)
This commit is contained in:
@@ -170,7 +170,8 @@ test("composer growth keeps a bottom-pinned chat at the bottom", async ({ page }
|
||||
async function pausePageClock(page: Page): Promise<void> {
|
||||
const now = Date.now();
|
||||
await page.clock.install({ time: now });
|
||||
await page.clock.pauseAt(now);
|
||||
// The installed clock advances between protocol calls; pause at a future time.
|
||||
await page.clock.pauseAt(now + 60_000);
|
||||
}
|
||||
|
||||
/** The send error shares the footer with Send, so whatever keeps Send visible keeps it visible. */
|
||||
@@ -206,7 +207,7 @@ test("compact long drafts stop growing before the header", async ({ page }) => {
|
||||
}
|
||||
});
|
||||
|
||||
test("compact fullscreen editing preserves the live draft and selection and stays open after send", async ({
|
||||
test("compact fullscreen editing preserves the live draft and selection and returns to chat after send", async ({
|
||||
page,
|
||||
}) => {
|
||||
const agent = await seedMockAgentWorkspace({
|
||||
@@ -260,7 +261,7 @@ test("compact fullscreen editing preserves the live draft and selection and stay
|
||||
await sendComposerWithButton(page);
|
||||
await expect(composerLocator(page)).toHaveValue("");
|
||||
});
|
||||
await test.step("sending inside fullscreen clears the editor and keeps fullscreen open", async () => {
|
||||
await test.step("sending inside fullscreen returns to chat and clears the editor", async () => {
|
||||
await writeCompactDraft(page, "First line\nSecond line\nThird line");
|
||||
await enterComposerFullscreen(page);
|
||||
await writeCompactDraft(page, "Short draft");
|
||||
@@ -274,10 +275,12 @@ test("compact fullscreen editing preserves the live draft and selection and stay
|
||||
await resizeComposerViewport(page, "portrait");
|
||||
await sendComposerWithButton(page);
|
||||
await expect(composerLocator(page)).toHaveValue("");
|
||||
await expectComposerFullscreenControls(page);
|
||||
await expect(page.getByRole("button", { name: "Send message", exact: true })).toBeDisabled();
|
||||
await expectWorkspaceHeaderVisible(page);
|
||||
await expect(page.getByTestId("composer-fullscreen")).toHaveCount(0);
|
||||
});
|
||||
await test.step("typing and sending keep working after leaving fullscreen again", async () => {
|
||||
await writeCompactDraft(page, "First line\nSecond line\nThird line");
|
||||
await enterComposerFullscreen(page);
|
||||
await writeCompactDraft(page, "Typed inside fullscreen");
|
||||
await expect(page.getByRole("button", { name: "Send message", exact: true })).toBeEnabled();
|
||||
await exitComposerFullscreen(page);
|
||||
@@ -339,16 +342,16 @@ test("fullscreen submit rejection retains the editable draft and supports retry"
|
||||
await writeCompactDraft(page, draft);
|
||||
await enterComposerFullscreen(page);
|
||||
await sendComposerWithButton(page);
|
||||
await expect(page.getByTestId("composer-fullscreen").getByRole("alert")).toHaveText(
|
||||
"Requested mock prompt rejection",
|
||||
);
|
||||
await expectWorkspaceHeaderVisible(page);
|
||||
await expect(page.getByRole("alert")).toHaveText("Requested mock prompt rejection");
|
||||
await enterComposerFullscreen(page);
|
||||
await expectFullscreenErrorAboveSend(page);
|
||||
await expect(composerLocator(page)).toHaveValue(draft);
|
||||
await expect(composerLocator(page)).toBeEditable();
|
||||
await expect(page.getByRole("button", { name: "Send message", exact: true })).toBeEnabled();
|
||||
await sendComposerWithButton(page);
|
||||
await expect(composerLocator(page)).toHaveValue("");
|
||||
await expectComposerFullscreenControls(page);
|
||||
await expectWorkspaceHeaderVisible(page);
|
||||
} finally {
|
||||
await agent.cleanup();
|
||||
}
|
||||
@@ -440,8 +443,7 @@ test("fullscreen Send keeps the configured queue behavior while an agent runs",
|
||||
await expectComposerFullscreenControls(page);
|
||||
await queueComposerWithButton(page);
|
||||
await expect(composerLocator(page)).toHaveValue("");
|
||||
await expectComposerFullscreenControls(page);
|
||||
await exitComposerFullscreen(page);
|
||||
await expectWorkspaceHeaderVisible(page);
|
||||
await expectQueuedMessageButton(page);
|
||||
} finally {
|
||||
await agent.cleanup();
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import {
|
||||
composerLocator,
|
||||
enterComposerFullscreen,
|
||||
exitComposerFullscreen,
|
||||
resizeComposerViewport,
|
||||
} from "../support/helpers/composer";
|
||||
import { expect, test } from "../support/fixtures";
|
||||
import { gotoAppShell } from "../support/helpers/app";
|
||||
import { getE2EDaemonPort } from "../support/helpers/daemon-port";
|
||||
import {
|
||||
delayBrowserWorkspaceCreatedResponse,
|
||||
expectNewWorkspaceDraft,
|
||||
expectNewWorkspaceProjectSelected,
|
||||
fillNewWorkspaceDraft,
|
||||
@@ -134,3 +141,45 @@ test.describe("New workspace composer draft", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("fullscreen creation returns inline and keeps submission locked when reopened", async ({
|
||||
page,
|
||||
}) => {
|
||||
const project = await seedWorkspace({ repoPrefix: "fullscreen-submit-pending-" });
|
||||
const delay = await delayBrowserWorkspaceCreatedResponse(page);
|
||||
try {
|
||||
await gotoAppShell(page);
|
||||
await waitForSidebarHydration(page);
|
||||
await openNewWorkspaceComposer(page, project);
|
||||
await resizeComposerViewport(page, "portrait");
|
||||
await fillNewWorkspaceDraft(page, DRAFT);
|
||||
await enterComposerFullscreen(page);
|
||||
await page.getByRole("button", { name: "Create", exact: true }).click();
|
||||
await delay.waitForCreateRequest();
|
||||
|
||||
await test.step("submission returns inline with the original draft and spinner", async () => {
|
||||
await expect(page.getByTestId("composer-fullscreen")).toHaveCount(0);
|
||||
await expect(composerLocator(page)).toHaveValue(DRAFT);
|
||||
await expect(composerLocator(page)).not.toBeEditable();
|
||||
await expect(page.getByRole("button", { name: "Create", exact: true })).toBeDisabled();
|
||||
await expect(page.getByRole("progressbar")).toBeVisible();
|
||||
});
|
||||
await test.step("fullscreen can reopen while pending without unlocking or duplicating submission", async () => {
|
||||
await enterComposerFullscreen(page);
|
||||
await expect(page.getByTestId("composer-fullscreen")).toBeVisible();
|
||||
await expect(composerLocator(page)).toHaveValue(DRAFT);
|
||||
await expect(composerLocator(page)).not.toBeEditable();
|
||||
await expect(page.getByRole("button", { name: "Create", exact: true })).toBeDisabled();
|
||||
await expect(page.getByRole("progressbar")).toBeVisible();
|
||||
await exitComposerFullscreen(page);
|
||||
});
|
||||
delay.release();
|
||||
await page.waitForURL((url) => url.pathname.includes("/workspace/"));
|
||||
await expect(composerLocator(page)).toHaveValue("");
|
||||
await expect(composerLocator(page)).toBeEditable();
|
||||
expect(delay.agentRequests).toHaveLength(1);
|
||||
} finally {
|
||||
delay.release();
|
||||
await project.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -942,6 +942,7 @@ interface SendMessageContext {
|
||||
onSubmit: (payload: MessagePayload) => void;
|
||||
onMinimizeHeight: () => void;
|
||||
preserveHeightOnSubmit: boolean;
|
||||
exitFullscreen: () => void;
|
||||
}
|
||||
|
||||
function sendMessageImpl(ctx: SendMessageContext): void {
|
||||
@@ -954,6 +955,7 @@ function sendMessageImpl(ctx: SendMessageContext): void {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
ctx.exitFullscreen();
|
||||
ctx.onSubmit({
|
||||
text: trimmed,
|
||||
attachments: ctx.attachments,
|
||||
@@ -974,12 +976,14 @@ interface QueueMessageContext {
|
||||
onQueue: ((payload: MessagePayload) => void) | undefined;
|
||||
replaceText: (text: string) => void;
|
||||
onMinimizeHeight: () => void;
|
||||
exitFullscreen: () => void;
|
||||
}
|
||||
|
||||
function queueMessageImpl(ctx: QueueMessageContext): void {
|
||||
if (!ctx.onQueue) return;
|
||||
const trimmed = ctx.value.trim();
|
||||
if (!trimmed && ctx.attachments.length === 0) return;
|
||||
ctx.exitFullscreen();
|
||||
ctx.onQueue({ text: trimmed, attachments: ctx.attachments, cwd: ctx.cwd });
|
||||
ctx.replaceText("");
|
||||
ctx.onMinimizeHeight();
|
||||
@@ -1640,6 +1644,7 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
|
||||
onSubmit,
|
||||
onMinimizeHeight: minimizeInputHeight,
|
||||
preserveHeightOnSubmit,
|
||||
exitFullscreen,
|
||||
});
|
||||
}, [
|
||||
allowEmptySubmit,
|
||||
@@ -1651,6 +1656,7 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
|
||||
minimizeInputHeight,
|
||||
preserveHeightOnSubmit,
|
||||
updateLiveTextPresence,
|
||||
exitFullscreen,
|
||||
]);
|
||||
|
||||
const handleQueueMessage = useCallback(
|
||||
@@ -1662,8 +1668,9 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
|
||||
onQueue,
|
||||
replaceText,
|
||||
onMinimizeHeight: minimizeInputHeight,
|
||||
exitFullscreen,
|
||||
}),
|
||||
[attachments, cwd, onQueue, replaceText, minimizeInputHeight],
|
||||
[attachments, cwd, onQueue, replaceText, minimizeInputHeight, exitFullscreen],
|
||||
);
|
||||
|
||||
const handleDefaultSendAction = useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user