From 0633cb45049773c203eebff39556136f6581ebab Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 3 May 2026 17:48:53 -0700 Subject: [PATCH] test(plugins): stabilize prerelease surface checks --- CHANGELOG.md | 2 + extensions/google-meet/index.test.ts | 46 ++++++++++++++----- .../contract/scenario-runtime-approval.ts | 6 +-- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bffbde9785d..4c7d21732e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,10 +67,12 @@ Docs: https://docs.openclaw.ai - Google Meet: refresh realtime browser state during status and retry delayed speech after Meet finishes joining, so a just-opened in-call tab no longer leaves speech stuck behind stale `not-in-call` health. - Plugins/install: recover the install ledger from the managed npm root when `plugins/installs.json` is empty or partial, so reinstalling Discord and Codex no longer makes the other installed plugin disappear. - Google Meet: grant Meet media permissions through the Playwright browser context when CDP grants do not affect the attached Chrome page, and report in-call microphone/speaker permission problems instead of marking realtime speech ready. +- Google Meet: keep Chrome realtime transport tests hermetic on Linux prerelease shards while preserving the macOS-only runtime guard. Thanks @vincentkoc. - QA/Slack: fail the live mention-gating scenario on any unexpected SUT reply, even when the reply does not echo the expected marker. Thanks @vincentkoc. - QA/Matrix: steer the live tool-progress preview check away from `HEARTBEAT.md` and report final preview candidates when the live marker reply misses the exact token. Thanks @vincentkoc. - QA/Matrix: let the live tool-progress preview and error checks verify progress replacement events without depending on the preview saying `Working`, `tool: read`, or unlabelled `read from`. Thanks @vincentkoc. - QA/Matrix: wait for live approval reactions to echo before starting the threaded approval decision timeout. Thanks @vincentkoc. +- QA/Matrix: reuse the primed driver sync stream when confirming approval reaction echoes, avoiding missed self-reactions in live release runs. Thanks @vincentkoc. - Tlon: expose `groupInviteAllowlist` in the channel config schema and clarify that group invite auto-accept fails closed without an invite allowlist. Thanks @vincentkoc. - Control UI/WebChat: collapse duplicate in-flight internal text sends onto the active Gateway run so rapid repeat submits do not start fresh `agent:main:main` dispatches. Fixes #75737. Thanks @dsdsddd1 and @BunsDev. - Mattermost: accept the documented `channels.mattermost.streaming` config and honor `streaming: "off"` by disabling draft preview posts. Thanks @vincentkoc. diff --git a/extensions/google-meet/index.test.ts b/extensions/google-meet/index.test.ts index 7ddead7e4b5..acd3b7a165e 100644 --- a/extensions/google-meet/index.test.ts +++ b/extensions/google-meet/index.test.ts @@ -94,6 +94,19 @@ function setup( return harness; } +async function withProcessPlatform( + platform: NodeJS.Platform, + callback: () => Promise, +): Promise { + const originalPlatform = process.platform; + Object.defineProperty(process, "platform", { value: platform }); + try { + return await callback(); + } finally { + Object.defineProperty(process, "platform", { value: originalPlatform }); + } +} + function jsonResponse(value: unknown): Response { return new Response(JSON.stringify(value), { status: 200, @@ -1893,9 +1906,11 @@ describe("google-meet plugin", () => { | undefined; const respond = vi.fn(); - await handler?.({ - params: { url: "https://meet.google.com/abc-defg-hij" }, - respond, + await withProcessPlatform("darwin", async () => { + await handler?.({ + params: { url: "https://meet.google.com/abc-defg-hij" }, + respond, + }); }); expect(respond.mock.calls[0]?.[0]).toBe(true); @@ -1982,9 +1997,11 @@ describe("google-meet plugin", () => { | undefined; const respond = vi.fn(); - await handler?.({ - params: { url: "https://meet.google.com/abc-defg-hij" }, - respond, + await withProcessPlatform("darwin", async () => { + await handler?.({ + params: { url: "https://meet.google.com/abc-defg-hij" }, + respond, + }); }); expect(respond.mock.calls[0]?.[0]).toBe(true); @@ -2060,9 +2077,11 @@ describe("google-meet plugin", () => { | undefined; const respond = vi.fn(); - await handler?.({ - params: { url: "https://meet.google.com/abc-defg-hij" }, - respond, + await withProcessPlatform("darwin", async () => { + await handler?.({ + params: { url: "https://meet.google.com/abc-defg-hij" }, + respond, + }); }); expect(respond.mock.calls[0]?.[0]).toBe(true); @@ -2310,14 +2329,19 @@ describe("google-meet plugin", () => { ).runInContext(context) as () => string | Promise; const first = JSON.parse(await inspect()) as { captionsEnabledAttempted?: boolean }; - const stateAfterFirst = windowState.__openclawMeetCaptions as { enabledAttempted?: boolean }; + const captionsStateKey = "__openclawMeetCaptions"; + const stateAfterFirst = windowState[captionsStateKey] as { + enabledAttempted?: boolean; + }; expect(first.captionsEnabledAttempted).toBe(false); expect(stateAfterFirst.enabledAttempted).toBe(false); expect(captionButton.click).not.toHaveBeenCalled(); page.buttons = [leaveButton, captionButton]; const second = JSON.parse(await inspect()) as { captionsEnabledAttempted?: boolean }; - const stateAfterSecond = windowState.__openclawMeetCaptions as { enabledAttempted?: boolean }; + const stateAfterSecond = windowState[captionsStateKey] as { + enabledAttempted?: boolean; + }; expect(second.captionsEnabledAttempted).toBe(true); expect(stateAfterSecond.enabledAttempted).toBe(true); expect(captionButton.click).toHaveBeenCalledTimes(1); diff --git a/extensions/qa-matrix/src/runners/contract/scenario-runtime-approval.ts b/extensions/qa-matrix/src/runners/contract/scenario-runtime-approval.ts index 20fdba30d1a..d17a6d859ec 100644 --- a/extensions/qa-matrix/src/runners/contract/scenario-runtime-approval.ts +++ b/extensions/qa-matrix/src/runners/contract/scenario-runtime-approval.ts @@ -4,6 +4,7 @@ import { MATRIX_QA_DRIVER_DM_ROOM_KEY, resolveMatrixQaScenarioRoomId } from "./s import { advanceMatrixQaActorCursor, buildMatrixQaToken, + createMatrixQaDriverScenarioClient, createMatrixQaScenarioClient, primeMatrixQaDriverScenarioClient, type MatrixQaScenarioContext, @@ -145,10 +146,7 @@ async function reactToApproval(params: { roomId: string; targetEventId: string; }) { - const client = createMatrixQaScenarioClient({ - accessToken: params.context.driverAccessToken, - baseUrl: params.context.baseUrl, - }); + const client = createMatrixQaDriverScenarioClient(params.context); const emoji = params.decision === "allow-once" ? MATRIX_QA_APPROVAL_ALLOW_ONCE_REACTION