Skip to content

Commit

Permalink
fix: only listen for the 'storage' event if using 'local' storage (#159)
Browse files Browse the repository at this point in the history
Co-authored-by: Hunter Johnston <[email protected]>
Co-authored-by: Hunter Johnston <[email protected]>
  • Loading branch information
3 people authored Dec 6, 2024
1 parent eacea9a commit f932fbf
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/two-pianos-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"runed": patch
---

fix: `PersistedState` - only listen for the `'storage'` event if using `'local'` storage
2 changes: 1 addition & 1 deletion packages/runed/src/lib/internal/utils/sleep.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export async function sleep(ms: number): Promise<void> {
export async function sleep(ms = 0): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ export class PersistedState<T> {
});

$effect(() => {
if (!syncTabs) return;
if (!syncTabs || storageType !== "local") return;

return addEventListener(window, "storage", this.#handleStorageEvent.bind(this));
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { describe, expect } from "vitest";

import { PersistedState } from "./index.js";
import { sleep } from "$lib/internal/utils/sleep.js";
import { testWithEffect } from "$lib/test/util.svelte.js";
import { PersistedState } from "./PersistedState.svelte.js";

const key = "test-key";
const initialValue = "test-value";
Expand Down Expand Up @@ -77,25 +78,54 @@ describe("PersistedState", () => {
});
});

describe.skip("syncTabs", () => {
describe("syncTabs", () => {
testWithEffect("updates persisted value when local storage changes independently", async () => {
// TODO: figure out why this test is failing even though it works in the browser. maybe jsdom doesn't emit storage events?
// expect(true).toBe(true);
// const persistedState = new PersistedState(key, initialValue);
// localStorage.setItem(key, JSON.stringify("new-value"));
// await new Promise((resolve) => setTimeout(resolve, 0));
// expect(persistedState.current).toBe("new-value");
const persistedState = new PersistedState(key, initialValue);
await sleep();
expect(persistedState.current).toBe(initialValue);
const newValue = "new-value";
localStorage.setItem(key, JSON.stringify(newValue));
const event = new StorageEvent("storage", {
key,
oldValue: initialValue,
newValue: JSON.stringify(newValue),
});
window.dispatchEvent(event);
await sleep();
expect(persistedState.current).toBe(newValue);
});

// TODO: this test passes, but likely only because the storage event is not being emitted either way from jsdom
testWithEffect(
"does not update persisted value when local storage changes independently if syncTabs is false",
async () => {
const persistedState = new PersistedState(key, initialValue, { syncTabs: false });
localStorage.setItem(key, JSON.stringify("new-value"));
await new Promise((resolve) => setTimeout(resolve, 0));
await sleep();
const newValue = "new-value";
localStorage.setItem(key, JSON.stringify(newValue));
const event = new StorageEvent("storage", {
key,
oldValue: initialValue,
newValue: JSON.stringify(newValue),
});
window.dispatchEvent(event);
await sleep();
expect(persistedState.current).toBe(initialValue);
}
);

testWithEffect("does not handle the storage event when 'session' storage is used", async () => {
const persistedState = new PersistedState(key, initialValue, { storage: "session" });
await sleep();
const newValue = "new-value";
localStorage.setItem(key, JSON.stringify(newValue));
const event = new StorageEvent("storage", {
key,
oldValue: initialValue,
newValue: JSON.stringify(newValue),
});
window.dispatchEvent(event);
await sleep();
expect(persistedState.current).toBe(initialValue);
});
});
});

0 comments on commit f932fbf

Please sign in to comment.