0

I'm working on a Angular 6 application with NGXS and I'm struggling with some tests...

One of our asynchronous action was returning a subscription, something like :

@Action(MyActions.MyAction, {cancelUncompleted: true})
myAction(ctx: StateContext<MyModel>) {
   return this.someHttpCall().subscribe(xxx => ctx.patchState({value: xxx}));
}

It was working well but the cancellation mechanism was not working because NGXS want us to return an observable and not a subscription so I fixed it following the guidelines (https://www.ngxs.io/advanced/actions-life-cycle#asynchronous-actions)

@Action(MyActions.MyAction, {cancelUncompleted: true})
myAction(ctx: StateContext<MyModel>) {
   return this.someHttpCall().pipe(tap(xxx => ctx.patchState({value: xxx})));
}

Now the cancellation mechanism is working but some tests failed because it seems the state is never patched.

I checked those links :

https://www.ngxs.io/recipes/unit-testing#testing-asynchronous-actions

Pipe and Tap VS subscribe with ngxs

And it seems I have to subscribe to the returned observable if I want the tap to be triggered so in my test I did something like this :

store.dispatch(new MyAction()).subscribe()

The subscribe in the test (last code) is called, the state is also called but the "tap" still never called...

I also try to change the state code to :

@Action(MyActions.MyAction, {cancelUncompleted: true})
myAction(ctx: StateContext<MyModel>) {
   return this.someHttpCall().pipe(tap(xxx => ctx.patchState({value: xxx}))).subscribe()
}

It works (the "tap" is called and the state is patched) but obviously the cancel mechanism is not working anymore...

Thanks in advance :-)

Arcord
  • 1,724
  • 1
  • 11
  • 16

1 Answers1

0

why don't you just follow reactive programming approach

@Action(MyActions.MyAction, {cancelUncompleted: true})
myAction(ctx: StateContext<MyModel>) {
   return from(this.someHttpCall()).pipe(
      tap(xxx => ctx.patchState({ value: xxx }))
   )
}
cagcak
  • 3,894
  • 2
  • 21
  • 22
  • My second code is using the pipe/tap as adviced by ngxs library but I do not unterstand the "from". An http call is already returning a observable so what is the point? Isn't my second code (the one we are currently using) already following the reactive programming approach ? – Arcord Apr 05 '21 at 15:45
  • I thought that your somehttpcall method is a promise so thats why its not patching but apparently not. so ignore that. normally ngxs handles both subscribing and unsubscribing itself. so no need to subscribe, but chaining subscribe method is a need to be ensure really subscribing and unsubscribing. unit testing must know it is handled. you may want to use reactive approach for your advanced test cases where the cancellation option is available. because it cancels current stream and switch it back to itself so you will never get the desired outcome – cagcak Apr 05 '21 at 19:48