In my react native project, I have recently installed node module react-native-async-storage as I received warnings about the native package from 'react-native' being deprecated and moved out to an individual module.
After installing the @react-native-community/async-storage
my jest test is failing.
first with following error: unexpected token at position 0
in file:
persistence.js
import AsyncStorage from '@react-native-community/async-storage';
storeData = async ({ key, value }) => {
try {
await AsyncStorage.setItem(key, value);
} catch (error) {
// Error saving data
}
}
retrieveData = async (key) => {
try {
const value = await AsyncStorage.getItem(key);
if (value !== null) {
// Our data is fetched successfully
return value;
}
} catch (error) {
// Error retrieving data
}
}
module.exports = {
storeData,
retrieveData
}
So I assume this is related to some babel configuration, since i encountered something similar last time i installed a package from the @react-native-community
So, to the transformIgnorePatterns
in my package.json I added following:
"jest": {
"preset": "react-native",
"transformIgnorePatterns": [
"node_modules/(?!react-native|@react-native-community/async-storage|native-base-shoutem-theme|@shoutem/animation|@shoutem/ui|tcomb-form-native)"
]
}
But now I'm getting a new error. @RNCommunity/AsyncStorage: NativeModule.RCTAsyncStorage is null.
I'm pasting the screenshot to show my project dir so that you can get an idea about which config files a have available to mess with.
As I can see most related topic are about mocking the asyncStorage function I've tried to do so, without any luck. I added following to my one and only tests file:
import MockAsyncStorage from 'mock-async-storage';
beforeAll(() => {
const mockImpl = new MockAsyncStorage()
jest.mock('AsyncStorage', () => mockImpl)
snapshot = renderer.create(<App />);
})
afterAll(() => {
jest.unmock('AsyncStorage')
});
Still no cigar. I have tried adding a setupFilesAfterEnv.js
with configurations as other answer suggests, also didn't do the trick.
Run yarn test to run tests with Jest. Let's create a snapshot test for a small intro component with a few views and text components and some styles: This is a React Native snapshot test. Now let's use React's test renderer and Jest's snapshot feature to interact with the component and capture the rendered output and create a snapshot file:
By default the jest-react-native preset only processes the project's own source files and react-native. If you have npm dependencies that have to be transformed you can customize this configuration option by including modules other than react-native by grouping them and separating them with the | operator:
Many react-native npm modules unfortunately don't pre-compile their source code before publishing. By default the jest-react-native preset only processes the project's own source files and react-native.
Mock native modules using jest.mock The Jest preset built into react-native comes with a few default mocks that are applied on a react-native repository. However, some react-native components or third party components rely on native code to be rendered. In such cases, Jest's manual mocking system can help to mock out the underlying implementation.
async-storage has published instructions on how to solve this issue.
Here is a shorten version:
export default from '@react-native-community/async-storage/jest/async-storage-mock'
I hope it can help others.
You can add this to your test file.
jest.mock("@react-native-community/async-storage", () =>
require("@react-native-community/async-storage/jest/async-storage-mock"),
);
For example
import React from "react";
jest.mock("@react-native-community/async-storage", () =>
require("@react-native-community/async-storage/jest/async-storage-mock"),
);
describe("Example test", () => {
it("should work", () => {
...
});
});
I found a way of mocking the @react-native-community/async-storage
in root of my project, (same dir as __test__
dir), I created a dir structure like this:
__mocks__/@react-native-community/async-storage/index.js
in index.js I mocked the following functions:
let cache = {};
export default {
setItem: (key, value) => {
return new Promise((resolve, reject) => {
return (typeof key !== 'string' || typeof value !== 'string')
? reject(new Error('key and value must be string'))
: resolve(cache[key] = value);
});
},
getItem: (key, value) => {
return new Promise((resolve) => {
return cache.hasOwnProperty(key)
? resolve(cache[key])
: resolve(null);
});
},
removeItem: (key) => {
return new Promise((resolve, reject) => {
return cache.hasOwnProperty(key)
? resolve(delete cache[key])
: reject('No such key!');
});
},
clear: (key) => {
return new Promise((resolve, reject) => resolve(cache = {}));
},
getAllKeys: (key) => {
return new Promise((resolve, reject) => resolve(Object.keys(cache)));
},
}
in my test file i added this:
beforeAll(() => {
jest.mock('@react-native-community/async-storage');
})
Screenshot of dir structure:
This did the trick. I found inspiration here: https://github.com/react-native-community/react-native-async-storage/issues/39
You need to add this piece of code to your setupTestFrameworkScriptFile
import { NativeModules } from 'react-native';
NativeModules.RNCAsyncStorage = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
mergeItem: jest.fn(),
clear: jest.fn(),
getAllKeys: jest.fn(),
flushGetRequests: jest.fn(),
multiGet: jest.fn(),
multiSet: jest.fn(),
multiRemove: jest.fn(),
multiMerge: jest.fn(),
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With