mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-31 09:28:30 +00:00
133 lines
3.9 KiB
TypeScript
133 lines
3.9 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { withTempDir } from "../test-utils/temp-dir.js";
|
|
import {
|
|
pruneExpiredPending,
|
|
readPairingStateRecord,
|
|
reconcilePendingPairingRequests,
|
|
writePairingStateRecord,
|
|
} from "./pairing-state.js";
|
|
|
|
describe("pairing state helpers", () => {
|
|
it("prunes only entries older than the ttl", () => {
|
|
const pendingById = {
|
|
stale: { ts: 10, requestId: "stale" },
|
|
edge: { ts: 50, requestId: "edge" },
|
|
fresh: { ts: 70, requestId: "fresh" },
|
|
};
|
|
|
|
pruneExpiredPending(pendingById, 100, 50);
|
|
|
|
expect(pendingById).toEqual({
|
|
edge: { ts: 50, requestId: "edge" },
|
|
fresh: { ts: 70, requestId: "fresh" },
|
|
});
|
|
});
|
|
|
|
it("refreshes a single matching pending request in place", async () => {
|
|
const persist = vi.fn(async () => undefined);
|
|
const existing = { requestId: "req-1", deviceId: "device-1", ts: 1, version: 1 };
|
|
const pendingById = { "req-1": existing };
|
|
|
|
await expect(
|
|
reconcilePendingPairingRequests({
|
|
pendingById,
|
|
existing: [existing],
|
|
incoming: { version: 2 },
|
|
canRefreshSingle: () => true,
|
|
refreshSingle: (pending, incoming) => ({ ...pending, version: incoming.version, ts: 2 }),
|
|
buildReplacement: vi.fn(() => ({ requestId: "req-2", deviceId: "device-1", ts: 2 })),
|
|
persist,
|
|
}),
|
|
).resolves.toEqual({
|
|
status: "pending",
|
|
request: { requestId: "req-1", deviceId: "device-1", ts: 2, version: 2 },
|
|
created: false,
|
|
});
|
|
expect(persist).toHaveBeenCalledOnce();
|
|
});
|
|
|
|
it("replaces existing pending requests with one merged request", async () => {
|
|
const persist = vi.fn(async () => undefined);
|
|
const pendingById = {
|
|
"req-1": { requestId: "req-1", deviceId: "device-2", ts: 1 },
|
|
"req-2": { requestId: "req-2", deviceId: "device-2", ts: 2 },
|
|
};
|
|
|
|
await expect(
|
|
reconcilePendingPairingRequests({
|
|
pendingById,
|
|
existing: Object.values(pendingById).toSorted((left, right) => right.ts - left.ts),
|
|
incoming: { deviceId: "device-2" },
|
|
canRefreshSingle: () => false,
|
|
refreshSingle: (pending) => pending,
|
|
buildReplacement: vi.fn(() => ({
|
|
requestId: "req-3",
|
|
deviceId: "device-2",
|
|
ts: 3,
|
|
isRepair: true,
|
|
})),
|
|
persist,
|
|
}),
|
|
).resolves.toEqual({
|
|
status: "pending",
|
|
request: { requestId: "req-3", deviceId: "device-2", ts: 3, isRepair: true },
|
|
created: true,
|
|
});
|
|
expect(persist).toHaveBeenCalledOnce();
|
|
expect(pendingById).toEqual({
|
|
"req-3": { requestId: "req-3", deviceId: "device-2", ts: 3, isRepair: true },
|
|
});
|
|
});
|
|
|
|
it("prunes stale sqlite rows while retaining current pairing rows", async () => {
|
|
await withTempDir("openclaw-pairing-state-", async (baseDir) => {
|
|
writePairingStateRecord({
|
|
baseDir,
|
|
subdir: "devices",
|
|
key: "pending",
|
|
value: {
|
|
"req-stale": {
|
|
requestId: "req-stale",
|
|
deviceId: "device-stale",
|
|
publicKey: "stale-key",
|
|
ts: 1,
|
|
},
|
|
"req-retained": {
|
|
requestId: "req-retained",
|
|
deviceId: "device-retained",
|
|
publicKey: "retained-key",
|
|
ts: 2,
|
|
},
|
|
},
|
|
});
|
|
|
|
writePairingStateRecord({
|
|
baseDir,
|
|
subdir: "devices",
|
|
key: "pending",
|
|
value: {
|
|
"req-retained": {
|
|
requestId: "req-retained",
|
|
deviceId: "device-retained",
|
|
publicKey: "retained-key-2",
|
|
ts: 3,
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(
|
|
readPairingStateRecord<{ publicKey: string }>({
|
|
baseDir,
|
|
subdir: "devices",
|
|
key: "pending",
|
|
}),
|
|
).toEqual({
|
|
"req-retained": expect.objectContaining({
|
|
publicKey: "retained-key-2",
|
|
ts: 3,
|
|
}),
|
|
});
|
|
});
|
|
});
|
|
});
|