mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
test: stabilize maintainer prepare baseline
This commit is contained in:
@@ -83,8 +83,8 @@ const SLACK_SUBTEAM_MENTION_RE = /<!subteam\^([^>|]+)(?:\|[^>]+)?>/g;
|
||||
const SLACK_SUBTEAM_MENTION_MARKER = "<!subteam^";
|
||||
const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
|
||||
const SLACK_HISTORY_MEDIA_MAX_BYTES = 10 * 1024 * 1024;
|
||||
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 1_000;
|
||||
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 3_000;
|
||||
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 10_000;
|
||||
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 15_000;
|
||||
|
||||
function recordString(
|
||||
record: Record<string, unknown> | undefined,
|
||||
|
||||
@@ -124,6 +124,53 @@ function resolveFlushTimerForDelay(setTimeoutSpy: ReturnType<typeof vi.spyOn>, d
|
||||
return flushTimer;
|
||||
}
|
||||
|
||||
type ScheduledTimer = {
|
||||
callback: () => unknown;
|
||||
handle: ReturnType<typeof setTimeout>;
|
||||
};
|
||||
|
||||
function resolveActiveScheduledTimersForDelay(
|
||||
setTimeoutSpy: ReturnType<typeof vi.spyOn>,
|
||||
clearTimeoutSpy: ReturnType<typeof vi.spyOn>,
|
||||
delayMs: number,
|
||||
): ScheduledTimer[] {
|
||||
const clearedHandles = new Set(
|
||||
(clearTimeoutSpy.mock.calls as Array<Parameters<typeof clearTimeout>>).map(
|
||||
([handle]) => handle,
|
||||
),
|
||||
);
|
||||
return (setTimeoutSpy.mock.calls as Array<Parameters<typeof setTimeout>>).flatMap(
|
||||
(call, index) => {
|
||||
if (call[1] !== delayMs) {
|
||||
return [];
|
||||
}
|
||||
const handle = setTimeoutSpy.mock.results[index]?.value as ReturnType<typeof setTimeout>;
|
||||
if (clearedHandles.has(handle) || typeof call[0] !== "function") {
|
||||
return [];
|
||||
}
|
||||
return [{ callback: call[0] as () => unknown, handle }];
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async function flushActiveScheduledTimersForDelay(params: {
|
||||
setTimeoutSpy: ReturnType<typeof vi.spyOn>;
|
||||
clearTimeoutSpy: ReturnType<typeof vi.spyOn>;
|
||||
delayMs: number;
|
||||
expectedCount: number;
|
||||
}) {
|
||||
const timers = resolveActiveScheduledTimersForDelay(
|
||||
params.setTimeoutSpy,
|
||||
params.clearTimeoutSpy,
|
||||
params.delayMs,
|
||||
);
|
||||
expect(timers).toHaveLength(params.expectedCount);
|
||||
for (const timer of timers) {
|
||||
clearTimeout(timer.handle);
|
||||
await timer.callback();
|
||||
}
|
||||
}
|
||||
|
||||
function createImageFetchSpy(params?: { body?: Uint8Array; contentType?: string }) {
|
||||
return vi.spyOn(globalThis, "fetch").mockImplementation(
|
||||
async () =>
|
||||
@@ -139,12 +186,13 @@ async function waitForBufferedProcessing() {
|
||||
}
|
||||
|
||||
async function waitForMockCalls(mock: { mock: { calls: unknown[] } }, count: number) {
|
||||
for (let index = 0; index < 80; index++) {
|
||||
for (let index = 0; index < 400; index++) {
|
||||
if (mock.mock.calls.length >= count) {
|
||||
return;
|
||||
}
|
||||
await delay(25);
|
||||
}
|
||||
throw new Error(`Timed out waiting for ${count} mock call(s); got ${mock.mock.calls.length}`);
|
||||
}
|
||||
|
||||
function createChannelPostContext(params: {
|
||||
@@ -271,8 +319,13 @@ describe("createTelegramBot channel_post media", () => {
|
||||
setOpenChannelPostConfig();
|
||||
|
||||
const fetchSpy = createImageFetchSpy();
|
||||
|
||||
const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout");
|
||||
let nextTimerHandle = 1;
|
||||
const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout").mockImplementation(() => {
|
||||
const handle = nextTimerHandle;
|
||||
nextTimerHandle += 1;
|
||||
return handle as unknown as ReturnType<typeof setTimeout>;
|
||||
});
|
||||
const clearTimeoutSpy = vi.spyOn(globalThis, "clearTimeout");
|
||||
try {
|
||||
const handler = getChannelPostHandler();
|
||||
await queueChannelPostAlbum(handler, {
|
||||
@@ -282,7 +335,12 @@ describe("createTelegramBot channel_post media", () => {
|
||||
secondMessageId: 202,
|
||||
});
|
||||
expect(replySpy).not.toHaveBeenCalled();
|
||||
await flushChannelPostMediaGroup(setTimeoutSpy);
|
||||
await flushActiveScheduledTimersForDelay({
|
||||
setTimeoutSpy,
|
||||
clearTimeoutSpy,
|
||||
delayMs: TELEGRAM_TEST_TIMINGS.mediaGroupFlushMs,
|
||||
expectedCount: 1,
|
||||
});
|
||||
await waitForMockCalls(replySpy, 1);
|
||||
|
||||
await vi.waitFor(() => expect(replySpy).toHaveBeenCalledTimes(1));
|
||||
@@ -290,6 +348,7 @@ describe("createTelegramBot channel_post media", () => {
|
||||
expect(payload.Body).toContain("album caption");
|
||||
} finally {
|
||||
setTimeoutSpy.mockRestore();
|
||||
clearTimeoutSpy.mockRestore();
|
||||
fetchSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
@@ -311,7 +370,13 @@ describe("createTelegramBot channel_post media", () => {
|
||||
});
|
||||
|
||||
const fetchSpy = createImageFetchSpy();
|
||||
const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout");
|
||||
let nextTimerHandle = 1;
|
||||
const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout").mockImplementation(() => {
|
||||
const handle = nextTimerHandle;
|
||||
nextTimerHandle += 1;
|
||||
return handle as unknown as ReturnType<typeof setTimeout>;
|
||||
});
|
||||
const clearTimeoutSpy = vi.spyOn(globalThis, "clearTimeout");
|
||||
try {
|
||||
const handler = getChannelPostHandlerWithRuntimeTimings();
|
||||
await queueChannelPostAlbum(handler, {
|
||||
@@ -321,7 +386,12 @@ describe("createTelegramBot channel_post media", () => {
|
||||
secondMessageId: 212,
|
||||
});
|
||||
expect(replySpy).not.toHaveBeenCalled();
|
||||
await flushChannelPostMediaGroupForDelay(setTimeoutSpy, 75);
|
||||
await flushActiveScheduledTimersForDelay({
|
||||
setTimeoutSpy,
|
||||
clearTimeoutSpy,
|
||||
delayMs: 75,
|
||||
expectedCount: 1,
|
||||
});
|
||||
await waitForMockCalls(replySpy, 1);
|
||||
|
||||
await vi.waitFor(() => expect(replySpy).toHaveBeenCalledTimes(1));
|
||||
@@ -329,6 +399,7 @@ describe("createTelegramBot channel_post media", () => {
|
||||
expect(payload.Body).toContain("configured album");
|
||||
} finally {
|
||||
setTimeoutSpy.mockRestore();
|
||||
clearTimeoutSpy.mockRestore();
|
||||
fetchSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import { handleInvoke } from "./invoke.js";
|
||||
|
||||
describe("node host invoke", () => {
|
||||
it.runIf(process.platform !== "win32")(
|
||||
"reports current allow-always coverage for prepared shell-wrapped system.run commands",
|
||||
"reports current allow-always coverage for prepared system.run commands",
|
||||
async () => {
|
||||
const request = vi.fn<GatewayClient["request"]>().mockResolvedValue(null);
|
||||
const skillBins: SkillBinsProvider = { current: async () => [] };
|
||||
@@ -21,7 +21,7 @@ describe("node host invoke", () => {
|
||||
nodeId: "node-1",
|
||||
command: "system.run.prepare",
|
||||
paramsJSON: JSON.stringify({
|
||||
command: ["/bin/sh", "-lc", "/bin/echo ok"],
|
||||
command: ["/bin/echo", "ok"],
|
||||
rawCommand: "/bin/echo ok",
|
||||
}),
|
||||
},
|
||||
@@ -29,7 +29,9 @@ describe("node host invoke", () => {
|
||||
skillBins,
|
||||
);
|
||||
|
||||
const result = request.mock.calls[0]?.[1] as { payloadJSON?: string } | undefined;
|
||||
const result = request.mock.calls.find(([method]) => method === "node.invoke.result")?.[1] as
|
||||
| { payloadJSON?: string }
|
||||
| undefined;
|
||||
const payload = JSON.parse(result?.payloadJSON ?? "{}") as {
|
||||
allowAlwaysCoverage?: {
|
||||
complete?: boolean;
|
||||
|
||||
@@ -60,7 +60,7 @@ describe("E2E temp state dirs", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it.runIf(process.platform !== "win32")(
|
||||
it.runIf(process.platform !== "win32" && process.getuid?.() !== 0)(
|
||||
"retries generated state cleanup after a failed removal",
|
||||
async () => {
|
||||
const root = mkdtempSync(path.join(tmpdir(), "openclaw-e2e-temp-state-retry-"));
|
||||
|
||||
@@ -78,7 +78,7 @@ describe("package-mac-app plist stamping", () => {
|
||||
writeFileSync(
|
||||
corepackPath,
|
||||
[
|
||||
"#!/usr/bin/env bash",
|
||||
"#!/bin/bash",
|
||||
"set -euo pipefail",
|
||||
'printf \'%s|%s\\n\' "$PWD" "$*" >> "$OPENCLAW_TEST_LOG"',
|
||||
'if [[ "${1:-}" == "pnpm" && "${2:-}" == "--version" ]]; then',
|
||||
@@ -95,7 +95,7 @@ describe("package-mac-app plist stamping", () => {
|
||||
ROOT_DIR=${JSON.stringify(tempRoot)}
|
||||
OPENCLAW_TEST_LOG=${JSON.stringify(logPath)}
|
||||
export OPENCLAW_TEST_LOG
|
||||
PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
|
||||
PATH=${JSON.stringify(toolsDir)}
|
||||
${helperBlock}
|
||||
run_pnpm install --frozen-lockfile --config.node-linker=hoisted
|
||||
run_pnpm build
|
||||
@@ -118,7 +118,7 @@ describe("package-mac-app plist stamping", () => {
|
||||
const result = runHelper(`
|
||||
set -euo pipefail
|
||||
ROOT_DIR=${JSON.stringify(tempRoot)}
|
||||
PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
|
||||
PATH=${JSON.stringify(toolsDir)}
|
||||
${helperBlock}
|
||||
run_pnpm build
|
||||
`);
|
||||
|
||||
Reference in New Issue
Block a user