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

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

Merged
merged 1 commit into from
Feb 10, 2018

Conversation

JiaLiPassion
Copy link
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

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
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

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
Collaborator Author

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

@alfaproject
Copy link

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
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

@JiaLiPassion that works, thank you for helping!

@insidewhy
Copy link

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

@insidewhy
Copy link

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

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

Thanks @JiaLiPassion!

@afeinber
Copy link

afeinber commented Oct 8, 2018

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

@JiaLiPassion
Copy link
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