import { expect, mock, test } from "bun:test"; // Deliberately the PACKAGE ENTRY POINT, not the modules behind it: this is the // surface an application gets, and it must be usable on its own. It pulls in // `polyfill-adapter.ts`, so this also proves the real `@ng-eventually/polyfill` // still loads and still exports everything this package compiles against. import * as published from "../src/index"; import { ENTRY_VALUE, INDEX_FIELD, indexing } from "../src/index"; import { indexingOn } from "../src/indexing"; import { FakeNextGraph, publishObject } from "./fake-nextgraph"; const PUBLISHED_AT = "http://schema.org/datePublished"; test("the published surface carries both acts, end to end", async () => { const network = new FakeNextGraph(); const ownerPort = network.portFor("alice"); const strangerPort = network.portFor("bob"); // `indexingOn` is what `indexing(sessionId)` calls once it has built the port for // you: the two acts below are the published ones, reached here over an in-memory // NextGraph. `adapter.test.ts` drives these same acts through the real adapter. const owner = indexingOn(ownerPort); const stranger = indexingOn(strangerPort); const index = await owner.create(PUBLISHED_AT); const article = await publishObject(strangerPort, PUBLISHED_AT, "2026-07-08"); await stranger.add(index, article); // What the two acts leave behind, and the whole of it: a document declaring its // field, and a bare reference waiting in its inbox. Making an entry of that // reference is the business of the layer below, and there is nothing on this // surface that does it or asks for it. expect(network.contentsOf(index)).toEqual([ { subject: index, predicate: INDEX_FIELD, values: [PUBLISHED_AT] }, ]); expect(network.depositsIn(index)?.map((deposit) => deposit.payload)).toEqual([article]); }); test("the published surface offers TWO acts, and neither reads nor processes anything", () => { const handle = indexingOn(new FakeNextGraph().portFor("alice")); // Read off the handle rather than from a list: an application gets these two acts // and nothing else. Reading an index is not one of them, and neither is anything // that would make its deposits into entries. expect(Object.keys(handle).sort()).toEqual(["add", "create"]); }); test("the package publishes ONE function and the two IRIs, and nothing else", () => { // Read off the module rather than from a list of names to remember: publishing a // helper again — a port builder, a deposit decoder, a read — fails here first. expect(Object.keys(published).sort()).toEqual(["ENTRY_VALUE", "INDEX_FIELD", "indexing"]); expect(INDEX_FIELD).toBe("urn:ng-helpers:index:field"); expect(ENTRY_VALUE).toBe("urn:ng-helpers:index:value"); }); test("indexing takes a session id and reaches nothing at all", () => { // The REAL polyfill, unconfigured — which would fail every call that needs a // broker. Building the handle does not make one, so this passes without any // arrangement, and there is nothing on the log stream to report. It also proves // the entry point builds its own port: an application hands over the session id // `init(…)` gave it, and never sees a port at all. const reported = mock((..._args: unknown[]) => {}); const original = console.error; console.error = reported; try { const handle = indexing("session-under-test"); expect(Object.keys(handle).sort()).toEqual(["add", "create"]); } finally { console.error = original; } expect(reported).not.toHaveBeenCalled(); });