angular: fakeAsync cannot work with FileReader event

verison

zone.js: 0.8.26

issue

For testing the FileReader event, like onload, if with setTimeout, test case can pass, while with fakeAsync, failed. The below is the code that can reproduce this issue and can just be pasted in the current test spec and run

// function need to be tested
function fileReaderTest(blob: Blob): number {
  const reader = new FileReader();

  let num = 0;

  reader.onload = () => {
    num++;
  };

  reader.readAsText(blob);

  return num;
}

// test the above function
fdescribe('', () => {
  let blob: Blob;

  beforeEach(() => {
    const data = 'Hello, World!';
    blob = new Blob([data]);
  });

  // can pass
  it('with setTimeout', () => {
    const number = fileReaderTest(blob);

    setTimeout(() => {
      expect(number).toEqual(1);
    });
  });

  // fail
  it('with fakeAsync', () => {
    let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec'];
    let testZoneSpec: any;
    let fakeAsyncTestZone: Zone;

    testZoneSpec = new FakeAsyncTestZoneSpec('name');
    fakeAsyncTestZone = Zone.current.fork(testZoneSpec);

    const num = fileReaderTest(blob);

    fakeAsyncTestZone.run(() => {

      testZoneSpec.tick(100);
      testZoneSpec.tick(100);
      testZoneSpec.flush(); 
      testZoneSpec.flushMicrotasks();
      expect(num).toEqual(1);
    });
  });
});

Background

Today when I tried to write some unit tests for a function with FileReader, I got this issue. But I’m not sure if it’s really a bug or just my misuse.

thanks

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 5
  • Comments: 17 (8 by maintainers)

Most upvoted comments

@JiaLiPassion I think Image is not supported by fakeAsync either if you have a chance to look at it.

The workaround is to not use fakeAsync or async. Will have to resort to good ol Jasmine done().

Here’s a working example https://stackblitz.com/edit/writing-ng-test-for-filereader.

P.S: it’s code to my usecase but I reckon it highlights how to test with FileReader in mind

I will begin to work on this soon.

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular’s feature request process in our documentation.

Any updates?

@Teamop That unfortunately does not work, see #1169

@Teamop, FileReader is not supported by fakeAsync by default because it is not a timer related async operation, and currently, FileReader.readAsText is not a macroTask either, so I need to make a PR to support this feature.

And BTW, your case is not correct.

// can pass
  it('with setTimeout', () => {
    const number = fileReaderTest(blob);

    setTimeout(() => {
      expect(number).toEqual(1);
    });
  });

This will not really pass, because number will be 0. No error thrown because you didn’t use done.

I will update a working sample later.