mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-23 01:32:40 +00:00
* fix(app): give Markdown and HTML file tabs back their Preview and Source views The built-in Markdown and HTML panels own one toolbar again: file size, line count, save status, vim mode, cursor, and a Preview | Source control over a body that shows the rendered preview or the editor from the same loaded content and editor model. Plain text files keep the toolbar on top. The host no longer renders a panel switcher. Source is the built-in panel for text files no other built-in claims, so it is never offered beside Markdown or HTML in the picker, the Open with menu, or Settings > Files. A line target opens the file's built-in panel in its Source view. * refactor(app): name the shared text file panel TextFilePanel Markdown and HTML own a Source view; they are not Source panels. The composite in file-panels/source/panel.tsx is now TextFilePanel, and SourcePanel is TextFilePanel without a Preview. Names only.
172 lines
7.3 KiB
TypeScript
172 lines
7.3 KiB
TypeScript
import type { TestInfo } from "@playwright/test";
|
|
import { expect, test, type Page } from "../support/fixtures";
|
|
import { seedWorkspace } from "../support/helpers/seed-client";
|
|
import { gotoWorkspace } from "../support/helpers/launcher";
|
|
import { expectFileTabOpen, openFileExplorer } from "../support/helpers/file-explorer";
|
|
import {
|
|
BUILTIN_MARKDOWN_OPTION,
|
|
MARKDOWN_PANEL_ID,
|
|
PLUGIN_MARKDOWN_OPTION,
|
|
expectBuiltinMarkdown,
|
|
expectPluginMarkdown,
|
|
filePanelPicker,
|
|
installMarkdownPanelPlugin,
|
|
openMarkdown,
|
|
storedFilePanelAssociations,
|
|
} from "../support/helpers/markdown-file-panel-plugin";
|
|
|
|
async function choosePanel(page: Page, option: string, options: { remember: boolean }) {
|
|
await page.getByRole("radio", { name: option, exact: true }).click();
|
|
if (options.remember) {
|
|
await page.getByRole("checkbox", { name: "Don't ask me again", exact: true }).click();
|
|
}
|
|
await page.getByRole("button", { name: "Use", exact: true }).click();
|
|
await expect(filePanelPicker(page)).toBeHidden();
|
|
}
|
|
|
|
async function openWithFromTabMenu(page: Page, name: string, option: string) {
|
|
await page.getByTestId(`workspace-tab-file_${name}`).first().click({ button: "right" });
|
|
await page.getByRole("menuitem", { name: "Open with…" }).hover();
|
|
await page.getByRole("menuitem", { name: option }).click();
|
|
}
|
|
|
|
async function toggleAlwaysUseFromTabMenu(page: Page, name: string) {
|
|
await openWithFromTabMenu(page, name, "Always use for .md");
|
|
}
|
|
|
|
/** The built-in panel's toolbar control between its Preview and Source views. */
|
|
function viewControl(page: Page) {
|
|
return page.getByTestId("file-preview-mode").filter({ visible: true });
|
|
}
|
|
|
|
async function selectFileView(page: Page, view: "Preview" | "Source") {
|
|
const option = viewControl(page).getByRole("button", { name: view, exact: true });
|
|
await option.click();
|
|
await expect(option).toHaveAttribute("aria-selected", "true");
|
|
}
|
|
|
|
async function expectNoOpenWith(page: Page, name: string) {
|
|
await page.getByTestId(`workspace-tab-file_${name}`).first().click({ button: "right" });
|
|
await expect(page.getByRole("menuitem", { name: "Close", exact: true })).toBeVisible();
|
|
await expect(page.getByRole("menuitem", { name: "Open with…" })).toHaveCount(0);
|
|
await page.keyboard.press("Escape");
|
|
}
|
|
|
|
async function capture(page: Page, testInfo: TestInfo, name: string) {
|
|
const file = testInfo.outputPath(`${name}.png`);
|
|
await page.screenshot({ path: file });
|
|
await testInfo.attach(name, { path: file, contentType: "image/png" });
|
|
}
|
|
|
|
test("opens Markdown with the built-in panel and its Preview and Source without asking", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
const workspace = await seedWorkspace({
|
|
repoPrefix: "file-panel-builtins-",
|
|
repo: { files: [{ path: "notes.md", content: "# notes heading\n" }] },
|
|
});
|
|
try {
|
|
await page.setViewportSize({ width: 1280, height: 900 });
|
|
await gotoWorkspace(page, workspace.workspaceId);
|
|
await openFileExplorer(page);
|
|
await openMarkdown(page, "notes.md");
|
|
await expectBuiltinMarkdown(page, "notes heading");
|
|
await expect(viewControl(page).getByRole("button")).toHaveText(["Preview", "Source"]);
|
|
await expect(filePanelPicker(page)).toBeHidden();
|
|
await expectNoOpenWith(page, "notes.md");
|
|
await capture(page, testInfo, "file-panel-builtins-wide");
|
|
|
|
await selectFileView(page, "Source");
|
|
await expect(page.getByTestId("file-source-editor").filter({ visible: true })).toBeVisible();
|
|
await selectFileView(page, "Preview");
|
|
await expectBuiltinMarkdown(page, "notes heading");
|
|
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
await expectBuiltinMarkdown(page, "notes heading");
|
|
await expect(
|
|
viewControl(page).getByRole("button", { name: "Source", exact: true }),
|
|
).toBeInViewport({ ratio: 1 });
|
|
await expect(filePanelPicker(page)).toBeHidden();
|
|
await capture(page, testInfo, "file-panel-builtins-compact");
|
|
} finally {
|
|
await workspace.cleanup();
|
|
}
|
|
});
|
|
|
|
test("asks once which panel opens Markdown and remembers it when told to", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
test.setTimeout(120_000);
|
|
const workspace = await seedWorkspace({
|
|
repoPrefix: "file-panel-picker-",
|
|
repo: {
|
|
files: ["first", "second", "third", "fourth"].map((name) => ({
|
|
path: `${name}.md`,
|
|
content: `# ${name} heading\n`,
|
|
})),
|
|
},
|
|
});
|
|
const plugin = await installMarkdownPanelPlugin();
|
|
try {
|
|
await page.setViewportSize({ width: 1280, height: 900 });
|
|
await gotoWorkspace(page, workspace.workspaceId);
|
|
await openFileExplorer(page);
|
|
|
|
// First open: the built-in renders under the picker.
|
|
await openMarkdown(page, "first.md");
|
|
await expect(filePanelPicker(page)).toBeVisible();
|
|
await expect(page.getByRole("radio", { name: BUILTIN_MARKDOWN_OPTION })).toBeChecked();
|
|
await expect(page.getByRole("radio", { name: PLUGIN_MARKDOWN_OPTION })).not.toBeChecked();
|
|
await expect(page.getByRole("radio")).toHaveCount(2);
|
|
await expectBuiltinMarkdown(page, "first heading");
|
|
await capture(page, testInfo, "file-panel-picker-wide");
|
|
|
|
// Don't ask me again: the plugin renders and later opens use it silently.
|
|
await choosePanel(page, PLUGIN_MARKDOWN_OPTION, { remember: true });
|
|
await expectPluginMarkdown(page, "first.md");
|
|
expect(await storedFilePanelAssociations(page)).toEqual({ "ext:md": MARKDOWN_PANEL_ID });
|
|
await openMarkdown(page, "second.md");
|
|
await expectPluginMarkdown(page, "second.md");
|
|
await expect(filePanelPicker(page)).toBeHidden();
|
|
|
|
// Forgetting from the tab menu keeps the tab on the plugin.
|
|
await toggleAlwaysUseFromTabMenu(page, "second.md");
|
|
await expect.poll(() => storedFilePanelAssociations(page)).toEqual({});
|
|
await expectPluginMarkdown(page, "second.md");
|
|
|
|
// An unremembered choice applies to this tab only; the next open asks again.
|
|
await openMarkdown(page, "third.md");
|
|
await expect(filePanelPicker(page)).toBeVisible();
|
|
await choosePanel(page, PLUGIN_MARKDOWN_OPTION, { remember: false });
|
|
await expectPluginMarkdown(page, "third.md");
|
|
expect(await storedFilePanelAssociations(page)).toEqual({});
|
|
|
|
// "Open with…" switches the open tab back to the built-in in place, with its own views.
|
|
await openWithFromTabMenu(page, "third.md", BUILTIN_MARKDOWN_OPTION);
|
|
await expectBuiltinMarkdown(page, "third heading");
|
|
await expectFileTabOpen(page, "third.md");
|
|
await selectFileView(page, "Source");
|
|
await expect(page.getByTestId("file-source-editor").filter({ visible: true })).toBeVisible();
|
|
await selectFileView(page, "Preview");
|
|
await expectBuiltinMarkdown(page, "third heading");
|
|
|
|
// Dismissing keeps the built-in; reopening the tab after a reload asks again.
|
|
await openMarkdown(page, "fourth.md");
|
|
await expect(filePanelPicker(page)).toBeVisible();
|
|
await page.keyboard.press("Escape");
|
|
await expect(filePanelPicker(page)).toBeHidden();
|
|
await expectBuiltinMarkdown(page, "fourth heading");
|
|
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
await page.reload();
|
|
await expect(filePanelPicker(page)).toBeVisible({ timeout: 30_000 });
|
|
await expect(page.getByRole("button", { name: "Use", exact: true })).toBeInViewport({
|
|
ratio: 1,
|
|
});
|
|
await capture(page, testInfo, "file-panel-picker-compact");
|
|
} finally {
|
|
await plugin.uninstall();
|
|
await workspace.cleanup();
|
|
}
|
|
});
|