Bug 1623919 - Add jest tests for toolbox redux store. r=jlast.

This patch adds some unit tests for the toolbox redux store,
especially for the threads reducers and actions.
In order for jest to work, we need to add babel as well as
some mocks.

Differential Revision: https://phabricator.services.mozilla.com/D68157

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Chevobbe 2020-03-25 20:59:56 +00:00
Родитель 46be890959
Коммит c77c585d14
11 изменённых файлов: 1684 добавлений и 1519 удалений

Просмотреть файл

@ -42,7 +42,7 @@ function threadsReducer(state = initialReducerState, action) {
);
let { selected } = state;
if (selected._targetFront === action.target) {
if (selected?._targetFront === action.target) {
selected = null;
}

Просмотреть файл

@ -0,0 +1,13 @@
/* 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 = {
plugins: [
"@babel/plugin-proposal-async-generator-functions",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
],
};

Просмотреть файл

@ -0,0 +1,11 @@
/* 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 = {
Cc: {},
Ci: {},
Cu: {},
};

Просмотреть файл

@ -0,0 +1,18 @@
/* 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 = {
appinfo: "",
obs: {
addObserver: function() {},
},
prefs: {
addObserver: function() {},
getBoolPref: function(prefName, defaultValue) {
return defaultValue;
},
},
};

Просмотреть файл

@ -0,0 +1,11 @@
/* 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 = {
getTopWindow(win) {
return win.top;
},
};

Просмотреть файл

@ -0,0 +1,5 @@
function generateUUID() {
return `${Date.now()}-${Math.round(Math.random() * 100)}`;
}
module.exports = { generateUUID };

Просмотреть файл

@ -8,7 +8,13 @@
module.exports = {
verbose: true,
moduleNameMapper: {
// Custom name mappers for modules that require m-c specific API.
"^chrome": `${__dirname}/fixtures/Chrome`,
"^Services": `${__dirname}/fixtures/Services`,
"^devtools/shared/DevToolsUtils": `${__dirname}/fixtures/devtools-utils`,
"^devtools/shared/generate-uuid": `${__dirname}/fixtures/generate-uuid`,
// Map all require("devtools/...") to the real devtools root.
"^devtools\\/(.*)": `${__dirname}/../../../../$1`,
},
setupFiles: ["<rootDir>setup.js"],
};

Просмотреть файл

@ -10,9 +10,13 @@
"test-ci": "jest --json"
},
"dependencies": {
"jest": "^23.0.0",
"@babel/plugin-proposal-async-generator-functions": "^7.2.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"babel-jest": "^25.1.0",
"jest": "^25.1.0",
"react-test-renderer": "16.4.1",
"react": "16.4.1",
"react-dom": "16.4.1"
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
/* 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";
/* global global */
global.loader = {
lazyGetter: (context, name, fn) => {
const module = fn();
global[name] = module;
},
lazyRequireGetter: (context, name, module, destructure) => {
const value = destructure ? require(module)[name] : require(module || name);
global[name] = value;
},
};
global.define = function(fn) {
fn(null, global, { exports: global });
};
global.requestIdleCallback = function() {};
global.isWorker = false;

Просмотреть файл

@ -0,0 +1,152 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Unit tests for threads management on the toolbox store.
*/
const { createToolboxStore } = require("devtools/client/framework/store");
const actions = require("devtools/client/framework/actions/threads");
const {
getSelectedThread,
getToolboxThreads,
} = require("devtools/client/framework/reducers/threads");
describe("Toolbox store - threads", () => {
describe("registerThread", () => {
it("adds the thread to the list", async () => {
const store = createToolboxStore();
const targetFront1 = getTargetFrontMock({
actorID: "thread/1",
});
await store.dispatch(actions.registerThread(targetFront1));
let threads = getToolboxThreads(store.getState());
expect(threads.length).toEqual(1);
expect(threads[0].actorID).toEqual("thread/1");
const targetFront2 = getTargetFrontMock({
actorID: "thread/2",
});
await store.dispatch(actions.registerThread(targetFront2));
threads = getToolboxThreads(store.getState());
expect(threads.length).toEqual(2);
expect(threads[0].actorID).toEqual("thread/1");
expect(threads[1].actorID).toEqual("thread/2");
});
});
describe("selectThread", () => {
it("updates the selected property when the thread is known", async () => {
const store = createToolboxStore();
const targetFront1 = getTargetFrontMock({
actorID: "thread/1",
});
await store.dispatch(actions.registerThread(targetFront1));
store.dispatch(actions.selectThread("thread/1"));
expect(getSelectedThread(store.getState()).actorID).toBe("thread/1");
});
it("does not update the selected property when the thread is unknown", async () => {
const store = createToolboxStore();
const targetFront1 = getTargetFrontMock({
actorID: "thread/1",
});
await store.dispatch(actions.registerThread(targetFront1));
store.dispatch(actions.selectThread("thread/1"));
expect(getSelectedThread(store.getState()).actorID).toBe("thread/1");
store.dispatch(actions.selectThread("thread/unknown"));
expect(getSelectedThread(store.getState()).actorID).toBe("thread/1");
});
it("does not update the state when the thread is already selected", async () => {
const store = createToolboxStore();
const targetFront1 = getTargetFrontMock({
actorID: "thread/1",
});
await store.dispatch(actions.registerThread(targetFront1));
store.dispatch(actions.selectThread("thread/1"));
const state = store.getState();
store.dispatch(actions.selectThread("thread/1"));
expect(store.getState()).toStrictEqual(state);
});
});
describe("clearThread", () => {
it("removes the thread from the list", async () => {
const store = createToolboxStore();
const targetFront1 = getTargetFrontMock({
actorID: "thread/1",
});
const targetFront2 = getTargetFrontMock({
actorID: "thread/2",
});
await store.dispatch(actions.registerThread(targetFront1));
await store.dispatch(actions.registerThread(targetFront2));
let threads = getToolboxThreads(store.getState());
expect(threads.length).toEqual(2);
store.dispatch(actions.clearThread(targetFront1));
threads = getToolboxThreads(store.getState());
expect(threads.length).toEqual(1);
expect(threads[0].actorID).toEqual("thread/2");
store.dispatch(actions.clearThread(targetFront2));
expect(getToolboxThreads(store.getState()).length).toEqual(0);
});
it("does not update the state when the thread is unknown", async () => {
const store = createToolboxStore();
const targetFront1 = getTargetFrontMock({
actorID: "thread/1",
});
const targetFront2 = getTargetFrontMock({
actorID: "thread/unknown",
});
await store.dispatch(actions.registerThread(targetFront1));
const state = store.getState();
store.dispatch(actions.clearThread(targetFront2));
expect(store.getState()).toStrictEqual(state);
});
it("resets the selected property when it was the selected thread", async () => {
const store = createToolboxStore();
const targetFront1 = getTargetFrontMock({
actorID: "thread/1",
});
await store.dispatch(actions.registerThread(targetFront1));
store.dispatch(actions.selectThread("thread/1"));
expect(getSelectedThread(store.getState()).actorID).toBe("thread/1");
store.dispatch(actions.clearThread(targetFront1));
expect(getSelectedThread(store.getState())).toBe(null);
});
});
});
function getTargetFrontMock(threadData) {
return {
getFront: async function(typeName) {
if (typeName === "thread") {
return threadData;
}
return null;
},
};
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу