84 lines
3.0 KiB
TypeScript
84 lines
3.0 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
countInitRequests,
|
|
firstPaintHeavyHits,
|
|
percentile,
|
|
redactResourceUrl,
|
|
summarizeLatencies,
|
|
summarizeResources,
|
|
} from './initialLoadMetrics';
|
|
|
|
test('redactResourceUrl drops query and origin', () => {
|
|
assert.equal(
|
|
redactResourceUrl('http://127.0.0.1:8080/api/v1/chat/sessions?project_id=1&token=secret'),
|
|
'/api/v1/chat/sessions',
|
|
);
|
|
assert.equal(redactResourceUrl('/assets/index-abc.js'), '/assets/index-abc.js');
|
|
});
|
|
|
|
test('summarizeResources flags deferred heavy chunks', () => {
|
|
const summary = summarizeResources([
|
|
{ path: '/assets/index-abc.js', initiator: 'script', durationMs: 12, transferBytes: 100, decodedBytes: 400 },
|
|
{ path: '/assets/katex-xyz.js', initiator: 'script', durationMs: 4, transferBytes: 50, decodedBytes: 200 },
|
|
]);
|
|
assert.equal(summary.jsCount, 2);
|
|
assert.equal(summary.transferBytes, 150);
|
|
assert.deepEqual(summary.heavyChunks, ['/assets/katex-xyz.js']);
|
|
});
|
|
|
|
test('firstPaintHeavyHits lists only deferred module paths', () => {
|
|
assert.deepEqual(
|
|
firstPaintHeavyHits([
|
|
{ path: '/assets/index-abc.js', initiator: 'script', durationMs: 1, transferBytes: 10, decodedBytes: 40 },
|
|
{ path: '/assets/mermaid-abc.js', initiator: 'script', durationMs: 2, transferBytes: 20, decodedBytes: 80 },
|
|
{ path: '/assets/docx-abc.js', initiator: 'script', durationMs: 3, transferBytes: 30, decodedBytes: 120 },
|
|
]),
|
|
['/assets/mermaid-abc.js', '/assets/docx-abc.js'],
|
|
);
|
|
assert.deepEqual(
|
|
firstPaintHeavyHits([
|
|
{ path: '/assets/index-abc.js', initiator: 'script', durationMs: 1, transferBytes: 10, decodedBytes: 40 },
|
|
]),
|
|
[],
|
|
);
|
|
});
|
|
|
|
test('countInitRequests separates member fanout from session lists', () => {
|
|
const counts = countInitRequests([
|
|
{ method: 'GET', path: '/api/v1/projects/1/members' },
|
|
{ method: 'GET', path: '/api/v1/projects/2/members' },
|
|
{ method: 'POST', path: '/api/v1/projects/2/members' },
|
|
{ method: 'GET', path: '/api/v1/chat/sessions' },
|
|
{ method: 'GET', path: '/api/v1/chat/sessions' },
|
|
]);
|
|
assert.equal(counts.memberGetCount, 2);
|
|
assert.equal(counts.distinctMemberProjects, 2);
|
|
assert.equal(counts.sessionListGetCount, 2);
|
|
});
|
|
|
|
test('percentile uses nearest-rank and stays null on empty input', () => {
|
|
assert.equal(percentile([], 75), null);
|
|
assert.equal(percentile([10, 20, 30, 40], 75), 30);
|
|
});
|
|
|
|
test('summarizeLatencies reports p50/p75/p95', () => {
|
|
assert.deepEqual(summarizeLatencies([]), {
|
|
n: 0,
|
|
p50: null,
|
|
p75: null,
|
|
p95: null,
|
|
min: null,
|
|
max: null,
|
|
});
|
|
// 20 samples: p50=rank10 → 1000; p75=rank15 → 1500; p95=rank19 → 1900
|
|
const values = Array.from({ length: 20 }, (_, i) => (i + 1) * 100);
|
|
const summary = summarizeLatencies(values);
|
|
assert.equal(summary.n, 20);
|
|
assert.equal(summary.p50, 1000);
|
|
assert.equal(summary.p75, 1500);
|
|
assert.equal(summary.p95, 1900);
|
|
assert.equal(summary.min, 100);
|
|
assert.equal(summary.max, 2000);
|
|
});
|