mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-04 02:00:10 +00:00
test(ci): settle cron wakes and refresh fast-lane fixtures
Worker-backed heartbeat preflight must settle before fixture assertions and runner retirement; otherwise unfinished notifications replay into later cases. Keep all routing, delivery, and timeout assertions. Use a pure command fixture for positive unit-fast routing now that status-overview-values uses theme spies. Main CI failures reproduced: cron 5/15 and routing 3/16. Corrected files pass 31/31 cases (cron 13.86s wall, routing 6.13s). Focused lint, formatting, static guards, services-cron and four root-test type graphs, and independent P0-P2 review pass. No production changes.
This commit is contained in:
parent
ea096eaebd
commit
e0ec544eb1
3 changed files with 43 additions and 20 deletions
|
|
@ -8,7 +8,7 @@ import {
|
|||
resolveHeartbeatRunPrompt,
|
||||
} from "../../infra/heartbeat-runner-prompt.js";
|
||||
import { startHeartbeatRunner } from "../../infra/heartbeat-runner-scheduler.js";
|
||||
import { requestHeartbeat as requestHeartbeatWake } from "../../infra/heartbeat-wake.js";
|
||||
import { requestHeartbeatAndWait } from "../../infra/heartbeat-wake.js";
|
||||
import {
|
||||
drainSystemEvents,
|
||||
enqueueSystemEvent as queueSystemEvent,
|
||||
|
|
@ -127,6 +127,7 @@ describe("startup run repair auto-disable", () => {
|
|||
const sessionKey =
|
||||
testCase.creatorSessionKey ?? resolveAgentMainSessionKey({ cfg, agentId: "main" });
|
||||
const prompts: string[] = [];
|
||||
const pendingWakes: Array<ReturnType<typeof requestHeartbeatAndWait>> = [];
|
||||
const runOnce = vi.fn(async (options: HeartbeatRunOptions) => {
|
||||
const preflight = await resolveHeartbeatPreflight({
|
||||
cfg,
|
||||
|
|
@ -165,12 +166,15 @@ describe("startup run repair auto-disable", () => {
|
|||
sessionKey: options?.sessionKey ?? sessionKey,
|
||||
contextKey: options?.contextKey,
|
||||
}),
|
||||
requestHeartbeat: (wake) =>
|
||||
requestHeartbeatWake({
|
||||
...wake,
|
||||
sessionKey: wake.sessionKey ?? sessionKey,
|
||||
coalesceMs: 0,
|
||||
}),
|
||||
requestHeartbeat: (wake) => {
|
||||
pendingWakes.push(
|
||||
requestHeartbeatAndWait({
|
||||
...wake,
|
||||
sessionKey: wake.sessionKey ?? sessionKey,
|
||||
coalesceMs: 0,
|
||||
}),
|
||||
);
|
||||
},
|
||||
runIsolatedAgentJob: vi.fn(),
|
||||
});
|
||||
const job: CronJob = {
|
||||
|
|
@ -200,6 +204,7 @@ describe("startup run repair auto-disable", () => {
|
|||
expect(deferredNotifications).toHaveLength(1);
|
||||
runPostPersistCronNotifications(state, structuredClone(deferredNotifications));
|
||||
await vi.advanceTimersByTimeAsync(1);
|
||||
await Promise.all(pendingWakes);
|
||||
|
||||
expect(runOnce).toHaveBeenCalledOnce();
|
||||
expect(runOnce).toHaveBeenCalledWith(
|
||||
|
|
@ -216,9 +221,15 @@ describe("startup run repair auto-disable", () => {
|
|||
expect(prompts[0]).toContain("openclaw automations enable restart-auto-disable-notification");
|
||||
expect(prompts[0]).toContain("Please relay this reminder to the user");
|
||||
} finally {
|
||||
runner.stop();
|
||||
drainSystemEvents(sessionKey);
|
||||
vi.useRealTimers();
|
||||
try {
|
||||
// Stopping the runner retains unfinished notifications for its successor.
|
||||
await vi.advanceTimersByTimeAsync(1);
|
||||
await Promise.all(pendingWakes);
|
||||
} finally {
|
||||
runner.stop();
|
||||
drainSystemEvents(sessionKey);
|
||||
vi.useRealTimers();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
resolveHeartbeatRunPrompt,
|
||||
} from "../../infra/heartbeat-runner-prompt.js";
|
||||
import { startHeartbeatRunner } from "../../infra/heartbeat-runner-scheduler.js";
|
||||
import { requestHeartbeat as requestHeartbeatWake } from "../../infra/heartbeat-wake.js";
|
||||
import { requestHeartbeatAndWait } from "../../infra/heartbeat-wake.js";
|
||||
import {
|
||||
drainSystemEvents,
|
||||
enqueueSystemEvent as queueSystemEvent,
|
||||
|
|
@ -60,6 +60,7 @@ describe("cron script immediate wake", () => {
|
|||
};
|
||||
const sessionKey = resolveAgentMainSessionKey({ cfg, agentId: "finn" });
|
||||
const prompts: string[] = [];
|
||||
const pendingWakes: Array<ReturnType<typeof requestHeartbeatAndWait>> = [];
|
||||
const runOnce = vi.fn(async (options: HeartbeatRunOptions) => {
|
||||
const prompt = resolveHeartbeatRunPrompt({
|
||||
cfg,
|
||||
|
|
@ -99,8 +100,11 @@ describe("cron script immediate wake", () => {
|
|||
contextKey: options?.contextKey,
|
||||
deliveryContext: options?.deliveryContext,
|
||||
}),
|
||||
requestHeartbeat: (wakeRequest) =>
|
||||
requestHeartbeatWake({ ...wakeRequest, sessionKey, coalesceMs: 0 }),
|
||||
requestHeartbeat: (wakeRequest) => {
|
||||
pendingWakes.push(
|
||||
requestHeartbeatAndWait({ ...wakeRequest, sessionKey, coalesceMs: 0 }),
|
||||
);
|
||||
},
|
||||
runIsolatedAgentJob: vi.fn(async () => ({ status: "ok" as const })),
|
||||
runScriptJob: vi.fn(async () => ({
|
||||
status: "ok" as const,
|
||||
|
|
@ -128,6 +132,7 @@ describe("cron script immediate wake", () => {
|
|||
]);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1);
|
||||
await Promise.all(pendingWakes);
|
||||
|
||||
if (!immediate) {
|
||||
expect(runOnce).not.toHaveBeenCalled();
|
||||
|
|
@ -150,9 +155,15 @@ describe("cron script immediate wake", () => {
|
|||
expect(prompts[0]).toContain(expectedText);
|
||||
expect(prompts[0]).toContain("Please relay this reminder to the user");
|
||||
} finally {
|
||||
runner.stop();
|
||||
drainSystemEvents(sessionKey);
|
||||
vi.useRealTimers();
|
||||
try {
|
||||
// Stopping the runner retains unfinished notifications for its successor.
|
||||
await vi.advanceTimersByTimeAsync(1);
|
||||
await Promise.all(pendingWakes);
|
||||
} finally {
|
||||
runner.stop();
|
||||
drainSystemEvents(sessionKey);
|
||||
vi.useRealTimers();
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ describe("unit-fast vitest lane", () => {
|
|||
"src/agents/agent-tools.deferred-followup-guidance.test.ts",
|
||||
);
|
||||
expect(testConfig.include).toContain("src/acp/runtime/registry.test.ts");
|
||||
expect(testConfig.include).toContain("src/commands/status-overview-values.test.ts");
|
||||
expect(testConfig.include).toContain("src/commands/text-format.test.ts");
|
||||
expect(testConfig.include).toContain("src/plugins/config-policy.test.ts");
|
||||
expect(testConfig.include).toContain("src/sessions/session-lifecycle-events.test.ts");
|
||||
expect(testConfig.include).toContain("src/plugin-sdk/text-chunking.test.ts");
|
||||
|
|
@ -443,7 +443,7 @@ describe("unit-fast vitest lane", () => {
|
|||
|
||||
const testConfig = requireTestConfig(config);
|
||||
expect(testConfig.include).toContain("src/plugin-sdk/text-chunking.test.ts");
|
||||
expect(testConfig.include).toContain("src/commands/status-overview-values.test.ts");
|
||||
expect(testConfig.include).toContain("src/commands/text-format.test.ts");
|
||||
});
|
||||
|
||||
it("keeps excluded stateful files out of directory-scoped CLI runs", () => {
|
||||
|
|
@ -491,6 +491,7 @@ describe("unit-fast vitest lane", () => {
|
|||
"src/agents/code-mode-quickjs.integration.test.ts",
|
||||
"src/agents/prepared-model-runtime.scoped-refresh.test.ts",
|
||||
"src/agents/provider-transport-fetch.headers.test.ts",
|
||||
"src/commands/status-overview-values.test.ts",
|
||||
]) {
|
||||
expect(isUnitFastTestFile(file), file).toBe(false);
|
||||
expect(resolveUnitFastTestIncludePattern(file), file).toBeNull();
|
||||
|
|
@ -528,8 +529,8 @@ describe("unit-fast vitest lane", () => {
|
|||
expect(resolveUnitFastTestIncludePattern("src/plugin-sdk/text-chunking.ts")).toBe(
|
||||
"src/plugin-sdk/text-chunking.test.ts",
|
||||
);
|
||||
expect(resolveUnitFastTestIncludePattern("src/commands/status-overview-values.ts")).toBe(
|
||||
"src/commands/status-overview-values.test.ts",
|
||||
expect(resolveUnitFastTestIncludePattern("src/commands/text-format.ts")).toBe(
|
||||
"src/commands/text-format.test.ts",
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue