fix(test): repair e2e standalone regressions

This commit is contained in:
Vincent Koc
2026-05-31 12:22:36 +02:00
parent f7a1d3f3f6
commit 6d76acc258
5 changed files with 49 additions and 20 deletions

View File

@@ -115,7 +115,7 @@ describe("Telegram message dispatch replay guard", () => {
await expect(reader.warmup("default")).resolves.toBe(keys.length);
});
it("falls back to same-process replay protection when plugin-state cannot open", async () => {
it("falls back to same-process replay protection when plugin-state is unavailable", async () => {
setTelegramMessageDispatchDedupeStoreForTest(undefined);
const errors: unknown[] = [];
const storePath = createStorePath();
@@ -142,7 +142,7 @@ describe("Telegram message dispatch replay guard", () => {
}),
).resolves.toEqual({ kind: "duplicate" });
await expect(guard.hasRecent(first.key, { namespace: "default" })).resolves.toBe(true);
expect(errors.length).toBeGreaterThan(0);
expect(errors).toEqual([]);
});
it("keeps same-process replay protection when plugin-state commit fails", async () => {

View File

@@ -11,7 +11,7 @@ import type {
PluginStateSyncKeyedStore,
} from "openclaw/plugin-sdk/plugin-state-runtime";
import { normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
import { getTelegramRuntime } from "./runtime.js";
import { getOptionalTelegramRuntime } from "./runtime.js";
const TELEGRAM_MESSAGE_DISPATCH_TTL_MS = 7 * 24 * 60 * 60 * 1000;
export const TELEGRAM_MESSAGE_DISPATCH_DEDUPE_NAMESPACE = "telegram.message-dispatch-dedupe";
@@ -53,14 +53,14 @@ export type TelegramMessageDispatchClaim =
| { kind: "duplicate" }
| { kind: "invalid" };
function openDispatchDedupeStore(): TelegramMessageDispatchDedupeStore {
return (
dispatchDedupeStoreForTest ??
getTelegramRuntime().state.openKeyedStore<TelegramMessageDispatchDedupeRecord>({
function openDispatchDedupeStore(): TelegramMessageDispatchDedupeStore | undefined {
if (dispatchDedupeStoreForTest) {
return dispatchDedupeStoreForTest;
}
return getOptionalTelegramRuntime()?.state.openKeyedStore<TelegramMessageDispatchDedupeRecord>({
namespace: TELEGRAM_MESSAGE_DISPATCH_DEDUPE_NAMESPACE,
maxEntries: TELEGRAM_MESSAGE_DISPATCH_DEDUPE_MAX_ENTRIES,
})
);
});
}
function resolveDispatchScopeKey(storePath: string): string {

View File

@@ -108,6 +108,24 @@ function tarballFileName(manifest: PackageManifest): string {
return `${manifest.name.replace(/^@/, "").replace("/", "-")}-${manifest.version}.tgz`;
}
async function createPackStagingRoot(packageRoot: string, destinationRoot: string): Promise<string> {
const manifest = await readPackageManifest(packageRoot);
const packageSlug = manifest.name.replace(/^@/, "").replace("/", "-");
const stagingRoot = path.join(destinationRoot, `pack-${packageSlug}`);
await fs.mkdir(stagingRoot, { recursive: true });
await fs.writeFile(path.join(stagingRoot, "package.json"), JSON.stringify(manifest, null, 2));
const files = Array.isArray(manifest.files) ? manifest.files : [];
for (const entry of files) {
if (typeof entry !== "string") {
continue;
}
await fs.cp(path.join(packageRoot, entry), path.join(stagingRoot, entry), {
recursive: true,
});
}
return stagingRoot;
}
function closeServer(server: Server): Promise<void> {
return new Promise((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
@@ -204,8 +222,9 @@ describe("OpenClaw SDK package e2e", () => {
});
}
for (const packageRoot of packageRoots) {
await runCommand("pnpm", ["pack", "--pack-destination", tempDir], {
cwd: packageRoot,
const stagingRoot = await createPackStagingRoot(packageRoot, tempDir);
await runCommand("npm", ["pack", "--ignore-scripts", "--pack-destination", tempDir], {
cwd: stagingRoot,
});
}

View File

@@ -81,7 +81,14 @@ async function restoreCliRunnerPrepareDeps() {
}
beforeEach(async () => {
const { setCliRunnerTestDeps } = await import("./cli-runner.js");
const { setCliRunnerPrepareTestDeps } = await import("./cli-runner/prepare.js");
setCliRunnerTestDeps({
// Bundle MCP wiring is the behavior under test; transcript flush has
// dedicated coverage and the fake Claude binary does not write real
// Claude transcript files.
claudeCliSessionTranscriptHasContent: vi.fn(async () => true),
});
setCliRunnerPrepareTestDeps({
// This test validates downstream bundle MCP config injection. The generic
// OpenClaw loopback tool inventory is covered by prepare-level tests and is
@@ -91,7 +98,9 @@ beforeEach(async () => {
});
afterEach(async () => {
const { restoreCliRunnerTestDeps } = await import("./cli-runner.js");
cliBackendsTesting.resetDepsForTest();
restoreCliRunnerTestDeps();
await restoreCliRunnerPrepareDeps();
await resetBundleMcpPluginState();
});

View File

@@ -13,13 +13,14 @@ import "./doctor.fast-path-mocks.js";
let doctorCommand: typeof import("./doctor.js").doctorCommand;
const CODEX_PROVIDER_ID = "openai";
const OPENAI_PROVIDER_ID = "openai";
const LEGACY_CODEX_PROVIDER_ID = "openai-codex";
const CODEX_PROFILE_ID = "openai:user@example.com";
const CODEX_PROFILE_EMAIL = "user@example.com";
function configCodexOAuthProfile() {
return {
provider: CODEX_PROVIDER_ID,
provider: OPENAI_PROVIDER_ID,
mode: "oauth",
email: CODEX_PROFILE_EMAIL,
};
@@ -28,7 +29,7 @@ function configCodexOAuthProfile() {
function storedCodexOAuthProfile() {
return {
type: "oauth",
provider: CODEX_PROVIDER_ID,
provider: OPENAI_PROVIDER_ID,
access: "access-token",
refresh: "refresh-token",
expires: Date.now() + 60_000,
@@ -51,7 +52,7 @@ function mockCodexProviderSnapshot(params: {
config: {
models: {
providers: {
[CODEX_PROVIDER_ID]: params.provider,
[LEGACY_CODEX_PROVIDER_ID]: params.provider,
},
},
...(params.withConfigOAuth
@@ -194,7 +195,7 @@ describe("doctor command", () => {
expect(warned).toBe(true);
});
it("warns when a legacy OpenAI provider override shadows configured Codex OAuth", async () => {
it("warns when a legacy Codex provider override shadows configured Codex OAuth", async () => {
mockCodexProviderSnapshot({
provider: {
api: "openai-responses",
@@ -206,10 +207,10 @@ describe("doctor command", () => {
await runDoctorNonInteractive();
expect(hasCodexOAuthWarning("models.providers.openai")).toBe(true);
expect(hasCodexOAuthWarning("models.providers.openai-codex")).toBe(true);
});
it("warns when a legacy OpenAI provider override shadows stored Codex OAuth", async () => {
it("warns when a legacy Codex provider override shadows stored Codex OAuth", async () => {
mockCodexProviderSnapshot({
provider: {
api: "openai-responses",
@@ -222,7 +223,7 @@ describe("doctor command", () => {
await runDoctorNonInteractive();
expect(hasCodexOAuthWarning("models.providers.openai")).toBe(true);
expect(hasCodexOAuthWarning("models.providers.openai-codex")).toBe(true);
});
it("warns when an inline OpenAI model keeps the legacy OpenAI transport", async () => {
@@ -275,7 +276,7 @@ describe("doctor command", () => {
expect(hasCodexOAuthWarning()).toBe(false);
});
it("does not warn about an OpenAI provider override without Codex OAuth", async () => {
it("does not warn about a legacy Codex provider override without Codex OAuth", async () => {
mockCodexProviderSnapshot({
provider: {
api: "openai-responses",