apollo-angular icon indicating copy to clipboard operation
apollo-angular copied to clipboard

Testing, flushing, and async expect - how is it done?

Open 0b10 opened this issue 5 years ago • 1 comments

I have a service class that looks like:

class PostDetailService {
  public post: IPost;
  getPostSub(): Subscription { /* ... */ } 
}

post is not observable, and the template uses the injected service properties directly: {{ service.post }} for example. The template is aware of changes, but I don't know how to await for changes after flushing in tests - see below:

const getFixtures = () => {
  TestBed.configureTestingModule({
    providers: [GetPostsGqlService, { provide: ConsoleLoggerService, useClass: NoopLoggerService }],
    imports: [ApolloTestingModule],
  });

  const controller: ApolloTestingController = TestBed.get(ApolloTestingController);
  const service: PostDetailService = TestBed.get(PostDetailService);

  return { controller, service };
};

fit('should initialise the post property', () => {
      const { controller, service } = getFixtures();
      const id = 1;
      const fakePost = getFakePost({ overrides: { id } });

      expect(service.post).toBeUndefined();

      service.getPostSub(id);
      controller.expectOne('getPost').flush({
        data: {
          post: fakePost, // { id, title, subtitle, ... }
        },
      });

      setTimeout(() => {
        // FIXME: service.post is not observable, how can this be 'waited' for? (instead of a timeout)
        expect(service.post).toEqual(fakePost);
      }, 200);

      controller.verify();
    });

What is the recommended way to deal with this?

0b10 avatar Jan 23 '20 12:01 0b10

You could use something like this:

const ongoingRequest$ = service.getPostSub(id);
/* expectOne */

// first() to  take the first response that comes
// await to block execution until some response came
await ongoingRequest$.pipe(first()).toPromise();

MarcusRiemer avatar Mar 31 '21 21:03 MarcusRiemer