Closed ysyyork closed 6 years ago
@ysyyork I apologize for the long delay (see #146). Since we can't get a handle to the promise (and thus have the test runner hook in and wait on it to resolve), there are at least two other options that, while they're not as clean as returning the promise in a beforeEach
or using a done
callback, they still work:
(forgive me - this is psuedo code I've pulled out of thin air)
describe( "when moving to B state" , () => {
let transitionArgs, backend, parameters;
beforeEach( ( done ) => {
backend = {
call: sinon.stub().resolves( { fakeValidData: true } )
};
parameters = { whateverMockParamsYouNeed: true };
const fsm = new machina.Fsm( {
eventListeners: {
transitioned: [
( { fromState, toState } ) => {
transitionArgs = [ fromState, toState ];
done();
}
]
},
states: {
A: {
_onEnter: function() {
backend.call( parameters ).then( data => {
if ( isValid( data ) ) {
this.transition( "B" );
}
} );
}
},
B: {}
}
} );
} );
it( "should call the backend", () => {
backend.call.should.be.calledOnce.and.calledWith( parameters );
} );
it( "should transition to B state", () => {
transitionArgs.should.eql( [ "A", "B" ] );
} );
} );
describe( "when moving to B state" , () => {
let thenableStub, backend, parameters, fsm;
beforeEach( ( done ) => {
thenableStub = {
then: sinon.stub().callsArgWith( 0, { fakeValidData: true } )
};
backend = {
call: sinon.stub().returns( thenableStub )
};
parameters = { whateverMockParamsYouNeed: true };
fsm = new machina.Fsm( {
states: {
A: {
_onEnter: function() {
backend.call( parameters ).then( data => {
if ( isValid( data ) ) {
this.transition( "B" );
}
} );
}
},
B: {}
}
} );
} );
it( "should call the backend", () => {
backend.call.should.be.calledOnce.and.calledWith( parameters );
} );
it( "should transition to B state", () => {
fsm.state.should.equal( "B" );
} );
} );
In case you're not familiar with some of the test assertion calls, it's worth checking out these libs:
Problem description
I have a fsm that when it enters state A, it will make a call to backend server and then transition to a new state. The backend call is async. I want to test this flow. I mocked backend call and want to assert the transition method being called after the call returns. But the test won't wait until the call gets back. So it will complain that transition is not called.
Typically to test async functions, I will use done() passed in as a callback function argument. But in this case, since I write the whole function inside the state. I don't know how to pass in argument. Do you have any suggestions in this case?
Below is a simplified version of my code:
Thank you so much