Javascript 使用Jest测试跨浏览器扩展,如何模拟Chrome存储API?
由于Cypress不允许访问Javascript 使用Jest测试跨浏览器扩展,如何模拟Chrome存储API?,javascript,reactjs,unit-testing,jestjs,mocking,Javascript,Reactjs,Unit Testing,Jestjs,Mocking,由于Cypress不允许访问chrome://URL,我将测试推迟了一段时间,之后我决定最终了解如何对我的扩展进行单元/集成测试。在此之前,我曾多次手动测试不断增长的功能,有时忘记检查一两件事。自动化测试肯定会加快过程,并帮助我在添加新功能时更加安心 为此,我选择了Jest,因为我的扩展是用React(CRA)完成的。我还使用React测试库(@testinglibrary/React)呈现所有React组件进行测试 正如我最近使Tabmerge开源一样,可以找到完整的测试脚本 下面是我想针对这
chrome://
URL,我将测试推迟了一段时间,之后我决定最终了解如何对我的扩展进行单元/集成测试。在此之前,我曾多次手动测试不断增长的功能,有时忘记检查一两件事。自动化测试肯定会加快过程,并帮助我在添加新功能时更加安心
为此,我选择了Jest,因为我的扩展是用React(CRA)完成的。我还使用React测试库(@testinglibrary/React
)呈现所有React组件进行测试
正如我最近使Tabmerge开源一样,可以找到完整的测试脚本
下面是我想针对这个问题重点关注的测试用例:
import React from "react";
import { render, fireEvent } from "@testing-library/react";
import * as TabFunc from "../src/Tab/Tab_functions";
import Tab from "../src/Tab/Tab";
var init_groups = {
"group-0": {
color: "#d6ffe0",
created: "11/12/2020 @ 22:13:24",
tabs: [
{
title:
"Stack Overflow - Where Developers Learn, Share, & Build Careersaaaaaaaaaaaaaaaaaaaaaa",
url: "https://stackoverflow.com/",
},
{
title: "lichess.org • Free Online Chess",
url: "https://lichess.org/",
},
{
title: "Chess.com - Play Chess Online - Free Games",
url: "https://www.chess.com/",
},
],
title: "Chess",
},
"group-1": {
color: "#c7eeff",
created: "11/12/2020 @ 22:15:11",
tabs: [
{
title: "Twitch",
url: "https://www.twitch.tv/",
},
{
title: "reddit: the front page of the internet",
url: "https://www.reddit.com/",
},
],
title: "Social",
},
};
describe("removeTab", () => {
it("correctly adjusts groups and counts when a tab is removed", () => {
var tabs = init_groups["group-0"].tabs;
const { container } = render(<Tab init_tabs={tabs} />);
expect(container.getElementsByClassName("draggable").length).toEqual(3);
var removeTabSpy = jest.spyOn(TabFunc, "removeTab");
fireEvent.click(container.querySelector(".close-tab"));
expect(removeTabSpy).toHaveBeenCalledTimes(1);
expect(container.getElementsByClassName("draggable").length).toEqual(2); // fails (does not remove the tab for some reason)
});
});
我认为模拟Chrome存储API不能正常工作的原因是,当我在测试中手动设置它时,选项卡的数量没有从0增加。这迫使我将一个道具(props.init_tabs
)传递给我的Tab
组件进行测试()——如果可能的话,我希望通过设置本地存储来避免这种情况
有人能给我指出正确的方向吗?我希望避免使用像
jest-chrome
这样的库,因为它们太过抽象,使我更难理解测试中发生的事情。我想我现在有一个解决方案,所以我将与其他人分享
我对我的chrome存储API进行了适当的模拟,以使用localStorage:
// __mocks__/chromeMock.js
...
storage: {
local: {
...,
get: function (key, cb) {
const item = JSON.parse(localStorage.getItem(key));
cb({ [key]: item });
},
...,
set: function (obj, cb) {
const key = Object.keys(obj)[0];
localStorage.setItem(key, JSON.stringify(obj[key]));
cb();
},
},
...
},
...
另外,为了模拟初始渲染时的选项卡设置,我有一个beforeach
hook,它使用上述模拟设置我的localStorage
:
// __tests__/Tab.spec.js
var init_ls_entry, init_tabs, mockSet;
beforeEach(() => {
chrome.storage.local.set({ groups: init_groups }, () => {});
init_ls_entry = JSON.parse(localStorage.getItem("groups"));
init_tabs = init_ls_entry["group-0"].tabs;
mockSet = jest.fn(); // mock for setState hooks
});
和最重要的是,当我render()
时,我注意到我没有提供导致任何渲染的id
道具(就localStorage
中的选项卡而言),所以现在我有了这个:
// __tests__/Tab.spec.js
describe("removeTab", () => {
it("correctly adjusts storage when a tab is removed", async () => {
const { container } = render(
<Tab id="group-0" setTabTotal={mockSet} setGroups={mockSet} />
);
var removeTabSpy = jest.spyOn(TabFunc, "removeTab");
var chromeSetSpy = jest.spyOn(chrome.storage.local, "set");
fireEvent.click(container.querySelector(".close-tab"));
await waitFor(() => {
expect(chromeSetSpy).toHaveBeenCalled();
});
chrome.storage.local.get("groups", (local) => {
expect(init_tabs.length).toEqual(3);
expect(local.groups["group-0"].tabs.length).toEqual(2);
expect(removeTabSpy).toHaveBeenCalledTimes(1);
});
expect.assertions(4);
});
});
/\uuuu测试\uuuu/Tab.spec.js
描述(“移除选项卡”,()=>{
它(“在删除选项卡时正确调整存储”,async()=>{
常量{container}=render(
);
var removeTabSpy=jest.spyOn(TabFunc,“removeTab”);
var chromeSetSpy=jest.spyOn(chrome.storage.local,“set”);
firevent.click(container.querySelector(“.close选项卡”);
等待等待(()=>{
expect(chromeSetSpy).tohavebeincall();
});
chrome.storage.local.get(“组”,(本地)=>{
期望值(初始标签长度).toEqual(3);
expect(local.groups[“group-0”]。tabs.length)。toEqual(2);
期望(移除Abspy)。已被催收时间(1);
});
期望.断言(4);
});
});
哪个通过了
现在开始拖放测试
// __tests__/Tab.spec.js
describe("removeTab", () => {
it("correctly adjusts storage when a tab is removed", async () => {
const { container } = render(
<Tab id="group-0" setTabTotal={mockSet} setGroups={mockSet} />
);
var removeTabSpy = jest.spyOn(TabFunc, "removeTab");
var chromeSetSpy = jest.spyOn(chrome.storage.local, "set");
fireEvent.click(container.querySelector(".close-tab"));
await waitFor(() => {
expect(chromeSetSpy).toHaveBeenCalled();
});
chrome.storage.local.get("groups", (local) => {
expect(init_tabs.length).toEqual(3);
expect(local.groups["group-0"].tabs.length).toEqual(2);
expect(removeTabSpy).toHaveBeenCalledTimes(1);
});
expect.assertions(4);
});
});