mirror of
https://github.com/Quad4-Software/MeshChatX.git
synced 2026-08-18 09:49:09 -04:00
129 lines
4.2 KiB
JavaScript
129 lines
4.2 KiB
JavaScript
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
import {
|
|
loadVisualiserCache,
|
|
saveVisualiserCache,
|
|
clearVisualiserCache,
|
|
resetVisualiserCacheDbHandle,
|
|
} from "@/js/networkVisualiserCache.js";
|
|
|
|
function mockIndexedDb() {
|
|
const stores = new Map();
|
|
const fakeDb = {
|
|
objectStoreNames: {
|
|
contains: (name) => name === "snapshots",
|
|
},
|
|
transaction(storeNames, mode) {
|
|
const storeName = Array.isArray(storeNames) ? storeNames[0] : storeNames;
|
|
if (!stores.has(storeName)) stores.set(storeName, new Map());
|
|
const data = stores.get(storeName);
|
|
const store = {
|
|
get(key) {
|
|
const req = {};
|
|
queueMicrotask(() => {
|
|
req.result = data.get(key);
|
|
req.onsuccess?.();
|
|
});
|
|
return req;
|
|
},
|
|
put(row) {
|
|
data.set(row.identityHash, row);
|
|
const req = {};
|
|
queueMicrotask(() => req.onsuccess?.());
|
|
return req;
|
|
},
|
|
delete(key) {
|
|
data.delete(key);
|
|
const req = {};
|
|
queueMicrotask(() => req.onsuccess?.());
|
|
return req;
|
|
},
|
|
};
|
|
const tx = {
|
|
objectStore: () => store,
|
|
oncomplete: null,
|
|
onerror: null,
|
|
};
|
|
queueMicrotask(() => tx.oncomplete?.());
|
|
return tx;
|
|
},
|
|
};
|
|
const idb = {
|
|
open() {
|
|
const req = {
|
|
result: fakeDb,
|
|
onupgradeneeded: null,
|
|
onsuccess: null,
|
|
onerror: null,
|
|
};
|
|
queueMicrotask(() => {
|
|
req.onupgradeneeded?.({ target: req });
|
|
req.onsuccess?.({ target: req });
|
|
});
|
|
return req;
|
|
},
|
|
};
|
|
return idb;
|
|
}
|
|
|
|
describe("networkVisualiserCache", () => {
|
|
beforeEach(() => {
|
|
resetVisualiserCacheDbHandle();
|
|
vi.stubGlobal("indexedDB", mockIndexedDb());
|
|
});
|
|
|
|
afterEach(() => {
|
|
resetVisualiserCacheDbHandle();
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it("round-trips path table announces and positions for one identity", async () => {
|
|
const ok = await saveVisualiserCache({
|
|
identityHash: "abc123",
|
|
pathTable: [{ hash: "n1", hops: 1, interface: "eth0" }],
|
|
announces: { n1: { destination_hash: "n1", aspect: "lxmf.delivery" } },
|
|
positions: { n1: { x: 10, y: 20 } },
|
|
});
|
|
expect(ok).toBe(true);
|
|
const loaded = await loadVisualiserCache("abc123");
|
|
expect(loaded.pathTable).toHaveLength(1);
|
|
expect(loaded.announces.n1.aspect).toBe("lxmf.delivery");
|
|
expect(loaded.positions.n1).toEqual({ x: 10, y: 20 });
|
|
});
|
|
|
|
it("isolates cache by identity hash", async () => {
|
|
await saveVisualiserCache({
|
|
identityHash: "id-a",
|
|
pathTable: [{ hash: "a" }],
|
|
announces: {},
|
|
positions: {},
|
|
});
|
|
await saveVisualiserCache({
|
|
identityHash: "id-b",
|
|
pathTable: [{ hash: "b" }],
|
|
announces: {},
|
|
positions: {},
|
|
});
|
|
expect((await loadVisualiserCache("id-a")).pathTable[0].hash).toBe("a");
|
|
expect((await loadVisualiserCache("id-b")).pathTable[0].hash).toBe("b");
|
|
});
|
|
|
|
it("clearVisualiserCache removes a snapshot", async () => {
|
|
await saveVisualiserCache({
|
|
identityHash: "gone",
|
|
pathTable: [{ hash: "x" }],
|
|
announces: {},
|
|
positions: {},
|
|
});
|
|
await clearVisualiserCache("gone");
|
|
expect(await loadVisualiserCache("gone")).toBeNull();
|
|
});
|
|
|
|
it("returns null when IndexedDB is unavailable", async () => {
|
|
resetVisualiserCacheDbHandle();
|
|
vi.stubGlobal("indexedDB", undefined);
|
|
expect(await loadVisualiserCache("x")).toBeNull();
|
|
expect(await saveVisualiserCache({ identityHash: "x", pathTable: [], announces: {}, positions: {} })).toBe(
|
|
false
|
|
);
|
|
});
|
|
});
|