// Noticing that the same table is open twice. // // Two tabs each hold their own copy in memory and each save writes the whole thing, // so the second one to act throws the first one's work away. This doesn't merge them // — replacing a table under a dealer's hands mid-hand would be its own hazard — it // notices, which is what lets them decide. const test = require("node:test"); const assert = require("node:assert"); const { HoldemState } = require("./load"); function withWindow() { const listeners = []; globalThis.window = { addEventListener(type, fn) { if (type === "storage") listeners.push(fn); }, removeEventListener(type, fn) { const i = listeners.indexOf(fn); if (i >= 0) listeners.splice(i, 1); }, }; return { listeners, fire(key) { listeners.forEach(fn => fn({ key })); }, }; } test.beforeEach(() => { HoldemState.otherTabActive = false; HoldemState.onOtherTab = null; HoldemState.tabWatcher = null; }); test.after(() => { delete globalThis.window; HoldemState.otherTabActive = false; HoldemState.onOtherTab = null; HoldemState.tabWatcher = null; }); test("a write to this table from elsewhere is noticed", () => { const win = withWindow(); let told = 0; HoldemState.onOtherTab = () => { told++; }; HoldemState.watchOtherTabs(); win.fire(HoldemState.STORAGE_KEY); assert.equal(HoldemState.otherTabActive, true); assert.equal(told, 1); }); test("somebody else's storage key is not our business", () => { const win = withWindow(); let told = 0; HoldemState.onOtherTab = () => { told++; }; HoldemState.watchOtherTabs(); win.fire("some.other.app.state"); win.fire(HoldemState.RECOVERY_KEY); assert.equal(HoldemState.otherTabActive, false); assert.equal(told, 0); }); test("told once, however many times the other tab acts", () => { const win = withWindow(); let told = 0; HoldemState.onOtherTab = () => { told++; }; HoldemState.watchOtherTabs(); for (let i = 0; i < 10; i++) win.fire(HoldemState.STORAGE_KEY); assert.equal(told, 1); }); test("watching twice doesn't listen twice", () => { const win = withWindow(); HoldemState.watchOtherTabs(); HoldemState.watchOtherTabs(); HoldemState.watchOtherTabs(); assert.equal(win.listeners.length, 1); }); test("no listener set is not an error", () => { const win = withWindow(); HoldemState.onOtherTab = null; HoldemState.watchOtherTabs(); assert.doesNotThrow(() => win.fire(HoldemState.STORAGE_KEY)); assert.equal(HoldemState.otherTabActive, true); }); test("no window at all is not an error", () => { // The same modules are loaded in Node by the test harness. delete globalThis.window; HoldemState.tabWatcher = null; assert.doesNotThrow(() => HoldemState.watchOtherTabs()); assert.equal(HoldemState.otherTabActive, false); });