Skip to content

Commit 7c14a0b

Browse files
committed
refactor: add tests
1 parent 673b5c4 commit 7c14a0b

7 files changed

Lines changed: 169 additions & 209 deletions

File tree

packages/utils/mocks/sink.mock.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type {
77

88
export class MockSink implements Sink<string, string> {
99
private writtenItems: string[] = [];
10-
private closed = false;
10+
private closed = true;
1111

1212
open = vi.fn((): void => {
1313
this.closed = false;
@@ -45,7 +45,7 @@ export class MockTraceEventFileSink extends MockSink implements Recoverable {
4545
records: this.getWrittenItems(),
4646
errors: [],
4747
partialTail: null,
48-
};
48+
} satisfies RecoverResult<string>;
4949
},
5050
);
5151

packages/utils/src/lib/performance-observer.int.test.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ describe('PerformanceObserverSink', () => {
2323

2424
beforeEach(() => {
2525
sink = new MockSink();
26+
sink.open();
2627
encode = vi.fn((entry: PerformanceEntry) => [
2728
`${entry.name}:${entry.entryType}`,
2829
]);
2930

3031
options = {
3132
sink,
32-
encode,
33+
encodePerfEntry: encode,
3334
};
3435

3536
performance.clearMarks();
@@ -169,7 +170,7 @@ describe('PerformanceObserverSink', () => {
169170
]);
170171
const observer = new PerformanceObserverSink({
171172
...options,
172-
encode: multiEncodeFn,
173+
encodePerfEntry: multiEncodeFn,
173174
});
174175

175176
observer.subscribe();
@@ -224,4 +225,16 @@ describe('PerformanceObserverSink', () => {
224225
expect.objectContaining({ name: 'first-measure' }),
225226
);
226227
});
228+
229+
it('throws error when subscribing with sink that is not open', () => {
230+
const closedSink = new MockSink();
231+
const observer = new PerformanceObserverSink({
232+
sink: closedSink,
233+
encodePerfEntry: encode,
234+
});
235+
236+
expect(() => observer.subscribe()).toThrow(
237+
'Sink MockSink must be opened before subscribing PerformanceObserver',
238+
);
239+
});
227240
});

packages/utils/src/lib/performance-observer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class PerformanceObserverSink<T>
6262
}
6363
if (this.#sink.isClosed()) {
6464
throw new Error(
65-
'Sink must be opened before subscribing PerformanceObserver',
65+
`Sink ${this.#sink.constructor.name} must be opened before subscribing PerformanceObserver`,
6666
);
6767
}
6868

@@ -93,7 +93,7 @@ export class PerformanceObserverSink<T>
9393
}
9494
if (this.#sink.isClosed()) {
9595
throw new Error(
96-
'Sink must be opened before subscribing PerformanceObserver',
96+
`Sink ${this.#sink.constructor.name} must be opened before subscribing PerformanceObserver`,
9797
);
9898
}
9999

packages/utils/src/lib/performance-observer.unit.test.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ import {
1515
} from './performance-observer.js';
1616

