Download src/boards/sqlite-board-store.batching.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 3.95 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/boards/sqlite-board-store.batching.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/boards/sqlite-board-store.batching.test.ts
-
curl -L -o sqlite-board-store.batching.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/boards/sqlite-board-store.batching.test.ts
3.95 kB
| import { afterEach, expect, it } from "vitest"; | |
| import { useAutoCleanupTempDirTracker } from "../../test/helpers/temp-dir.js"; | |
| import { | |
| closeOpenClawAgentDatabasesForTest, | |
| openOpenClawAgentDatabase, | |
| } from "../state/openclaw-agent-db.js"; | |
| import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js"; | |
| import { createTestBoardStore, readBoardHtml } from "./board-store.test-support.js"; | |
| const tempDirs = useAutoCleanupTempDirTracker(afterEach); | |
| afterEach(() => { | |
| closeOpenClawAgentDatabasesForTest(); | |
| closeOpenClawStateDatabaseForTest(); | |
| }); | |
| it("round-trips and removes a board with many tabs", async () => { | |
| const store = createTestBoardStore(); | |
| const target = { sessionKey: "agent:main:many-tabs" }; | |
| const tabIds = Array.from({ length: 130 }, (_, index) => `tab-${index}`); | |
| const created = await store.applyOps( | |
| target, | |
| tabIds.map((tabId) => ({ kind: "tab_create", tabId, title: tabId })), | |
| ); | |
| expect(created.tabs.map((tab) => tab.tabId)).toEqual(tabIds); | |
| expect(await store.getSnapshot(target)).toEqual(created); | |
| expect( | |
| await store.applyOps( | |
| target, | |
| tabIds.map((tabId) => ({ kind: "tab_delete", tabId })), | |
| ), | |
| ).toEqual({ | |
| ...target, | |
| revision: 2, | |
| tabs: [], | |
| widgets: [], | |
| }); | |
| expect(await store.getSnapshot(target)).toEqual({ | |
| ...target, | |
| revision: 0, | |
| tabs: [], | |
| widgets: [], | |
| }); | |
| }); | |
| it("rolls back late board writes and preserves surviving widget documents", async () => { | |
| const stateDir = tempDirs.make("openclaw-board-batch-rollback-"); | |
| const env = { OPENCLAW_STATE_DIR: stateDir }; | |
| const sessionKey = "agent:main:batch-rollback"; | |
| const store = createTestBoardStore({ stateDir }); | |
| const tabIds = Array.from({ length: 130 }, (_, index) => `tab-${index}`); | |
| await store.applyOps( | |
| { sessionKey }, | |
| tabIds.map((tabId) => ({ | |
| kind: "tab_create", | |
| tabId, | |
| title: tabId, | |
| })), | |
| ); | |
| const widgetNames = tabIds.slice(0, 48); | |
| for (const name of widgetNames) { | |
| await store.putWidget({ sessionKey, name, content: { kind: "html", html: name } }); | |
| } | |
| const before = await store.getSnapshot({ sessionKey }); | |
| const database = openOpenClawAgentDatabase({ agentId: "main", env }); | |
| const readRows = () => ({ | |
| tabs: database.db.prepare("SELECT * FROM board_tabs ORDER BY session_key, tab_id").all(), | |
| widgets: database.db.prepare("SELECT * FROM board_widgets ORDER BY session_key, name").all(), | |
| }); | |
| const beforeRows = readRows(); | |
| database.db.exec(`CREATE TEMP TRIGGER reject_late_tab_write BEFORE UPDATE ON board_tabs | |
| WHEN NEW.tab_id = 'tab-129' BEGIN SELECT RAISE(ABORT, 'late tab write'); END;`); | |
| await expect( | |
| store.applyOps({ sessionKey }, [ | |
| { | |
| kind: "tab_update", | |
| tabId: "tab-0", | |
| title: "changed", | |
| }, | |
| ]), | |
| ).rejects.toThrow("late tab write"); | |
| expect(readRows()).toEqual(beforeRows); | |
| database.db.exec("DROP TRIGGER reject_late_tab_write"); | |
| expect(await store.getSnapshot({ sessionKey })).toEqual(before); | |
| const removedNames = widgetNames.slice(0, -1); | |
| const removeOps = removedNames.map((name) => ({ kind: "widget_remove" as const, name })); | |
| database.db.exec(`CREATE TEMP TRIGGER reject_late_widget_delete BEFORE DELETE ON board_widgets | |
| WHEN OLD.name = 'tab-46' BEGIN SELECT RAISE(ABORT, 'late widget delete'); END;`); | |
| await expect(store.applyOps({ sessionKey }, removeOps)).rejects.toThrow("late widget delete"); | |
| expect(readRows()).toEqual(beforeRows); | |
| database.db.exec("DROP TRIGGER reject_late_widget_delete"); | |
| const removed = await store.applyOps({ sessionKey }, removeOps); | |
| expect(removed.widgets.map((widget) => widget.name)).toEqual(["tab-47"]); | |
| expect(await store.getSnapshot({ sessionKey })).toEqual(removed); | |
| expect(await readBoardHtml(store, { sessionKey }, "tab-47")).toMatchObject({ | |
| html: "tab-47", | |
| }); | |
| expect(await readBoardHtml(store, { sessionKey }, "tab-46")).toBeUndefined(); | |
| }); | |