Skip to content

Commit

Permalink
Merge pull request #1 from RomanSavarin/master
Browse files Browse the repository at this point in the history
Broadcast store changes to popup
  • Loading branch information
eduardoacskimlinks authored Aug 8, 2022
2 parents 933ae45 + ef1627a commit 1e71a62
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 45 deletions.
18 changes: 10 additions & 8 deletions src/wrap-store/wrapStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/**
Expand Down Expand Up @@ -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 = () => {
Expand Down
77 changes: 40 additions & 37 deletions test/wrapStore.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,36 @@ 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];

// Mock chrome.runtime API
self.chrome = {
runtime: {
onMessage: {
addListener: () => {},
addListener: () => { },
},
onMessageExternal: {
addListener: () => {},
addListener: () => { },
},
onConnectExternal: {
addListener: () => {},
addListener: () => { },
},
sendMessage: () => { }
},
tabs: {
query: (tabObject, cb) => {
cb(tabs);
},
sendMessage: () => {}
sendMessage: () => { }
}
};
});
Expand All @@ -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(),
Expand All @@ -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);
Expand All @@ -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));

Expand All @@ -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));
Expand All @@ -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());
Expand Down Expand Up @@ -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));
Expand All @@ -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());

Expand Down Expand Up @@ -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 }));
Expand All @@ -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: () => {
Expand All @@ -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(),
Expand All @@ -294,14 +296,15 @@ describe('wrapStore', function () {
self.chrome = {
runtime: {
onMessage: {
addListener: () => {},
addListener: () => { },
},
onMessageExternal: {
addListener: () => {},
addListener: () => { },
},
onConnectExternal: {
addListener: () => {},
addListener: () => { },
},
sendMessage: () => { }
},
tabs: {
query: (tabObject, cb) => {
Expand All @@ -313,7 +316,7 @@ describe('wrapStore', function () {
}
};

wrapStore(store, {portName});
wrapStore(store, { portName });

tabResponders.length.should.equal(5);
},
Expand Down

0 comments on commit 1e71a62

Please sign in to comment.