diff --git a/tests/app-batch-fetch-profiles.test.mjs b/tests/app-batch-fetch-profiles.test.mjs index df90a4bc..45148645 100644 --- a/tests/app-batch-fetch-profiles.test.mjs +++ b/tests/app-batch-fetch-profiles.test.mjs @@ -49,6 +49,9 @@ test("batchFetchProfiles handles fast and failing relays", async () => { const originalRelays = Array.isArray(nostrClient.relays) ? [...nostrClient.relays] : []; + const originalReadRelays = Array.isArray(nostrClient.readRelays) + ? [...nostrClient.readRelays] + : nostrClient.readRelays; const originalWriteRelays = Array.isArray(nostrClient.writeRelays) ? [...nostrClient.writeRelays] : nostrClient.writeRelays; @@ -57,6 +60,7 @@ test("batchFetchProfiles handles fast and failing relays", async () => { const poolListCalls = []; nostrClient.relays = [FAST_RELAY, FAIL_RELAY]; + nostrClient.readRelays = [FAST_RELAY, FAIL_RELAY]; nostrClient.writeRelays = [FAST_RELAY, FAIL_RELAY]; nostrClient.pool = { list: (relays, filters) => { @@ -92,6 +96,7 @@ test("batchFetchProfiles handles fast and failing relays", async () => { }); } finally { nostrClient.relays = originalRelays; + nostrClient.readRelays = originalReadRelays; nostrClient.writeRelays = originalWriteRelays; nostrClient.pool = originalPool; } diff --git a/tests/utils/lruCache.test.mjs b/tests/utils/lruCache.test.mjs new file mode 100644 index 00000000..199c50fc --- /dev/null +++ b/tests/utils/lruCache.test.mjs @@ -0,0 +1,86 @@ +import { describe, it, beforeEach } from "node:test"; +import assert from "node:assert/strict"; +import { LRUCache } from "../../js/utils/lruCache.js"; + +describe("LRUCache", () => { + let cache; + + beforeEach(() => { + cache = new LRUCache({ maxSize: 3 }); + }); + + it("should initialize with default options", () => { + const defaultCache = new LRUCache(); + assert.equal(defaultCache.maxSize, 100); + assert.equal(defaultCache.size(), 0); + }); + + it("should store and retrieve values", () => { + cache.set("a", 1); + assert.equal(cache.get("a"), 1); + assert.equal(cache.has("a"), true); + assert.equal(cache.size(), 1); + }); + + it("should evict oldest item when limit is reached", () => { + cache.set("a", 1); + cache.set("b", 2); + cache.set("c", 3); + assert.equal(cache.size(), 3); + + cache.set("d", 4); // Should evict 'a' + assert.equal(cache.size(), 3); + assert.equal(cache.has("a"), false); + assert.equal(cache.get("b"), 2); + assert.equal(cache.get("d"), 4); + }); + + it("should refresh recency on access", () => { + cache.set("a", 1); + cache.set("b", 2); + cache.set("c", 3); + + // Access 'a', making it newest + cache.get("a"); + + cache.set("d", 4); // Should evict 'b' (oldest is now 'b') + + assert.equal(cache.has("b"), false); + assert.equal(cache.has("a"), true); + assert.equal(cache.has("c"), true); + assert.equal(cache.has("d"), true); + }); + + it("should update value and refresh recency on set", () => { + cache.set("a", 1); + cache.set("b", 2); + cache.set("c", 3); + + // Update 'a' + cache.set("a", 10); + + cache.set("d", 4); // Should evict 'b' + + assert.equal(cache.get("a"), 10); + assert.equal(cache.has("b"), false); + }); + + it("should track stats", () => { + cache.set("a", 1); + cache.get("a"); // Hit + cache.get("b"); // Miss + + const stats = cache.getStats(); + assert.equal(stats.hits, 1); + assert.equal(stats.misses, 1); + assert.equal(stats.size, 1); + assert.equal(stats.maxSize, 3); + }); + + it("should clear cache", () => { + cache.set("a", 1); + cache.clear(); + assert.equal(cache.size(), 0); + assert.equal(cache.getStats().hits, 0); + }); +});