react-native-sensitive-info
react-native-sensitive-info copied to clipboard
Jest cannot read property setItem
I have a little problem with Jest. When I try to test a function using SInfo jest crash and says :
TypeError: Cannot read property 'setItem' of undefined
Do you have any hint ?
I had the same issue, i made a PR, which is already merged. Should be fixed in version 5.2.6. Could you check your version?
Ok I was on 5.2.4, I upgrade this dependency but that change nothing. Did I miss something ?
I'm still having this problem with the version "5.3.0"
Same issue version 5.4.0, trying to make a mock.
TypeError: _reactNativeSensitiveInfo.default.deleteItem is not a function
Similar issue with 5.4.1
TypeError: _reactNativeSensitiveInfo.default.getItem is not a function
I am also having this issue when attempting:
const key = "buzzes"
var value = JSON.stringify(this.state.buzzes)
await SInfo.setItem(key, value, {});
TypeError: _reactNativeSensitiveInfo.default.getItem is not a function
Well in my case
$ cd ios
$ pod install
$ cd ..
this works for me...
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I have a little problem with Jest. When I try to test a function using SInfo jest crash and says :
TypeError: Cannot read property 'setItem' of undefined
Do you have any hint ?
I'm still having this issue with 6.0.0-alpha.6
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
You can create a mock for it. I created a simple one that satisfies my needs without needing to mock every function. Got some inspiration in @react-native-async-storage/async-storage mock.
__mocks__/react-native-sensitive-info.js:
const asMock = {
__INTERNAL_MOCK_STORAGE__: {},
getItem: jest.fn(async (key, options) => {
const storeName = _getStoreName(options);
const result = asMock.__INTERNAL_MOCK_STORAGE__[storeName]
? asMock.__INTERNAL_MOCK_STORAGE__[storeName][key]
: undefined;
return result;
}),
setItem: jest.fn(async (key, value, options) => {
const storeName = _getStoreName(options);
if (asMock.__INTERNAL_MOCK_STORAGE__[storeName] === undefined) {
asMock.__INTERNAL_MOCK_STORAGE__[storeName] = {};
}
asMock.__INTERNAL_MOCK_STORAGE__[storeName][key] = value;
return null;
}),
};
const _getStoreName = options =>
options.sharedPreferencesName || options.keychainService || 'default';
module.exports = asMock;
And when I need to mock a specific result in a test:
it('should mock', () => {
const sensitiveInfoMock = jest.spyOn(RNSInfo, 'getItem');
sensitiveInfoMock.mockImplementation(async () => 'specific value');
// ... test
sensitiveInfoMock.mockRestore();
});
If someone can mock all functions using the "options" object, I bet a PR would be welcome.
PS: The code above won't distinguish iOS and Android for sharedPreferencesName
and keychainService
due to _getStoreName
implementation being unware of the current platform.
Blind code so take it for what it is...
// __mocks__/react-native-sensitive-info.js
class RNSInfo {
static stores = new Map()
static getServiceName(o) {
return o.sharedPreferencesName
|| o.keychainService
|| 'default'
}
static validateString(s){
if (typeof s !== 'string') throw new Error('Invalid string:', s)
}
static getItem = jest.fn(async (k, o) => {
RNSInfo.validateString(k)
const serviceName = RNSInfo.getServiceName(o)
const service = RNSInfo.stores.get(serviceName)
if(service) return service.get(k) || null
})
static getAllItems = jest.fn(async (o) => {
const serviceName = RNSInfo.getServiceName(o)
const service = RNSInfo.stores.get(serviceName)
const mappedValues = []
if(service?.size){
for(const [k, v] of service.entries()){
mappedValues.push({key: k, value: v, service: serviceName})
}
}
return mappedValues
})
static setItem = jest.fn(async (k, v, o) => {
RNSInfo.validateString(k)
RNSInfo.validateString(v)
const serviceName = getServiceName(o)
let service = RNSInfo.stores.get(serviceName)
if (!service){
RNSInfo.stores.set(serviceName, new Map())
service = RNSInfo.stores.get(serviceName)
}
service.set(k, v)
return null
})
static deleteItem = jest.fn(async (k, o) => {
RNSInfo.validateString(k)
const serviceName = RNSInfo.getServiceName(o)
const service = RNSInfo.stores.get(serviceName)
if (service) service.delete(k)
return null
})
static hasEnrolledFingerprints = jest.fn(async () => true)
static setInvalidatedByBiometricEnrollment = jest.fn()
// "Touch ID" | "Face ID" | false
static isSensorAvailable = jest.fn(async () => 'Face ID')
}
module.exports = RNSInfo
For some reason writing the mocks as __mocks__/react-native-sensitive-info.js
didn't work for me.
So I added it inside jest.setup.js
file
jest.mock('react-native-sensitive-info', () => {
// your mock here
});
Had to change the contents of __mocks__/@react-native-async-storage/async-storage.js
to:
const asyncMock = require('@react-native-async-storage/async-storage/jest/async-storage-mock')
export default asyncMock
The import from the corresponding d.ts
file is just the type, so AsyncStorage
object is empty. Haven't looked into root causing this though.