Ctrl K
ComunidadGuías…

electron/cloud-provider-move.node-test.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import assert from "node:assert/strict";
import test from "node:test";

import { parseCloudSummary } from "./cloud-home.mjs";
import { myCloudOf, parseCloudList, withoutOldCloudHome } from "./cloud-list.mjs";
import { homeOf } from "./home-window.mjs";
import { createOneHome } from "./one-home.mjs";
import { oneHomeCloud } from "./one-home-main.mjs";

// My Cloud moves to another provider: the same Cloud (its id) answers at a new address, and the Admin lists the old one
// among its `formerOrigins`. A computer whose bots moved to it keeps them there, follows it, and never brings them back,
// which would run them in two places; a Cloud that truly is another still ends the move as before. Every side is faked;
// nothing reaches the network or the disk.
const OLD = "https://omb-u-1a2b3c4d5e6f.fly.dev", NEW = "https://omb-u-1a2b3c4d5e6f.homes.example", OTHER = "https://omb-u-other.homes.example";
const reply = (status, body = {}) => ({ ok: status < 400, status, body });

function computer({ journal, cloud = {}, admin = {} }) {
  const w = {
    journal, admin, asked: [], opened: [], logged: [],
    server: { marker: { frozen: true, cloud: OLD }, thaws: [], frozenFor: [] },
    cloud: { origin: NEW, account: "acct-1", machine: NEW, ready: true, moves: true, ended: false, paid: true, verified: true, ...cloud },
  };
  w.home = createOneHome({
    journal: { read: () => structuredClone(w.journal), write: (value) => { w.journal = structuredClone(value); } },
    cloud: () => ({ ...w.cloud }),
    gone: async (origin) => { w.asked.push(origin); return w.admin[origin] ?? null; },
    send: { move: async () => {}, check: async () => ({ ok: true }), switches: () => ({}), snapshot: () => ({ running: null }) },
    local: {
      async freeze(origin) { w.server.frozenFor.push(origin); w.server.marker = { frozen: true, cloud: origin }; return { frozen: true }; },
      async unfreeze(options) { w.server.thaws.push(options ?? null); w.server.marker = { frozen: false }; },
      frozen: async () => Boolean(w.server.marker.frozen),
      marker: async () => structuredClone(w.server.marker),
      json: async (route) => (route.startsWith("/api/bots") ? { bots: [] } : { items: [], conversations: [], automations: [] }),
      call: async () => reply(200),
    },
    session: async () => ({ call: async () => reply(200, { v: 1 }), close: async () => {} }),
    openHome: () => w.opened.push("cloud"),
    openLocal: () => w.opened.push("local"),
    lastInput: () => 0,
    version: "0.1.151",
    now: () => 2_000_000,
    log: (line) => w.logged.push(line),
    timers: { set: () => ({}), clear: () => {} },
  });
  return w;
}

const movedTo = (origin, extra = {}) => ({ origin, account: "acct-1", machine: origin, ...extra });
const doneTo = (cloud) => ({ v: 1, phase: "done", cloud, startedAt: 1_000, doneAt: 1_500, frozenAt: 1_400, version: "0.1.151", lent: true });

test("a done move keyed by the Cloud's id follows it to its new address and stays done: nothing comes home, nothing is asked", async () => {
  const w = computer({ journal: doneTo(movedTo(OLD, { id: "c-home" })), cloud: { id: "c-home" } });
  await w.home.kick();
  assert.equal(w.journal.phase, "done");
  assert.deepEqual(w.journal.cloud, movedTo(NEW, { id: "c-home" }));
  assert.deepEqual([w.server.thaws, w.opened, w.asked], [[], [], []], "the freeze stays, the window stays, the Admin isn't asked whether it is gone");
  assert.equal(w.server.marker.frozen, true);
  assert.equal(w.logged.filter((line) => line.includes("new address")).length, 1);
  await w.home.kick();
  assert.deepEqual([w.journal.phase, w.journal.cloud.origin, w.server.thaws], ["done", NEW, []], "and on every run after");
});

test("a journal from before ids were kept is known again by the address the Cloud had before, and keeps its id from then on", async () => {
  const w = computer({ journal: doneTo(movedTo(OLD)), cloud: { id: "c-home", formerOrigins: [OLD] } });
  await w.home.kick();
  assert.equal(w.journal.phase, "done");
  assert.deepEqual(w.journal.cloud, movedTo(NEW, { id: "c-home" }));
  assert.deepEqual([w.server.thaws, w.opened], [[], []]);
  const without = computer({ journal: doneTo(movedTo(OLD)), cloud: { formerOrigins: [OLD] } });
  await without.home.kick();
  assert.deepEqual(without.journal.cloud, movedTo(NEW), "an Admin that lists no id: the address alone, and no id is made up");
});

