Am a newborn in sinon.js, mocha, chai.
Am trying to write unit-test by using above libraries.
Project Front-End is in AngularJS with the combination of ECMASCRIPT6.
From the docs of Sinonjs I understand nothing! It's complicated.
Here is my JS Snippet:
login() {
let loginData = this.loginData;
return this.authService.login(loginData).then(userData => {
let msg = `${this.niceToSeeYouAgain} ${userData.email}!`;
this.userAlertsService.showSuccessToast(msg);
this.navigationService.afterLoggedIn();
}, errorInfo => {
this.userAlertsService.showAlertToast(errorInfo);
});
}
And here is my UNIT-TEST snippet:
it('.login() - should load user data and showSuccessToast and call navigationService afterLoggedIn', sinon.test(() => {
let msg = `Nice to see you again ${userData.email}!`;
let loginData ={
email: "sarfaraz#walkover.in",
password: "designer99",
remember: true
}
let stub = sinon.stub(authService, 'login').resolves(userData);
// let spy1 = sinon.spy(controller.userAlertsService, 'showSuccessToast');
//call function
controller.login();
$timeout.flush();
// expect things
expect(stub.called).to.eq(true);
// restore
stub.restore();
}));
But unfortunately am stucked.
My code not runs after .then lines.
am expecting it should throws error. cause I have not spies on userAlertsService and navigationService.
Please let me know what am doing wrong
Related
I changed the code in a module and now when I run 'npm run build' I get the above error, altough the code works just fine on my local host! Is there a work around to make it work?
value: function render() {
var _props2 = this.props,
onPlaceSelected = _props2.onPlaceSelected,
types = _props2.types,
componentRestrictions = _props2.componentRestrictions,
bounds = _props2.bounds,
rest = _objectWithoutProperties(_props2, ['onPlaceSelected', 'types', 'componentRestrictions', 'bounds']);
return _react2.default.createElement('input', _extends({
ref: 'input',
onChange: (e) => {
if (!e.target.value) {
this.props.haveri(null)
} else {
let a = e.target.value;
var options = {
types: ['(cities)'] //this should work !
};
The error specifies the line with 'onChange: (e) => {', it's a code that I added to manipulate the module.
Thanks in advance
The module code you shared looks like it's already transpiled, so the arrow function might be off there as well as the let inside.
Try changing both, the arrow function for a normal function declaration and the let for a var and see how it goes.
I have an action in my ReactJS project that calls a notification service. It is required that, if the service call fails once, I must try calling the service again only one time before proceeding with the error state in the application. I used the promise-retry module for this and was able to get it working locally. However, I am now trying to write unit tests (Mocha) for the promiseRetry-wrapped service calls themselves and having incredible difficulty getting meaningful tests to pass. First, here is the action that calls the service, wrapped in a promiseRetry.
import promiseRetry from 'promise-retry';
...
const sendNotification = () => {
return (dispatch, getState) => {
const request = buildNotificationRequest(getState);
dispatch(createNotificationAttempt());
promiseRetry((retry) => {
return createNotificationService(request)
.catch(retry);
}, {retries: 1}).then(
() => {
dispatch(createNotificationSuccess());
},
(error) => {
dispatch(createNotificationError(error));
}
);
};
};
Typically, the way that I would write unit tests for actions calling services is something like this:
describe('notification actions', () => {
beforeEach(() => {
sendNotification = sinon.stub(services, 'createNotificationService').returns(Promise.resolve({}));
});
it('should log an attempt', () => {
store.dispatch(notificationActions.sendNotification());
const actions = store.getActions();
expect(actions[0].type).to.equal(notificationActions.ACTION_TYPES.CREATE_NOTIFICATION_ATTEMPT);
});
});
This works fine for testing the initial attempt, but for some reason, even though I can debug and step through the tests and hit all of the code inside the promiseRetry, the actions inside of them (such as dispatch(createNotificationSuccess())) are not logged in the store, so I cannot run expect statements on them. Every angle I have tried up to this point only retrieves the attempt from the store, and I cannot get any data from the success or failure side of the Promise.
I have found some information on Stack Overflow about testing promise-retry itself, but I need to know that if I stub the service I'm calling and force it to fail, that it will log another attempt and another failure. Or, if I stub the service and force it to succeed, it will only log one attempt, one success, and complete. As I mentioned previously, the only action I am getting in the store is the attempt, and nothing about success or failure, even though stepping through debug shows that all of those lines of code are hit.
Here is an example of a test that I cannot get to pass:
import * as services from 'services.js';
...
describe('the first time the service call fails', () => {
const error = {status: 404};
beforeEach(() => {
sendNotification = sinon.stub(services, 'createNotificationService').returns(Promise.reject(error));
});
it('should log a retry', () => {
store.dispatch(notificationActions.sendNotification());
const actions = store.getActions();
expect(actions[0].type).to.equal(notificationActions.ACTION_TYPES.CREATE_NOTIFICATION_ATTEMPT); // this passes
expect(actions[1].type).to.equal(notificationActions.ACTION_TYPES.CREATE_NOTIFICATION_FAILURE); // this fails because there are no other actions logged in the store.
Maybe I am misunderstanding the way promise-retry works? Shouldn't it hit my error action (dispatch(createNotificationError(error)) the first time it fails, and the second time (if applicable)? If not, it should be at least logging two attempts. Any advice?
I am very new to Jasmine and struggle with its concepts. I would like to test if an array 'reduce' has been called.
export class QuestionController implements Controller {
private questionnaireList: Questionnaire[];
private questionList: Question[];
I build a select table that I want to test:
buildSelect(): void {
let options = this.questionnaireList.reduce((result, qset) => result + this.templateForQuestionnaire(qset), '');
let select = this.util.getElementById('quest-select');
select.innerHTML = options;
}
I have tried things like:
beforeEach(() => {
spyOn(dummyQuestionnaireList, "reduce");
spyOn(qc, "buildSelect").and.callThrough();
});
it('should call reduce on this.questionnaireList', () => {
qc.buildSelect();
expect(dummyQuestionnaireList.reduce).toHaveBeenCalled();
});
it('should call util.getElementById', () => {
qc.buildSelect();
expect(u.getElementById).toHaveBeenCalled();
});
but I really have no idea what I am doing, in that I cannot even identify which tools are the right tools from Jasmine from its docs page.
I'm having problems using findOne because it always returns undefined.
This code:
Routine.js
Meteor.methods({
.... // Some lines missing
'routines.getRoutine'(routineId) {
check(routineId, String);
return Routines.findOne(routineId);
},
});
Note: If I do a console.log of Routines.findOne(routineId) it correctly shows the element that i'm looking for.
App.jsx
handleSubmit(event) {
event.preventDefault();
const comment = ReactDOM.findDOMNode(this.refs.comment).value.trim();
Meteor.call('routines.addComment', this.state.routine._id, comment);
let a = Meteor.call('routines.getRoutine', this.state.routine._id);
ReactDOM.findDOMNode(this.refs.comment).value = '';
this.setState({
routine: a,
});
}
In my Appjs doesn't matter how I try 'a' is always undefined, what am I doing wrong?
Thanks for the help in advance!
I'm pretty sure your problem is that Meteor calls on the client are async and so the method you're calling hasn't completed by the time you're querying the same data.
Try putting the rest of the code in the callback like so:
handleSubmit(event) {
event.preventDefault();
const comment = ReactDOM.findDOMNode(this.refs.comment).value.trim();
Meteor.call('routines.addComment', this.state.routine._id, comment, function() {
let a = Meteor.call('routines.getRoutine', this.state.routine._id);
ReactDOM.findDOMNode(this.refs.comment).value = '';
this.setState({
routine: a,
});
});
}
Am trying to invoke fail condition in my snippet.
But when I use sinon.stub().throws() method It shows me error.
Am unable to handle it in code.
Here is my snippet:
login() {
let loginData = this.loginData;
return this.authService.login(loginData).then(userData => {
let msg = `${this.niceToSeeYouAgain} ${userData.email}!`;
this.userAlertsService.showSuccessToast(msg);
this.navigationService.afterLoggedIn();
//above lines are covered in test cases
}, errorInfo => {
// below line are needed to test
this.userAlertsService.showAlertToast(errorInfo);
});
}
**And here is my unit-test snippet: **
it('.login() - should throw exception - in failure case', sinon.test(() => {
let errorInfo = "some error";
let stub = sinon.stub(authService, 'login').throws();
let spy1 = sinon.spy(controller.userAlertsService, 'showAlertToast');
//call function
controller.login();
// $timeout.flush();
// expect things
console.log(stub.callCount, stub.args[0]);
}));
Please let me know what am doing wrong
You need to wrap the function that you know is going to fail, and then call it. e.g.
it('handles errors in methodThatCallsAnotherFailingMethod', function() {
error = new Error("some fake error");
sandbox.stub(SomeObject, "doSomething").throws(error);
call = function() {
// methodThatCallsAnotherFailingMethod calls SomeObject.doSomething()
methodThatCallsAnotherFailingMethod();
};
expect(call).to.throw(Error);
});
When testing (or spying on) other stuff in methodThatCallsAnotherFailingMethod you can do this in your test:
try {
call();
} catch (error) {
expect(MySpy).to.have.been.calledWith(error);
}
This question is a month old as of this answer, but I encountered a similar error, and Google hasn't yielded any explanation for this behavior. I wanted to test the failure branch of my login as well, and stub.throws() actually threw the error (causing the test to fail) instead of rejecting the login promise. If anyone knows why this happens, I'd appreciate it.
In any case, this is what worked for me:
let d = Q.defer(); // Or whichever promise library you use
d.reject(); // Force the promise to fail
let stub = sinon.stub(authService, 'login').returns(d.promise); // Should do what you want
// The rest of the test