Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

feat(jasmine): support Date.now in fakeAsyncTest#1009

Merged
mhevery merged 1 commit intoangular:masterfrom
JiaLiPassion:date
Feb 10, 2018
Merged

feat(jasmine): support Date.now in fakeAsyncTest#1009
mhevery merged 1 commit intoangular:masterfrom
JiaLiPassion:date

Conversation

@JiaLiPassion
Copy link
Copy Markdown
Collaborator

@JiaLiPassion JiaLiPassion commented Jan 31, 2018

fix angular/angular#8678

support Date.now in fakeAsyncTest. there are 3 features in this PR.

  • support auto patch Date.now and new Date() in fakeAsync.
 fakeAsyncTestZone.run(() => {
        const start = Date.now();
        testZoneSpec.tick(100);
        const end = Date.now();
        expect(end - start).toBe(100);
  });

 fakeAsyncTestZone.run(() => {
        const start = new Date();
        testZoneSpec.tick(100);
        const end = new Date();
        expect(end.getTime() - start.getTime()).toBe(100);
  });
  • automatically run a fakeAsync test when jasmine.clock().install is called.
beforeEach(() => {
      jasmine.clock().install();
    });

    afterEach(() => {
      jasmine.clock().uninstall();
    });

    it('should get date diff correctly', () => {  // we don't need fakeAsync here.
      // automatically run into fake async zone, because jasmine.clock() is installed.
      const start = Date.now();
      jasmine.clock().tick(100);
      const end = Date.now();
      expect(end - start).toBe(100);
    });
  • rxjs Scheduler support, need to import zone.js/dist/zone-patch-rxjs-fake-async.
    import '../../lib/rxjs/rxjs-fake-async';
    it('should get date diff correctly', (done) => {
      fakeAsyncTestZone.run(() => {
        let result = null;
        const observable = new Observable((subscribe: any) => {
          subscribe.next('hello');
        });
        observable.delay(1000).subscribe(v => {
          result = v;
        });
        expect(result).toBeNull();
        testZoneSpec.tick(1000);
        expect(result).toBe('hello');
        done();
      });
    });

@mhevery , @vikerman , please review, thank you!

@Jopie64
Copy link
Copy Markdown

Jopie64 commented Jan 31, 2018

@JiaLiPassion
For your info, your last test leaks a subscription.
Instead of this:

const observable = new Observable((subscribe: any) => {
  subscribe.next('hello');
});
observable.delay(1000).subscribe(v => {
  result = v;
});

You can write this to fix it:

Observable.of('hello').delay(1000).subscribe(v => result = v);

(Observable.of() completes after sending the single value)

Anyway, thanks for making my library obsolete! 👍 XD

@JiaLiPassion
Copy link
Copy Markdown
Collaborator Author

@Jopie64 , thank you for the comment.

I didn't use Observable.of() because there is a bug in another patch zone-patch-rxjs. I have updated the test case to complete subscriber.

mhevery
mhevery previously approved these changes Jan 31, 2018
@alfaproject
Copy link
Copy Markdown

alfaproject commented Apr 3, 2018

I couldn't make this work, so I'm a bit confused. angular-testing-ext npm package works out of the box as expected, and I was hoping to replace it. ):

@JiaLiPassion
Copy link
Copy Markdown
Collaborator Author

@alfaproject , with angular/angular#23108 merged, it should work, current angular not using newest version of zone.js.

@alfaproject
Copy link
Copy Markdown

But can't I use the latest version of zone.js with Angular 5? If not, I guess I'll have to wait then. ):

@JiaLiPassion
Copy link
Copy Markdown
Collaborator Author

JiaLiPassion commented Apr 4, 2018

@alfaproject , you can use latest version of zone.js (0.8.25) and old version of angular5. But you need a little setup. You need to import async, fakeAsync from zone instead of from angular/core/testing.

declare let Zone: any;
const async = Zone[Zone.__symbol__('asyncTest')];
const { fakeAsync, tick, flush, flushMicrotasks, discardPeriodicTasks, resetFakeAsyncZone } = Zone[Zone.__symbol__('fakeAsyncTest')];

and if you use jasmine.clock() feature, you need to add a flag before loading zone-testing in src/test.ts.

(window as any)['__zone_symbol__fakeAsyncPatchLock'] = true;
import 'zone.js/dist/zone-testing';

if you use rxjs.delay/scheduler, you need to

import 'zone.js/dist/zone-patch-rxjs-fake-async';

Could you try this in your project to see everything work fine or not? thank you!

@alfaproject
Copy link
Copy Markdown

@JiaLiPassion that works, thank you for helping!

@insidewhy
Copy link
Copy Markdown

Tried this out but my tests are still broken as clock.mockDate(new Date(...)); has no effect now.

@insidewhy
Copy link
Copy Markdown

insidewhy commented Jun 26, 2018

Okay so clock.mockDate(new Date(...)); does work but only if used inside of your it, not when called in the beforeEach along with jasmine.clock().install() (before or after). Inconvenient when you have many tests grouped in a describe that should all be using the same mocked date.

@nschipperbrainsmith
Copy link
Copy Markdown

nschipperbrainsmith commented Aug 15, 2018

@JiaLiPassion Thanks for that, it's finally working though a note: I figured out the hard way that you have to import the delay operator above your snipped for this to function properly in angular 5:

import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/delay";

declare let Zone: any;
const async = Zone[Zone.__symbol__("asyncTest")];
const {fakeAsync, tick, flush, flushMicrotasks, discardPeriodicTasks, resetFakeAsyncZone} = Zone[Zone.__symbol__(
	"fakeAsyncTest")];

import 'zone.js/dist/zone-patch-rxjs-fake-async';

@vicneanschi
Copy link
Copy Markdown

Thanks @JiaLiPassion!

@afeinber
Copy link
Copy Markdown

afeinber commented Oct 8, 2018

@JiaLiPassion Where are we supposed to get fakeAsyncTestZone from to call fakeAsyncTestZone.run?

@JiaLiPassion
Copy link
Copy Markdown
Collaborator Author

@afeinber, do you mean you want to get FakeAsyncTestZone or FakeASyncTestZoneSpec instance inside a fakeAsyncTestZone? You can get them like this.

const fakeAsyncTestZone = Zone.current.fork(Zone['FakeAsyncTestZoneSpec']);
fakeAsyncTestZone.run(() => {
  setTimeout(() => {
     const zone = Zone.current; // this will be === fakeAsyncTestZone;
     const fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
  });
});

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fakeAsync tick does not mock the Date object

9 participants