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

Commit 08cdb0e

Browse files
committed
fix(test): fix #1069, FakeDate should handle constructor parameter
1 parent a86bddb commit 08cdb0e

File tree

4 files changed

+223
-36
lines changed

4 files changed

+223
-36
lines changed

lib/jasmine/jasmine.ts

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,14 @@
6767
return originalJasmineFn.apply(this, arguments);
6868
};
6969
});
70-
if (enableClockPatch) {
71-
const originalClockFn: Function = ((jasmine as any)[symbol('clock')] = jasmine['clock']);
72-
(jasmine as any)['clock'] = function() {
73-
const clock = originalClockFn.apply(this, arguments);
70+
71+
// need to patch jasmine.clock().mockDate and jasmine.clock().tick() so
72+
// they can work properly in FakeAsyncTest
73+
const originalClockFn: Function = ((jasmine as any)[symbol('clock')] = jasmine['clock']);
74+
(jasmine as any)['clock'] = function() {
75+
const clock = originalClockFn.apply(this, arguments);
76+
if (!clock[symbol('patched')]) {
77+
clock[symbol('patched')] = symbol('patched');
7478
const originalTick = (clock[symbol('tick')] = clock.tick);
7579
clock.tick = function() {
7680
const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
@@ -83,28 +87,31 @@
8387
clock.mockDate = function() {
8488
const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
8589
if (fakeAsyncZoneSpec) {
86-
const dateTime = arguments[0];
90+
const dateTime = arguments.length > 0 ? arguments[0] : new Date();
8791
return fakeAsyncZoneSpec.setCurrentRealTime.apply(
8892
fakeAsyncZoneSpec,
8993
dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] :
9094
arguments);
9195
}
9296
return originalMockDate.apply(this, arguments);
9397
};
94-
['install', 'uninstall'].forEach(methodName => {
95-
const originalClockFn: Function = (clock[symbol(methodName)] = clock[methodName]);
96-
clock[methodName] = function() {
97-
const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec'];
98-
if (FakeAsyncTestZoneSpec) {
99-
(jasmine as any)[symbol('clockInstalled')] = 'install' === methodName;
100-
return;
101-
}
102-
return originalClockFn.apply(this, arguments);
103-
};
104-
});
105-
return clock;
106-
};
107-
}
98+
// for auto go into fakeAsync feature, we need the flag to enable it
99+
if (enableClockPatch) {
100+
['install', 'uninstall'].forEach(methodName => {
101+
const originalClockFn: Function = (clock[symbol(methodName)] = clock[methodName]);
102+
clock[methodName] = function() {
103+
const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec'];
104+
if (FakeAsyncTestZoneSpec) {
105+
(jasmine as any)[symbol('clockInstalled')] = 'install' === methodName;
106+
return;
107+
}
108+
return originalClockFn.apply(this, arguments);
109+
};
110+
});
111+
}
112+
}
113+
return clock;
114+
};
108115

