Fix live camera analysis loop

这个提交包含在:
cryptocommuniums-afk
2026-03-14 22:54:15 +08:00
父节点 bc01a40564
当前提交 6943754838
修改 3 个文件,包含 96 行新增11 行删除

查看文件

@@ -40,6 +40,21 @@ test("live camera page exposes camera startup controls", async ({ page }) => {
await expect(page.getByTestId("live-camera-start-button")).toBeVisible();
});
test("live camera starts analysis and produces scores", async ({ page }) => {
await installAppMocks(page, { authenticated: true });
await page.goto("/live-camera");
await page.getByRole("button", { name: "下一步" }).click();
await page.getByRole("button", { name: "下一步" }).click();
await page.getByRole("button", { name: "下一步" }).click();
await page.getByRole("button", { name: /启用摄像头/ }).click();
await expect(page.getByTestId("live-camera-analyze-button")).toBeVisible();
await page.getByTestId("live-camera-analyze-button").click();
await expect(page.getByTestId("live-camera-score-overall")).toBeVisible();
});
test("recorder flow archives a session and exposes it in videos", async ({ page }) => {
await installAppMocks(page, { authenticated: true, videos: [] });

查看文件

@@ -322,6 +322,54 @@ export async function installAppMocks(
};
await page.addInitScript(() => {
const buildFakeLandmarks = () => {
const points = Array.from({ length: 33 }, () => ({
x: 0.5,
y: 0.5,
z: 0,
visibility: 0.99,
}));
points[0] = { x: 0.5, y: 0.15, z: 0, visibility: 0.99 };
points[11] = { x: 0.42, y: 0.28, z: 0, visibility: 0.99 };
points[12] = { x: 0.58, y: 0.28, z: 0, visibility: 0.99 };
points[13] = { x: 0.36, y: 0.42, z: 0, visibility: 0.99 };
points[14] = { x: 0.64, y: 0.42, z: 0, visibility: 0.99 };
points[15] = { x: 0.3, y: 0.54, z: 0, visibility: 0.99 };
points[16] = { x: 0.7, y: 0.52, z: 0, visibility: 0.99 };
points[23] = { x: 0.45, y: 0.58, z: 0, visibility: 0.99 };
points[24] = { x: 0.55, y: 0.58, z: 0, visibility: 0.99 };
points[25] = { x: 0.44, y: 0.76, z: 0, visibility: 0.99 };
points[26] = { x: 0.56, y: 0.76, z: 0, visibility: 0.99 };
points[27] = { x: 0.42, y: 0.94, z: 0, visibility: 0.99 };
points[28] = { x: 0.58, y: 0.94, z: 0, visibility: 0.99 };
return points;
};
class FakePose {
callback = null;
constructor(_config: unknown) {}
setOptions() {}
onResults(callback: (results: { poseLandmarks: ReturnType<typeof buildFakeLandmarks> }) => void) {
this.callback = callback;
}
async send() {
this.callback?.({ poseLandmarks: buildFakeLandmarks() });
}
close() {}
}
Object.defineProperty(window, "__TEST_MEDIAPIPE_FACTORY__", {
configurable: true,
value: async () => ({ Pose: FakePose }),
});
Object.defineProperty(HTMLMediaElement.prototype, "play", {
configurable: true,
value: async () => undefined,