Implemented Stopwatch to simplify measurements

This commit is contained in:
Kir_Antipov 2022-07-05 17:44:29 +03:00
parent 4989430f1a
commit 2483a4d02b
2 changed files with 127 additions and 0 deletions

68
src/utils/stopwatch.ts Normal file
View file

@ -0,0 +1,68 @@
interface StartCallback {
(currentDate: Date, stopwatch: Stopwatch): void;
}
interface StopCallback {
(elapsedMilliseconds: number, currentDate: Date, stopwatch: Stopwatch): void;
}
export default class Stopwatch {
#initialDate = 0;
#isRunning = false;
#elapsedMilliseconds = 0;
#onStart: StartCallback = null;
#onStop: StopCallback = null;
public constructor(onStart?: StartCallback, onStop?: StopCallback) {
this.#onStart = onStart;
this.#onStop = onStop;
}
public get elapsedMilliseconds(): number {
return this.#isRunning
? (this.#elapsedMilliseconds + new Date().valueOf() - this.#initialDate)
: this.#elapsedMilliseconds;
}
public get isRunning(): boolean {
return this.#isRunning;
}
public start(): boolean {
if (!this.#isRunning) {
const currentDate = new Date();
this.#initialDate = currentDate.valueOf();
this.#isRunning = true;
this.#onStart?.(currentDate, this);
return true;
}
return false;
}
public stop(): boolean {
if (this.#isRunning) {
const currentDate = new Date();
this.#elapsedMilliseconds += currentDate.valueOf() - this.#initialDate;
this.#isRunning = false;
this.#onStop?.(this.#elapsedMilliseconds, currentDate, this);
return true;
}
return false;
}
public reset(): void {
this.stop();
this.#elapsedMilliseconds = 0;
}
public restart(): void {
this.reset();
this.start();
}
public static startNew(onStart?: StartCallback, onStop?: StopCallback): Stopwatch {
const stopwatch = new Stopwatch(onStart, onStop);
stopwatch.start();
return stopwatch;
}
}

59
test/stopwatch.test.ts Normal file
View file

@ -0,0 +1,59 @@
import { describe, test, expect } from "@jest/globals";
import sleep from "../src/utils/sleep";
import Stopwatch from "../src/utils/stopwatch";
describe("Stopwatch", () => {
test("base functionality of Stopwatch works", async () => {
const stopwatch = new Stopwatch();
expect(stopwatch.isRunning).toBe(false);
expect(stopwatch.elapsedMilliseconds).toBe(0);
expect(stopwatch.start()).toBe(true);
await sleep(100);
expect(stopwatch.start()).toBe(false);
expect(stopwatch.stop()).toBe(true);
expect(stopwatch.stop()).toBe(false);
expect(stopwatch.elapsedMilliseconds).toBeGreaterThan(50);
expect(stopwatch.elapsedMilliseconds).toBeLessThan(200);
stopwatch.reset();
expect(stopwatch.elapsedMilliseconds).toBe(0);
});
test("Stopwatch executes callbacks on start and end", async () => {
let started = 0;
let stopped = 0;
let ms = 0;
const stopwatch = new Stopwatch(() => ++started, elapsedMilliseconds => {
++stopped;
ms = elapsedMilliseconds;
});
expect(stopwatch.isRunning).toBe(false);
expect(stopwatch.elapsedMilliseconds).toBe(0);
expect(stopwatch.start()).toBe(true);
expect(started).toBe(1);
expect(stopped).toBe(0);
await sleep(100);
expect(stopwatch.start()).toBe(false);
expect(started).toBe(1);
expect(stopped).toBe(0);
expect(stopwatch.stop()).toBe(true);
expect(started).toBe(1);
expect(stopped).toBe(1);
expect(stopwatch.stop()).toBe(false);
expect(started).toBe(1);
expect(stopped).toBe(1);
expect(stopwatch.elapsedMilliseconds).toBeGreaterThan(50);
expect(stopwatch.elapsedMilliseconds).toBeLessThan(200);
expect(stopwatch.elapsedMilliseconds).toBe(ms);
stopwatch.reset();
expect(stopwatch.elapsedMilliseconds).toBe(0);
});
});