Expo secure-store unavailable in jest tests - react-native

This question is specifically about expo-secure-store and jest.
Currently, I am using expo-secure-store to store my JWT when logging in. It works fine when running on emulator however, it doesn't work at all in Jest tests; token comes back as undefined. I am able to call the functions like normal.
Excuse any typos I might have made refactoring this.
Calling from tests:
test('when logging in, given correct credentials, gets response token.', async () => {
try {
var token = await SecureStore.getItemAsync("token");
await SecureStore.setItemAsync('token', 'test');
token = await SecureStore.getItemAsync('token');
console.log(token);
expect(token).toBeDefined();
expect(token).toBe("test");
} catch (err) {
console.log(err);
throw err;
}
}
Question: Does expo-secure-store not load/work without an actual device/emulator?
There are no documentation at all about testing with secure-store and from what I can tell I might have to mock this module.

you have to mock any native module that you use because their implementations live primarily in native code that is intended to be run on ios and android devices. so the same applies here - you should mock expo-secure-store.

Related

How to test global middlware in expressJS?

This seems like a simple question, but I'm stumped. How do I test my expressjs middleware is setting up the user session properly?
app.use((req:Req, res:Response, next:NextFunction) => {
req.userSessionId = uuid();
next();
});
I am not sure how to test that an incoming request is being captured and setting the userSessionId correctly. I want something like
describe('setting up middleware', ()=> {
//instantiate the app
expect(app.use).tobeCalled();
expect(mockReq).toBeSetWith(userSessionId)
});
You can refactor your middleware code into a function, and write unit-tests that test this function logic.
Your unit tests, in my opinion (and others), should only test your code and avoid testing Express logic (calling your middleware). For this you should have integration tests which test your app is working properly as a whole
// This middleware code needs to be tested
const userSessionMiddleare = (req: Request, res:Response, next: NextFunction) => {
req.userSessionId = uuid();
next();
};
// This Express logic should not be unit-tested but rather tested in your integration testing
app.use(userSessionMiddleare);

How to Activate AppCheck on React Native in Debug

I am following the documentation https://rnfirebase.io/app-check/usage to use appcheck on React Native.
When I am testing in on my Emmulator, It is not responding to the realtime database requests.
All the requests are showing as unverified requests in firebase appcheck console.
When I went through the documentation : https://rnfirebase.io/app-check/usage#activate
It is written that :
On Android, App Check is not activated until you call the activate method. The provider is not configurable here either but if your app is "debuggable", then the Debug app check provider will be installed, otherwise the SafetyNet provider will be installed.
But process not given, how to activate ?
can some one please help me.
activate api is documented here https://rnfirebase.io/reference/app-check#activate
You can check a sample implementation in their e2e test script.
try {
await firebase.appCheck().activate();
// await firebase.appCheck().activate('ignored');
// await firebase.appCheck().activate('ignored', false);
} catch (e) {
console.log(e);
}

Use require('../assets/file.mp3') in ES6

I am trying to load a local mp3 file to be played using Expo Audio SDK.
Here's an example from the documentation:
const soundObject = new Audio.Sound();
try {
await soundObject.loadAsync(require('./assets/sounds/hello.mp3'));
await soundObject.playAsync();
// Your sound is playing!
} catch (error) {
// An error occurred!
}
I am also using ES6 in my project which makes require unavailable.
Is there any way I could still load a local resource in ES6?
As far as I know, require is still a thing in ES6. I've used it plenty of times throughout my apps. The example should work, have you tried it?

AsyncStorage is not returning the callback

I am using redux-persist in a react native project, that runs just fine in a broad number of devices except Android 7. I am trying to debug the problem on why my local storage is nor persisting and found this:
The following code executes inside React Native component lifecycle's
componentDidMount() {
attachObservables(store)
setInterval(async () => {
console.log('Inside setInterval')
const data = await AsyncStorage.getAllKeys()
console.log('inside the getAllKeys')
data.forEach(async k => {
const value = await AsyncStorage.getItem(k)
console.group(k)
console.log(value)
console.groupEnd()
})
}, 3000)
}
Code after 'Inside setInterval' is never called. It only runs once if outside the setInterval. If I call once the code outside the setInterval it appears to run just fine. I also tried callback format vs async / await version but it does not seem to matter.
Same problem I had using firebase js library (callbacks never return after the first one). I am now looking for alternatives to workaround the problem.
Any ideas?
As of React Native 0.51 in some Android versions, the runtime can get blocked by other native modules, impeding the resolution of the mentioned methods.
It can be fixed via https://github.com/facebook/react-native/issues/14101#issuecomment-345563563, ensuring this methods use a free thread from the thread pool.
A PR has been submitted and I hope that will be released in future versions. If you want it to use this fix right now, it is available here https://github.com/netbeast/react-native
EDIT:
I am not experiencing this anymore on real devices over react-native#0.53, anyhow others have also reported, so the issue is still open.

XMLHttpRequest is not defined when testing react-native app with jest

i am trying to test a apiwrapper in a react-native based app using jest (integration testing).
When i run it in the iOs simulator everything runs fine however it wont run my jest tests correctly - i always get:
ReferenceError: XMLHttpRequest is not defined
when i try to run tests using my api wrapper, eg.:
it('Login successful with correct data', () => {
let api = Api.getInstance();
return api.login("test", "testpass")
.then(result => expect(result).toEqual('login_successful'));
});
the api class i am trying to test here does use the fetch api (not vanilla xhr). I assume its something related to jest trying to mock something but have not found a way to make it work yet.
Thanks in advance.
In my case, I'm not testing the search code but only importing it somewhere in my code path, so I decided to just mock it at the global level in a setup.js file (loaded using --require at test run). The following works for me:
// needed in react-instantsearch
class XMLHttpRequest {}
global.XMLHttpRequest = XMLHttpRequest;
I had a similar problem with lokka using XMLHttpRequest. I made a mock for lokka, which my api wrapper class depends on. You could try mocking your api wrapper.
This is what my lokka mock looks like for now. I'll add more to it when I start testing error handling.
export default class {
query() {
return new Promise(resolve => {
resolve(200);
});
}
}
You might be able to mock your api wrapper with something similar:
export default class Api {
getInstance() {
\\ However you implemented getInstance
}
login(user, password) {
return new Promise(resolve => {
resolve('login_successful');
});
}
}