testLibrariesFromAnnouncements

tcmts.cli.test.e2e.libraries.testLibrariesFromAnnouncements · #2mmwejx4 · term

a library from a release its author announced: @handle/geo@1.0.0 is found among their records, fetched by hash from the servers the record names, and kept by their DID, so an upgrade reads their announcements (and nobody's who takes the handle after)

import { startFakeAtproto } from "#codebase/tcmts/cli/test/e2e/examples";
import { withChildren } from "#codebase/tcmts/cli/test/e2e/harness";
import { codebase, onFakeNetwork } from "#codebase/tcmts/cli/test/e2e/releases";
import { startServerInfo } from "#codebase/tcmts/cli/test/e2e/sync";
import assert from "node:assert/strict";

export const testLibrariesFromAnnouncements = () =>
  withChildren(async (keep) => {
    const alice = {
      did: "did:plc:alice000000000000000000",
      handle: "alice.test",
      password: "a-pass",
    };
    const mallory = {
      did: "did:plc:mallory0000000000000000",
      handle: "mallory.test",
      password: "m-pass",
    };
    const net = await startFakeAtproto(keep, [alice, mallory]);
    const { run, ok } = onFakeNetwork(keep, net);
    const geo = codebase("announced geo");
    geo.save(
      `// tcm: namespace geo\nexport const manifest = { name: "geo" };\nexport const area = (side: number) => side * side;\n`,
      "add",
    );
    const server = (await startServerInfo(keep, geo.dir, "tok", "--public")).url;
    await ok(
      geo.dir,
      "release",
      "geo@1.0.0",
      "--announce",
      "--as",
      "alice.test",
      "--source",
      server,
    );

    const me = codebase("announced me");
    me.save(`// tcm: namespace app\nexport const total = () => 1;\n`, "add");
    const added = await ok(me.dir, "lib", "add", "@alice.test/geo@1.0.0");
    assert.match(
      added,
      /added app\.lib\.geo: geo@1\.0\.0 by @alice\.test from http:\/\/127\.0\.0\.1:\d+ \(\d+ names; \d+ definitions received, verified by re-hashing\)/,
    );
    const entry = me.tcm("view", "app.lib.libraries");
    assert.match(entry, new RegExp(`"did": "${alice.did}"`));
    assert.match(entry, /"handle": "alice\.test"/);
    assert.match(entry, /"sources": \[\s*"http:\/\/127\.0\.0\.1:\d+"\s*\]/);
    assert.match(
      me.tcm("lib"),
      /app\.lib\.geo {2}geo@1\.0\.0 {2}by @alice\.test, from http:\/\/127\.0\.0\.1:\d+ · /,
    );

    // a newer release, announced: the upgrade finds it among hers
    geo.save(`// tcm: namespace geo\nexport const cube = (side: number) => side ** 3;\n`, "add");
    await ok(geo.dir, "release", "--announce");
    assert.match(
      await ok(me.dir, "lib", "upgrade", "geo"),
      /geo@1\.0\.0 → geo@1\.1\.0: additions[\s\S]*upgraded app\.lib\.geo to geo@1\.1\.0/,
    );

    // the handle changes hands: upgrades still read her announcements, by her DID, not the new holder's
    alice.handle = "alice-new.test";
    mallory.handle = "alice.test";
    net.seed(mallory.did, "codes.tcm.release", "geo:9.0.0", {
      package: "geo",
      version: "9.0.0",
      namespace: "notalice",
      entry: "x",
      hashFormat: 2,
      notes: "",
      sources: [server],
      createdAt: new Date().toISOString(),
    });
    assert.match(await ok(me.dir, "lib", "upgrade", "geo"), /app\.lib\.geo is geo@1\.1\.0 already/);
    // (adding by the handle now is the new holder's, and no source has what she claims)
    assert.match(
      (await run(me.dir, "lib", "add", "@alice.test/geo", "--at", "app.other")).out,
      /no source has #notalice/,
    );

    // what isn't announced
    assert.match(
      (await run(me.dir, "lib", "add", "@alice-new.test/nothing", "--at", "app.x")).out,
      /@alice-new\.test hasn't announced any releases of nothing/,
    );
    assert.match(
      (await run(me.dir, "lib", "add", "@alice-new.test/geo@3.0.0", "--at", "app.x")).out,
      /@alice-new\.test hasn't announced geo@3\.0\.0; they've announced 1\.1\.0, 1\.0\.0/,
    );
    assert.match(
      (await run(me.dir, "lib", "add", "@nobody.test/geo", "--at", "app.x")).out,
      /nobody\.test/,
    );
  })

uses