This repository has been archived on 2022-08-19. You can view files and clone it, but cannot push or open issues or pull requests.
hydrogen-web/src/mocks/Clock.js
2020-05-05 23:12:14 +02:00

120 lines
3.1 KiB
JavaScript

import {ObservableValue} from "../observable/ObservableValue.js";
class Timeout {
constructor(elapsed, ms) {
this._reject = null;
this._handle = null;
const timeoutValue = elapsed.get() + ms;
this._waitHandle = elapsed.waitFor(t => t >= timeoutValue);
}
elapsed() {
return this._waitHandle.promise;
}
abort() {
// will reject with AbortError
this._waitHandle.dispose();
}
}
class Interval {
constructor(elapsed, ms, callback) {
this._start = elapsed.get();
this._last = this._start;
this._interval = ms;
this._callback = callback;
this._subscription = elapsed.subscribe(this._update.bind(this));
}
_update(elapsed) {
const prevAmount = Math.floor((this._last - this._start) / this._interval);
const newAmount = Math.floor((elapsed - this._start) / this._interval);
const amountDiff = Math.max(0, newAmount - prevAmount);
this._last = elapsed;
for (let i = 0; i < amountDiff; ++i) {
this._callback();
}
}
dispose() {
if (this._subscription) {
this._subscription();
this._subscription = null;
}
}
}
class TimeMeasure {
constructor(elapsed) {
this._elapsed = elapsed;
this._start = elapsed.get();
}
measure() {
return this._elapsed.get() - this._start;
}
}
export class Clock {
constructor(baseTimestamp = 0) {
this._baseTimestamp = baseTimestamp;
this._elapsed = new ObservableValue(0);
// should be callable as a function as well as a method
this.createMeasure = this.createMeasure.bind(this);
this.createTimeout = this.createTimeout.bind(this);
this.now = this.now.bind(this);
}
createMeasure() {
return new TimeMeasure(this._elapsed);
}
createTimeout(ms) {
return new Timeout(this._elapsed, ms);
}
createInterval(callback, ms) {
return new Interval(this._elapsed, ms, callback);
}
now() {
return this._baseTimestamp + this.elapsed;
}
elapse(ms) {
this._elapsed.set(this._elapsed.get() + Math.max(0, ms));
}
get elapsed() {
return this._elapsed.get();
}
}
export function tests() {
return {
"test timeout": async assert => {
const clock = new Clock();
Promise.resolve().then(() => {
clock.elapse(500);
clock.elapse(500);
}).catch(assert.fail);
const timeout = clock.createTimeout(1000);
const promise = timeout.elapsed();
assert(promise instanceof Promise);
await promise;
},
"test interval": assert => {
const clock = new Clock();
let counter = 0;
const interval = clock.createInterval(() => counter += 1, 200);
clock.elapse(150);
assert.strictEqual(counter, 0);
clock.elapse(500);
assert.strictEqual(counter, 3);
interval.dispose();
}
}
}