Files
Piik/tests/stats-grid.test.ts
T
2026-08-26 19:05:21 +08:00

199 lines
5.6 KiB
TypeScript

import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it } from "vitest";
import { StatsGrid } from "../src/client/components/StatsGrid.tsx";
import {
EMPTY_METRICS,
type ConnectionMetrics,
} from "../src/client/types.ts";
const metrics = {
...EMPTY_METRICS,
bitrateKbps: 4_200,
framesPerSecond: 59.8,
resolution: "1920x1080",
rttMs: 21,
packetLossPercent: 0.4,
availableOutgoingKbps: 8_100,
iceProtocol: "udp",
localCandidateType: "srflx",
remoteCandidateType: "host",
localCandidateAddress: "192.0.2.10",
localCandidatePort: 50_000,
remoteCandidateAddress: "2001:db8::10",
remoteCandidatePort: 50_001,
selectedCandidatePairId: "candidate-pair-7",
codec: "video/VP8",
codecParameters: "max-fs=8160",
captureWidth: 1_920,
captureHeight: 1_080,
captureFramesPerSecond: 60,
mediaSourceFramesPerSecond: 58.5,
rtpRid: "h",
audioBitrateKbps: 128,
audioCodec: "audio/opus",
encoderImplementation: "ExternalEncoder",
intervalFramesEncoded: 116,
intervalEncodeTimeMs: 371.2,
intervalEncodeMs: 3.2,
qualityLimitationReason: "bandwidth",
} satisfies ConnectionMetrics;
describe("StatsGrid progressive disclosure", () => {
it("keeps one-glance picture results above an accessible detail panel", () => {
const html = renderToStaticMarkup(
createElement(StatsGrid, {
metrics,
direction: "send",
progressive: true,
}),
);
for (const label of ["分辨率", "帧率", "码率", "丢包率"]) {
expect(html).toContain(label);
}
expect(html).toContain('aria-expanded="false"');
expect(html).toContain('title="展开详细指标"');
const controlId = html.match(/aria-controls="([^"]+)"/)?.[1];
expect(controlId).toBeTruthy();
const panelStart = html.indexOf(`<dl id="${controlId}"`);
expect(panelStart).toBeGreaterThan(0);
expect(html.slice(panelStart, html.indexOf(">", panelStart))).toContain(
'hidden=""',
);
for (const label of [
"RTT",
"视频编码",
"可用上行",
"质量状态",
"捕获设置",
"编码输入帧率",
"编码器",
"编码耗时/帧",
"音频码率",
]) {
expect(html.indexOf(label)).toBeGreaterThan(panelStart);
}
expect(html).toContain("58.5 fps");
expect(html).toContain("VP8");
});
it("shows the negotiated video codec but omits browser-internal transport details", () => {
const html = renderToStaticMarkup(
createElement(StatsGrid, { metrics, direction: "send" }),
);
expect(html).toContain("<dt>视频编码</dt><dd>VP8</dd>");
for (const omitted of [
"音频 Codec",
"候选路径",
"本地候选地址",
"远端候选地址",
"候选对 ID",
"STUN 响应",
"candidate-pair-7",
"192.0.2.10",
"当前 RID",
"max-fs=8160",
"请求 / 应用",
]) {
expect(html).not.toContain(omitted);
}
expect(html).not.toContain("详细指标");
expect(html).not.toContain("aria-expanded");
});
it("shows codecs only when the negotiated contract is unexpected", () => {
const html = renderToStaticMarkup(
createElement(StatsGrid, {
metrics: {
...metrics,
codec: "video/VP9",
audioCodec: "audio/PCMU",
},
direction: "receive",
}),
);
expect(html).toContain("视频编码为 VP9,预期 H264 或 VP8");
expect(html).toContain("音频编码为 PCMU,预期 Opus");
expect(html).not.toContain("视频 Codec");
expect(html).not.toContain("音频 Codec");
});
it("does not expose an unknown browser quality-limitation value", () => {
const html = renderToStaticMarkup(
createElement(StatsGrid, {
metrics: {
...metrics,
qualityLimitationReason: "browser-internal-sentinel",
},
direction: "send",
}),
);
expect(html).toContain("未分类限制");
expect(html).not.toContain("browser-internal-sentinel");
});
it("shows available inbound playback and repair evidence only for receivers", () => {
const receiverMetrics = {
...metrics,
jitterMs: 4.5,
framesDropped: 2,
intervalDecodeMs: 2.1,
intervalFreezeCount: 1,
intervalFreezeDurationMs: 120,
audioVideoPlayoutDeltaMs: -12.5,
videoJitterBufferDelayMs: 24.5,
audioJitterBufferDelayMs: 18.5,
audioConcealedSamplesPercent: 1.25,
intervalAudioConcealmentEvents: 3,
} satisfies ConnectionMetrics;
const receiveHtml = renderToStaticMarkup(
createElement(StatsGrid, {
metrics: receiverMetrics,
direction: "receive",
}),
);
const sendHtml = renderToStaticMarkup(
createElement(StatsGrid, {
metrics: receiverMetrics,
direction: "send",
}),
);
for (const label of [
"网络抖动",
"丢帧",
"解码耗时/帧",
"画面冻结",
"冻结时长",
"音视频播放差",
"视频缓冲",
"音频缓冲",
"音频补偿率",
"音频补偿",
]) {
expect(receiveHtml).toContain(label);
expect(sendHtml).not.toContain(label);
}
expect(receiveHtml).toContain("-12.5 ms");
expect(receiveHtml).toContain("1.3%");
});
it("does not render an empty second level", () => {
const html = renderToStaticMarkup(
createElement(StatsGrid, {
metrics: EMPTY_METRICS,
direction: "receive",
progressive: true,
}),
);
expect(html).not.toContain("详细指标");
expect(html).not.toContain("aria-expanded");
});
});