Files
Piik/tests/native-client.test.ts
T
AAA ff50e0609e fix(media): preserve playback through native connection recovery
## Problem and outcome / 问题与结果

Compatible Native receiver renegotiation rebuilt the encoded source and its playback/relay consumers. Replacement backends could also lose committed-route recovery ownership, while queued events and unfinished SFU cleanup could reach a replacement with the same logical identity. Retain compatible receivers, keep recovery on the committed route, and validate physical ownership through final control delivery. SFU activation waits for the existing retirement barrier.

This phase also consumes renewed same-page invitations through the existing grant owner and avoids closing uninitialized Windows capture objects after preview failure. Camera, microphone, interaction and control redesign remain outside this patch.

## Release notes

### 中文

这是一次以连接稳定性为重点的小修复更新。

- 修复 App 接收端重新协商时不必要地中断播放和中继的问题,并保留正确的连接恢复行为。
- 修复旧连接的迟到事件及关闭时序干扰替代连接的问题。
- 修复重新打开同页邀请链接后仍沿用旧邀请的问题。
- 修复 Windows 选源预览失败时的一处异常退出。

更新 App 并刷新网页即可使用这些修复,无需修改配置。

### English

This maintenance update focuses on connection stability.

- Preserve App playback, relay connections and recovery behavior during compatible renegotiation.
- Prevent delayed events and cleanup from retired connections from disrupting their replacements.
- Use the new invitation when another invite link opens in the same page.
- Fix a Windows crash during failed source-preview cleanup.

Update Piik App and refresh the page to use these fixes. No configuration changes are required.

## Verification / 验证

- TypeScript type checking, 71 Vitest files / 1,015 tests and Web production build.
- Go core tests, vet and supported cross-target builds; receiver tests exercise H.264/VP8/Opus, ICE restart, fresh gathering and retained downstream media.
- Windows native compile/probe and deterministic capture checks, including failed-preview cleanup.
- Documentation and repository hygiene checks; independent review of the extracted patch and old/new Web/App capability negotiation.
- Local full-suite runs reached the unchanged Git fixture's 5-second timeout; that suite passed alone. The complete suite was rerun with two workers and a 15-second test deadline.

## Impact / 影响

Planned version: v1.5.6. Existing public wire versions and configuration are retained. Receiver reuse is capability-negotiated: old Apps receive no new request field, and old pages receive no new answer field. Room authority, routing policy and retry budgets are unchanged.

The established-viewing interruption report still lacks paired diagnostics; these reproduced defects do not establish that reporter's exact cause. Physical device/network endurance remains outside local deterministic acceptance. Git/PRs retain this repair history; the TODO ledger retains outstanding reports and separate feature candidates.
2026-09-20 09:45:55 +08:00

