mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:10:42 +00:00
test: share matrix maintenance fixtures
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createMatrixReplyContextResolver, summarizeMatrixReplyEvent } from "./reply-context.js";
|
||||
import { createPollStartEvent } from "./test-events.js";
|
||||
import type { MatrixRawEvent } from "./types.js";
|
||||
|
||||
describe("matrix reply context", () => {
|
||||
@@ -51,25 +52,9 @@ describe("matrix reply context", () => {
|
||||
});
|
||||
|
||||
it("summarizes poll start events from poll content", () => {
|
||||
expect(
|
||||
summarizeMatrixReplyEvent({
|
||||
event_id: "$poll",
|
||||
sender: "@alice:example.org",
|
||||
type: "m.poll.start",
|
||||
origin_server_ts: Date.now(),
|
||||
content: {
|
||||
"m.poll.start": {
|
||||
question: { "m.text": "Lunch?" },
|
||||
kind: "m.poll.disclosed",
|
||||
max_selections: 1,
|
||||
answers: [
|
||||
{ id: "a1", "m.text": "Pizza" },
|
||||
{ id: "a2", "m.text": "Sushi" },
|
||||
],
|
||||
},
|
||||
},
|
||||
} as MatrixRawEvent),
|
||||
).toBe("[Poll]\nLunch?\n\n1. Pizza\n2. Sushi");
|
||||
expect(summarizeMatrixReplyEvent(createPollStartEvent("$poll"))).toBe(
|
||||
"[Poll]\nLunch?\n\n1. Pizza\n2. Sushi",
|
||||
);
|
||||
});
|
||||
|
||||
it("resolves and caches reply context", async () => {
|
||||
|
||||
21
extensions/matrix/src/matrix/monitor/test-events.ts
Normal file
21
extensions/matrix/src/matrix/monitor/test-events.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { MatrixRawEvent } from "./types.js";
|
||||
|
||||
export function createPollStartEvent(eventId: string): MatrixRawEvent {
|
||||
return {
|
||||
event_id: eventId,
|
||||
sender: "@alice:example.org",
|
||||
type: "m.poll.start",
|
||||
origin_server_ts: Date.now(),
|
||||
content: {
|
||||
"m.poll.start": {
|
||||
question: { "m.text": "Lunch?" },
|
||||
kind: "m.poll.disclosed",
|
||||
max_selections: 1,
|
||||
answers: [
|
||||
{ id: "a1", "m.text": "Pizza" },
|
||||
{ id: "a2", "m.text": "Sushi" },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createPollStartEvent } from "./test-events.js";
|
||||
import {
|
||||
createMatrixThreadContextResolver,
|
||||
summarizeMatrixThreadStarterEvent,
|
||||
@@ -126,24 +127,8 @@ describe("matrix thread context", () => {
|
||||
});
|
||||
|
||||
it("summarizes poll start thread roots from poll content", () => {
|
||||
expect(
|
||||
summarizeMatrixThreadStarterEvent({
|
||||
event_id: "$root",
|
||||
sender: "@alice:example.org",
|
||||
type: "m.poll.start",
|
||||
origin_server_ts: Date.now(),
|
||||
content: {
|
||||
"m.poll.start": {
|
||||
question: { "m.text": "Lunch?" },
|
||||
kind: "m.poll.disclosed",
|
||||
max_selections: 1,
|
||||
answers: [
|
||||
{ id: "a1", "m.text": "Pizza" },
|
||||
{ id: "a2", "m.text": "Sushi" },
|
||||
],
|
||||
},
|
||||
},
|
||||
} as MatrixRawEvent),
|
||||
).toBe("[Poll]\nLunch?\n\n1. Pizza\n2. Sushi");
|
||||
expect(summarizeMatrixThreadStarterEvent(createPollStartEvent("$root"))).toBe(
|
||||
"[Poll]\nLunch?\n\n1. Pizza\n2. Sushi",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -645,6 +645,19 @@ describe("handleMatrixSubagentDeliveryTarget", () => {
|
||||
});
|
||||
|
||||
describe("concurrent spawns across accounts", () => {
|
||||
function spawnForAccount(accountId: "ops" | "forge") {
|
||||
return handleMatrixSubagentSpawning(fakeApi, {
|
||||
threadRequested: true,
|
||||
requester: {
|
||||
channel: "matrix",
|
||||
accountId,
|
||||
to: `room:!room-${accountId}:example.org`,
|
||||
},
|
||||
childSessionKey: `agent:${accountId}:subagent:child-${accountId}`,
|
||||
agentId: `worker-${accountId}`,
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
bindMock.mockReset();
|
||||
getManagerMock.mockReset();
|
||||
@@ -664,18 +677,8 @@ describe("concurrent spawns across accounts", () => {
|
||||
.mockResolvedValueOnce({ conversation: { accountId: "forge", conversationId: "$t-forge" } });
|
||||
|
||||
const [opsResult, forgeResult] = await Promise.all([
|
||||
handleMatrixSubagentSpawning(fakeApi, {
|
||||
threadRequested: true,
|
||||
requester: { channel: "matrix", accountId: "ops", to: "room:!room-ops:example.org" },
|
||||
childSessionKey: "agent:ops:subagent:child-ops",
|
||||
agentId: "worker-ops",
|
||||
}),
|
||||
handleMatrixSubagentSpawning(fakeApi, {
|
||||
threadRequested: true,
|
||||
requester: { channel: "matrix", accountId: "forge", to: "room:!room-forge:example.org" },
|
||||
childSessionKey: "agent:forge:subagent:child-forge",
|
||||
agentId: "worker-forge",
|
||||
}),
|
||||
spawnForAccount("ops"),
|
||||
spawnForAccount("forge"),
|
||||
]);
|
||||
|
||||
expect(opsResult).toMatchObject({ status: "ok", threadBindingReady: true });
|
||||
@@ -709,18 +712,8 @@ describe("concurrent spawns across accounts", () => {
|
||||
.mockResolvedValueOnce({ conversation: { accountId: "forge", conversationId: "$t-forge" } });
|
||||
|
||||
const [opsResult, forgeResult] = await Promise.all([
|
||||
handleMatrixSubagentSpawning(fakeApi, {
|
||||
threadRequested: true,
|
||||
requester: { channel: "matrix", accountId: "ops", to: "room:!room-ops:example.org" },
|
||||
childSessionKey: "agent:ops:subagent:child-ops",
|
||||
agentId: "worker-ops",
|
||||
}),
|
||||
handleMatrixSubagentSpawning(fakeApi, {
|
||||
threadRequested: true,
|
||||
requester: { channel: "matrix", accountId: "forge", to: "room:!room-forge:example.org" },
|
||||
childSessionKey: "agent:forge:subagent:child-forge",
|
||||
agentId: "worker-forge",
|
||||
}),
|
||||
spawnForAccount("ops"),
|
||||
spawnForAccount("forge"),
|
||||
]);
|
||||
|
||||
expect(opsResult).toEqual(
|
||||
|
||||
@@ -67,6 +67,31 @@ function createSuccessfulMatrixMigrationDeps() {
|
||||
};
|
||||
}
|
||||
|
||||
function createWarningOnlyMaintenanceHarness() {
|
||||
return {
|
||||
deps: {
|
||||
maybeCreateMatrixMigrationSnapshot: vi.fn(),
|
||||
autoMigrateLegacyMatrixState: vi.fn(),
|
||||
autoPrepareLegacyMatrixCrypto: vi.fn(),
|
||||
},
|
||||
log: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function expectWarningOnlyMaintenanceSkipped(
|
||||
harness: ReturnType<typeof createWarningOnlyMaintenanceHarness>,
|
||||
) {
|
||||
expect(harness.deps.maybeCreateMatrixMigrationSnapshot).not.toHaveBeenCalled();
|
||||
expect(harness.deps.autoMigrateLegacyMatrixState).not.toHaveBeenCalled();
|
||||
expect(harness.deps.autoPrepareLegacyMatrixCrypto).not.toHaveBeenCalled();
|
||||
expect(harness.log.info).toHaveBeenCalledWith(
|
||||
"matrix: migration remains in a warning-only state; no pre-migration snapshot was needed yet",
|
||||
);
|
||||
}
|
||||
|
||||
describe("runMatrixStartupMaintenance", () => {
|
||||
beforeEach(() => {
|
||||
legacyCryptoInspectorAvailability.available = true;
|
||||
@@ -104,30 +129,19 @@ describe("runMatrixStartupMaintenance", () => {
|
||||
it("skips snapshot creation when startup only has warning-only migration state", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
await seedLegacyMatrixState(home);
|
||||
const maybeCreateMatrixMigrationSnapshotMock = vi.fn();
|
||||
const autoMigrateLegacyMatrixStateMock = vi.fn();
|
||||
const autoPrepareLegacyMatrixCryptoMock = vi.fn();
|
||||
const info = vi.fn();
|
||||
const warn = vi.fn();
|
||||
const harness = createWarningOnlyMaintenanceHarness();
|
||||
|
||||
await runMatrixStartupMaintenance({
|
||||
cfg: makeMatrixStartupConfig(false),
|
||||
env: process.env,
|
||||
deps: {
|
||||
maybeCreateMatrixMigrationSnapshot: maybeCreateMatrixMigrationSnapshotMock as never,
|
||||
autoMigrateLegacyMatrixState: autoMigrateLegacyMatrixStateMock as never,
|
||||
autoPrepareLegacyMatrixCrypto: autoPrepareLegacyMatrixCryptoMock as never,
|
||||
},
|
||||
log: { info, warn },
|
||||
deps: harness.deps as never,
|
||||
log: harness.log,
|
||||
});
|
||||
|
||||
expect(maybeCreateMatrixMigrationSnapshotMock).not.toHaveBeenCalled();
|
||||
expect(autoMigrateLegacyMatrixStateMock).not.toHaveBeenCalled();
|
||||
expect(autoPrepareLegacyMatrixCryptoMock).not.toHaveBeenCalled();
|
||||
expect(info).toHaveBeenCalledWith(
|
||||
"matrix: migration remains in a warning-only state; no pre-migration snapshot was needed yet",
|
||||
expectWarningOnlyMaintenanceSkipped(harness);
|
||||
expect(harness.log.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining("could not be resolved yet"),
|
||||
);
|
||||
expect(warn).toHaveBeenCalledWith(expect.stringContaining("could not be resolved yet"));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -136,30 +150,17 @@ describe("runMatrixStartupMaintenance", () => {
|
||||
|
||||
await withTempHome(async (home) => {
|
||||
await seedLegacyMatrixCrypto(home);
|
||||
const maybeCreateMatrixMigrationSnapshotMock = vi.fn();
|
||||
const autoMigrateLegacyMatrixStateMock = vi.fn();
|
||||
const autoPrepareLegacyMatrixCryptoMock = vi.fn();
|
||||
const info = vi.fn();
|
||||
const warn = vi.fn();
|
||||
const harness = createWarningOnlyMaintenanceHarness();
|
||||
|
||||
await runMatrixStartupMaintenance({
|
||||
cfg: makeMatrixStartupConfig(),
|
||||
env: process.env,
|
||||
deps: {
|
||||
maybeCreateMatrixMigrationSnapshot: maybeCreateMatrixMigrationSnapshotMock as never,
|
||||
autoMigrateLegacyMatrixState: autoMigrateLegacyMatrixStateMock as never,
|
||||
autoPrepareLegacyMatrixCrypto: autoPrepareLegacyMatrixCryptoMock as never,
|
||||
},
|
||||
log: { info, warn },
|
||||
deps: harness.deps as never,
|
||||
log: harness.log,
|
||||
});
|
||||
|
||||
expect(maybeCreateMatrixMigrationSnapshotMock).not.toHaveBeenCalled();
|
||||
expect(autoMigrateLegacyMatrixStateMock).not.toHaveBeenCalled();
|
||||
expect(autoPrepareLegacyMatrixCryptoMock).not.toHaveBeenCalled();
|
||||
expect(info).toHaveBeenCalledWith(
|
||||
"matrix: migration remains in a warning-only state; no pre-migration snapshot was needed yet",
|
||||
);
|
||||
expect(warn).toHaveBeenCalledWith(
|
||||
expectWarningOnlyMaintenanceSkipped(harness);
|
||||
expect(harness.log.warn).toHaveBeenCalledWith(
|
||||
"matrix: legacy encrypted-state warnings:\n- Legacy Matrix encrypted state was detected, but the Matrix crypto inspector is unavailable.",
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user