Created
August 8, 2017 23:25
-
-
Save dralletje/52cf89e93d22d235de4d2a854f90ab21 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // @flow | |
| const useful_times = { | |
| ten_am_monday: 1500884100000, | |
| }; | |
| // '2017-07-27T21:29:45.301' | |
| const base_time_timestamp = useful_times.ten_am_monday; | |
| const Original_Date = Date; | |
| const Mock_Date = Object.assign( | |
| function(value = Mock_Date.now()) { | |
| return new Original_Date(value); | |
| }, | |
| { | |
| mocked_current_time: base_time_timestamp, | |
| now: () => { | |
| const time = Mock_Date.mocked_current_time; | |
| Mock_Date.mocked_current_time = time + 1; | |
| return time; | |
| }, | |
| UTC: Original_Date.UTC, | |
| prototype: Original_Date.prototype, | |
| }, | |
| ); | |
| global.Date = Mock_Date; | |
| type TTimer = { | |
| id: number, | |
| type: 'interval' | 'timeout' | 'immediate', | |
| projected_time: number, // timestamp it is supposed to have it's next run | |
| duration: number, // Necessary for interval to repeat | |
| fn_to_execute: () => mixed, | |
| }; | |
| class TimeMockerClass { | |
| initial_id = 1; | |
| mocked_timers = ([]: Array<TTimer>); | |
| // mocked_nextTicks = []; | |
| mocks = { | |
| setInterval: _setInterval => (fn, duration) => { | |
| this.mocked_timers.push({ | |
| id: this.initial_id, | |
| type: 'interval', | |
| projected_time: Date.now() + duration, | |
| duration: duration, | |
| fn_to_execute: fn, | |
| }); | |
| this.initial_id = this.initial_id + 1; | |
| return this.initial_id; | |
| }, | |
| setImmediate: _setImmediate => fn => { | |
| fn(); | |
| // this.mocked_nextTicks.push({ | |
| // fn: fn, | |
| // }); | |
| }, | |
| setTimeout: _setTimeout => (fn, duration) => { | |
| this.mocked_timers.push({ | |
| id: this.initial_id, | |
| type: 'timeout', | |
| projected_time: Date.now() + duration, | |
| duration: duration, | |
| fn_to_execute: fn, | |
| }); | |
| this.initial_id = this.initial_id + 1; | |
| return this.initial_id; | |
| }, | |
| clearTimeout: _clearTimeout => id => { | |
| this.mocked_timers = this.mocked_timers.filter(x => x.id !== id); | |
| }, | |
| clearInterval: _clearInterval => id => { | |
| this.mocked_timers = this.mocked_timers.filter(x => x.id !== id); | |
| }, | |
| }; | |
| original_functions = {}; | |
| active = false; | |
| constructor(obj) { | |
| Object.entries(this.mocks).forEach(([key, mockFn]) => { | |
| this.original_functions[key] = obj[key]; | |
| const with_original = mockFn(obj[key]); | |
| obj[key] = (...args) => { | |
| if (this.active) { | |
| return with_original(...args); | |
| } else { | |
| return this.original_functions[key](...args); | |
| } | |
| }; | |
| }); | |
| } | |
| activate() { | |
| this.active = true; | |
| Mock_Date.mocked_current_time = base_time_timestamp; | |
| } | |
| deactivate() { | |
| this.active = false; | |
| } | |
| mock_forward_time = async (to_date: Date) => { | |
| const timers = this.mocked_timers | |
| .filter(timer => timer.projected_time <= to_date) | |
| // TODO Make sure this is sorting the right way | |
| .sort((a, b) => a.projected_time - b.projected_time); | |
| const current = timers[0]; | |
| if (!current) return; | |
| this.mocked_timers = this.mocked_timers.filter(x => x.id !== current.id); | |
| Mock_Date.mocked_current_time = current.projected_time; | |
| const x = current.fn_to_execute(); | |
| // Give it another second to execute... wondering if there is another way | |
| // to wait for all async/await calls to finish :( | |
| await new Promise(yell => { | |
| const fn = this.original_functions.setTimeout; | |
| fn(() => yell(), 20); | |
| }); | |
| return this.mock_forward_time(to_date); | |
| }; | |
| } | |
| // global.nextTick = fn => { | |
| // console.log('fn:', fn); | |
| // throw new Error(`Nexttick`); | |
| // }; | |
| global.TimeMocker = new TimeMockerClass(global); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment