fast-browser-with-jev
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { getSettingsListTheme, initTheme } from "@earendil-works/pi-coding-agent";
|
||||
import { SettingsList, visibleWidth } from "@earendil-works/pi-tui";
|
||||
import {
|
||||
FAST_BROWSER_SETTING_IDS,
|
||||
FAST_BROWSER_SETTING_LABELS,
|
||||
FastBrowserSettingsView,
|
||||
buildFastBrowserSettingItems,
|
||||
fastBrowserSettingValue,
|
||||
} from "./settings-view.ts";
|
||||
|
||||
const stripAnsi = (value: string): string => value.replace(/\u001b\[[0-9;]*m/g, "");
|
||||
|
||||
test.before(() => initTheme("dark", false));
|
||||
|
||||
function options(
|
||||
draft: Record<string, unknown> = {},
|
||||
inherited: Record<string, unknown> = {},
|
||||
onEvent: (event: any) => void = () => {},
|
||||
) {
|
||||
return {
|
||||
scope: "project" as const,
|
||||
draft,
|
||||
inherited,
|
||||
onEvent,
|
||||
};
|
||||
}
|
||||
|
||||
test("renders native SettingsList values subdued on the right", () => {
|
||||
const view = new FastBrowserSettingsView(options(
|
||||
{ cdpUrl: "http://127.0.0.1:9333" },
|
||||
{ allowedOrigins: ["https://example.test"], textModel: "fixture/small" },
|
||||
));
|
||||
const lines = view.render(80);
|
||||
const endpoint = lines.find((line) => stripAnsi(line).includes("CDP endpoint"));
|
||||
assert(endpoint);
|
||||
assert.match(stripAnsi(endpoint), /CDP endpoint\s+http:\/\/127\.0\.0\.1:9333/);
|
||||
// The native theme wraps an unselected value in its muted ANSI color.
|
||||
assert.match(endpoint, /\u001b\[[0-9;]*mhttp:\/\/127\.0\.0\.1:9333\u001b\[[0-9;]*m/);
|
||||
|
||||
const inherited = fastBrowserSettingValue(
|
||||
FAST_BROWSER_SETTING_IDS.textModel,
|
||||
{},
|
||||
{ textModel: "fixture/small" },
|
||||
);
|
||||
assert.equal(inherited, "(inherited) fixture/small");
|
||||
});
|
||||
|
||||
test("displays unrestricted origin policy and inherited default values", () => {
|
||||
assert.equal(fastBrowserSettingValue(
|
||||
FAST_BROWSER_SETTING_IDS.allowedOrigins,
|
||||
{ allowedOrigins: "*" },
|
||||
{},
|
||||
), "All web origins");
|
||||
assert.equal(fastBrowserSettingValue(
|
||||
FAST_BROWSER_SETTING_IDS.allowedOrigins,
|
||||
{},
|
||||
{ allowedOrigins: "*" },
|
||||
), "(inherited) All web origins");
|
||||
});
|
||||
|
||||
test("shows named profiles as explicit or inherited browser settings", () => {
|
||||
const explicit = fastBrowserSettingValue(
|
||||
FAST_BROWSER_SETTING_IDS.browserProfile,
|
||||
{ browser: { mode: "launch", profile: "evebot" } },
|
||||
{},
|
||||
);
|
||||
const inherited = fastBrowserSettingValue(
|
||||
FAST_BROWSER_SETTING_IDS.browserProfile,
|
||||
{},
|
||||
{ browser: { mode: "launch", profile: "global-profile" } },
|
||||
);
|
||||
assert.equal(explicit, "evebot");
|
||||
assert.equal(inherited, "(inherited) global-profile");
|
||||
});
|
||||
|
||||
test("updates displayed rows with the latest draft after an edit", () => {
|
||||
const draft: Record<string, unknown> = {};
|
||||
const inherited = { textModel: "global/model" };
|
||||
const view = new FastBrowserSettingsView(options(draft, inherited));
|
||||
const before = view.render(80).join("\n");
|
||||
assert.match(stripAnsi(before), /Auxiliary text model\s+\(inherited\) global\/model/);
|
||||
draft.textModel = "project/model";
|
||||
view.updateValues(draft, inherited);
|
||||
const after = view.render(80).join("\n");
|
||||
assert.match(stripAnsi(after), /Auxiliary text model\s+project\/model/);
|
||||
});
|
||||
|
||||
test("keeps long URLs, paths, and CJK labels within narrow terminal widths", () => {
|
||||
const view = new FastBrowserSettingsView(options(
|
||||
{
|
||||
cdpUrl: "http://127.0.0.1:9222",
|
||||
python: "/very/long/path/项目/with/a/credential-free/python-executable",
|
||||
browser: {
|
||||
mode: "launch",
|
||||
product: "chromium",
|
||||
executablePath: "/very/long/path/项目/with/a/browser-executable",
|
||||
startUrl: "https://example.test/非常長い開始URL/with/more/path",
|
||||
},
|
||||
},
|
||||
{ allowedOrigins: ["https://example.test/非常長い起点"] },
|
||||
));
|
||||
for (const width of [60, 80, 120]) {
|
||||
for (const line of view.render(width)) assert(visibleWidth(line) <= width, `${width}: ${stripAnsi(line)}`);
|
||||
}
|
||||
});
|
||||
|
||||
test("dispatches by stable id even when a displayed label changes", () => {
|
||||
const events: any[] = [];
|
||||
const items = buildFastBrowserSettingItems(options({}, {}, (event) => events.push(event)));
|
||||
const first = items.find((item) => item.id === FAST_BROWSER_SETTING_IDS.cdpUrl);
|
||||
assert(first);
|
||||
first.label = "Endpoint label changed";
|
||||
const list = new SettingsList(items, 10, getSettingsListTheme(), (id) => {
|
||||
events.push({ kind: "edit", id });
|
||||
}, () => {});
|
||||
list.handleInput("\r");
|
||||
assert.deepEqual(events, [{ kind: "edit", id: FAST_BROWSER_SETTING_IDS.cdpUrl }]);
|
||||
assert.equal(FAST_BROWSER_SETTING_LABELS.cdpUrl, "CDP endpoint");
|
||||
});
|
||||
|
||||
test("does not render explicit save or discard actions", () => {
|
||||
const labels = buildFastBrowserSettingItems(options()).map((item) => item.label);
|
||||
assert(!labels.includes("Save settings"));
|
||||
assert(!labels.includes("Cancel"));
|
||||
const view = new FastBrowserSettingsView(options());
|
||||
assert.match(stripAnsi(view.render(120).join("\n")), /Changes save automatically/);
|
||||
});
|
||||
|
||||
test("Escape dispatches cancel without mutating the draft", () => {
|
||||
const draft = { textModel: "keep-me" };
|
||||
const events: any[] = [];
|
||||
const view = new FastBrowserSettingsView(options(draft, {}, (event) => events.push(event)));
|
||||
view.handleInput("\u001b");
|
||||
assert.deepEqual(events, [{ kind: "cancel" }]);
|
||||
assert.deepEqual(draft, { textModel: "keep-me" });
|
||||
});
|
||||
Reference in New Issue
Block a user