char-slop/berry

multipurpose self-modifiable agentic harness

git clone https://git.t4t.associates/char-slop/berry

Charlotte Somtests: drop those that only pin what the UI shows, and assertions on its own wording6f4605c

main
2.8 KiB81 linesraw
1import { assert, assertEquals } from "@std/assert";
2import { until } from "@berry/util";
3import { viewContext, withDom } from "@berry/util/dom.ts";
4import type { ViewContext } from "@berry/api/web.ts";
5import { browserView } from "./view.ts";
6import type { BrowserViewData, Snapshot } from "./types.ts";
7
8const page = (tab: string, title: string): Snapshot => ({
9  tab,
10  title,
11  url: "https://example.com/",
12  text: `<script>untrusted()</script> ${title}`,
13  elements: [{ ref: "e1", role: "button", name: "Continue" }],
14  truncated: false,
15  frames: [],
16  diagnostics: ["HTTP 404: https://example.com/missing"],
17});
18const context = (request: ViewContext["request"], latest = 1) =>
19  viewContext({ tid: "conversation", latest, request });
20
21Deno.test("the close button ends a live session and then shows it as ended", () =>
22  withDom(async () => {
23    const view = browserView();
24    const requests: string[] = [];
25    let active = true;
26    view.update(context((name) => {
27      requests.push(name);
28      if (name === "close") active = false;
29      return Promise.resolve(
30        name === "close"
31          ? null
32          : { active, tabs: [page("t1", "First")], history: [], screenshots: [] },
33      );
34    }));
35    try {
36      const close = [...view.element.querySelectorAll("button")]
37        .find((button) => button.textContent === "Close browser") as HTMLButtonElement;
38      await until(() => !close.disabled);
39      close.click();
40      await until(() =>
41        view.element.querySelector('[role="status"]')?.textContent?.includes("historical") ?? false
42      );
43      assertEquals(requests, ["view", "close", "view"]);
44      assert(close.disabled);
45    } finally {
46      view.dispose?.();
47    }
48  }));
49
50Deno.test("outdated view responses and disposed requests cannot replace the current conversation", () =>
51  withDom(async () => {
52    const view = browserView();
53    let resolveOld!: (value: BrowserViewData) => void;
54    let oldSignal!: AbortSignal;
55    const old = context((_, __, options) => {
56      oldSignal = options!.signal!;
57      return new Promise<BrowserViewData>((resolve) => {
58        resolveOld = resolve;
59      });
60    });
61    view.update(old);
62    const fresh: BrowserViewData = {
63      active: true,
64      tabs: [page("t8", "Current")],
65      history: [],
66      screenshots: [],
67    };
68    view.update({ ...context(() => Promise.resolve(fresh)), tid: "another" });
69    await until(() => view.element.textContent?.includes("Current") ?? false);
70    assert(oldSignal.aborted);
71    resolveOld({ active: false, tabs: [page("t1", "Outdated")], history: [], screenshots: [] });
72    await Promise.resolve();
73    assert(!view.element.textContent?.includes("Outdated"));
74    let signal!: AbortSignal;
75    view.update(context((_, __, options) => {
76      signal = options!.signal!;
77      return new Promise(() => {});
78    }, 3));
79    view.dispose?.();
80    assert(signal.aborted);
81  }));