637 lines
26 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
import { discoverNativeHealth, NativeClient, NativeCompatibilityError, notifyNativePresentation } from "../src/client/native/client";
import { DEFAULT_QUALITY_SETTINGS } from "../src/shared/protocol";
import {
nativeEventSchema,
nativeHealthSchema,
NATIVE_CLIENT_PROTOCOL,
NATIVE_CLIENT_PORT_START,
NATIVE_CLIENT_PORT_END,
nativeCaptureTargetSchema,
shareSourceReplacedResponseSchema,
shareStartedResponseSchema,
shareUpdatedResponseSchema,
sourcePreviewResponseSchema,
receiveAnswerResponseSchema,
} from "../src/client/native/wire";
afterEach(() => {
vi.useRealTimers();
vi.unstubAllGlobals();
});
describe("native App private wire", () => {
const health = {
protocol: NATIVE_CLIENT_PROTOCOL,
service: "piik-client",
port: NATIVE_CLIENT_PORT_START,
instanceToken: "a".repeat(43),
nativeMedia: { video: true, hardwareH264: true },
};
it.each(["prompt", "denied"] as const)("does not hold Viewer reception for %s permission and observes a later grant", async (state) => {
vi.stubGlobal("window", { setTimeout, clearTimeout, location: { hostname: "piik.example" } });
const query = vi.fn().mockResolvedValue({ state });
vi.stubGlobal("navigator", { permissions: { query } });
const fetcher = vi.fn(async () => new Response(JSON.stringify(health)));
vi.stubGlobal("fetch", fetcher);
const socket = vi.fn();
vi.stubGlobal("WebSocket", socket);
await expect(NativeClient.connect({ waitForPermission: false })).resolves.toBeNull();
expect(fetcher).not.toHaveBeenCalled();
expect(socket).not.toHaveBeenCalled();
query.mockResolvedValue({ state: "granted" });
await expect(discoverNativeHealth({ waitForPermission: false })).resolves.toMatchObject({ port: health.port });
});
it("still lets explicit source discovery ask for local permission", async () => {
vi.stubGlobal("window", { setTimeout, clearTimeout, location: { hostname: "piik.example" } });
const query = vi.fn().mockResolvedValue({ state: "prompt" });
vi.stubGlobal("navigator", { permissions: { query } });
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify(health))));
await expect(discoverNativeHealth()).resolves.toMatchObject({ port: health.port });
expect(query).not.toHaveBeenCalled();
});
it.each(["localhost", "127.0.0.1", "[::1]"])("keeps App Local reception on %s available without cross-address-space consent", async (hostname) => {
vi.stubGlobal("window", { setTimeout, clearTimeout, location: { hostname } });
const query = vi.fn().mockResolvedValue({ state: "prompt" });
vi.stubGlobal("navigator", { permissions: { query } });
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify(health))));
await expect(discoverNativeHealth({ waitForPermission: false })).resolves.toMatchObject({ port: health.port });
expect(query).not.toHaveBeenCalled();
});
it("uses the older combined permission when split permission is unsupported", async () => {
vi.stubGlobal("window", { setTimeout, clearTimeout, location: { hostname: "piik.example" } });
const query = vi.fn().mockRejectedValueOnce(new TypeError("Unsupported permission"))
.mockResolvedValue({ state: "prompt" });
vi.stubGlobal("navigator", { permissions: { query } });
const fetcher = vi.fn();
vi.stubGlobal("fetch", fetcher);
await expect(discoverNativeHealth({ waitForPermission: false })).resolves.toBeNull();
expect(query).toHaveBeenLastCalledWith({ name: "local-network-access" });
expect(fetcher).not.toHaveBeenCalled();
});
it.each([undefined, { query: vi.fn().mockRejectedValue(new TypeError("Unsupported permission")) }])(
"retains ordinary discovery when local permissions cannot be queried",
async (permissions) => {
vi.stubGlobal("window", { setTimeout, clearTimeout, location: { hostname: "piik.example" } });
vi.stubGlobal("navigator", { permissions });
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify(health))));
await expect(discoverNativeHealth({ waitForPermission: false })).resolves.toMatchObject({ port: health.port });
},
);
it.each([NATIVE_CLIENT_PROTOCOL - 1, NATIVE_CLIENT_PROTOCOL + 1])(
"reports observed Piik App protocol %s without opening control or presentation",
async (protocol) => {
vi.stubGlobal("window", { setTimeout, clearTimeout });
const socket = vi.fn();
vi.stubGlobal("WebSocket", socket);
const fetcher = vi.fn(async (url: string) => url === `http://127.0.0.1:${health.port}/health`
? new Response(JSON.stringify({ ...health, protocol }))
: new Response(null, { status: 403 }));
vi.stubGlobal("fetch", fetcher);
await expect(NativeClient.connect()).rejects.toMatchObject({
name: "NativeCompatibilityError", actualProtocol: protocol,
});
await expect(notifyNativePresentation("en", new AbortController().signal))
.rejects.toBeInstanceOf(NativeCompatibilityError);
expect(socket).not.toHaveBeenCalled();
expect(fetcher.mock.calls.every(([url]) => url.endsWith("/health"))).toBe(true);
expect(fetcher).toHaveBeenCalledTimes(2 * (NATIVE_CLIENT_PORT_END - NATIVE_CLIENT_PORT_START + 1));
},
);
it("prefers a compatible App on a later port after observing an incompatible App", async () => {
vi.stubGlobal("window", { setTimeout, clearTimeout });
const fetcher = vi.fn(async (url: string) => {
const port = Number(new URL(url).port);
return new Response(JSON.stringify({ ...health, port,
protocol: port === health.port ? NATIVE_CLIENT_PROTOCOL + 1 : NATIVE_CLIENT_PROTOCOL,
}));
});
vi.stubGlobal("fetch", fetcher);
await expect(discoverNativeHealth()).resolves.toMatchObject({
protocol: NATIVE_CLIENT_PROTOCOL, port: NATIVE_CLIENT_PORT_START + 1,
});
expect(fetcher).toHaveBeenCalledTimes(NATIVE_CLIENT_PORT_END - NATIVE_CLIENT_PORT_START + 1);
});
it("keeps discovery alive while local access takes longer than 400 ms", async () => {
vi.useFakeTimers();
vi.stubGlobal("window", { setTimeout, clearTimeout });
vi.stubGlobal("fetch", vi.fn(async (url: string, options: RequestInit) => {
if (new URL(url).port !== String(health.port)) throw new TypeError("No listener");
await new Promise<void>((resolve, reject) => {
const timer = setTimeout(resolve, 1_500);
options.signal!.addEventListener("abort", () => {
clearTimeout(timer);
reject(new DOMException("Aborted", "AbortError"));
}, { once: true });
});
return new Response(JSON.stringify(health));
}));
const discovery = discoverNativeHealth();
await vi.advanceTimersByTimeAsync(1_500);
await expect(discovery).resolves.toMatchObject({ port: health.port });
expect(vi.getTimerCount()).toBe(0);
});
it("finds a later App without waiting for a silent port and aborts the unused probe", async () => {
vi.stubGlobal("window", { setTimeout, clearTimeout });
let silentSignal: AbortSignal | undefined;
vi.stubGlobal("fetch", vi.fn(async (url: string, options: RequestInit) => {
const port = Number(new URL(url).port);
if (port === health.port) {
silentSignal = options.signal!;
return new Promise<Response>((_resolve, reject) => {
silentSignal!.addEventListener("abort", () => reject(new DOMException("Aborted", "AbortError")), { once: true });
});
}
if (port !== health.port + 1) throw new TypeError("No listener");
return new Response(JSON.stringify({ ...health, port }));
}));
await expect(discoverNativeHealth()).resolves.toMatchObject({ port: health.port + 1 });
expect(silentSignal?.aborted).toBe(true);
});
it("bounds all silent discovery ports with one deadline", async () => {
vi.useFakeTimers();
vi.stubGlobal("window", { setTimeout, clearTimeout });
const signals: AbortSignal[] = [];
vi.stubGlobal("fetch", vi.fn(async (_url: string, options: RequestInit) => {
signals.push(options.signal!);
return new Promise<Response>((_resolve, reject) => {
options.signal!.addEventListener("abort", () => reject(new DOMException("Aborted", "AbortError")), { once: true });
});
}));
const discovery = discoverNativeHealth();
await vi.advanceTimersByTimeAsync(8_000);
await expect(discovery).resolves.toBeNull();
expect(signals).toHaveLength(NATIVE_CLIENT_PORT_END - NATIVE_CLIENT_PORT_START + 1);
expect(signals.every((signal) => signal.aborted)).toBe(true);
expect(vi.getTimerCount()).toBe(0);
});
it("identifies an incompatible App even when that protocol uses different token or media metadata", async () => {
vi.stubGlobal("window", { setTimeout, clearTimeout });
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({
...health, protocol: NATIVE_CLIENT_PROTOCOL + 1,
instanceToken: { format: "different-protocol" }, nativeMedia: "different-protocol",
}))));
await expect(NativeClient.connect()).rejects.toMatchObject({
name: "NativeCompatibilityError", actualProtocol: NATIVE_CLIENT_PROTOCOL + 1,
});
});
it("treats denied, absent and malformed endpoints as ordinary Browser-only operation", async () => {
vi.stubGlobal("window", { setTimeout, clearTimeout });
const malformed = [
{ ...health, service: "another-service" },
{ ...health, protocol: "8" },
{ ...health, instanceToken: "invalid" },
{ ...health, nativeMedia: { video: "yes" } },
{ ...health, protocol: 8, port: NATIVE_CLIENT_PORT_END },
];
let responseIndex = 0;
vi.stubGlobal("fetch", vi.fn(async () => {
const body = malformed[responseIndex++];
if (body) return new Response(JSON.stringify(body));
if (responseIndex % 2 === 0) return new Response(null, { status: 403 });
throw new TypeError("Network unavailable");
}));
await expect(NativeClient.connect()).resolves.toBeNull();
});
it("notifies only the current presentation request after App discovery", async () => {
vi.stubGlobal("window", {
setTimeout: globalThis.setTimeout,
clearTimeout: globalThis.clearTimeout,
});
const fetcher = vi.fn(async (url: string) => url.endsWith("/health")
? new Response(JSON.stringify({
protocol: 9, service: "piik-client", port: 39_721,
instanceToken: "a".repeat(43),
nativeMedia: {video: true, processAudio: false, systemAudio: true, hardwareH264: true, softwareVP8: true},
}), {status: 200})
: new Response(null, {status: 204}));
vi.stubGlobal("fetch", fetcher);
const stale = new AbortController();
const staleNotification = notifyNativePresentation("zh", stale.signal);
stale.abort();
await staleNotification;
expect(fetcher).toHaveBeenCalledTimes(NATIVE_CLIENT_PORT_END - NATIVE_CLIENT_PORT_START + 1);
expect(fetcher).toHaveBeenCalledWith("http://127.0.0.1:39721/health", expect.anything());
const current = new AbortController();
await notifyNativePresentation("vis", current.signal);
expect(fetcher).toHaveBeenLastCalledWith("http://127.0.0.1:39721/presentation", expect.objectContaining({
method: "POST", body: JSON.stringify({language: "vis"}), signal: current.signal,
}));
});
it("notifies the owner once on an unexpected close and stays silent on cleanup", async () => {
const sockets: FakeWebSocket[] = [];
const token = "a".repeat(43);
class FakeWebSocket extends EventTarget {
static readonly OPEN = 1;
static readonly CLOSING = 2;
static readonly CLOSED = 3;
readyState = FakeWebSocket.OPEN;
protocol = `piik-client-v9.${token}`;
readonly close = vi.fn(() => {
this.readyState = FakeWebSocket.CLOSING;
});
constructor(readonly url: string, readonly protocols: string[]) {
super();
sockets.push(this);
queueMicrotask(() => this.dispatchEvent(new Event("open")));
}
send(payload: string): void {
const request = JSON.parse(payload) as { id: string; type: string };
if (!["hello", "update-share", "ping"].includes(request.type)) return;
queueMicrotask(() => {
const event = new Event("message");
Object.defineProperty(event, "data", {
value: JSON.stringify({
version: 9,
id: request.id,
type: request.type === "hello" ? "ready" : request.type === "ping" ? "pong" : "request-failed",
...(request.type === "update-share" ? { code: "operation-failed" } : {}),
}),
});
this.dispatchEvent(event);
});
}
emitUnexpectedClose(): void {
this.readyState = FakeWebSocket.CLOSED;
this.dispatchEvent(new Event("close"));
}
}
vi.stubGlobal("WebSocket", FakeWebSocket);
vi.stubGlobal("window", {
setTimeout: globalThis.setTimeout,
clearTimeout: globalThis.clearTimeout,
});
vi.stubGlobal("fetch", vi.fn(async () =>
new Response(JSON.stringify({
protocol: 9,
service: "piik-client",
port: 39_721,
instanceToken: token,
nativeMedia: {
video: true,
processAudio: false,
systemAudio: false,
hardwareH264: true,
softwareVP8: true,
},
}), { status: 200 }),
));
const client = await NativeClient.connect();
expect(client).not.toBeNull();
const unexpected = vi.fn();
client!.onClose(unexpected);
await expect(client!.updateShare("share_123456", DEFAULT_QUALITY_SETTINGS))
.rejects.toThrow("Piik App request failed");
await client!.ping();
expect(sockets[0]!.close).not.toHaveBeenCalled();
expect(unexpected).not.toHaveBeenCalled();
sockets[0]!.emitUnexpectedClose();
sockets[0]!.emitUnexpectedClose();
expect(unexpected).toHaveBeenCalledOnce();
const cleanClient = await NativeClient.connect();
expect(cleanClient).not.toBeNull();
const intentional = vi.fn();
cleanClient!.onClose(intentional);
cleanClient!.close();
sockets[1]!.emitUnexpectedClose();
expect(intentional).not.toHaveBeenCalled();
});
it("accepts descriptive health extensions and treats absent media features as unavailable", () => {
expect(
nativeHealthSchema.parse({
protocol: 9,
service: "piik-client",
port: 39_721,
instanceToken: "a".repeat(43),
nativeMedia: {
video: true,
processAudio: false,
systemAudio: true,
hardwareH264: true,
softwareVP8: true,
},
}),
).toMatchObject({ nativeMedia: { processAudio: false } });
expect(
nativeHealthSchema.safeParse({
protocol: NATIVE_CLIENT_PROTOCOL,
service: "piik-client",
port: 39_721,
instanceToken: "a".repeat(43),
nativeMedia: {
video: true,
processAudio: true,
systemAudio: true,
hardwareH264: true,
softwareVP8: false,
},
adapters: ["private"],
}).success,
).toBe(true);
expect(nativeHealthSchema.parse({
...health, futureDescription: "ignored", nativeMedia: { video: true, futureFeature: true },
})).toEqual({
...health, nativeMedia: {
receiverReuse: false,
video: true, processAudio: false, systemAudio: false, captureBorderControl: false, hardwareH264: false, softwareVP8: false,
},
});
expect(nativeHealthSchema.parse({ ...health, nativeMedia: undefined }).nativeMedia)
.toEqual({ receiverReuse: false, video: false, processAudio: false, systemAudio: false, captureBorderControl: false, hardwareH264: false, softwareVP8: false });
for (const invalid of [
{ protocol: 0 }, { protocol: 9.5 }, { protocol: Number.MAX_SAFE_INTEGER + 1 },
{ service: "other" }, { port: NATIVE_CLIENT_PORT_END + 1 }, { instanceToken: "short" },
{ nativeMedia: { softwareVP8: "true" } }, { nativeMedia: { captureBorderControl: "true" } }, { nativeMedia: null },
]) expect(nativeHealthSchema.safeParse({ ...health, ...invalid }).success).toBe(false);
});
it.each([undefined, false, true])("gates capture-border commands on advertised support: %s", async (supported) => {
const requests: Record<string, unknown>[] = [];
class CaptureSocket extends EventTarget {
static readonly OPEN = 1;
static readonly CLOSING = 2;
readyState = CaptureSocket.OPEN;
protocol = `piik-client-v9.${health.instanceToken}`;
constructor() {
super();
queueMicrotask(() => this.dispatchEvent(new Event("open")));
}
close() { this.readyState = CaptureSocket.CLOSING; }
send(payload: string) {
const request = JSON.parse(payload) as Record<string, unknown>;
requests.push(request);
queueMicrotask(() => this.dispatchEvent(new MessageEvent("message", {
data: JSON.stringify({
version: NATIVE_CLIENT_PROTOCOL, id: request.id,
...(request.type === "hello" ? { type: "ready" } : {
type: request.type === "start-share" ? "share-started" : "share-source-replaced",
shareId: request.shareId,
...(request.type === "start-share" ? { audio: true, codec: "h264" } : {}),
}),
}),
})));
}
}
vi.stubGlobal("WebSocket", CaptureSocket);
vi.stubGlobal("window", { setTimeout, clearTimeout });
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({
...health, nativeMedia: { ...health.nativeMedia, captureBorderControl: supported },
}))));
const client = await NativeClient.connect();
expect(client).not.toBeNull();
expect(client!.health.nativeMedia.captureBorderControl).toBe(supported ?? false);
const input = {
shareId: "share_123456", source: { kind: "display" as const, sourceId: "2", title: "Display 1" },
audio: true, adapterIndex: 0, encoderIndex: 0, edgeCapacity: 2,
profile: DEFAULT_QUALITY_SETTINGS, codec: "auto" as const,
};
try {
for (const showCaptureBorder of [undefined, false, true]) {
await client!.startShare({ ...input, showCaptureBorder });
await client!.replaceShareSource(input.shareId, input.source, input.audio, input, showCaptureBorder);
const extension = supported ? { showCaptureBorder: showCaptureBorder ?? false } : {};
expect(requests.at(-2)).toEqual({
version: NATIVE_CLIENT_PROTOCOL, id: expect.any(String), type: "start-share", ...input, ...extension,
});
expect(requests.at(-1)).toEqual({
version: NATIVE_CLIENT_PROTOCOL, id: expect.any(String), type: "replace-share-source",
shareId: input.shareId, source: input.source, audio: true, adapterIndex: 0, encoderIndex: 0, ...extension,
});
}
} finally { client!.close(); }
});
it.each([false, true])("requests receiver reuse only from a capable App (%s)", async (supported) => {
const requests: Record<string, unknown>[] = [];
class Socket extends EventTarget {
static readonly OPEN = 1;
static readonly CLOSING = 2;
readyState = Socket.OPEN;
protocol = `piik-client-v9.${health.instanceToken}`;
constructor() { super(); queueMicrotask(() => this.dispatchEvent(new Event("open"))); }
close() { this.readyState = Socket.CLOSING; }
send(payload: string) {
const request = JSON.parse(payload) as Record<string, unknown>;
requests.push(request);
queueMicrotask(() => this.dispatchEvent(new MessageEvent("message", { data: JSON.stringify({
version: 9, id: request.id, ...(request.type === "hello" ? { type: "ready" } : {
type: "receive-answer", shareId: request.shareId, connectionId: request.connectionId,
sdp: "answer", audio: false, codec: "vp8", ...(supported ? { reused: true } : {}),
}),
}) })));
}
}
vi.stubGlobal("WebSocket", Socket);
vi.stubGlobal("window", { setTimeout, clearTimeout });
vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({
...health, nativeMedia: { ...health.nativeMedia, ...(supported ? { receiverReuse: true } : {}) },
}))));
const client = (await NativeClient.connect())!;
try {
const result = await client.receiveOffer("share_123456", "connection_1234", { type: "offer", sdp: "offer" }, { iceServers: [] }, 2);
expect(requests.at(-1)).toEqual({ version: 9, id: expect.any(String), type: "receive-offer",
shareId: "share_123456", connectionId: "connection_1234", sdp: "offer", iceServers: [], edgeCapacity: 2,
...(supported ? { reuseReceiver: true } : {}),
});
expect(result.reused).toBe(supported);
} finally { client.close(); }
});
it("keeps 64-bit Windows identities as exact decimal strings", () => {
expect(
nativeCaptureTargetSchema.safeParse({
kind: "window",
sourceId: "12345678901234567890",
pid: 1234,
creationTime: "134327999999999999",
title: "Game",
}).success,
).toBe(true);
expect(
nativeCaptureTargetSchema.safeParse({
kind: "window",
sourceId: 12345678901234567890,
pid: 1234,
creationTime: 134327999999999999,
title: "Game",
}).success,
).toBe(false);
expect(
nativeCaptureTargetSchema.safeParse({
kind: "display",
sourceId: "65537",
title: "Display 1",
}).success,
).toBe(true);
expect(
nativeCaptureTargetSchema.safeParse({
kind: "picker",
sourceId: "1",
title: "System picker",
}).success,
).toBe(true);
});
it("fences native events by share and connection identity", () => {
const event = {
version: 9,
type: "edge-state",
shareId: "share_123456",
connectionId: "edge_1234567",
state: "connected",
};
expect(nativeEventSchema.safeParse(event).success).toBe(true);
expect(
nativeEventSchema.safeParse({ ...event, connectionId: "short" }).success,
).toBe(false);
expect(
nativeEventSchema.safeParse({ ...event, routeRevision: 1 }).success,
).toBe(false);
const path = {
version: 9,
type: "edge-path",
shareId: "share_123456",
connectionId: "edge_1234567",
localType: "host",
remoteType: "srflx",
natTraversalPath: "predicted",
};
expect(nativeEventSchema.safeParse(path).success).toBe(true);
const { natTraversalPath: _missing, ...incompletePath } = path;
expect(nativeEventSchema.safeParse(incompletePath).success).toBe(false);
});
it("keeps an unavailable preview advisory instead of treating it as media failure", () => {
const preview = {
version: 9,
id: "request_preview",
type: "source-preview",
sourceKey: "display:65537",
mime: "image/bmp",
data: "",
};
expect(sourcePreviewResponseSchema.safeParse(preview).success).toBe(true);
expect(sourcePreviewResponseSchema.safeParse({
...preview,
data: Buffer.alloc(54 + 320 * 180 * 3).toString("base64"),
}).success).toBe(true);
expect(sourcePreviewResponseSchema.safeParse({
...preview,
data: "A".repeat(256 * 1024 + 1),
}).success).toBe(false);
});
it("keeps native share lifecycle responses as strict acknowledgements", () => {
const profile = {
resolution: "1440p",
maxFramerate: 60,
maxBitrate: 12_000_000,
degradationPreference: "maintain-framerate",
screenAudioQuality: "very-high",
};
expect(shareStartedResponseSchema.safeParse({
version: 9,
id: "request_start",
type: "share-started",
shareId: "share_123456",
audio: true,
codec: "h264",
}).success).toBe(true);
expect(shareUpdatedResponseSchema.safeParse({
version: 9,
id: "request_update",
type: "share-updated",
shareId: "share_123456",
}).success).toBe(true);
expect(shareSourceReplacedResponseSchema.safeParse({
version: 9,
id: "request_source",
type: "share-source-replaced",
shareId: "share_123456",
}).success).toBe(true);
expect(shareUpdatedResponseSchema.safeParse({
version: 9,
id: "request_update",
type: "share-updated",
shareId: "share_123456",
profile,
}).success).toBe(false);
});
it("requires the actual Native codec instead of reporting Auto as media", () => {
const response = {
version: 9,
id: "request_receive",
type: "receive-answer",
shareId: "share_123456",
connectionId: "edge_1234567",
sdp: "v=0\r\n",
audio: false,
};
for (const codec of ["h264", "vp8"]) {
expect(receiveAnswerResponseSchema.safeParse({ ...response, codec }).success).toBe(true);
expect(shareStartedResponseSchema.safeParse({
version: 9, id: "request_start", type: "share-started",
shareId: response.shareId, audio: false, codec,
}).success).toBe(true);
}
expect(receiveAnswerResponseSchema.safeParse(response).success).toBe(false);
expect(receiveAnswerResponseSchema.safeParse({ ...response, codec: "auto" }).success).toBe(false);
});
it("accepts only internally consistent native quality evidence", () => {
const event = {
version: 9,
type: "edge-quality",
shareId: "share_123456",
connectionId: "edge_1234567",
sampleTimestampMs: 10_000,
sampleWindowMs: 2_000,
rtpStatsId: "pc_12345678",
trackIdentifier: "screen",
state: "degraded",
reason: "bandwidth",
intervalFramesEncoded: 60,
framesPerSecond: 30,
bitrateKbps: 3_000,
availableOutgoingKbps: 1_000,
width: 1280,
height: 720,
};
expect(nativeEventSchema.safeParse(event).success).toBe(true);
expect(
nativeEventSchema.safeParse({ ...event, reason: "none" }).success,
).toBe(false);
expect(
nativeEventSchema.safeParse({
...event,
state: "unknown",
reason: null,
}).success,
).toBe(true);
});
});