Skip to content

Commit cdd1779

Browse files
author
Deepak Kumar
committed
test: add unit tests for Ticker with interval and worker strategies
1 parent bf6d65c commit cdd1779

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

spec/unit/ticker.spec.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { expect, test } from '@playwright/test';
2+
import sinon from 'sinon';
3+
import { Ticker } from '../../src/ticker.js';
4+
import { TickerStrategy } from '../../src/types.js';
5+
6+
class FakeWorker {
7+
public onmessage: ((ev: { data: any }) => void) | null = null;
8+
public terminate = sinon.spy();
9+
public readonly url: string;
10+
11+
constructor(url: string) {
12+
this.url = url;
13+
FakeWorker.instances.push(this);
14+
}
15+
16+
fire(data: any): void {
17+
this.onmessage?.({ data });
18+
}
19+
20+
static instances: FakeWorker[] = [];
21+
static reset(): void {
22+
FakeWorker.instances = [];
23+
}
24+
}
25+
26+
test.describe('Ticker', () => {
27+
let originalWorker: any;
28+
let debug: sinon.SinonSpy;
29+
30+
test.beforeEach(() => {
31+
FakeWorker.reset();
32+
originalWorker = (globalThis as any).Worker;
33+
(globalThis as any).Worker = FakeWorker;
34+
debug = sinon.spy();
35+
});
36+
37+
test.afterEach(() => {
38+
if (originalWorker === undefined) {
39+
delete (globalThis as any).Worker;
40+
} else {
41+
(globalThis as any).Worker = originalWorker;
42+
}
43+
});
44+
45+
test.describe('Interval strategy (default)', () => {
46+
test('start invokes tick after interval and stop clears it', async () => {
47+
const ticker = new Ticker(20, TickerStrategy.Interval, debug);
48+
const tick = sinon.spy();
49+
50+
ticker.start(tick);
51+
await new Promise(r => setTimeout(r, 70));
52+
ticker.stop();
53+
54+
const callsAfterStop = tick.callCount;
55+
expect(callsAfterStop).toBeGreaterThanOrEqual(2);
56+
expect(tick.firstCall.args[0]).toBeGreaterThanOrEqual(0);
57+
58+
await new Promise(r => setTimeout(r, 50));
59+
expect(tick.callCount).toBe(callsAfterStop);
60+
expect(debug.calledWith('Using runInterval for outgoing pings')).toBe(
61+
true,
62+
);
63+
expect(debug.calledWith('Outgoing ping disposeInterval')).toBe(true);
64+
});
65+
66+
test('falls back to interval when strategy is Worker but Worker is undefined', () => {
67+
delete (globalThis as any).Worker;
68+
69+
const ticker = new Ticker(50, TickerStrategy.Worker, debug);
70+
ticker.start(() => {});
71+
72+
expect(FakeWorker.instances.length).toBe(0);
73+
expect(debug.calledWith('Using runInterval for outgoing pings')).toBe(
74+
true,
75+
);
76+
ticker.stop();
77+
});
78+
});
79+
80+
test.describe('Worker strategy', () => {
81+
test('start constructs a Worker and forwards messages to tick', () => {
82+
const ticker = new Ticker(50, TickerStrategy.Worker, debug);
83+
const tick = sinon.spy();
84+
85+
ticker.start(tick);
86+
87+
expect(FakeWorker.instances.length).toBe(1);
88+
const worker = FakeWorker.instances[0];
89+
expect(worker.url).toMatch(/^blob:/);
90+
expect(typeof worker.onmessage).toBe('function');
91+
92+
worker.fire(123);
93+
worker.fire(456);
94+
95+
expect(tick.callCount).toBe(2);
96+
expect(tick.firstCall.args[0]).toBe(123);
97+
expect(tick.secondCall.args[0]).toBe(456);
98+
expect(debug.calledWith('Using runWorker for outgoing pings')).toBe(true);
99+
100+
ticker.stop();
101+
});
102+
103+
test('stop terminates the worker', () => {
104+
const ticker = new Ticker(50, TickerStrategy.Worker, debug);
105+
ticker.start(() => {});
106+
107+
const worker = FakeWorker.instances[0];
108+
ticker.stop();
109+
110+
expect(worker.terminate.calledOnce).toBe(true);
111+
expect(debug.calledWith('Outgoing ping disposeWorker')).toBe(true);
112+
113+
ticker.stop();
114+
expect(worker.terminate.calledOnce).toBe(true);
115+
});
116+
117+
test('start after stop creates a fresh worker', () => {
118+
const ticker = new Ticker(50, TickerStrategy.Worker, debug);
119+
ticker.start(() => {});
120+
ticker.stop();
121+
ticker.start(() => {});
122+
123+
expect(FakeWorker.instances.length).toBe(2);
124+
expect(FakeWorker.instances[0].terminate.calledOnce).toBe(true);
125+
126+
ticker.stop();
127+
});
128+
});
129+
});

0 commit comments

Comments
 (0)