mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-04 07:33:18 +00:00
* fix(app): open a nested-repo file when the workspace-root path is missing A workspace that contains another git repo often gets paths written relative to that nested repo. `schema/x.md` is really `repo-a/schema/x.md`. A markdown link was joined onto the workspace root and opened a missing file. Inline code already asked the daemon for a suffix match. Resolved workspace-relative paths that contain a slash now use that same lookup before opening. An exact hit stays on the original path. A suffix hit replaces it and keeps the line range. A failed lookup still opens the original path. Bare names, absolute paths, and `~/` paths are unchanged. Example: - Input: workspace `/repo`, link `schema/x.md`, file at `repo-a/schema/x.md` - Before: open `/repo/schema/x.md` (missing) - After: open `/repo/repo-a/schema/x.md` * fix(app): preserve explicit destinations when finding nested files Relative chat links can name a file inside a nested repository. Retain the suffix lookup while using the original href and document base to preserve absolute paths, preview links, and folder destinations. Co-authored-by: Ouyang Xingyuan <galaxyroaming@qq.com> * fix(app): keep network share links on their absolute destination Use the shared absolute-path classifier so network share hrefs retain their destination alongside drive and POSIX paths. * fix(app): keep nested-file lookup inside ordered path opening Resolve the original directory before considering suffix matches, and allocate click ordering before asynchronous lookup. The existing opener now owns the complete operation so a slow earlier click cannot replace a later selection. * test(app): load UI modules before test lifecycle hooks Cold module transformation exceeded the lifecycle hook deadline before these suites could run. Complete module initialization before registering the tests, retaining their assertions and timeout settings. --------- Co-authored-by: Ouyang Xingyuan <galaxyroaming@qq.com> Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
122 lines
4.8 KiB
TypeScript
122 lines
4.8 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { test, expect, type Page } from "../support/fixtures";
|
|
import { openAgentRoute, seedMockAgentWorkspace } from "../support/helpers/mock-agent";
|
|
|
|
async function readFileLinkTooltip(page: Page): Promise<void> {
|
|
const link = page.getByRole("link", { name: "the guide", exact: true });
|
|
await link.hover();
|
|
await expect(page.getByRole("tooltip")).toContainText("guide.md");
|
|
}
|
|
|
|
async function leaveFileLink(page: Page): Promise<void> {
|
|
await page.mouse.move(5, 5);
|
|
await expect(page.getByRole("tooltip")).toHaveCount(0);
|
|
}
|
|
|
|
async function openLinkedFile(page: Page): Promise<void> {
|
|
await page.getByRole("link", { name: "the guide", exact: true }).click();
|
|
await expect(page.getByTestId("markdown-preview-frame")).toContainText("Example guide");
|
|
await leaveFileLink(page);
|
|
}
|
|
|
|
async function returnToAgent(page: Page): Promise<void> {
|
|
await page.getByRole("button", { name: "Tooltip regression", exact: true }).click();
|
|
await expect(page.getByRole("link", { name: "the guide", exact: true })).toBeVisible();
|
|
await leaveFileLink(page);
|
|
}
|
|
|
|
async function switchToFileTab(page: Page): Promise<void> {
|
|
await page.getByRole("button", { name: "guide.md", exact: true }).click();
|
|
await expect(page.getByTestId("markdown-preview-frame")).toContainText("Example guide");
|
|
await leaveFileLink(page);
|
|
}
|
|
|
|
test("opening an assistant file link dismisses its tooltip over the file tab", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
testInfo.setTimeout(120_000);
|
|
const agent = await seedMockAgentWorkspace({
|
|
repoPrefix: "tooltip-5811-",
|
|
title: "Tooltip regression",
|
|
featureValues: {
|
|
mockStreamingAssistantResponse: "Read [the guide](./guide.md).",
|
|
mockStreamingAssistantIntervalMs: 5,
|
|
},
|
|
});
|
|
try {
|
|
await writeFile(
|
|
path.join(agent.cwd, "guide.md"),
|
|
"# Example guide\n\n" + "Plain paragraph.\n\n".repeat(150),
|
|
);
|
|
await openAgentRoute(page, agent);
|
|
await agent.client.sendAgentMessage(agent.agentId, "Show the file link.");
|
|
await agent.client.waitForFinish(agent.agentId, 30_000);
|
|
|
|
await readFileLinkTooltip(page);
|
|
await leaveFileLink(page);
|
|
await readFileLinkTooltip(page);
|
|
await openLinkedFile(page);
|
|
await returnToAgent(page);
|
|
await readFileLinkTooltip(page);
|
|
await switchToFileTab(page);
|
|
await returnToAgent(page);
|
|
await readFileLinkTooltip(page);
|
|
await leaveFileLink(page);
|
|
} finally {
|
|
await agent.cleanup();
|
|
}
|
|
});
|
|
|
|
async function readLinkedGuide(page: Page, linkName: string, content: string): Promise<void> {
|
|
await page.getByRole("link", { name: linkName, exact: true }).click();
|
|
await expect(page.getByTestId("markdown-preview-frame").filter({ visible: true })).toContainText(
|
|
content,
|
|
);
|
|
}
|
|
|
|
async function returnToNestedLinks(page: Page): Promise<void> {
|
|
await page.getByRole("button", { name: "Nested file links", exact: true }).click();
|
|
await expect(page.getByRole("link", { name: "nested guide", exact: true })).toBeVisible();
|
|
}
|
|
|
|
test("assistant directory paths find nested files and preserve exact workspace paths", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
testInfo.setTimeout(120_000);
|
|
const agent = await seedMockAgentWorkspace({
|
|
repoPrefix: "nested-file-link-",
|
|
title: "Nested file links",
|
|
featureValues: {
|
|
mockStreamingAssistantResponse:
|
|
"Read [nested guide](schema/x.md), [exact guide](schema/exact.md), and [missing guide](schema/missing.md).",
|
|
mockStreamingAssistantIntervalMs: 5,
|
|
},
|
|
});
|
|
try {
|
|
await mkdir(path.join(agent.cwd, "repo-a/schema"), { recursive: true });
|
|
execFileSync("git", ["init", "-b", "main"], { cwd: path.join(agent.cwd, "repo-a") });
|
|
await writeFile(
|
|
path.join(agent.cwd, "repo-a/schema/x.md"),
|
|
"# Nested file content\n\nDetails\n",
|
|
);
|
|
await mkdir(path.join(agent.cwd, "schema"), { recursive: true });
|
|
await writeFile(path.join(agent.cwd, "schema/exact.md"), "# Exact file content\n");
|
|
await writeFile(path.join(agent.cwd, "repo-a/schema/exact.md"), "# Wrong nested content\n");
|
|
await openAgentRoute(page, agent);
|
|
await agent.client.sendAgentMessage(agent.agentId, "Show the file links.");
|
|
await agent.client.waitForFinish(agent.agentId, 30_000);
|
|
|
|
await expect(page.getByRole("textbox", { name: "Message agent..." }).first()).toBeEnabled();
|
|
await readLinkedGuide(page, "nested guide", "Nested file content");
|
|
await returnToNestedLinks(page);
|
|
await readLinkedGuide(page, "exact guide", "Exact file content");
|
|
await returnToNestedLinks(page);
|
|
await page.getByRole("link", { name: "missing guide", exact: true }).click();
|
|
await expect(page.getByText("File not found", { exact: true })).toBeVisible();
|
|
} finally {
|
|
await agent.cleanup();
|
|
}
|
|
});
|