Skip to content
This repository has been archived by the owner on Feb 29, 2020. It is now read-only.

Commit

Permalink
Merge pull request #1529 from k88hudson/gh1512
Browse files Browse the repository at this point in the history
Debounce pageWorker updates
  • Loading branch information
k88hudson committed Oct 11, 2016
2 parents 600bcae + 6fa1f6a commit 7d4ad2b
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
9 changes: 6 additions & 3 deletions addon/PageWorker.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
const vendor = require("common/vendor");
const {Page} = require("sdk/page-worker");
const {data} = require("sdk/self");
const {LOCAL_STORAGE_KEY} = require("common/constants");
const {ADDON_TO_CONTENT} = require("common/event-constants");
const watch = require("common/vendor")("redux-watch");
const watch = vendor("redux-watch");
const debounce = vendor("lodash.debounce");

class PageWorker {
constructor({store} = {}) {
constructor({store, wait} = {}) {
if (!store) {
throw new Error("options.store is required");
}
this._page = null;
this._onDispatch = this._onDispatch.bind(this);
this._unsubscribe = null;
this._store = store;
this._wait = wait || 1000;
}
_onDispatch() {
this._page.port.emit(ADDON_TO_CONTENT, {
Expand All @@ -32,7 +35,7 @@ class PageWorker {
const w = watch(this._store.getState);
// Note: According to the redux docs, calling .subscribe on a store
// returns a function which will unsubscribe
this._unsubscribe = this._store.subscribe(w(this._onDispatch));
this._unsubscribe = this._store.subscribe(debounce(w(this._onDispatch), this._wait));
}
destroy() {
if (this._page) {
Expand Down
9 changes: 8 additions & 1 deletion common/vendor-src.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
// Instead, import depdencies like this:
// require("common/vendor")("my-dependency");

if (typeof platform_require !== "undefined") {
const {setTimeout, clearTimeout} = platform_require("sdk/timers");
global.setTimeout = setTimeout;
global.clearTimeout = clearTimeout;
}

const vendorModules = {
"redux": require("redux"),
"redux-thunk": require("redux-thunk"),
"seedrandom": require("seedrandom"),
"url-parse": require("url-parse"),
"DoublyLinkedList": require("DoublyLinkedList/doubly-linked-list").DoublyLinkedList,
"PageMetadataParser": require("page-metadata-parser"),
"redux-watch": require("redux-watch")
"redux-watch": require("redux-watch"),
"lodash.debounce": require("lodash.debounce")
};

module.exports = function vendor(moduleName) {
Expand Down
28 changes: 26 additions & 2 deletions content-test/addon/PageWorker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,25 @@ function createStore() {
describe("PageWorker", () => {
let pageWorker;
let store;
let clock;
beforeEach(() => {
store = createStore();
pageWorker = new PageWorker({store});
clock = sinon.useFakeTimers();
});
afterEach(() => {
pageWorker.destroy();
clock.restore();
});
afterEach(() => pageWorker.destroy());
it("should create a PageWorker with a store", () => {
assert.equal(pageWorker._store, store);
assert.isNull(pageWorker._page);
assert.isNull(pageWorker._unsubscribe);
assert.equal(pageWorker._wait, 1000);
});
it("should allow overriding ._wait", () => {
const pw = new PageWorker({store, wait: 300});
assert.equal(pw._wait, 300);
});
it("should throw if you try to create a PageWorker without a store", () => {
assert.throws(() => {
Expand All @@ -39,15 +49,26 @@ describe("PageWorker", () => {
sinon.spy(pageWorker, "_onDispatch");
pageWorker.connect();
store.dispatch({type: "add", number: 42});
clock.tick(pageWorker._wait);
assert.deepEqual(store.getState(), {number: 42});
assert.called(pageWorker._onDispatch);
});
});
describe("_onDispatch", () => {
it("should debounce according to the ._wait value", () => {
sinon.spy(pageWorker, "_onDispatch");
pageWorker.connect();
store.dispatch({type: "add", number: 10});
store.dispatch({type: "add", number: 2});
store.dispatch({type: "add", number: 8});
clock.tick(pageWorker._wait);
assert.deepEqual(store.getState(), {number: 20});
assert.calledOnce(pageWorker._onDispatch);
});
it("should emit a message to Page instance when store dispatches an action", () => {
pageWorker.connect();
store.dispatch({type: "add", number: 3});

clock.tick(pageWorker._wait);
const expectedMessage = {type: LOCAL_STORAGE_KEY, data: {number: 3}};
assert.calledWith(pageWorker._page.port.emit, ADDON_TO_CONTENT, expectedMessage);
assert.deepEqual(pageWorker._store.getState(), {number: 3});
Expand All @@ -58,6 +79,7 @@ describe("PageWorker", () => {
assert.notCalled(pageWorker._page.port.emit);
});
});

describe("#destroy", () => {
it("should not throw if called twice or without connect", () => {
pageWorker.destroy();
Expand Down Expand Up @@ -87,8 +109,10 @@ describe("PageWorker", () => {
sinon.spy(pageWorker, "_onDispatch");
pageWorker.connect();
store.dispatch({type: "add", number: 2});
clock.tick(pageWorker._wait);
pageWorker.destroy();
store.dispatch({type: "add", number: 8});
clock.tick(pageWorker._wait);

assert.deepEqual(store.getState(), {number: 10});
assert.isNull(pageWorker._unsubscribe);
Expand Down
6 changes: 5 additions & 1 deletion webpack.addon.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
const absolute = relPath => require("path").join(__dirname, relPath);
const webpack = require("webpack");

module.exports = {
entry: {"vendor": absolute("common/vendor-src.js")},
Expand All @@ -8,5 +9,8 @@ module.exports = {
filename: "vendor.js",
libraryTarget: "commonjs2"
},
module: {loaders: [{test: /\.json$/, loader: "json"}]}
module: {loaders: [{test: /\.json$/, loader: "json"}]},
plugins: [
new webpack.BannerPlugin("let platform_require = require;\n", {raw: true})
]
};

0 comments on commit 7d4ad2b

Please sign in to comment.