UNPKG

@serenity-js/core

Version:

The core Serenity/JS framework, providing the Screenplay Pattern interfaces, as well as the test reporting and integration infrastructure

81 lines (70 loc) 2.41 kB
import { ensure, isDefined, type JSONObject } from 'tiny-types'; import { Duration } from './Duration'; import { Timestamp } from './Timestamp'; /** * A [`Clock`](https://serenity-js.org/api/core/class/Clock/) tells the time. This abstraction allows Serenity/JS to have a single place * in the framework responsible for telling the time, and one that can be easily mocked for internal testing. * * ```ts * const now: Timestamp = new Clock().now() * ``` * * ## Learn more * - [`Timestamp`](https://serenity-js.org/api/core/class/Timestamp/) * - [`Duration`](https://serenity-js.org/api/core/class/Duration/) * * @group Time */ export class Clock { private static resolution: Duration = Duration.ofMilliseconds(10); private timeAdjustment: Duration = Duration.ofMilliseconds(0); constructor(private readonly checkTime: () => Date = () => new Date()) { } toJSON(): JSONObject { return { timeAdjustment: this.timeAdjustment.toJSON(), }; } /** * Sets the clock ahead to force early resolution of promises * returned by [`Clock.waitFor`](https://serenity-js.org/api/core/class/Clock/#waitFor). * * Useful for test purposes to avoid unnecessary delays. * * @param duration */ setAhead(duration: Duration): void { this.timeAdjustment = ensure('duration', duration, isDefined()); } /** * Returns a Promise that resolves after one tick of the clock. * * Useful for test purposes to avoid unnecessary delays. */ async tick(): Promise<void> { return new Promise(resolve => setTimeout(resolve, Clock.resolution.inMilliseconds())); } /** * Returns current time */ now(): Timestamp { return new Timestamp(this.checkTime()).plus(this.timeAdjustment); } /** * Returns a Promise that will be resolved after the given duration * * @param duration */ async waitFor(duration: Duration): Promise<void> { const stopAt = this.now().plus(duration); let timer: NodeJS.Timeout; return new Promise<void>(resolve => { timer = setInterval(() => { if (this.now().isAfterOrEqual(stopAt)) { clearInterval(timer); return resolve(); } }, Clock.resolution.inMilliseconds()); }); } }