diff options
Diffstat (limited to 'devtools/client/shared/redux/middleware/xpcshell')
6 files changed, 247 insertions, 0 deletions
diff --git a/devtools/client/shared/redux/middleware/xpcshell/.eslintrc.js b/devtools/client/shared/redux/middleware/xpcshell/.eslintrc.js new file mode 100644 index 0000000000..f69336917a --- /dev/null +++ b/devtools/client/shared/redux/middleware/xpcshell/.eslintrc.js @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +module.exports = { + // Extend from the shared list of defined globals for mochitests. + extends: "../../../../../.eslintrc.xpcshell.js", +}; diff --git a/devtools/client/shared/redux/middleware/xpcshell/head.js b/devtools/client/shared/redux/middleware/xpcshell/head.js new file mode 100644 index 0000000000..9f4ba4392a --- /dev/null +++ b/devtools/client/shared/redux/middleware/xpcshell/head.js @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* exported waitUntilState */ + +"use strict"; + +const { require } = ChromeUtils.importESModule( + "resource://devtools/shared/loader/Loader.sys.mjs" +); + +function waitUntilState(store, predicate) { + return new Promise(resolve => { + const unsubscribe = store.subscribe(check); + function check() { + if (predicate(store.getState())) { + unsubscribe(); + resolve(); + } + } + + // Fire the check immediately incase the action has already occurred + check(); + }); +} diff --git a/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-01.js b/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-01.js new file mode 100644 index 0000000000..d8516feecc --- /dev/null +++ b/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-01.js @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + createStore, + applyMiddleware, +} = require("resource://devtools/client/shared/vendor/redux.js"); +const { + task, +} = require("resource://devtools/client/shared/redux/middleware/task.js"); + +/** + * Tests that task middleware allows dispatching generators, promises and objects + * that return actions; + */ +add_task(async function () { + const store = applyMiddleware(task)(createStore)(reducer); + + store.dispatch(fetch1("generator")); + await waitUntilState(store, () => store.getState().length === 1); + equal( + store.getState()[0].data, + "generator", + "task middleware async dispatches an action via generator" + ); + + store.dispatch(fetch2("sync")); + await waitUntilState(store, () => store.getState().length === 2); + equal( + store.getState()[1].data, + "sync", + "task middleware sync dispatches an action via sync" + ); +}); + +function fetch1(data) { + return async function ({ dispatch, getState }) { + equal( + getState().length, + 0, + "`getState` is accessible in a generator action" + ); + let moreData = await new Promise(resolve => resolve(data)); + // Ensure it handles more than one yield + moreData = await new Promise(resolve => resolve(data)); + dispatch({ type: "fetch1", data: moreData }); + }; +} + +function fetch2(data) { + return { + type: "fetch2", + data, + }; +} + +function reducer(state = [], action) { + info("Action called: " + action.type); + if (["fetch1", "fetch2"].includes(action.type)) { + state.push(action); + } + return [...state]; +} diff --git a/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-02.js b/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-02.js new file mode 100644 index 0000000000..eaa573a8ae --- /dev/null +++ b/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-02.js @@ -0,0 +1,86 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * Tests that task middleware allows dispatching generators that dispatch + * additional sync and async actions. + */ + +const { + createStore, + applyMiddleware, +} = require("resource://devtools/client/shared/vendor/redux.js"); +const { + task, +} = require("resource://devtools/client/shared/redux/middleware/task.js"); + +add_task(async function () { + const store = applyMiddleware(task)(createStore)(reducer); + + store.dispatch(comboAction()); + await waitUntilState(store, () => store.getState().length === 4); + + equal( + store.getState()[0].type, + "fetchAsync-start", + "Async dispatched actions in a generator task are fired" + ); + equal( + store.getState()[1].type, + "fetchAsync-end", + "Async dispatched actions in a generator task are fired" + ); + equal( + store.getState()[2].type, + "fetchSync", + "Return values of yielded sync dispatched actions are correct" + ); + equal( + store.getState()[3].type, + "fetch-done", + "Return values of yielded async dispatched actions are correct" + ); + equal( + store.getState()[3].data.sync.data, + "sync", + "Return values of dispatched sync values are correct" + ); + equal( + store.getState()[3].data.async, + "async", + "Return values of dispatched async values are correct" + ); +}); + +function comboAction() { + return async function ({ dispatch, getState }) { + const data = {}; + data.async = await dispatch(fetchAsync("async")); + data.sync = await dispatch(fetchSync("sync")); + dispatch({ type: "fetch-done", data }); + }; +} + +function fetchSync(data) { + return { type: "fetchSync", data }; +} + +function fetchAsync(data) { + return async function ({ dispatch }) { + dispatch({ type: "fetchAsync-start" }); + const val = await new Promise(resolve => resolve(data)); + dispatch({ type: "fetchAsync-end" }); + return val; + }; +} + +function reducer(state = [], action) { + info("Action called: " + action.type); + if (/fetch/.test(action.type)) { + state.push(action); + } + return [...state]; +} diff --git a/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-03.js b/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-03.js new file mode 100644 index 0000000000..94087e31de --- /dev/null +++ b/devtools/client/shared/redux/middleware/xpcshell/test_middleware-task-03.js @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + createStore, + applyMiddleware, +} = require("resource://devtools/client/shared/vendor/redux.js"); +const { + task, + ERROR_TYPE, +} = require("resource://devtools/client/shared/redux/middleware/task.js"); + +/** + * Tests that the middleware handles errors thrown in tasks, and rejected promises. + */ + +add_task(async function () { + const store = applyMiddleware(task)(createStore)(reducer); + + store.dispatch(asyncError()); + await waitUntilState(store, () => store.getState().length === 1); + equal( + store.getState()[0].type, + ERROR_TYPE, + "generator errors dispatch ERROR_TYPE actions" + ); + equal( + store.getState()[0].error, + "task-middleware-error-generator", + "generator errors dispatch ERROR_TYPE actions with error" + ); +}); + +function asyncError() { + return async ({ dispatch, getState }) => { + const error = "task-middleware-error-generator"; + throw error; + }; +} + +function reducer(state = [], action) { + info("Action called: " + action.type); + if (action.type === ERROR_TYPE) { + state.push(action); + } + return [...state]; +} diff --git a/devtools/client/shared/redux/middleware/xpcshell/xpcshell.ini b/devtools/client/shared/redux/middleware/xpcshell/xpcshell.ini new file mode 100644 index 0000000000..ec33920b13 --- /dev/null +++ b/devtools/client/shared/redux/middleware/xpcshell/xpcshell.ini @@ -0,0 +1,9 @@ +[DEFAULT] +tags = devtools +head = head.js +firefox-appdir = browser +skip-if = toolkit == 'android' + +[test_middleware-task-01.js] +[test_middleware-task-02.js] +[test_middleware-task-03.js] |