Files
bitvid/tests/nostr/syncMetadataStore.test.mjs
T

116 lines
4.1 KiB
JavaScript

import { test, describe, beforeEach, afterEach } from "node:test";
import assert from "node:assert";
import "../test-helpers/setup-localstorage.mjs";
import { SyncMetadataStore, __testExports } from "../../js/nostr/syncMetadataStore.js";
const { SYNC_METADATA_STORAGE_KEY } = __testExports;
describe("SyncMetadataStore", () => {
beforeEach(() => {
localStorage.clear();
});
afterEach(() => {
localStorage.clear();
});
test("should load from localStorage on initialization", () => {
const data = [["key1", 1234567890]];
localStorage.setItem(SYNC_METADATA_STORAGE_KEY, JSON.stringify(data));
const store = new SyncMetadataStore();
// computeKey(kind, pubkey, dTag, relayUrl)
// We don't know the components of "key1" but it should be in the map.
// However, the class treats keys opaquely once computed.
// Let's use internal map to verify if possible, or verify via public API if we know the key components.
// Accessing private property? logic uses `this.metadata`.
// We can't easily access `this.metadata` if it's not exposed.
// But we can verify with `getLastSeen`.
// Wait, "key1" isn't a valid key format generated by computeKey, but load() just loads the map.
// getLastSeen computes the key again.
// So if we pre-populate with a valid key, we can test it.
const kind = 1;
const pubkey = "pubkey1";
const dTag = "dtag1";
const relayUrl = "wss://relay1.com";
const key = `${kind}:${pubkey}:${dTag}:${relayUrl}`;
const timestamp = 1000;
localStorage.setItem(SYNC_METADATA_STORAGE_KEY, JSON.stringify([[key, timestamp]]));
const store2 = new SyncMetadataStore();
assert.strictEqual(store2.getLastSeen(kind, pubkey, dTag, relayUrl), timestamp);
});
test("should update last seen and save to localStorage", () => {
const store = new SyncMetadataStore();
const kind = 1;
const pubkey = "pubkey1";
const dTag = "dtag1";
const relayUrl = "wss://relay1.com";
const timestamp = 2000;
store.updateLastSeen(kind, pubkey, dTag, relayUrl, timestamp);
assert.strictEqual(store.getLastSeen(kind, pubkey, dTag, relayUrl), timestamp);
const saved = JSON.parse(localStorage.getItem(SYNC_METADATA_STORAGE_KEY));
const key = `${kind}:${pubkey}:${dTag}:${relayUrl}`;
const entry = saved.find(e => e[0] === key);
assert.ok(entry);
assert.strictEqual(entry[1], timestamp);
});
test("should only update if timestamp is newer", () => {
const store = new SyncMetadataStore();
const kind = 1;
const pubkey = "pubkey1";
const dTag = "dtag1";
const relayUrl = "wss://relay1.com";
store.updateLastSeen(kind, pubkey, dTag, relayUrl, 2000);
assert.strictEqual(store.getLastSeen(kind, pubkey, dTag, relayUrl), 2000);
// Try older
store.updateLastSeen(kind, pubkey, dTag, relayUrl, 1000);
assert.strictEqual(store.getLastSeen(kind, pubkey, dTag, relayUrl), 2000);
// Try newer
store.updateLastSeen(kind, pubkey, dTag, relayUrl, 3000);
assert.strictEqual(store.getLastSeen(kind, pubkey, dTag, relayUrl), 3000);
});
test("should get per-relay last seen", () => {
const store = new SyncMetadataStore();
const kind = 1;
const pubkey = "pubkey1";
const dTag = "dtag1";
store.updateLastSeen(kind, pubkey, dTag, "wss://relay1.com", 1000);
store.updateLastSeen(kind, pubkey, dTag, "wss://relay2.com", 2000);
store.updateLastSeen(kind, pubkey, "other", "wss://relay1.com", 3000); // Should be ignored
const result = store.getPerRelayLastSeen(kind, pubkey, dTag);
assert.deepStrictEqual(result, {
"wss://relay1.com": 1000,
"wss://relay2.com": 2000
});
});
test("should handle missing localStorage gracefully", () => {
const originalLocalStorage = globalThis.localStorage;
delete globalThis.localStorage; // Simulate missing localStorage
try {
const store = new SyncMetadataStore();
store.updateLastSeen(1, "p", "d", "r", 100); // Should not throw
// Can't check persistence, but ensure no crash
} finally {
globalThis.localStorage = originalLocalStorage;
}
});
});