Files
openclaw/src/proxy-capture/store.sqlite.test.ts
Tak Hoffman 958c34e82c feat(qa-lab): Add proxy capture stack and QA Lab inspector (#64895)
* Add proxy capture core and CLI

* Expand transport capture coverage

* Add QA Lab capture backend

* Refine QA Lab capture UI

* Fix proxy capture review feedback

* Fix proxy run cleanup and TTS capture

* Fix proxy capture transport follow-ups

* Fix debug proxy CONNECT target parsing

* Harden QA Lab asset path containment
2026-04-11 12:34:57 -05:00

123 lines
3.4 KiB
TypeScript

import { mkdtempSync, rmSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { DebugProxyCaptureStore, persistEventPayload } from "./store.sqlite.js";
const cleanupDirs: string[] = [];
afterEach(() => {
while (cleanupDirs.length > 0) {
const dir = cleanupDirs.pop();
if (dir) {
rmSync(dir, { recursive: true, force: true });
}
}
});
function makeStore() {
const root = mkdtempSync(path.join(os.tmpdir(), "openclaw-proxy-capture-"));
cleanupDirs.push(root);
return new DebugProxyCaptureStore(path.join(root, "capture.sqlite"), path.join(root, "blobs"));
}
describe("DebugProxyCaptureStore", () => {
it("stores sessions, blobs, and duplicate-send query results", () => {
const store = makeStore();
store.upsertSession({
id: "session-1",
startedAt: Date.now(),
mode: "proxy-run",
sourceScope: "openclaw",
sourceProcess: "openclaw",
dbPath: store.dbPath,
blobDir: store.blobDir,
});
const firstPayload = persistEventPayload(store, {
data: '{"ok":true}',
contentType: "application/json",
});
store.recordEvent({
sessionId: "session-1",
ts: 1,
sourceScope: "openclaw",
sourceProcess: "openclaw",
protocol: "https",
direction: "outbound",
kind: "request",
flowId: "flow-1",
method: "POST",
host: "api.example.com",
path: "/v1/send",
...firstPayload,
});
store.recordEvent({
sessionId: "session-1",
ts: 2,
sourceScope: "openclaw",
sourceProcess: "openclaw",
protocol: "https",
direction: "outbound",
kind: "request",
flowId: "flow-2",
method: "POST",
host: "api.example.com",
path: "/v1/send",
...firstPayload,
});
expect(store.listSessions(10)).toHaveLength(1);
expect(store.queryPreset("double-sends", "session-1")).toEqual([
expect.objectContaining({
host: "api.example.com",
path: "/v1/send",
method: "POST",
duplicateCount: 2,
}),
]);
expect(store.readBlob(firstPayload.dataBlobId ?? "")).toContain('"ok":true');
});
it("keeps shared blobs when deleting one of multiple referencing sessions", () => {
const store = makeStore();
const sharedPayload = persistEventPayload(store, {
data: '{"shared":true}',
contentType: "application/json",
});
for (const sessionId of ["session-a", "session-b"]) {
store.upsertSession({
id: sessionId,
startedAt: Date.now(),
mode: "proxy-run",
sourceScope: "openclaw",
sourceProcess: "openclaw",
dbPath: store.dbPath,
blobDir: store.blobDir,
});
store.recordEvent({
sessionId,
ts: Date.now(),
sourceScope: "openclaw",
sourceProcess: "openclaw",
protocol: "https",
direction: "outbound",
kind: "request",
flowId: `flow-${sessionId}`,
method: "POST",
host: "api.example.com",
path: "/v1/shared",
...sharedPayload,
});
}
const result = store.deleteSessions(["session-a"]);
expect(result.sessions).toBe(1);
expect(result.events).toBe(1);
expect(result.blobs).toBe(0);
expect(store.readBlob(sharedPayload.dataBlobId ?? "")).toContain('"shared":true');
expect(store.listSessions(10).map((session) => session.id)).toEqual(["session-b"]);
});
});