testReleasesAnnounced

tcmts.cli.test.e2e.releases.testReleasesAnnounced · #eq3brsec · term

tcm release --announce: signed in once in the browser (the loopback OAuth client, against a fake network), the release's record is written to the author's repository, naming the namespace hash tcm lib add mounts; the sign-in is kept (and refreshed) for next time, as are the sources; a version is one record.

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 assert from "node:assert/strict";
import fs from "node:fs";
import path_1 from "node:path";

export const testReleasesAnnounced = () =>
  withChildren(async (keep) => {
    const alice = {
      did: "did:plc:alice000000000000000000",
      handle: "alice.test",
      password: "a-pass",
    };
    const net = await startFakeAtproto(keep, [alice]);
    const network = onFakeNetwork(keep, net);
    const home = network.home;
    const geo = codebase("announce");
    const tcm = (...args: string[]) => network.run(geo.dir, ...args);
    const ok = (...args: string[]) => network.ok(geo.dir, ...args);
    const record = (version: string) =>
      net.records.get(`at://${alice.did}/codes.tcm.release/geo:${version}`)?.value;
    geo.save(
      `// tcm: namespace geo\nexport const manifest = { name: "geo" };\nexport const area = (side: number) => side * side;\n`,
      "add",
    );

    // nowhere to fetch it from, or no one to announce it as: refused before anything's released
    assert.match(
      (await tcm("release", "geo@1.0.0", "--announce")).out,
      /announcing geo needs a URL it can be fetched from: --source <url>/,
    );
    geo.tcm("remote", "add", "origin", "http://127.0.0.1:1");
    assert.match(
      (await tcm("release", "geo@1.0.0", "--announce")).out,
      /sign in with --as <handle> \(once: it's kept for next time\)/,
    );
    assert.match(
      (await tcm("release", "--source", "https://x.example")).out,
      /give --announce too/,
    );
    assert.doesNotMatch(geo.tcm("releases"), /1\.0\.0/);

    // signed in in the browser, released, announced: from origin, which doesn't answer (said, not refused)
    const first = await ok("release", "geo@1.0.0", "--announce", "--as", "alice.test");
    assert.match(first, /signing in as alice\.test, in the browser/);
    assert.match(first, /released geo@1\.0\.0/);
    assert.match(
      first,
      /announced geo@1\.0\.0 as @alice\.test: at:\/\/did:plc:alice0+\/codes\.tcm\.release\/geo:1\.0\.0/,
    );
    assert.match(
      first,
      /fetched from http:\/\/127\.0\.0\.1:1\n {2}http:\/\/127\.0\.0\.1:1 didn't answer/,
    );
    assert.equal(net.oauth.signIns, 1);
    const r1 = record("1.0.0")!;
    assert.equal(r1.$type, "codes.tcm.release");
    assert.deepEqual(r1.sources, ["http://127.0.0.1:1"]);
    assert.equal(r1.hashFormat, 2);
    assert.match(String(r1.notes), /^## 1\.0\.0/m);
    assert.ok(!Number.isNaN(Date.parse(String(r1.createdAt))));
    // (the namespace is the one `tcm lib add` mounts for that release)
    const user = codebase("announce user");
    user.save(`// tcm: namespace app\nexport const x = 1;\n`, "add");
    user.tcm("lib", "add", geo.dir, "geo@1.0.0");
    assert.equal(
      r1.namespace,
      /"namespace": "(\w+)"/.exec(user.tcm("view", "app.lib.libraries"))![1],
    );
    // (kept for you alone)
    const kept = path_1.join(home, "tcm", "atproto.json");
    if (process.platform !== "win32") assert.equal(fs.statSync(kept).mode & 0o777, 0o600);

    // the next release: no sign-in (it's kept), sources given (and kept)
    geo.save(`// tcm: namespace geo\nexport const cube = (side: number) => side ** 3;\n`, "add");
    const second = await ok("release", "--announce", "--source", "https://mirror.example");
    assert.doesNotMatch(second, /signing in/);
    assert.match(second, /announced geo@1\.1\.0 as @alice\.test/);
    assert.equal(net.oauth.signIns, 1);
    assert.deepEqual(record("1.1.0")!.sources, ["https://mirror.example"]);

    // its tokens expired, they're refreshed; announced again as it is, nothing changes
    const sessions = JSON.parse(fs.readFileSync(kept, "utf8")) as {
      sessions: Record<string, { expiresAt: number }>;
    };
    sessions.sessions[alice.did]!.expiresAt = 0;
    fs.writeFileSync(kept, JSON.stringify(sessions));
    assert.match(
      await ok("release", "geo@1.1.0", "--announce"),
      /geo@1\.1\.0 is already announced as @alice\.test, as it is/,
    );
    assert.equal(net.oauth.refreshes, 1);
    assert.equal(net.oauth.signIns, 1);

    // an existing version, announced with other sources: the same record, with its sources now
    assert.match(
      await ok("release", "geo@1.0.0", "--announce"),
      /announced again geo@1\.0\.0 as @alice\.test \(with its sources now\)/,
    );
    assert.deepEqual(record("1.0.0")!.sources, ["https://mirror.example"]);
    assert.equal(record("1.0.0")!.namespace, r1.namespace);

    // a version names one release: a record saying otherwise isn't overwritten
    record("1.0.0")!.namespace = "elsewhere";
    assert.match(
      (await tcm("release", "geo@1.0.0", "--announce")).out,
      /already announces geo@1\.0\.0 as #elsewhere, not #\w+: a version names one release/,
    );
  })

uses