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_SUBTEAM_MENTION_MARKER = "<!subteam^";
|
||||||
const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
|
const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
|
||||||
const SLACK_HISTORY_MEDIA_MAX_BYTES = 10 * 1024 * 1024;
|
const SLACK_HISTORY_MEDIA_MAX_BYTES = 10 * 1024 * 1024;
|
||||||
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 1_000;
|
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 10_000;
|
||||||
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 3_000;
|
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 15_000;
|
||||||
|
|
||||||
function recordString(
|
function recordString(
|
||||||
record: Record<string, unknown> | undefined,
|
record: Record<string, unknown> | undefined,
|
||||||
|
|||||||
@@ -124,6 +124,53 @@ function resolveFlushTimerForDelay(setTimeoutSpy: ReturnType<typeof vi.spyOn>, d
|
|||||||
return flushTimer;
|
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 }) {
|
function createImageFetchSpy(params?: { body?: Uint8Array; contentType?: string }) {
|
||||||
return vi.spyOn(globalThis, "fetch").mockImplementation(
|
return vi.spyOn(globalThis, "fetch").mockImplementation(
|
||||||
async () =>
|
async () =>
|
||||||
@@ -139,12 +186,13 @@ async function waitForBufferedProcessing() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function waitForMockCalls(mock: { mock: { calls: unknown[] } }, count: number) {
|
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) {
|
if (mock.mock.calls.length >= count) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await delay(25);
|
await delay(25);
|
||||||
}
|
}
|
||||||
|
throw new Error(`Timed out waiting for ${count} mock call(s); got ${mock.mock.calls.length}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createChannelPostContext(params: {
|
function createChannelPostContext(params: {
|
||||||
@@ -271,8 +319,13 @@ describe("createTelegramBot channel_post media", () => {
|
|||||||
setOpenChannelPostConfig();
|
setOpenChannelPostConfig();
|
||||||
|
|
||||||
const fetchSpy = createImageFetchSpy();
|
const fetchSpy = createImageFetchSpy();
|
||||||
|
let nextTimerHandle = 1;
|
||||||
const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout");
|
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 {
|
try {
|
||||||
const handler = getChannelPostHandler();
|
const handler = getChannelPostHandler();
|
||||||
await queueChannelPostAlbum(handler, {
|
await queueChannelPostAlbum(handler, {
|
||||||
@@ -282,7 +335,12 @@ describe("createTelegramBot channel_post media", () => {
|
|||||||
secondMessageId: 202,
|
secondMessageId: 202,
|
||||||
});
|
});
|
||||||
expect(replySpy).not.toHaveBeenCalled();
|
expect(replySpy).not.toHaveBeenCalled();
|
||||||
await flushChannelPostMediaGroup(setTimeoutSpy);
|
await flushActiveScheduledTimersForDelay({
|
||||||
|
setTimeoutSpy,
|
||||||
|
clearTimeoutSpy,
|
||||||
|
delayMs: TELEGRAM_TEST_TIMINGS.mediaGroupFlushMs,
|
||||||
|
expectedCount: 1,
|
||||||
|
});
|
||||||
await waitForMockCalls(replySpy, 1);
|
await waitForMockCalls(replySpy, 1);
|
||||||
|
|
||||||
await vi.waitFor(() => expect(replySpy).toHaveBeenCalledTimes(1));
|
await vi.waitFor(() => expect(replySpy).toHaveBeenCalledTimes(1));
|
||||||
@@ -290,6 +348,7 @@ describe("createTelegramBot channel_post media", () => {
|
|||||||
expect(payload.Body).toContain("album caption");
|
expect(payload.Body).toContain("album caption");
|
||||||
} finally {
|
} finally {
|
||||||
setTimeoutSpy.mockRestore();
|
setTimeoutSpy.mockRestore();
|
||||||
|
clearTimeoutSpy.mockRestore();
|
||||||
fetchSpy.mockRestore();
|
fetchSpy.mockRestore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -311,7 +370,13 @@ describe("createTelegramBot channel_post media", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const fetchSpy = createImageFetchSpy();
|
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 {
|
try {
|
||||||
const handler = getChannelPostHandlerWithRuntimeTimings();
|
const handler = getChannelPostHandlerWithRuntimeTimings();
|
||||||
await queueChannelPostAlbum(handler, {
|
await queueChannelPostAlbum(handler, {
|
||||||
@@ -321,7 +386,12 @@ describe("createTelegramBot channel_post media", () => {
|
|||||||
secondMessageId: 212,
|
secondMessageId: 212,
|
||||||
});
|
});
|
||||||
expect(replySpy).not.toHaveBeenCalled();
|
expect(replySpy).not.toHaveBeenCalled();
|
||||||
await flushChannelPostMediaGroupForDelay(setTimeoutSpy, 75);
|
await flushActiveScheduledTimersForDelay({
|
||||||
|
setTimeoutSpy,
|
||||||
|
clearTimeoutSpy,
|
||||||
|
delayMs: 75,
|
||||||
|
expectedCount: 1,
|
||||||
|
});
|
||||||
await waitForMockCalls(replySpy, 1);
|
await waitForMockCalls(replySpy, 1);
|
||||||
|
|
||||||
await vi.waitFor(() => expect(replySpy).toHaveBeenCalledTimes(1));
|
await vi.waitFor(() => expect(replySpy).toHaveBeenCalledTimes(1));
|
||||||
@@ -329,6 +399,7 @@ describe("createTelegramBot channel_post media", () => {
|
|||||||
expect(payload.Body).toContain("configured album");
|
expect(payload.Body).toContain("configured album");
|
||||||
} finally {
|
} finally {
|
||||||
setTimeoutSpy.mockRestore();
|
setTimeoutSpy.mockRestore();
|
||||||
|
clearTimeoutSpy.mockRestore();
|
||||||
fetchSpy.mockRestore();
|
fetchSpy.mockRestore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { handleInvoke } from "./invoke.js";
|
|||||||
|
|
||||||
describe("node host invoke", () => {
|
describe("node host invoke", () => {
|
||||||
it.runIf(process.platform !== "win32")(
|
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 () => {
|
async () => {
|
||||||
const request = vi.fn<GatewayClient["request"]>().mockResolvedValue(null);
|
const request = vi.fn<GatewayClient["request"]>().mockResolvedValue(null);
|
||||||
const skillBins: SkillBinsProvider = { current: async () => [] };
|
const skillBins: SkillBinsProvider = { current: async () => [] };
|
||||||
@@ -21,7 +21,7 @@ describe("node host invoke", () => {
|
|||||||
nodeId: "node-1",
|
nodeId: "node-1",
|
||||||
command: "system.run.prepare",
|
command: "system.run.prepare",
|
||||||
paramsJSON: JSON.stringify({
|
paramsJSON: JSON.stringify({
|
||||||
command: ["/bin/sh", "-lc", "/bin/echo ok"],
|
command: ["/bin/echo", "ok"],
|
||||||
rawCommand: "/bin/echo ok",
|
rawCommand: "/bin/echo ok",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -29,7 +29,9 @@ describe("node host invoke", () => {
|
|||||||
skillBins,
|
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 {
|
const payload = JSON.parse(result?.payloadJSON ?? "{}") as {
|
||||||
allowAlwaysCoverage?: {
|
allowAlwaysCoverage?: {
|
||||||
complete?: boolean;
|
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",
|
"retries generated state cleanup after a failed removal",
|
||||||
async () => {
|
async () => {
|
||||||
const root = mkdtempSync(path.join(tmpdir(), "openclaw-e2e-temp-state-retry-"));
|
const root = mkdtempSync(path.join(tmpdir(), "openclaw-e2e-temp-state-retry-"));
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ describe("package-mac-app plist stamping", () => {
|
|||||||
writeFileSync(
|
writeFileSync(
|
||||||
corepackPath,
|
corepackPath,
|
||||||
[
|
[
|
||||||
"#!/usr/bin/env bash",
|
"#!/bin/bash",
|
||||||
"set -euo pipefail",
|
"set -euo pipefail",
|
||||||
'printf \'%s|%s\\n\' "$PWD" "$*" >> "$OPENCLAW_TEST_LOG"',
|
'printf \'%s|%s\\n\' "$PWD" "$*" >> "$OPENCLAW_TEST_LOG"',
|
||||||
'if [[ "${1:-}" == "pnpm" && "${2:-}" == "--version" ]]; then',
|
'if [[ "${1:-}" == "pnpm" && "${2:-}" == "--version" ]]; then',
|
||||||
@@ -95,7 +95,7 @@ describe("package-mac-app plist stamping", () => {
|
|||||||
ROOT_DIR=${JSON.stringify(tempRoot)}
|
ROOT_DIR=${JSON.stringify(tempRoot)}
|
||||||
OPENCLAW_TEST_LOG=${JSON.stringify(logPath)}
|
OPENCLAW_TEST_LOG=${JSON.stringify(logPath)}
|
||||||
export OPENCLAW_TEST_LOG
|
export OPENCLAW_TEST_LOG
|
||||||
PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
|
PATH=${JSON.stringify(toolsDir)}
|
||||||
${helperBlock}
|
${helperBlock}
|
||||||
run_pnpm install --frozen-lockfile --config.node-linker=hoisted
|
run_pnpm install --frozen-lockfile --config.node-linker=hoisted
|
||||||
run_pnpm build
|
run_pnpm build
|
||||||
@@ -118,7 +118,7 @@ describe("package-mac-app plist stamping", () => {
|
|||||||
const result = runHelper(`
|
const result = runHelper(`
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
ROOT_DIR=${JSON.stringify(tempRoot)}
|
ROOT_DIR=${JSON.stringify(tempRoot)}
|
||||||
PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
|
PATH=${JSON.stringify(toolsDir)}
|
||||||
${helperBlock}
|
${helperBlock}
|
||||||
run_pnpm build
|
run_pnpm build
|
||||||
`);
|
`);
|
||||||
|
|||||||
Reference in New Issue
Block a user