mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-09 20:50:20 +08:00
106 lines
3.9 KiB
JavaScript
106 lines
3.9 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("node:assert/strict");
|
|
const test = require("node:test");
|
|
|
|
const { CompositeRelayTransport } = require("../vscode-extension/dist/compositeRelay.js");
|
|
|
|
class FakeRelay {
|
|
constructor({ connectError } = {}) {
|
|
this.connectError = connectError;
|
|
this.frames = [];
|
|
this.closed = false;
|
|
this.listeners = { message: new Set(), open: new Set(), close: new Set() };
|
|
}
|
|
|
|
async connect() {
|
|
if (this.connectError) throw this.connectError;
|
|
for (const listener of this.listeners.open) listener();
|
|
}
|
|
|
|
send(frame) { this.frames.push(frame); }
|
|
close() { this.closed = true; }
|
|
onMessage(listener) { return this.add("message", listener); }
|
|
onOpen(listener) { return this.add("open", listener); }
|
|
onClose(listener) { return this.add("close", listener); }
|
|
add(type, listener) {
|
|
this.listeners[type].add(listener);
|
|
return { dispose: () => this.listeners[type].delete(listener) };
|
|
}
|
|
receive(frame) { for (const listener of this.listeners.message) listener(frame); }
|
|
disconnect(error) { for (const listener of this.listeners.close) listener(error); }
|
|
}
|
|
|
|
test("CompositeRelayTransport keeps local control available when optional cloud connect fails", async () => {
|
|
const local = new FakeRelay();
|
|
const cloud = new FakeRelay({ connectError: new Error("cloud offline") });
|
|
const relay = new CompositeRelayTransport([
|
|
{ id: "local", transport: local, required: true },
|
|
{ id: "cloud", transport: cloud },
|
|
]);
|
|
|
|
await relay.connect();
|
|
assert.equal(relay.isConnected("local"), true);
|
|
assert.equal(relay.isConnected("cloud"), false);
|
|
relay.send({ kind: "event", type: "session.snapshot" });
|
|
assert.equal(local.frames.length, 1);
|
|
assert.equal(cloud.frames.length, 1, "optional transport may queue events for reconnect");
|
|
relay.close();
|
|
assert.equal(local.closed, true);
|
|
assert.equal(cloud.closed, true);
|
|
});
|
|
|
|
test("CompositeRelayTransport forwards commands and reports offline only after every relay closes", async () => {
|
|
const local = new FakeRelay();
|
|
const cloud = new FakeRelay();
|
|
const relay = new CompositeRelayTransport([
|
|
{ id: "local", transport: local, required: true },
|
|
{ id: "cloud", transport: cloud },
|
|
]);
|
|
const messages = [];
|
|
const closes = [];
|
|
relay.onMessage((frame) => messages.push(frame));
|
|
relay.onClose((error) => closes.push(error?.message));
|
|
|
|
await relay.connect();
|
|
assert.equal(relay.isConnected("local"), true);
|
|
assert.equal(relay.isConnected("cloud"), true);
|
|
cloud.receive({ kind: "command", type: "turn.start" });
|
|
assert.equal(messages.length, 1);
|
|
local.disconnect(new Error("local offline"));
|
|
assert.equal(relay.isConnected("local"), false);
|
|
assert.deepEqual(closes, []);
|
|
cloud.disconnect(new Error("cloud offline"));
|
|
assert.deepEqual(closes, ["cloud offline"]);
|
|
relay.close();
|
|
});
|
|
|
|
test("CompositeRelayTransport surfaces each member reconnect for snapshot hydration", async () => {
|
|
const local = new FakeRelay();
|
|
const cloud = new FakeRelay();
|
|
const relay = new CompositeRelayTransport([
|
|
{ id: "local", transport: local, required: true },
|
|
{ id: "cloud", transport: cloud },
|
|
]);
|
|
let opens = 0;
|
|
relay.onOpen(() => { opens += 1; });
|
|
await relay.connect();
|
|
assert.equal(opens, 2);
|
|
cloud.disconnect(new Error("cloud offline"));
|
|
for (const listener of cloud.listeners.open) listener();
|
|
assert.equal(opens, 3, "cloud recovery must prompt RelayHost to publish a fresh snapshot");
|
|
relay.close();
|
|
});
|
|
|
|
test("CompositeRelayTransport fails when the required local relay cannot connect", async () => {
|
|
const local = new FakeRelay({ connectError: new Error("local offline") });
|
|
const cloud = new FakeRelay();
|
|
const relay = new CompositeRelayTransport([
|
|
{ id: "local", transport: local, required: true },
|
|
{ id: "cloud", transport: cloud },
|
|
]);
|
|
await assert.rejects(relay.connect(), /local: local offline/);
|
|
assert.equal(local.closed, true);
|
|
assert.equal(cloud.closed, true);
|
|
});
|