import { assertEquals } from "@std/assert"; import type { View } from "@berry/api/web.ts"; import { viewContext, withDom } from "@berry/util/dom.ts"; import { extensionView, viewHref, viewRoute } from "./views.ts"; Deno.test("a view opens with its route, follows it and new entries, and is disposed as it closes", () => withDom(() => { const events: string[] = []; const factory = (name: string) => (): View => { events.push(`${name}:create`); const element = document.createElement("section"); return { element, update: ({ route, latest }) => events.push(`${name}:${route}@${latest}:${element.isConnected ? "shown" : "unshown"}`), dispose: () => events.push(`${name}:dispose`), }; }; const diff = { name: "diff", create: factory("diff") }; const context = viewContext({ tid: "test", latest: 1 }); const pane = extensionView(); document.body.append(pane.element); assertEquals(pane.element.hidden, true); pane.update(diff, context); assertEquals(pane.element.hidden, false); // a conversation draws again as it streams, without anything the view shows changing pane.update(diff, { ...context }); pane.update(diff, { ...context, route: "abc" }); pane.update(diff, { ...context, route: "abc", latest: 2 }); pane.update({ name: "diff", create: factory("reloaded") }, context); pane.update(null, context); assertEquals(pane.element.hidden, true); assertEquals(pane.element.childNodes.length, 0); pane.update({ name: "diff", create: null }, context); pane.dispose(); assertEquals(events, [ "diff:create", "diff:@1:unshown", "diff:abc@1:shown", "diff:abc@2:shown", "diff:dispose", "reloaded:create", "reloaded:@1:unshown", "reloaded:dispose", ]); })); Deno.test("a view's route survives its address, whatever it holds", () => { for (const route of ["", "abc", "a b/c%d", "x/#y?z", "ünï/cødé"]) { const href = viewHref("3mxd6epszps5d", "diff", route); const escaped = href.match(/^#\/3mxd6epszps5d\/diff\/?(.*)$/)![1]; assertEquals(viewRoute(escaped), route); } }); Deno.test("flush reaches the open view, and is a no-op without one", () => withDom(async () => { const pane = extensionView(); document.body.append(pane.element); assertEquals(await pane.flush(), undefined); let flushed = 0; const element = document.createElement("section"); const view: View = { element, update: () => {}, flush: () => { flushed++; return Promise.resolve(); }, }; const context = viewContext({ tid: "test", latest: 1 }); pane.update({ name: "diff", create: () => view }, context); await pane.flush(); assertEquals(flushed, 1); pane.update(null, context); assertEquals(await pane.flush(), undefined); pane.dispose(); }));