mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-22 01:02:41 +00:00
test(app): exercise plugin Escape through the real composer
Keep the contributor fix and replace the substitute shortcut-listener test with an installed-plugin browser regression. The first Escape must close the preview without cancelling the turn; the second must cancel it. Co-authored-by: luke <luopeihuan@gmail.com> Co-authored-by: RoundRedDot <roundreddot@gmail.com>
This commit is contained in:
co-authored by
luke
RoundRedDot
parent
199aae9dde
commit
80aa0ca32a
@@ -0,0 +1,47 @@
|
||||
import { expect, test, type Page } from "../support/fixtures";
|
||||
import { composerLocator, submitMessageWithButton } from "../support/helpers/composer";
|
||||
import { seedMockAgentWorkspace, openAgentRoute } from "../support/helpers/mock-agent";
|
||||
import { withPopoverTimelinePlugin } from "../support/helpers/plugin-timeline";
|
||||
|
||||
async function openPreviewWhileTyping(page: Page): Promise<void> {
|
||||
await composerLocator(page).focus();
|
||||
await page.getByRole("button", { name: "Hover plugin preview", exact: true }).hover();
|
||||
await expect(page.getByRole("dialog", { name: "Plugin preview" })).toBeVisible();
|
||||
await expect(composerLocator(page)).toBeFocused();
|
||||
}
|
||||
|
||||
async function dismissPreview(page: Page): Promise<void> {
|
||||
await page.keyboard.press("Escape");
|
||||
await expect(page.getByRole("dialog", { name: "Plugin preview" })).not.toBeVisible();
|
||||
}
|
||||
|
||||
test("Escape dismisses a plugin preview before interrupting the agent", async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
const agent = await seedMockAgentWorkspace({
|
||||
repoPrefix: "plugin-popover-",
|
||||
title: "Plugin preview keyboard regression",
|
||||
model: "e2e-fast-stream",
|
||||
});
|
||||
try {
|
||||
await withPopoverTimelinePlugin(async () => {
|
||||
await openAgentRoute(page, agent);
|
||||
await submitMessageWithButton(page, "Show the plugin preview.");
|
||||
await agent.client.waitForFinish(agent.agentId, 30_000);
|
||||
await expect(page.getByRole("button", { name: "Hover plugin preview" })).toBeVisible();
|
||||
await submitMessageWithButton(page, "withhold synthetic user message until interrupted");
|
||||
const stop = page.getByRole("button", { name: "Stop agent", exact: true });
|
||||
await expect(stop).toBeVisible();
|
||||
|
||||
await openPreviewWhileTyping(page);
|
||||
await dismissPreview(page);
|
||||
await expect(stop).toBeVisible();
|
||||
await expect(composerLocator(page)).toBeFocused();
|
||||
|
||||
await page.keyboard.press("Escape");
|
||||
await expect(stop).not.toBeVisible();
|
||||
await agent.client.waitForFinish(agent.agentId, 15_000);
|
||||
});
|
||||
} finally {
|
||||
await agent.cleanup();
|
||||
}
|
||||
});
|
||||
@@ -231,3 +231,46 @@ export async function attachPromptTimelineEvidence(page: Page, info: TestInfo):
|
||||
contentType: "image/png",
|
||||
});
|
||||
}
|
||||
|
||||
const POPOVER_CLIENT_SOURCE = `import React, { useEffect, useRef } from "react";
|
||||
import { z } from "zod";
|
||||
|
||||
function Preview() {
|
||||
const panel = useRef(null);
|
||||
useEffect(() => {
|
||||
const close = (event) => {
|
||||
if (event.key === "Escape" && panel.current.matches(":popover-open")) {
|
||||
panel.current.hidePopover();
|
||||
}
|
||||
};
|
||||
document.addEventListener("keydown", close, true);
|
||||
return () => document.removeEventListener("keydown", close, true);
|
||||
}, []);
|
||||
return <div>
|
||||
<button onMouseEnter={() => panel.current.showPopover()}>Hover plugin preview</button>
|
||||
<div ref={panel} popover="manual" role="dialog" aria-label="Plugin preview">Plugin hover preview</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
export default function contribute(client) {
|
||||
client.addTimelineTransformer({
|
||||
id: "preview", query: { itemType: "user_message" },
|
||||
transform({ item }) {
|
||||
if (item.text !== "Show the plugin preview.") return;
|
||||
return { items: [{ type: "plugin", kind: "preview", version: 1, data: {} }] };
|
||||
},
|
||||
});
|
||||
client.addTimelineRenderer({
|
||||
kind: "preview", version: 1, schema: z.object({}), Component: Preview,
|
||||
});
|
||||
return () => {};
|
||||
}`;
|
||||
|
||||
/** Installs a timeline preview that owns Escape through the DOM Popover API. */
|
||||
export async function withPopoverTimelinePlugin(run: () => Promise<void>): Promise<void> {
|
||||
await withDirectoryPlugin({
|
||||
pluginId: "timeline-popover-e2e",
|
||||
source: POPOVER_CLIENT_SOURCE,
|
||||
run,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -95,39 +95,6 @@ describe("Escape with a plugin popover open", () => {
|
||||
document.body.replaceChildren();
|
||||
});
|
||||
|
||||
it("closes the popover first, and interrupts only on the next press", () => {
|
||||
// A plugin's panel: shown with the Popover API, closed by its own Escape listener.
|
||||
const panel = document.createElement("div");
|
||||
panel.setAttribute("popover", "manual");
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape" && panel.matches(":popover-open")) panel.hidePopover();
|
||||
});
|
||||
const composer = document.createElement("textarea");
|
||||
document.body.append(composer, panel);
|
||||
// The shortcut engine: a window capture listener that interrupts on Escape.
|
||||
let interrupts = 0;
|
||||
const shortcuts = (event: KeyboardEvent) => {
|
||||
if (keyBelongsToDomPopover(event)) return;
|
||||
if (event.key === "Escape") interrupts += 1;
|
||||
};
|
||||
window.addEventListener("keydown", shortcuts, true);
|
||||
try {
|
||||
composer.focus();
|
||||
panel.showPopover();
|
||||
const escape = () =>
|
||||
composer.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true }));
|
||||
|
||||
escape();
|
||||
expect(panel.matches(":popover-open")).toBe(false);
|
||||
expect(interrupts).toBe(0);
|
||||
|
||||
escape();
|
||||
expect(interrupts).toBe(1);
|
||||
} finally {
|
||||
window.removeEventListener("keydown", shortcuts, true);
|
||||
}
|
||||
});
|
||||
|
||||
it("leaves other keys to the shortcuts while a popover is open", () => {
|
||||
const panel = document.createElement("div");
|
||||
panel.setAttribute("popover", "manual");
|
||||
|
||||
Reference in New Issue
Block a user