Estoy usando xstate para implementar un flujo de inicio de sesión. Tengo una máquina en la que initialState invoca una Promesa y, si se rechaza, se redirigirá a un estado que tiene una acción de entry . Me gustaría probar que la acción se llama en el momento adecuado correctamente.
máquina.ts
{ id: 'entrance', initial: States.FETCHING_SESSION, states: { [States.FETCHING_SESSION]: { invoke: { src: 'fetchSession', onError: { target: States.LOGGED_OUT, } } }, [States.LOGGED_OUT]: { entry: ['navigateToLogin'] type: 'final' }, } }máquina.spec.ts
const mockFetchSession = jest.fn() .mockRejectedValueOnce({ error: new Error('401 unauthorized') }) const mockNavigateToLogin = jest.fn() const service = interpret(entranceMachine.withConfig({ services: { fetchSession: mockFetchSession }, actions: { navigateToLogin: mockNavigateToLogin } })) it('Goes to login page on fail', (done) => { service.onTransition((state) => { expect(state.matches(States.LOGGED_OUT)) expect(mockNavigateToLogin).toHaveBeenCalled() // <- this test case always fails done() }) service.start() })Me las arreglé para hacer que funcionara de una manera un poco fea envolviendo expect alrededor de un setTimout.
setTimeout(() => expect(mockNavigateToLogin).toHaveBeenCalled(), 100)Me pregunto si hay una mejor opción? Gracias
Primero, sospecho que setTimeout simplemente se salta la espera...
Me encontré con el mismo problema al usar withConfig . Las acciones, al menos, no se llaman en absoluto, incluso si aparecen en machine.options.actions .
Mi código se ve así:
const myAction = jest.fn(); const actions = { myAction }; const withCfg = machine.withConfig({ actions, }); const spy = jest .spyOn(actions, 'myAction') .mockImplementation(() => myAction()); // ... expect(spy).toHaveBeenCalledTimes(1);Tenga en cuenta que en la aplicación esas acciones se ejecutan bien