test: share matrix sync lifecycle harness

This commit is contained in:
Peter Steinberger
2026-04-20 20:25:38 +01:00
parent 135578b4e9
commit 577dc17d0c

View File

@@ -11,17 +11,34 @@ function createClientEmitter() {
};
}
function createSyncLifecycleHarness(options?: { withStopping?: boolean }) {
const client = createClientEmitter();
const setStatus = vi.fn();
let stopping = false;
const statusController = createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
});
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController,
...(options?.withStopping ? { isStopping: () => stopping } : {}),
});
return {
client,
lifecycle,
setStatus,
statusController,
setStopping: (value: boolean) => {
stopping = value;
},
};
}
describe("createMatrixMonitorSyncLifecycle", () => {
it("rejects the channel wait on unexpected sync errors", async () => {
const client = createClientEmitter();
const setStatus = vi.fn();
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController: createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
}),
});
const { client, lifecycle, setStatus } = createSyncLifecycleHarness();
const waitPromise = lifecycle.waitForFatalStop();
client.emit("sync.unexpected_error", new Error("sync exploded"));
@@ -37,20 +54,12 @@ describe("createMatrixMonitorSyncLifecycle", () => {
});
it("ignores STOPPED emitted during intentional shutdown", async () => {
const client = createClientEmitter();
const setStatus = vi.fn();
let stopping = false;
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController: createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
}),
isStopping: () => stopping,
const { client, lifecycle, setStatus, setStopping } = createSyncLifecycleHarness({
withStopping: true,
});
const waitPromise = lifecycle.waitForFatalStop();
stopping = true;
setStopping(true);
client.emit("sync.state", "STOPPED", "SYNCING", undefined);
lifecycle.dispose();
@@ -64,15 +73,7 @@ describe("createMatrixMonitorSyncLifecycle", () => {
});
it("marks unexpected STOPPED sync as an error state", async () => {
const client = createClientEmitter();
const setStatus = vi.fn();
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController: createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
}),
});
const { client, lifecycle, setStatus } = createSyncLifecycleHarness();
const waitPromise = lifecycle.waitForFatalStop();
client.emit("sync.state", "STOPPED", "SYNCING", undefined);
@@ -88,20 +89,12 @@ describe("createMatrixMonitorSyncLifecycle", () => {
});
it("ignores unexpected sync errors emitted during intentional shutdown", async () => {
const client = createClientEmitter();
const setStatus = vi.fn();
let stopping = false;
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController: createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
}),
isStopping: () => stopping,
const { client, lifecycle, setStatus, setStopping } = createSyncLifecycleHarness({
withStopping: true,
});
const waitPromise = lifecycle.waitForFatalStop();
stopping = true;
setStopping(true);
client.emit("sync.unexpected_error", new Error("shutdown noise"));
lifecycle.dispose();
@@ -115,21 +108,13 @@ describe("createMatrixMonitorSyncLifecycle", () => {
});
it("ignores non-terminal sync states emitted during intentional shutdown", async () => {
const client = createClientEmitter();
const setStatus = vi.fn();
let stopping = false;
const statusController = createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
});
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController,
isStopping: () => stopping,
});
const { client, lifecycle, setStatus, setStopping, statusController } =
createSyncLifecycleHarness({
withStopping: true,
});
const waitPromise = lifecycle.waitForFatalStop();
stopping = true;
setStopping(true);
client.emit("sync.state", "ERROR", "RECONNECTING", new Error("shutdown noise"));
lifecycle.dispose();
statusController.markStopped();
@@ -145,24 +130,16 @@ describe("createMatrixMonitorSyncLifecycle", () => {
});
it("does not downgrade a fatal error to stopped during shutdown", async () => {
const client = createClientEmitter();
const setStatus = vi.fn();
let stopping = false;
const statusController = createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
});
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController,
isStopping: () => stopping,
});
const { client, lifecycle, setStatus, setStopping, statusController } =
createSyncLifecycleHarness({
withStopping: true,
});
const waitPromise = lifecycle.waitForFatalStop();
client.emit("sync.unexpected_error", new Error("sync exploded"));
await expect(waitPromise).rejects.toThrow("sync exploded");
stopping = true;
setStopping(true);
client.emit("sync.state", "STOPPED", "SYNCING", undefined);
lifecycle.dispose();
statusController.markStopped();
@@ -177,15 +154,7 @@ describe("createMatrixMonitorSyncLifecycle", () => {
});
it("ignores follow-up sync states after a fatal sync error", async () => {
const client = createClientEmitter();
const setStatus = vi.fn();
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController: createMatrixMonitorStatusController({
accountId: "default",
statusSink: setStatus,
}),
});
const { client, lifecycle, setStatus } = createSyncLifecycleHarness();
const waitPromise = lifecycle.waitForFatalStop();
client.emit("sync.unexpected_error", new Error("sync exploded"));
@@ -204,13 +173,7 @@ describe("createMatrixMonitorSyncLifecycle", () => {
});
it("rejects a second concurrent fatal-stop waiter", async () => {
const client = createClientEmitter();
const lifecycle = createMatrixMonitorSyncLifecycle({
client: client as never,
statusController: createMatrixMonitorStatusController({
accountId: "default",
}),
});
const { lifecycle } = createSyncLifecycleHarness();
const firstWait = lifecycle.waitForFatalStop();