Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

133 lines
3.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type {
BrowserNodeChromeImportPromptAdapter,
BrowserNodeEvent,
BrowserNodeHostApi
} from "@tutti-os/browser-node";
import type { I18nRuntime } from "@tutti-os/ui-i18n-runtime";
import { createAgentToolBrowserFeature } from "./AgentToolBrowserPanel.tsx";
import { createAgentToolBrowserPage } from "./agentToolBrowserPage.ts";
describe("AgentToolBrowserPanel", () => {
it("scopes host events to its browser surface and child tabs", () => {
let emitEvent = (_event: BrowserNodeEvent): void => undefined;
const feature = createAgentToolBrowserFeature({
browserApi: createBrowserApi((listener) => {
emitEvent = listener;
}),
i18n: { t: (key) => key } as I18nRuntime<string>,
nodeId: "browser:agent-tool:one"
});
const disconnect = feature.connect();
emitEvent(
createStateEvent("browser:another-window", "https://other.test/")
);
expect(
feature.runtimeStore.getNodeState("browser:agent-tool:one").url
).toBeNull();
emitEvent(
createStateEvent("browser:agent-tool:one:tab:1", "https://tutti.app/")
);
expect(
feature.runtimeStore.getNodeState("browser:agent-tool:one:tab:1").url
).toBe("https://tutti.app/");
expect(feature.resolveAddressInput("browser tool").url).toBe(
"https://www.google.com/search?q=browser+tool"
);
disconnect();
});
it("forwards the host-owned Chrome import prompt adapter", () => {
const prompt: BrowserNodeChromeImportPromptAdapter = {
dismiss() {},
isDismissed: () => false,
subscribe: () => () => undefined
};
const browserApi = createBrowserApi(() => undefined);
browserApi.cancelChromeCookieImport = async () => undefined;
browserApi.discoverChromeCookieProfiles = async () => ({
profiles: [],
status: "available"
});
browserApi.importChromeCookies = async () => ({
canceled: false,
failed: 0,
imported: 0,
partial: false,
skipped: 0,
status: "completed"
});
const feature = createAgentToolBrowserFeature({
browserApi,
chromeCookieImportPrompt: prompt,
i18n: { t: (key) => key } as I18nRuntime<string>,
nodeId: "browser:agent-tool:one"
});
expect(feature.chromeCookieImport?.prompt).toBe(prompt);
});
it("materializes an automation-created about:blank page", () => {
const feature = createAgentToolBrowserFeature({
browserApi: createBrowserApi(() => undefined),
i18n: { t: (key) => key } as I18nRuntime<string>,
nodeId: "browser:agent-tool:one"
});
const nodeId = createAgentToolBrowserPage(
feature,
"browser:agent-tool:one",
"about:blank",
null
);
expect(nodeId).toBe("browser:agent-tool:one:tab:1");
expect(
feature.tabsStore.getSurfaceState("browser:agent-tool:one")?.tabs
).toEqual([
expect.objectContaining({
materializeCold: true,
nodeId
})
]);
});
});
function createBrowserApi(
subscribe: (listener: (event: BrowserNodeEvent) => void) => void
): BrowserNodeHostApi {
return {
activate: async () => undefined,
close: async () => undefined,
goBack: async () => undefined,
goForward: async () => undefined,
navigate: async () => undefined,
onEvent(listener) {
subscribe(listener);
return () => undefined;
},
prepareSession: async () => undefined,
registerGuest: async () => undefined,
reload: async () => undefined,
unregisterGuest: async () => undefined
};
}
function createStateEvent(nodeId: string, url: string): BrowserNodeEvent {
return {
canGoBack: false,
canGoForward: false,
isLoading: false,
isOccluded: false,
lifecycle: "active",
nodeId,
title: null,
type: "state",
url
};
}