test("a move under way follows the Cloud too, so the freeze names its new address", async () => {
  const w = computer({ journal: { v: 1, phase: "wait", cloud: movedTo(OLD), startedAt: 1_000 }, cloud: { id: "c-home", formerOrigins: [OLD] } });
  w.server.marker = { frozen: false };
  await w.home.kick();
  assert.deepEqual(w.server.frozenFor, [NEW]);
  assert.equal(w.journal.cloud.origin, NEW);
  assert.equal(w.journal.phase, "done");
});

test("the id is kept once the session lists it, even before the Cloud ever moves", async () => {
  const w = computer({ journal: doneTo(movedTo(NEW)), cloud: { id: "c-home" } });
  await w.home.kick();
  assert.deepEqual(w.journal.cloud, movedTo(NEW, { id: "c-home" }));
  const fresh = computer({ journal: null, cloud: { id: "c-home" } });
  fresh.server.marker = { frozen: false };
  await fresh.home.kick();
  assert.equal(fresh.journal.cloud.id, "c-home", "a new move keeps the id from its start");
});

test("a Cloud that truly is another still counts as ended: a move not switched yet stops, and a done one comes home on the Admin's word", async () => {
  // Another id, another address, and the journal's address not among the ones it had before.
  const other = { origin: OTHER, machine: OTHER, id: "c-other", formerOrigins: ["https://omb-u-other.fly.dev"] };
  const moving = computer({ journal: { v: 1, phase: "copy", cloud: movedTo(OLD, { id: "c-home" }), startedAt: 1_000 }, cloud: other });
  moving.server.marker = { frozen: false };
  await moving.home.kick();
  assert.equal(moving.journal, null, "the move to the old Cloud stops: nothing runs there yet");
  const done = computer({ journal: doneTo(movedTo(OLD, { id: "c-home" })), cloud: other, admin: { [OLD]: "deleted" } });
  await done.home.kick();
  assert.deepEqual(done.asked, [OLD], "the Admin is asked about the Cloud this computer moved to, at its own address");
  assert.equal(done.journal.phase, "back");
  assert.equal(done.journal.gone, "deleted");
  assert.deepEqual(done.server.thaws, [{ automations: "off" }]);
  const waiting = computer({ journal: doneTo(movedTo(OLD, { id: "c-home" })), cloud: other });
  await waiting.home.kick();
  assert.deepEqual([waiting.journal.phase, waiting.journal.cloud.origin, waiting.server.thaws], ["done", OLD, []], "no word from the Admin: it stays, and is not followed");
  const sameAddress = computer({ journal: doneTo(movedTo(OLD, { id: "c-home" })), cloud: { origin: OTHER, machine: OTHER, id: "c-other" }, admin: { [OLD]: "ended" } });
  await sameAddress.home.kick();
  assert.equal(sameAddress.journal.gone, "ended", "an id of its own is no sign of being the same Cloud");
  const twoIds = computer({ journal: doneTo(movedTo(OLD, { id: "c-home" })), cloud: { ...other, formerOrigins: [OLD] }, admin: { [OLD]: "deleted" } });
  await twoIds.home.kick();
  assert.equal(twoIds.journal.gone, "deleted", "an old address listed for a Cloud with another known id never makes it this journal's");
});

test("the same Cloud that moved and then ended still brings this computer home, as My Cloud ending always has", async () => {
  const w = computer({ journal: doneTo(movedTo(OLD, { id: "c-home" })), cloud: { id: "c-home", ended: true, ready: false } });
  await w.home.kick();
  assert.equal(w.journal.cloud.origin, NEW, "its things come home from where it is now");
  assert.equal(w.journal.phase, "back");
  assert.deepEqual(w.server.thaws, [null]);
});

test("nobody else's word moves a journal: a session not verified, or another account's", async () => {
  for (const cloud of [{ id: "c-home", formerOrigins: [OLD], verified: false }, { id: "c-home", formerOrigins: [OLD], account: "acct-2" }]) {
    const w = computer({ journal: doneTo(movedTo(OLD, { id: "c-home" })), cloud });
    await w.home.kick();
    assert.equal(w.journal.cloud.origin, OLD, JSON.stringify(cloud));
    assert.deepEqual(w.server.thaws, [], JSON.stringify(cloud));
  }
});

test("a freeze with no journal that names the Cloud's old address is My Cloud's, never asked about as another", async () => {
  const w = computer({ journal: null, cloud: { id: "c-home", formerOrigins: [OLD] }, admin: { [OLD]: "deleted" } });
  await w.home.kick();
  assert.deepEqual([w.asked, w.server.thaws], [[], []]);
});

const session = ({ machine = {}, clouds } = {}) => ({
  status: "connected", account: { id: "acct-1" }, entitlement: { status: "active" },
  machine: { status: "ready", origin: NEW, ...machine },
  ...(clouds ? { clouds } : {}),
});
const listed = (over = {}) => ({ id: "c-home", name: "My Cloud", color: null, role: "owner", tier: "pro", runsOn: "cloud", status: "ready", origin: NEW, teamId: null, primary: true, managed: true, ...over });

