Create a working chrome.storage and fetch() for your Chrome/edge browser extension during jest

Elvis Ciotti
2 min readOct 3, 2023

--

If you need to define a global chrome storage object during Jest runs, you can do that via setupFilesAfterEnv (See related jest config).

In your jest.config.js add this line



module.exports = {
...
setupFilesAfterEnv: ['./jest.mocks.js'],
};

And define jest.mocks.js as follows

let localStorage = {}
let syncStorage = {}
const R = require('ramda');

global.chrome = {
storage: {
local: {
clear: () => {
localStorage = {}
},
set: (toMergeIntoStorage) => {
localStorage = {...localStorage, ...toMergeIntoStorage}
},
get: (keysToInclude) => {
return R.pick(keysToInclude, localStorage);
}
},
sync: {
clear: () => {
syncStorage = {}
},
set: (toMergeIntoStorage) => {
syncStorage = {...syncStorage, ...toMergeIntoStorage}
},
get: (keysToInclude) => {
return R.pick(keysToInclude, syncStorage);
}
}
}
}

Note: you need to add rambda (yarn add ramda --dev).

Your tests using chrome storage will now store and return data in memory.

To wipe the content before each test, you can add this into a beforeEach. See also this test verifying the behaviour.

beforeEach(() => {
chrome.storage.local.clear();
chrome.storage.sync.clear();
});

describe("chrome.storage", () => {
const id = 'id.name';
const dataElements = ['data', 1.2, {a: {b: [1, 2]}}];
for (const data of dataElements) {
it(`local persist + load ${JSON.stringify(data)}`, async () => {
await chrome.storage.local.set({[id]: data});
expect(await chrome.storage.local.get([id])).toEqual({[id]: data});
expect(await chrome.storage.local.get('not existing')).toEqual({});
});
}
for (const data of dataElements) {
it(`local persist + load ${JSON.stringify(data)}`, async () => {
await chrome.storage.local.set({[id]: data});
expect(await chrome.storage.sync.get([id])).toEqual({[id]: data});
expect(await chrome.storage.sync.get('not existing')).toEqual({});
});
}
})

Using a similar approach you can mock functions, like fetch . If you place this code into the jest.mocks.js the calls to fetch() will return the invoking params…



global.fetchLastCallParams = {}
global.fetch = async (url, params) => {
global.fetchLastCallParams = {url, ...params};
return {
status: 200,
json: async () => {
return {
jest: true,
url,
...params
}
}
};
}

So that you can verify the from the jest test accessing the global variable.

// @ts-ignore
expect(global.fetchLastCallParams).toEqual({
url: "http://S...",
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(...)
});

Note that you can’t override global constants this way. To override a global constant, do the following at the top of your jest

jest.mock("../path/to/file-with-constant", () => ({
__esModule: true,
MY_CONSTANT: "my value"
}))

Correct what I wrote if you know more, I’m a Java backend and I don’t normally do Typescript

--

--

Elvis Ciotti
Elvis Ciotti

Written by Elvis Ciotti

Software Contractor — Java, Spring, k8s, AWS, Javascript @ London - hire me at https://elvisciotti.github.io/

No responses yet