From ef1627a8205df8732b8110c72d02114f2080931e Mon Sep 17 00:00:00 2001 From: Roman Savarin Date: Wed, 13 Jul 2022 17:18:52 +0300 Subject: [PATCH] Brodcast store changes to popup --- src/wrap-store/wrapStore.js | 18 +++++---- test/wrapStore.test.js | 77 +++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/wrap-store/wrapStore.js b/src/wrap-store/wrapStore.js index 7abe2aa..dc8d306 100644 --- a/src/wrap-store/wrapStore.js +++ b/src/wrap-store/wrapStore.js @@ -6,7 +6,7 @@ import { DEFAULT_PORT_NAME } from '../constants'; import { withSerializer, withDeserializer, noop } from "../serialization"; -import {getBrowserAPI} from '../util'; +import { getBrowserAPI } from '../util'; import shallowDiff from '../strategies/shallowDiff/diff'; /** @@ -95,20 +95,22 @@ export default (store, { * Setup for state updates */ const serializedMessagePoster = withSerializer(serializer)((...args) => { + const onErrorCallback = () => { + if (browserAPI.runtime.lastError) { + // do nothing - errors can be present + // if no content script exists on receiver + } + }; + + browserAPI.runtime.sendMessage(...args, onErrorCallback); // We will broadcast state changes to all tabs to sync state across content scripts return browserAPI.tabs.query({}, (tabs) => { for (const tab of tabs) { - browserAPI.tabs.sendMessage(tab.id, ...args, () => { - if (chrome.runtime.lastError) { - // do nothing - errors can be present - // if no content script exists on receiver - } - }); + browserAPI.tabs.sendMessage(tab.id, ...args, onErrorCallback); } }); }); - let currentState = store.getState(); const patchState = () => { diff --git a/test/wrapStore.test.js b/test/wrapStore.test.js index 2cfaa50..7fdb11d 100644 --- a/test/wrapStore.test.js +++ b/test/wrapStore.test.js @@ -3,14 +3,14 @@ import '@babel/polyfill'; import sinon from 'sinon'; import should from 'should'; -import {wrapStore} from '../src'; +import { wrapStore } from '../src'; import shallowDiff from '../src/strategies/shallowDiff/diff'; -import {DISPATCH_TYPE, STATE_TYPE, PATCH_STATE_TYPE} from '../src/constants'; +import { DISPATCH_TYPE, STATE_TYPE, PATCH_STATE_TYPE } from '../src/constants'; -describe('wrapStore', function () { +describe('wrapStore', function() { const portName = 'test'; - beforeEach(function () { + beforeEach(function() { global.self = {}; const tabs = [1]; @@ -18,20 +18,21 @@ describe('wrapStore', function () { self.chrome = { runtime: { onMessage: { - addListener: () => {}, + addListener: () => { }, }, onMessageExternal: { - addListener: () => {}, + addListener: () => { }, }, onConnectExternal: { - addListener: () => {}, + addListener: () => { }, }, + sendMessage: () => { } }, tabs: { query: (tabObject, cb) => { cb(tabs); }, - sendMessage: () => {} + sendMessage: () => { } } }; }); @@ -55,22 +56,23 @@ describe('wrapStore', function () { onConnectExternal: { addListener: fn => listeners.onConnectExternal.push(fn), }, + sendMessage: () => { } }, tabs: { query: (tabObject, cb) => { cb(tabs); }, - sendMessage: () => {} + sendMessage: () => { } } }; return listeners; } - describe("on receiving messages", function () { + describe("on receiving messages", function() { let listeners, store, payload, message, sender, callback; - beforeEach(function () { + beforeEach(function() { listeners = setupListeners(); store = { dispatch: sinon.spy(), @@ -89,11 +91,11 @@ describe('wrapStore', function () { payload }; sender = {}; - callback = () => {}; // noop. Maybe should validate it is invoked? + callback = () => { }; // noop. Maybe should validate it is invoked? }); - it('should dispatch actions received on onMessage to store', function () { - wrapStore(store, {portName}); + it('should dispatch actions received on onMessage to store', function() { + wrapStore(store, { portName }); listeners.onMessage.forEach(l => l(message, sender, callback)); store.dispatch.calledOnce.should.eql(true); @@ -106,18 +108,18 @@ describe('wrapStore', function () { .should.eql(true); }); - it('should not dispatch actions received on onMessage for other ports', function () { - wrapStore(store, {portName}); + it('should not dispatch actions received on onMessage for other ports', function() { + wrapStore(store, { portName }); message.portName = portName + '2'; listeners.onMessage.forEach(l => l(message, sender, callback)); store.dispatch.notCalled.should.eql(true); }); - it('should deserialize incoming messages correctly', function () { + it('should deserialize incoming messages correctly', function() { const deserializer = sinon.spy(JSON.parse); - wrapStore(store, {portName, deserializer}); + wrapStore(store, { portName, deserializer }); message.payload = JSON.stringify(payload); listeners.onMessage.forEach(l => l(message, sender, callback)); @@ -131,10 +133,10 @@ describe('wrapStore', function () { .should.eql(true); }); - it('should not deserialize incoming messages for other ports', function () { + it('should not deserialize incoming messages for other ports', function() { const deserializer = sinon.spy(JSON.parse); - wrapStore(store, {portName, deserializer}); + wrapStore(store, { portName, deserializer }); message.portName = portName + '2'; message.payload = JSON.stringify(payload); listeners.onMessage.forEach(l => l(message, sender, callback)); @@ -143,7 +145,7 @@ describe('wrapStore', function () { }); }); - it('should serialize initial state and subsequent patches correctly', function () { + it('should serialize initial state and subsequent patches correctly', function() { const listeners = setupListeners(); const sendMessage = (self.chrome.tabs.sendMessage = sinon.spy()); @@ -175,7 +177,7 @@ describe('wrapStore', function () { const serializer = (payload) => JSON.stringify(payload); - wrapStore(store, {portName, serializer}); + wrapStore(store, { portName, serializer }); // Listen for state changes listeners.onMessage.forEach(l => l(tabs)); @@ -198,7 +200,7 @@ describe('wrapStore', function () { sendMessage.secondCall.args[1].should.eql(expectedPatchMessage); }); - it('should use the provided diff strategy', function () { + it('should use the provided diff strategy', function() { const listeners = setupListeners(); const sendMessage = (self.chrome.tabs.sendMessage = sinon.spy()); @@ -228,7 +230,7 @@ describe('wrapStore', function () { oldObj, newObj }]); - wrapStore(store, {portName, diffStrategy}); + wrapStore(store, { portName, diffStrategy }); // Listen for state changes listeners.onMessage.forEach(l => l({ portName })); @@ -246,7 +248,7 @@ describe('wrapStore', function () { sendMessage.secondCall.args[1].should.eql(expectedPatchMessage); }); - describe("when validating options", function () { + describe("when validating options", function() { const store = { dispatch: sinon.spy(), subscribe: () => { @@ -255,33 +257,33 @@ describe('wrapStore', function () { getState: () => ({}) }; - it('should use defaults if no options present', function () { + it('should use defaults if no options present', function() { should.doesNotThrow(() => wrapStore(store)); }); - it('should throw an error if serializer is not a function', function () { + it('should throw an error if serializer is not a function', function() { should.throws(() => { wrapStore(store, { portName, serializer: "abc" }); }, Error); }); - it('should throw an error if deserializer is not a function', function () { + it('should throw an error if deserializer is not a function', function() { should.throws(() => { - wrapStore(store, {portName, deserializer: "abc"}); + wrapStore(store, { portName, deserializer: "abc" }); }, Error); }); - it('should throw an error if diffStrategy is not a function', function () { + it('should throw an error if diffStrategy is not a function', function() { should.throws(() => { - wrapStore(store, {portName, diffStrategy: "abc"}); + wrapStore(store, { portName, diffStrategy: "abc" }); }, Error); }); }); it( 'should send a safety message to all tabs once initialized', - function () { - const tabs = [123,456,789,1011,1213]; + function() { + const tabs = [123, 456, 789, 1011, 1213]; const tabResponders = []; const store = { dispatch: sinon.spy(), @@ -294,14 +296,15 @@ describe('wrapStore', function () { self.chrome = { runtime: { onMessage: { - addListener: () => {}, + addListener: () => { }, }, onMessageExternal: { - addListener: () => {}, + addListener: () => { }, }, onConnectExternal: { - addListener: () => {}, + addListener: () => { }, }, + sendMessage: () => { } }, tabs: { query: (tabObject, cb) => { @@ -313,7 +316,7 @@ describe('wrapStore', function () { } }; - wrapStore(store, {portName}); + wrapStore(store, { portName }); tabResponders.length.should.equal(5); },