test("the Admin's formerOrigins are read beside a Cloud's origin, strictly, and an Admin without them reads as before", () => {
  assert.deepEqual(parseCloudSummary({ state: "ready", origin: NEW, formerOrigins: [OLD, OLD, NEW, "http://omb-u-x.fly.dev", `${OLD}/path`, 7, null] }),
    { status: "ready", origin: NEW, formerOrigins: [OLD] });
  assert.deepEqual(parseCloudSummary({ state: "ready", origin: NEW }), { status: "ready", origin: NEW });
  for (const formerOrigins of [OLD, {}, [], ["nope"]]) assert.deepEqual(parseCloudSummary({ state: "ready", origin: NEW, formerOrigins }), { status: "ready", origin: NEW }, JSON.stringify(formerOrigins));
  const [entry] = parseCloudList([{ ...listed(), formerOrigins: [OLD, "ftp://x.example"] }]);
  assert.deepEqual(entry.formerOrigins, [OLD]);
  assert.equal("formerOrigins" in parseCloudList([listed()])[0], false);
});

test("My Cloud's identity: its id from the list at its address, and every address it had before, the summary's and the list's", () => {
  assert.deepEqual(myCloudOf(session({ machine: { formerOrigins: [OLD] }, clouds: [listed({ formerOrigins: ["https://omb-u-older.fly.dev"] })] })),
    { origin: NEW, id: "c-home", formerOrigins: [OLD, "https://omb-u-older.fly.dev"] });
  assert.deepEqual(myCloudOf(session({ clouds: [listed({ origin: OTHER })] })), { origin: NEW, id: null, formerOrigins: [] }, "an id only from the Cloud at its address");
  assert.deepEqual(myCloudOf(session({ clouds: [listed({ role: "member" })] })).id, null, "never a team's");
  assert.equal(myCloudOf({ status: "unavailable", machine: { status: "ready", origin: NEW } }), null, "only a verified session's word");
  const cloud = oneHomeCloud(session({ machine: { formerOrigins: [OLD] }, clouds: [listed()] }));
  assert.deepEqual([cloud.id, cloud.formerOrigins, cloud.origin], ["c-home", [OLD], NEW]);
});

test("the window opens My Cloud at its new address for a journal or a freeze kept at its old one, and nothing else changes", () => {
  const state = session({ machine: { formerOrigins: [OLD] }, clouds: [listed()] });
  assert.deepEqual(homeOf({ journal: doneTo(movedTo(OLD)), state }), { kind: "cloud", origin: NEW });
  assert.deepEqual(homeOf({ journal: doneTo(movedTo(OLD, { id: "c-home" })), state: session({ clouds: [listed()] }) }), { kind: "cloud", origin: NEW }, "by id alone");
  assert.deepEqual(homeOf({ frozenCloud: OLD, state }), { kind: "cloud", origin: NEW }, "a freeze with no journal is not another account's");
  assert.deepEqual(homeOf({ journal: doneTo(movedTo(OLD)), state: session({ machine: { hold: { until: 9 }, formerOrigins: [OLD] } }) }), { kind: "computer" }, "it ended: home is this computer");
  assert.deepEqual(homeOf({ journal: doneTo(movedTo(OLD)), state: session({ machine: { origin: OTHER }, clouds: [listed({ origin: OTHER, id: "c-other" })] }) }), { kind: "cloud", origin: OLD },
    "another Cloud: the one moved to opens, as before");
  assert.deepEqual(homeOf({ journal: doneTo(movedTo(OLD)), state: { ...state, account: { id: "acct-2" } } }), { kind: "cloud", origin: NEW, otherAccount: true },
    "another account's Cloud is never this journal's");
});

test("My Cloud's saved place moves to its new address with it, keeping its id, name and colour", () => {
  const garage = { id: "garage", kind: "remote", name: "Garage", origin: "https://garage.example" };
  const saved = { environments: [{ id: "home", kind: "remote", name: "Anagama", color: "teal", origin: OLD, home: true }, garage], activeId: "home" };
  const moved = withoutOldCloudHome(saved, session({ machine: { formerOrigins: [OLD] }, clouds: [listed()] }));
  assert.deepEqual(moved.environments, [{ id: "home", kind: "remote", name: "Anagama", color: "teal", origin: NEW, home: true }, garage]);
  assert.equal(moved.activeId, "home");
  const already = { ...saved, environments: [...saved.environments, { id: "new", kind: "remote", name: "My Cloud", origin: NEW, home: true }] };
  assert.deepEqual(withoutOldCloudHome(already, session({ machine: { formerOrigins: [OLD] }, clouds: [listed()] })).environments.map((entry) => entry.id), ["garage", "new"],
    "one already saved at the new address stays the only one");
});