Files
Piik/tests/native-capture-selection.test.ts
T
AAA 9579a91168 fix: finish native client lifecycle and capture aspect
Accepted native Client lifecycle and Windows capture aspect phase. All Web/Server and three-platform Client checks passed.
2026-09-05 22:41:46 +08:00

117 lines
3.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { CaptureSourcePicker } from "../src/client/components/living/CaptureSourcePicker";
import {
defaultNativeCapturePath,
nativeCaptureTargetKey,
} from "../src/client/native/capture-selection";
import type {
NativeAdapter,
NativeCaptureTarget,
} from "../src/client/native/wire";
function target(
title: string,
sourceId: string,
): Extract<NativeCaptureTarget, { kind: "window" }> {
return {
kind: "window",
title,
sourceId,
pid: 10,
creationTime: "123456",
};
}
describe("native capture source selection", () => {
const game = target("My Game", "1");
it("uses the complete window identity as the UI key", () => {
expect(nativeCaptureTargetKey(game)).toBe("window:1:10:123456");
expect(
nativeCaptureTargetKey({ ...game, creationTime: "654321" }),
).not.toBe(nativeCaptureTargetKey(game));
expect(
nativeCaptureTargetKey({
kind: "display",
sourceId: "2",
title: "Display 1",
}),
).toBe("display:2");
});
it("separates windows from displays and locks Browser switching during native sharing", () => {
const html = renderToStaticMarkup(createElement(CaptureSourcePicker, {
nativeSources: {
kind: "ready",
sources: [game, { kind: "display", sourceId: "2", title: "Display 1" }],
processAudio: false,
systemAudio: true,
},
browserAvailable: false,
audioLocked: true,
onBrowser: () => {},
onNative: () => {},
onPreview: async () => null,
onRefresh: () => {},
onCancel: () => {},
}));
expect(html).toContain('data-source-tab="browser"');
expect(html).toMatch(/data-source-tab="browser"[^>]*disabled=""/);
expect(html).toMatch(/data-native-source="window:1:10:123456"[^>]*disabled=""/);
expect(html).not.toContain('data-native-source="display:2"');
expect(html.match(/role="tab"/g)).toHaveLength(3);
});
it("retains the platform-owned combined source picker", () => {
const html = renderToStaticMarkup(createElement(CaptureSourcePicker, {
nativeSources: {
kind: "ready",
sources: [{ kind: "picker", sourceId: "1", title: "System picker" }],
processAudio: false,
systemAudio: true,
},
onBrowser: () => {},
onNative: () => {},
onPreview: async () => null,
onRefresh: () => {},
onCancel: () => {},
}));
expect(html).toContain('data-native-source="picker:1"');
expect(html).toContain('aria-checked="true"');
});
});
describe("native adapter selection", () => {
const adapters: NativeAdapter[] = [
{ index: 0, name: "GPU A", identity: "a", hardwareH264: [] },
{
index: 1,
name: "GPU B",
identity: "b",
hardwareH264: [{ index: 0, name: "H264", identity: "encoder" }],
},
];
it("selects the first complete hardware path for UI capture", () => {
expect(defaultNativeCapturePath(adapters)).toEqual({
adapterIndex: 1,
encoderIndex: 0,
});
expect(defaultNativeCapturePath([adapters[0]!])).toBeNull();
});
it("uses software VP8 only when that capture capability exists", () => {
expect(defaultNativeCapturePath(adapters, "vp8", true)).toEqual({
adapterIndex: 0, encoderIndex: 0,
});
expect(defaultNativeCapturePath(adapters, "vp8", false)).toBeNull();
expect(defaultNativeCapturePath(adapters, "auto", true)?.adapterIndex).toBe(1);
expect(defaultNativeCapturePath([adapters[0]!], "auto", true)?.adapterIndex).toBe(0);
expect(defaultNativeCapturePath([adapters[0]!], "h264", true)).toBeNull();
});
});