1717
describe('PerformanceObserverSink', () => {
18-
let encode: MockedFunction<(entry: PerformanceEntry) => string[]>;
18+
let encodePerfEntry: MockedFunction<(entry: PerformanceEntry) => string[]>;
1919
let sink: MockSink;
2020
let options: PerformanceObserverOptions<string>;
2121

2222
beforeEach(() => {
2323
vi.clearAllMocks();
2424
sink = new MockSink();
25-
encode = vi.fn((entry: PerformanceEntry) => [
25+
sink.open();
26+
encodePerfEntry = vi.fn((entry: PerformanceEntry) => [
2627
`${entry.name}:${entry.entryType}`,
2728
]);
2829
options = {
2930
sink,
30-
encode,
31-
// we test buffered behavior separately
31+
encodePerfEntry,
3232
flushThreshold: 1,
3333
};
3434

@@ -46,17 +46,16 @@ describe('PerformanceObserverSink', () => {
4646
() =>
4747
new PerformanceObserverSink({
4848
sink,
49-
encode,
49+
encodePerfEntry,
5050
}),
5151
).not.toThrow();
5252
expect(MockPerformanceObserver.instances).toHaveLength(0);
53-
// Instance creation covers the default flushThreshold assignment
5453
});
5554

5655
it('automatically flushes when pendingCount reaches flushThreshold', () => {
5756
const observer = new PerformanceObserverSink({
5857
sink,
59-
encode,
58+
encodePerfEntry,
6059
flushThreshold: 2, // Set threshold to 2
6160
});
6261
observer.subscribe();
@@ -149,15 +148,15 @@ describe('PerformanceObserverSink', () => {
149148
performance.mark('test-mark');
150149
performance.measure('test-measure');
151150
observer.flush();
152-
expect(encode).toHaveBeenCalledTimes(2);
153-
expect(encode).toHaveBeenNthCalledWith(
151+
expect(encodePerfEntry).toHaveBeenCalledTimes(2);
152+
expect(encodePerfEntry).toHaveBeenNthCalledWith(
154153
1,
155154
expect.objectContaining({
156155
name: 'test-mark',
157156
entryType: 'mark',
158157
}),
159158
);
160-
expect(encode).toHaveBeenNthCalledWith(
159+
expect(encodePerfEntry).toHaveBeenNthCalledWith(
161160
2,
162161
expect.objectContaining({
163162
name: 'test-measure',
@@ -171,7 +170,7 @@ describe('PerformanceObserverSink', () => {
171170
observer.subscribe();
172171

173172
MockPerformanceObserver.lastInstance()?.emitNavigation('test-navigation');
174-
expect(encode).not.toHaveBeenCalled();
173+
expect(encodePerfEntry).not.toHaveBeenCalled();
175174
});
176175

177176
it('isSubscribed returns false when not observing', () => {
@@ -211,7 +210,7 @@ describe('PerformanceObserverSink', () => {
211210
]);
212211
});
213212

214-
it('flush calls encode for each entry', () => {
213+
it('flush calls encodePerfEntry for each entry', () => {
215214
const observer = new PerformanceObserverSink(options);
216215
observer.subscribe();
217216

@@ -220,13 +219,13 @@ describe('PerformanceObserverSink', () => {
220219

221220
observer.flush();
222221

223-
expect(encode).toHaveBeenCalledWith({
222+
expect(encodePerfEntry).toHaveBeenCalledWith({
224223
name: 'test-mark1',
225224
entryType: 'mark',
226225
startTime: 0,
227226
duration: 0,
228227
});
229-
expect(encode).toHaveBeenCalledWith({
228+
expect(encodePerfEntry).toHaveBeenCalledWith({
230229
name: 'test-mark2',
231230
entryType: 'mark',
232231
startTime: 0,
@@ -239,7 +238,7 @@ describe('PerformanceObserverSink', () => {
239238

240239
performance.mark('test-mark');
241240
observer.flush();
242-
expect(encode).not.toHaveBeenCalled();
241+
expect(encodePerfEntry).not.toHaveBeenCalled();
243242
expect(sink.getWrittenItems()).toStrictEqual([]);
244243
});
245244

@@ -259,11 +258,12 @@ describe('PerformanceObserverSink', () => {
259258
write: vi.fn(() => {
260259
throw new Error('Sink write failed');
261260
}),
261+
isClosed: vi.fn(() => false),
262262
};
263263

264264
const observer = new PerformanceObserverSink({
265265
sink: failingSink as any,
266-
encode,
266+
encodePerfEntry,
267267
flushThreshold: 1,
268268
});
269269

@@ -281,14 +281,14 @@ describe('PerformanceObserverSink', () => {
281281
);
282282
});
283283

284-
it('flush wraps encode errors with descriptive error message', () => {
284+
it('flush wraps encodePerfEntry errors with descriptive error message', () => {
285285
const failingEncode = vi.fn(() => {
286286
throw new Error('Encode failed');
287287
});
288288

289289
const observer = new PerformanceObserverSink({
290290
sink,
291-
encode: failingEncode,
291+
encodePerfEntry: failingEncode,
292292
flushThreshold: 1,
293293
});
294294

@@ -305,4 +305,16 @@ describe('PerformanceObserverSink', () => {
305305
}),
306306
);
307307
});
308+
309+
it('throws error when subscribing with sink that is not open', () => {
310+
const closedSink = new MockSink(); // Note: not calling open()
311+
const observer = new PerformanceObserverSink({
312+
sink: closedSink,
313+
encodePerfEntry,
314+
});
315+
316+
expect(() => observer.subscribe()).toThrow(
317+
'Sink MockSink must be opened before subscribing PerformanceObserver',
318+
);
319+
});
308320
});

0 commit comments

Comments
 (0)