test(plugins): stabilize prerelease surface checks

This commit is contained in:
Vincent Koc
2026-05-03 17:48:53 -07:00
parent d85fa16e8f
commit 0633cb4504
3 changed files with 39 additions and 15 deletions

View File

@@ -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.

View File

@@ -94,6 +94,19 @@ function setup(
return harness;
}
async function withProcessPlatform<T>(
platform: NodeJS.Platform,
callback: () => Promise<T>,
): Promise<T> {
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<string>;
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);

View File

@@ -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