Files
kandev/apps/web/e2e/tests/terminal-links.spec.ts
T
José Almeida 06e5114174 feat: add clickable terminal links with configurable open behavior (#401)
* feat: add clickable terminal links with configurable open behavior

Add @xterm/addon-web-links to both passthrough and shell terminals,
enabling Cmd+Click on URLs. Users can configure whether links open
in a new browser tab (default) or the built-in browser panel via a
new setting in the Settings page.

* style: fix prettier formatting

* fix: address CodeRabbit review comments

- Extract applyTerminalLinkBehavior helper to reduce complexity
- Set default terminalLinkBehavior for first-time users in empty settings path
- Use storeApi.getState() for optimistic rollback to avoid stale closures
- Add beforeEach settings reset in E2E tests
- Use 4xx range assertion instead of hardcoded 500

* fix: return 400 for user settings validation errors

Add ErrValidation sentinel to user service and wrap validation errors
from apply* functions. Handler now returns 400 Bad Request instead of
500 Internal Server Error for invalid input. Update E2E test assertion
to enforce client error status (< 500).

* fix: remove cmd+click mention from terminal links description

* fix: mirror validation error handling in WS update path

* style: fix prettier formatting
2026-03-10 15:37:51 +00:00

67 lines
2.6 KiB
TypeScript

import { test, expect } from "../fixtures/test-base";
// ---------------------------------------------------------------------------
// Terminal clickable links — settings persistence and UI
// ---------------------------------------------------------------------------
test.describe("terminal clickable links", () => {
test.beforeEach(async ({ apiClient }) => {
await apiClient.saveUserSettings({ terminal_link_behavior: "new_tab" });
});
test("terminal_link_behavior defaults to new_tab and can be updated via API", async ({
apiClient,
}) => {
// Default value
const initial = await apiClient.getUserSettings();
expect(initial.settings.terminal_link_behavior).toBe("new_tab");
// Switch to browser_panel
await apiClient.saveUserSettings({ terminal_link_behavior: "browser_panel" });
const updated = await apiClient.getUserSettings();
expect(updated.settings.terminal_link_behavior).toBe("browser_panel");
// Revert to new_tab
await apiClient.saveUserSettings({ terminal_link_behavior: "new_tab" });
const reverted = await apiClient.getUserSettings();
expect(reverted.settings.terminal_link_behavior).toBe("new_tab");
});
test("rejects invalid terminal_link_behavior values", async ({ apiClient }) => {
const res = await apiClient.rawRequest("PATCH", "/api/v1/user/settings", {
terminal_link_behavior: "invalid_value",
});
expect(res.status).toBeGreaterThanOrEqual(400);
expect(res.status).toBeLessThan(500);
// Setting should remain unchanged
const current = await apiClient.getUserSettings();
expect(current.settings.terminal_link_behavior).toBe("new_tab");
});
test("settings page shows terminal links card and allows toggling", async ({ testPage }) => {
await testPage.goto("/settings");
// Terminal Links section visible
await expect(testPage.locator("text=Terminal Links").first()).toBeVisible({ timeout: 10_000 });
// Select trigger is visible
const trigger = testPage.locator("#terminal-link-behavior");
await expect(trigger).toBeVisible();
// Switch to "Built-in browser panel"
await trigger.click();
const browserOption = testPage.getByRole("option", { name: "Built-in browser panel" });
await expect(browserOption).toBeVisible();
await browserOption.click();
await expect(trigger).toHaveText(/Built-in browser panel/);
// Switch back to "New browser tab"
await trigger.click();
const tabOption = testPage.getByRole("option", { name: "New browser tab" });
await expect(tabOption).toBeVisible();
await tabOption.click();
await expect(trigger).toHaveText(/New browser tab/);
});
});