From d6412e5536b0babfd50c6e4eb8b2cb8019ee06e9 Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Wed, 26 Nov 2025 19:30:36 -0500 Subject: [PATCH] test: add unit tests for localStorage persistence and error handling in message channels --- .../message_channel/message_channel.spec.ts | 56 +++++++++++++++++++ .../persistent_history.spec.ts | 37 ++++++++++++ 2 files changed, 93 insertions(+) diff --git a/packages/sds/src/message_channel/message_channel.spec.ts b/packages/sds/src/message_channel/message_channel.spec.ts index 2ba2758452..461d1ba9c3 100644 --- a/packages/sds/src/message_channel/message_channel.spec.ts +++ b/packages/sds/src/message_channel/message_channel.spec.ts @@ -1259,4 +1259,60 @@ describe("MessageChannel", function () { expect(channelB["lamportTimestamp"]).to.equal(timestampBefore); }); }); + + describe("Default localStorage persistence", () => { + it("should restore messages from localStorage on channel recreation", async () => { + const persistentChannelId = "persistent-channel"; + + const channel1 = new MessageChannel(persistentChannelId, "alice"); + + await sendMessage(channel1, utf8ToBytes("msg-1"), callback); + await sendMessage(channel1, utf8ToBytes("msg-2"), callback); + + expect(channel1["localHistory"].length).to.equal(2); + + // Recreate channel with same storage - should load history + const channel2 = new MessageChannel(persistentChannelId, "alice"); + + expect(channel2["localHistory"].length).to.equal(2); + expect( + channel2["localHistory"].slice(0).map((m) => m.messageId) + ).to.deep.equal([ + MessageChannel.getMessageId(utf8ToBytes("msg-1")), + MessageChannel.getMessageId(utf8ToBytes("msg-2")) + ]); + }); + + it("should include persisted messages in causal history after restart", async () => { + const persistentChannelId = "persistent-causal"; + + const channel1 = new MessageChannel(persistentChannelId, "alice", { + causalHistorySize: 2 + }); + + await sendMessage(channel1, utf8ToBytes("msg-1"), callback); + await sendMessage(channel1, utf8ToBytes("msg-2"), callback); + await sendMessage(channel1, utf8ToBytes("msg-3"), callback); + + const channel2 = new MessageChannel(persistentChannelId, "alice", { + causalHistorySize: 2 + }); + + let capturedMessage: ContentMessage | null = null; + await sendMessage(channel2, utf8ToBytes("msg-4"), async (message) => { + capturedMessage = message; + return { success: true }; + }); + + expect(capturedMessage).to.not.be.null; + expect(capturedMessage!.causalHistory).to.have.lengthOf(2); + // Should reference the last 2 messages (msg-2 and msg-3) + expect(capturedMessage!.causalHistory[0].messageId).to.equal( + MessageChannel.getMessageId(utf8ToBytes("msg-2")) + ); + expect(capturedMessage!.causalHistory[1].messageId).to.equal( + MessageChannel.getMessageId(utf8ToBytes("msg-3")) + ); + }); + }); }); diff --git a/packages/sds/src/message_channel/persistent_history.spec.ts b/packages/sds/src/message_channel/persistent_history.spec.ts index 941473dd94..7ee1c7914f 100644 --- a/packages/sds/src/message_channel/persistent_history.spec.ts +++ b/packages/sds/src/message_channel/persistent_history.spec.ts @@ -59,4 +59,41 @@ describe("PersistentHistory", () => { expect(history.length).to.equal(1); expect(history.slice(0)[0].messageId).to.equal("msg-3"); }); + + it("handles corrupt data in storage gracefully", () => { + const storage = new MemoryStorage(); + storage.setItem("waku:sds:history:channel-1", "{ invalid json }"); + + const history = new PersistentHistory({ channelId, storage }); + expect(history.length).to.equal(0); + + // Local history should be empty + expect(storage.getItem("waku:sds:history:channel-1")).to.equal(null); + }); + + it("isolates history by channel ID", () => { + const storage = new MemoryStorage(); + + const history1 = new PersistentHistory({ + channelId: "channel-1", + storage + }); + const history2 = new PersistentHistory({ + channelId: "channel-2", + storage + }); + + history1.push(createMessage("msg-1", 1)); + history2.push(createMessage("msg-2", 2)); + + // Each channel should only see its own messages + expect(history1.length).to.equal(1); + expect(history1.slice(0)[0].messageId).to.equal("msg-1"); + + expect(history2.length).to.equal(1); + expect(history2.slice(0)[0].messageId).to.equal("msg-2"); + + expect(storage.getItem("waku:sds:history:channel-1")).to.not.be.null; + expect(storage.getItem("waku:sds:history:channel-2")).to.not.be.null; + }); });