109116
/**
110117
* Gets a function wrapping the body of a Jasmine `describe` block to execute in a

lib/zone-spec/fake-async-test.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@
3232
const OriginalDate = global.Date;
3333
class FakeDate {
3434
constructor() {
35-
const d = new OriginalDate();
36-
d.setTime(global.Date.now());
37-
return d;
38-
}
39-
40-
static UTC() {
41-
return OriginalDate.UTC();
35+
if (arguments.length === 0) {
36+
const d = new OriginalDate();
37+
d.setTime(FakeDate.now());
38+
return d;
39+
} else {
40+
const args = Array.prototype.slice.call(arguments);
41+
return new OriginalDate(...args);
42+
}
4243
}
4344

4445
static now() {
@@ -48,12 +49,19 @@
4849
}
4950
return OriginalDate.now.apply(this, arguments);
5051
}
51-
52-
static parse() {
53-
return OriginalDate.parse();
54-
}
5552
}
5653

54+
(FakeDate as any).UTC = OriginalDate.UTC;
55+
(FakeDate as any).parse = OriginalDate.parse;
56+
57+
// keep a reference for zone patched timer function
58+
const timers = {
59+
setTimeout: global.setTimeout,
60+
setInterval: global.setInterval,
61+
clearTimeout: global.clearTimeout,
62+
clearInterval: global.clearInterval
63+
};
64+
5765
class Scheduler {
5866
// Next scheduler id.
5967
public nextId: number = 1;
@@ -63,7 +71,7 @@
6371
// Current simulated time in millis.
6472
private _currentTime: number = 0;
6573
// Current real time in millis.
66-
private _currentRealTime: number = Date.now();
74+
private _currentRealTime: number = OriginalDate.now();
6775

6876
constructor() {}
6977

@@ -341,6 +349,11 @@
341349
}
342350
global['Date'] = FakeDate;
343351
FakeDate.prototype = OriginalDate.prototype;
352+
353+
// try check and reset timers
354+
// because jasmine.clock().install() may
355+
// have replaced the global timer
356+
FakeAsyncTestZoneSpec.checkTimerPatch();
344357
}
345358

346359
static resetDate() {
@@ -349,6 +362,17 @@
349362
}
350363
}
351364

365+
static checkTimerPatch() {
366+
if (global.setTimeout !== timers.setTimeout) {
367+
global.setTimeout = timers.setTimeout;
368+
global.clearTimeout = timers.clearTimeout;
369+
}
370+
if (global.setInterval !== timers.setInterval) {
371+
global.setInterval = timers.setInterval;
372+
global.clearInterval = timers.clearInterval;
373+
}
374+
}
375+
352376
lockDatePatch() {
353377
this.patchDateLocked = true;
354378
FakeAsyncTestZoneSpec.patchDate();

test/test-env-setup-mocha.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ declare const global: any;
8181
throw new Error(`Expected ${expected} to be greater than ${actual}`);
8282
}
8383
},
84+
toBeLessThan: function(actual: number) {
85+
if (expected >= actual) {
86+
throw new Error(`Expected ${expected} to be lesser than ${actual}`);
87+
}
88+
},
8489
toBeDefined: function() {
8590
if (!expected) {
8691
throw new Error(`Expected ${expected} to be defined`);
@@ -159,7 +164,11 @@ declare const global: any;
159164
if (expected > actual) {
160165
throw new Error(`Expected ${expected} not to be greater than ${actual}`);
161166
}
162-
167+
},
168+
toBeLessThan: function(actual: number) {
169+
if (expected < actual) {
170+
throw new Error(`Expected ${expected} not to be lesser than ${actual}`);
171+
}
163172
},
164173
toHaveBeenCalledWith: function(params: any[]) {
165174
if (!eq(expected.callArgs, params)) {

test/zone-spec/fake-async-test.spec.ts

Lines changed: 151 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -913,17 +913,51 @@ describe('FakeAsyncTestZoneSpec', () => {
913913
expect(d instanceof Date).toBe(true);
914914
});
915915
});
916+
917+
it('should new Date with parameter correctly', () => {
918+
fakeAsyncTestZone.run(() => {
919+
const d: Date = new Date(0);
920+
expect(d.getFullYear()).toBeLessThan(1971);
921+
const d1: Date = new Date('December 17, 1995 03:24:00');
922+
expect(d1.getFullYear()).toEqual(1995);
923+
const d2: Date = new Date(1995, 11, 17, 3, 24, 0);
924+
expect(d2.getFullYear()).toEqual(1995);
925+
926+
d2.setFullYear(1985);
927+
expect(isNaN(d2.getTime())).toBeFalsy();
928+
expect(d2.getFullYear()).toBe(1985);
929+
expect(d2.getMonth()).toBe(11);
930+
expect(d2.getDate()).toBe(17);
931+
});
932+
});
933+
934+
it('should get Date.UTC() correctly', () => {
935+
fakeAsyncTestZone.run(() => {
936+
const utcDate = new Date(Date.UTC(96, 11, 1, 0, 0, 0));
937+
expect(utcDate.getFullYear()).toBe(1996);
938+
});
939+
});
940+
941+
it('should call Date.parse() correctly', () => {
942+
fakeAsyncTestZone.run(() => {
943+
const unixTimeZero = Date.parse('01 Jan 1970 00:00:00 GMT');
944+
expect(unixTimeZero).toBe(0);
945+
});
946+
});
947+
916948
});
917949

918950
describe(
919-
'fakeAsyncTest should work without jasmine.clock',
951+
'fakeAsyncTest should work without patch jasmine.clock',
920952
ifEnvSupports(
921953
() => {
922954
return !supportClock() && supportNode();
923955
},
924956
() => {
925957
const fakeAsync = (Zone as any)[Zone.__symbol__('fakeAsyncTest')].fakeAsync;
958+
let spy: any;
926959
beforeEach(() => {
960+
spy = jasmine.createSpy('timer');
927961
jasmine.clock().install();
928962
});
929963

@@ -932,11 +966,44 @@ describe('FakeAsyncTestZoneSpec', () => {
932966
});
933967

934968
it('should check date type correctly', fakeAsync(() => {
969+
const d: any = new Date();
970+
expect(d instanceof Date).toBe(true);
971+
}));
972+
973+
it('should check date type correctly without fakeAsync', () => {
935974
const d: any = new Date();
936975
expect(d instanceof Date).toBe(true);
937-
}));
976+
});
977+
978+
it('should tick correctly', fakeAsync(() => {
979+
jasmine.clock().mockDate();
980+
const start = Date.now();
981+
jasmine.clock().tick(100);
982+
const end = Date.now();
983+
expect(end - start).toBe(100);
984+
}));
985+
986+
it('should tick correctly without fakeAsync', () => {
987+
jasmine.clock().mockDate();
988+
const start = Date.now();
989+
jasmine.clock().tick(100);
990+
const end = Date.now();
991+
expect(end - start).toBe(100);
992+
});
938993

939994
it('should mock date correctly', fakeAsync(() => {
995+
const baseTime = new Date(2013, 9, 23);
996+
jasmine.clock().mockDate(baseTime);
997+
const start = Date.now();
998+
expect(start).toBe(baseTime.getTime());
999+
jasmine.clock().tick(100);
1000+
const end = Date.now();
1001+
expect(end - start).toBe(100);
1002+
expect(end).toBe(baseTime.getTime() + 100);
1003+
expect(new Date().getFullYear()).toEqual(2013);
1004+
}));
1005+
1006+
it('should mock date correctly without fakeAsync', () => {
9401007
const baseTime = new Date(2013, 9, 23);
9411008
jasmine.clock().mockDate(baseTime);
9421009
const start = Date.now();
@@ -945,9 +1012,21 @@ describe('FakeAsyncTestZoneSpec', () => {
9451012
const end = Date.now();
9461013
expect(end - start).toBe(100);
9471014
expect(end).toBe(baseTime.getTime() + 100);
948-
}));
1015+
expect(new Date().getFullYear()).toEqual(2013);
1016+
});
9491017

9501018
it('should handle new Date correctly', fakeAsync(() => {
1019+
const baseTime = new Date(2013, 9, 23);
1020+
jasmine.clock().mockDate(baseTime);
1021+
const start = new Date();
1022+
expect(start.getTime()).toBe(baseTime.getTime());
1023+
jasmine.clock().tick(100);
1024+
const end = new Date();
1025+
expect(end.getTime() - start.getTime()).toBe(100);
1026+
expect(end.getTime()).toBe(baseTime.getTime() + 100);
1027+
}));
1028+
1029+
it('should handle new Date correctly without fakeAsync', () => {
9511030
const baseTime = new Date(2013, 9, 23);
9521031
jasmine.clock().mockDate(baseTime);
9531032
const start = new Date();
@@ -956,11 +1035,27 @@ describe('FakeAsyncTestZoneSpec', () => {
9561035
const end = new Date();
9571036
expect(end.getTime() - start.getTime()).toBe(100);
9581037
expect(end.getTime()).toBe(baseTime.getTime() + 100);
959-
}));
1038+
});
1039+
1040+
it('should handle setTimeout correctly', fakeAsync(() => {
1041+
setTimeout(spy, 100);
1042+
expect(spy).not.toHaveBeenCalled();
1043+
jasmine.clock().tick(100);
1044+
expect(spy).toHaveBeenCalled();
1045+
}));
1046+
1047+
it('should handle setTimeout correctly without fakeAsync', () => {
1048+
setTimeout(spy, 100);
1049+
expect(spy).not.toHaveBeenCalled();
1050+
jasmine.clock().tick(100);
1051+
expect(spy).toHaveBeenCalled();
1052+
});
9601053
}));
9611054

9621055
describe('fakeAsyncTest should patch jasmine.clock', ifEnvSupports(supportClock, () => {
1056+
let spy: any;
9631057
beforeEach(() => {
1058+
spy = jasmine.createSpy('timer');
9641059
jasmine.clock().install();
9651060
});
9661061

@@ -980,6 +1075,13 @@ describe('FakeAsyncTestZoneSpec', () => {
9801075
expect(end - start).toBe(100);
9811076
});
9821077

1078+
it('should tick correctly', () => {
1079+
const start = Date.now();
1080+
jasmine.clock().tick(100);
1081+
const end = Date.now();
1082+
expect(end - start).toBe(100);
1083+
});
1084+
9831085
it('should mock date correctly', () => {
9841086
const baseTime = new Date(2013, 9, 23);
9851087
jasmine.clock().mockDate(baseTime);
@@ -1001,6 +1103,13 @@ describe('FakeAsyncTestZoneSpec', () => {
10011103
expect(end.getTime() - start.getTime()).toBe(100);
10021104
expect(end.getTime()).toBe(baseTime.getTime() + 100);
10031105
});
1106+
1107+
it('should handle setTimeout correctly', () => {
1108+
setTimeout(spy, 100);
1109+
expect(spy).not.toHaveBeenCalled();
1110+
jasmine.clock().tick(100);
1111+
expect(spy).toHaveBeenCalled();
1112+
});
10041113
}));
10051114

10061115
describe('fakeAsyncTest should patch rxjs scheduler', ifEnvSupports(supportClock, () => {
@@ -1427,6 +1536,44 @@ const {fakeAsync, tick, discardPeriodicTasks, flush, flushMicrotasks} = fakeAsyn
14271536
expect(zoneInTest1).toBe(zoneInBeforeEach);
14281537
}));
14291538
});
1539+
1540+
describe('fakeAsync should work with Date', () => {
1541+
it('should get date diff correctly', fakeAsync(() => {
1542+
const start = Date.now();
1543+
tick(100);
1544+
const end = Date.now();
1545+
expect(end - start).toBe(100);
1546+
}));
1547+
1548+
it('should check date type correctly', fakeAsync(() => {
1549+
const d: any = new Date();
1550+
expect(d instanceof Date).toBe(true);
1551+
}));
1552+
1553+
it('should new Date with parameter correctly', fakeAsync(() => {
1554+
const d: Date = new Date(0);
1555+
expect(d.getFullYear()).toBeLessThan(1971);
1556+
const d1: Date = new Date('December 17, 1995 03:24:00');
1557+
expect(d1.getFullYear()).toEqual(1995);
1558+
const d2: Date = new Date(1995, 11, 17, 3, 24, 0);
1559+
expect(isNaN(d2.getTime())).toBeFalsy();
1560+
expect(d2.getFullYear()).toEqual(1995);
1561+
d2.setFullYear(1985);
1562+
expect(d2.getFullYear()).toBe(1985);
1563+
expect(d2.getMonth()).toBe(11);
1564+
expect(d2.getDate()).toBe(17);
1565+
}));
1566+
1567+
it('should get Date.UTC() correctly', fakeAsync(() => {
1568+
const utcDate = new Date(Date.UTC(96, 11, 1, 0, 0, 0));
1569+
expect(utcDate.getFullYear()).toBe(1996);
1570+
}));
1571+
1572+
it('should call Date.parse() correctly', fakeAsync(() => {
1573+
const unixTimeZero = Date.parse('01 Jan 1970 00:00:00 GMT');
1574+
expect(unixTimeZero).toBe(0);
1575+
}));
1576+
});
14301577
});
14311578

14321579
describe('ProxyZone', () => {

0 commit comments

Comments
 (0)