feat: import Chinese-localized Buzz source snapshot
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
/**
|
||||
* Stub getUserMedia with a canvas-generated stream (animated gradient with a
|
||||
* moving circle) so the camera phases work headless and deterministically —
|
||||
* Playwright's bundled headless shell has no media capture support.
|
||||
*/
|
||||
export function installFakeCamera(
|
||||
page: Page,
|
||||
options: {
|
||||
cameraDelayMs?: number;
|
||||
failRequests?: number;
|
||||
holdCamera?: boolean;
|
||||
} = {},
|
||||
) {
|
||||
return page.addInitScript(
|
||||
(cameraOptions) => {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = 640;
|
||||
canvas.height = 480;
|
||||
const context = canvas.getContext("2d");
|
||||
let hue = 0;
|
||||
setInterval(() => {
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
hue = (hue + 7) % 360;
|
||||
context.fillStyle = `hsl(${hue} 80% 60%)`;
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
context.fillStyle = "#ffffff";
|
||||
context.beginPath();
|
||||
context.arc(
|
||||
canvas.width / 2 + Math.sin(hue / 30) * 60,
|
||||
canvas.height / 2,
|
||||
90,
|
||||
0,
|
||||
Math.PI * 2,
|
||||
);
|
||||
context.fill();
|
||||
}, 90);
|
||||
const stream = canvas.captureStream(15);
|
||||
const mediaDevices = navigator.mediaDevices ?? ({} as MediaDevices);
|
||||
if (!navigator.mediaDevices) {
|
||||
Object.defineProperty(navigator, "mediaDevices", {
|
||||
configurable: true,
|
||||
value: mediaDevices,
|
||||
});
|
||||
}
|
||||
const devices: MediaDeviceInfo[] = [
|
||||
{
|
||||
deviceId: "builtin-camera",
|
||||
groupId: "mac",
|
||||
kind: "videoinput",
|
||||
label: "FaceTime HD Camera",
|
||||
toJSON() {
|
||||
return this;
|
||||
},
|
||||
} as MediaDeviceInfo,
|
||||
{
|
||||
deviceId: "iphone-continuity",
|
||||
groupId: "iphone",
|
||||
kind: "videoinput",
|
||||
label: "Kenny's iPhone Camera",
|
||||
toJSON() {
|
||||
return this;
|
||||
},
|
||||
} as MediaDeviceInfo,
|
||||
];
|
||||
const testWindow = window as Window & {
|
||||
__BUZZ_E2E_CAMERA_CONSTRAINTS__?: MediaStreamConstraints[];
|
||||
__BUZZ_E2E_CAMERA_REQUEST_COUNT__?: number;
|
||||
__BUZZ_E2E_RELEASE_CAMERA__?: () => void;
|
||||
};
|
||||
testWindow.__BUZZ_E2E_CAMERA_CONSTRAINTS__ = [];
|
||||
testWindow.__BUZZ_E2E_CAMERA_REQUEST_COUNT__ = 0;
|
||||
let releaseCamera: (() => void) | null = null;
|
||||
testWindow.__BUZZ_E2E_RELEASE_CAMERA__ = () => {
|
||||
releaseCamera?.();
|
||||
releaseCamera = null;
|
||||
};
|
||||
Object.defineProperty(mediaDevices, "enumerateDevices", {
|
||||
configurable: true,
|
||||
value: () => Promise.resolve(devices),
|
||||
});
|
||||
Object.defineProperty(mediaDevices, "addEventListener", {
|
||||
configurable: true,
|
||||
value: () => {},
|
||||
});
|
||||
Object.defineProperty(mediaDevices, "removeEventListener", {
|
||||
configurable: true,
|
||||
value: () => {},
|
||||
});
|
||||
Object.defineProperty(mediaDevices, "getUserMedia", {
|
||||
configurable: true,
|
||||
value: async (constraints: MediaStreamConstraints) => {
|
||||
testWindow.__BUZZ_E2E_CAMERA_CONSTRAINTS__?.push(constraints);
|
||||
testWindow.__BUZZ_E2E_CAMERA_REQUEST_COUNT__ =
|
||||
(testWindow.__BUZZ_E2E_CAMERA_REQUEST_COUNT__ ?? 0) + 1;
|
||||
if (
|
||||
testWindow.__BUZZ_E2E_CAMERA_REQUEST_COUNT__ <=
|
||||
cameraOptions.failRequests
|
||||
) {
|
||||
throw new DOMException("Camera access denied", "NotAllowedError");
|
||||
}
|
||||
if (cameraOptions.holdCamera) {
|
||||
await new Promise<void>((resolve) => {
|
||||
releaseCamera = resolve;
|
||||
});
|
||||
} else if (cameraOptions.cameraDelayMs > 0) {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, cameraOptions.cameraDelayMs),
|
||||
);
|
||||
}
|
||||
return Promise.resolve(stream);
|
||||
},
|
||||
});
|
||||
},
|
||||
{
|
||||
cameraDelayMs: options.cameraDelayMs ?? 0,
|
||||
failRequests: options.failRequests ?? 0,
|
||||
holdCamera: options.holdCamera ?? false,
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user