How to test 'ErrorAlert' which is using native 'Alert' ?
Closed this issue · 12 comments
Hello,
This is not an issue, but rather a question.
I would like to test (thanks to Jest) my 'ErrorAlert' component, which is exactly the same as snowflake except that it uses the native 'Alert' rather than 'SimpleAlert'.
I tried to test it the same way @bartonhammond does but no results, do you guys have any ideas ?
Here is my ErrorAlert :
'use strict';
import {Alert} from 'react-native';
import _ from 'underscore';
var ErrorAlert = class ErrorAlertClass{
checkError(obj) {
let errorMessage = '';
if (!_.isNull(obj) && !_.isUndefined(obj)) {
if (!_.isUndefined(obj.error)) {
if (!_.isUndefined(obj.error.error)) {
errorMessage = obj.error.error;
} else {
errorMessage = obj.error;
}
} else {
errorMessage = obj;
}
if (errorMessage !== '') {
if (!_.isUndefined(errorMessage.message)) {
Alert.alert("Une erreur s'est produite",errorMessage.message);
} else {
Alert.alert("Une erreur s'est produite",errorMessage);
}
}
}
}
};
module.exports = ErrorAlert;
And my actual test (I tried several tests) :
'use strict';
import 'react-native';
import React from 'react';
var Alert = require('react-native');
Alert.alert = jest.genMockFunction();
var ErrorAlert = require('../ErrorAlert');
describe('ErrorAlert', () => {
it('should be fine', () => {
const errorAlertProps = {
error: {
error: 'Error occurred'
}
};
new ErrorAlert().checkError(errorAlertProps);
expect(Alert.alert.mock.calls[0][0]).toEqual("Error");
expect(Alert.alert.mock.calls[0][1]).toEqual(errorAlertProps.error.error);
});
});
I know I'm missing something... :/
Note how I am mocking out the react-native-simpledialog-android
object. See src/__mocks__/react-native-simpledialog-android.js
.
I'm not sure if defining the mock w/in the test class works. You might want to dump that object to the console.log to confirm you are getting that Alert as a mock.
Please provide the output from the test run npm run test src/components/__tests__/ErrorAlert-test.js
Thank you for your fast answer.
Here is my "Alert" log :
{ ActivityIndicator: [Getter],
[...]
PointPropType: [Getter],
addons:
{ LinkedStateMixin: [Getter],
Perf: [Getter],
PureRenderMixin: [Getter],
TestModule: [Getter],
TestUtils: [Getter],
batchedUpdates: [Getter],
createFragment: [Getter],
update: [Getter] },
hasReactNativeInitialized: false,
findNodeHandle: [Function: findNodeHandle],
render: [Function],
unmountComponentAtNode: [Function],
unstable_batchedUpdates: [Function: batchedUpdates],
unmountComponentAtNodeAndRemoveContainer: [Function],
alert:
{ [Function]
_isMockFunction: true,
getMockImplementation: [Function],
mock: { calls: [], instances: [] },
mockClear: [Function],
mockReturnValueOnce: [Function],
mockReturnValue: [Function],
mockImplementationOnce: [Function],
mockImpl: [Function],
mockImplementation: [Function],
mockReturnThis: [Function] } }
I just tried your exact implementation (but with Alert) I've the exact same output as before, which is :
Using Jest CLI v14.1.0, jasmine2, babel-jest, jest-react-native preset
FAIL src\components\__tests__\ErrorAlert-test.js (5.003s)
ErrorAlert › it should be fine
- TypeError: Cannot read property '0' of undefined
at Object.<anonymous> (src\components\__tests__\ErrorAlert-test.js:51:37)
ErrorAlert
✕ it should be fine (33ms)
1 test failed, 0 tests passed (1 total in 1 test suite, run time 12.332s)
-----------------------|----------|----------|----------|----------|----------------|
File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
-----------------------|----------|----------|----------|----------|----------------|
components\ | 86.11 | 61.54 | 100 | 82.35 | |
ErrorAlert.js | 86.11 | 61.54 | 100 | 82.35 | 37,40,44 |
components\__tests__\ | 92.31 | 75 | 100 | 90.91 | |
ErrorAlert-test.js | 92.31 | 75 | 100 | 90.91 | 52 |
-----------------------|----------|----------|----------|----------|----------------|
All files | 87.76 | 63.33 | 100 | 85.71 | |
-----------------------|----------|----------|----------|----------|----------------|
I'm a little lost. Thanks again for your precious help.
It seems like, indeed I have a mocked Alert but the call made by "ErrorAlert().checkError(errorAlertProps):", do not fill the mock.calls array - when I log it, it is just an empty array.
Note TypeError: Cannot read property '0' of undefined
. I would update the test after this line new ErrorAlert().checkError(errorAlertProps);
to dump the mocked object (e.g. console.log(Alert.alert))
You need to see what values are actually in that mocked object.
I agree, I already logged it (see the last two lines of my precedent post).
I'm not sure I understand what you mean by "update the test". How would you do that ?
Here is the logs (right after new ErrorAlert().checkError(errorAlertProps);
) :
Alert.alert.mock : { calls: [], instances: [] }
Alert.alert :
function () {
instances.push(this);
calls.push(Array.prototype.slice.call(arguments));
if (this instanceof f) {
// This is probably being called as a constructor
prototypeSlots.forEach(slot => {
// Copy prototype methods to the instance to make
// it easier to interact with mock instance call and
// return values
if (prototype[slot].type === 'function') {
const protoImpl = this[slot];
this[slot] = generateFromMetadata(prototype[slot]);
this[slot]._protoImpl = protoImpl;}});
// Run the mock constructor implementation
return mockImpl && mockImpl.apply(this, arguments);}
let returnValue;
// If return value is last set, either specific or default, i.e.
// mockReturnValueOnce()/mockReturnValue() is called and no
// mockImplementationOnce()/mockImplementation() is called after that.
// use the set return value.
if (isReturnValueLastSet) {
returnValue = specificReturnValues.shift();
if (returnValue === undefined) {
returnValue = defaultReturnValue;}}
// If mockImplementationOnce()/mockImplementation() is last set,
// or specific return values are used up, use the mock implementation.
let specificMockImpl;
if (returnValue === undefined) {
specificMockImpl = specificMockImpls.shift();
if (specificMockImpl === undefined) {
specificMockImpl = mockImpl;}
if (specificMockImpl) {
return specificMockImpl.apply(this, arguments);}}
// Otherwise use prototype implementation
if (returnValue === undefined && f._protoImpl) {
return f._protoImpl.apply(this, arguments);}
return returnValue;}
What I meant is to update the test like this, so that after the checkError
, you dump the mock object
new ErrorAlert().checkError(errorAlertProps);
console.log(Alert.alert.mock.calls); //<<<<<< add this
//expect(Alert.alert.mock.calls[0][0]).toEqual("Error");
//expect(Alert.alert.mock.calls[0][1]).toEqual(errorAlertProps.error.error);
Alright then, that is exactly what I've done.
The Alert.alert.mock.calls
array is empty but I don't understand why. :|
One thing I'm concerned about, I don't like that the mock object is defined w/in the __test__
class. I'm not sure that the ErrorAlert
class will pick up that mock. Try moving the implementation to src/__mocks__/Alert.js
similar to src/__mocks__/react-native-simpledialog-android.js
.
See if that makes a difference. I suspect the test class knows about the mock but the ErrorAlert
class, which is being test, does not.
I think having the mock
defined in the location that Jest defines is the correct design pattern and I've had very good success with it.
Since Alert
is a node_module
, the proper way, or recommended way, to mock it is put it in the top level directory so that all references to it will pick it up automatically. That's why the react-native-simpledialog-android.js
is declared there.
If moving the mock
class to src/__mocks__
doesn't provide any insight, then I would suspect the implementation code of the ErrorAlert
class.
Try putting a debugger
statement in your ErrorAlert
class and, from the snowflake
terminal, enter npm run test-chrome src/components/__tests__/ErrorAlert-test.js
and try debugging it.
Thank you for all your time and effort. I've already tried to move the implementation to src/__mocks__/Alert.js
and implement it exactly the same way as you do but without success. In fact I obtain the exact same result w/ your implementation or mine.
I will try to debug ErrorAlert
monday and edit this post with fresh news.
Thank you again.
I would recommend staying with the mocks location for consistency.
Good luck...let me know how it goes.
On Aug 26, 2016 12:45 PM, "Brokray" notifications@github.com wrote:
Thank you for all your time and effort. I've already tried to move the
implementation to src/mocks/Alert.js and implement it exactly the
same way as you do but without success. In fact I obtain the exact same
result w/ your implementation or mine.I will try to debug ErrorAlert monday and edit this post with fresh news.
Thank you again.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#131 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABORPA7-cPLltHwqj1WbjRup06Vtr8iBks5qjyZMgaJpZM4JtCnO
.
@Brokray , any update on this?
@bartonhammond Not really, I didn't find anything to debug in my ErrorAlert.js.
At the moment I put this aside because I've other tasks to fulfil.
I will continue this a bit later and let you know how it goes. Thanks again for all your help.
I think I've answered this as best I can and have nothing more to contribute.