diff --git a/src/cli/pairing-cli.test.ts b/src/cli/pairing-cli.test.ts index 3689f7c703f..5c888ddd55d 100644 --- a/src/cli/pairing-cli.test.ts +++ b/src/cli/pairing-cli.test.ts @@ -1,5 +1,6 @@ import { Command } from "commander"; import { beforeEach, describe, expect, it, vi } from "vitest"; +import { theme } from "../terminal/theme.js"; import { registerPairingCli } from "./pairing-cli.js"; const mocks = vi.hoisted(() => ({ @@ -229,8 +230,12 @@ describe("pairing cli", () => { | { nextConfig?: { commands?: { ownerAllowFrom?: string[] } } } | undefined; expect(replaceCall?.nextConfig?.commands?.ownerAllowFrom).toEqual(["telegram:123"]); - expect(log).toHaveBeenCalledWith(expect.stringContaining("Approved")); - expect(log).toHaveBeenCalledWith(expect.stringContaining("Command owner configured")); + expect(log.mock.calls).toEqual([ + [`${theme.success("Approved")} ${theme.muted("telegram")} sender ${theme.command("123")}.`], + [ + `${theme.success("Command owner configured")} ${theme.command("telegram:123")} ${theme.muted("(commands.ownerAllowFrom was empty).")}`, + ], + ]); } finally { log.mockRestore(); } diff --git a/src/docker-setup.e2e.test.ts b/src/docker-setup.e2e.test.ts index ffea67ea011..56a3b637f72 100644 --- a/src/docker-setup.e2e.test.ts +++ b/src/docker-setup.e2e.test.ts @@ -503,8 +503,8 @@ describe("scripts/docker/setup.sh", () => { const forceRecreateLine = log .split("\n") .find((line) => line.includes("up -d --force-recreate openclaw-gateway")); - expect(forceRecreateLine).toEqual( - expect.stringContaining("up -d --force-recreate openclaw-gateway"), + expect(forceRecreateLine).toBe( + `compose compose -f ${join(activeSandbox.rootDir, "docker-compose.yml")} up -d --force-recreate openclaw-gateway`, ); expect(forceRecreateLine).not.toContain("docker-compose.sandbox.yml"); await expectMissingPath(join(activeSandbox.rootDir, "docker-compose.sandbox.yml")); diff --git a/src/infra/widearea-dns.test.ts b/src/infra/widearea-dns.test.ts index b832d113b68..4027e8742bb 100644 --- a/src/infra/widearea-dns.test.ts +++ b/src/infra/widearea-dns.test.ts @@ -184,9 +184,13 @@ describe("wide-area DNS zone writes", () => { zonePath: getWideAreaZonePath("openclaw.internal."), changed: true, }); + const expectedZoneText = renderWideAreaGatewayZoneText({ + ...makeZoneOpts({ gatewayTlsEnabled: true, gatewayTlsFingerprintSha256: "abc123" }), + serial: 2026031305, + }); expect(writeSpy).toHaveBeenCalledWith( getWideAreaZonePath("openclaw.internal."), - expect.stringContaining("@ IN SOA ns1 hostmaster 2026031305 7200 3600 1209600 60"), + expectedZoneText, "utf-8", ); }); diff --git a/src/media-understanding/media-understanding-url-fallback.test.ts b/src/media-understanding/media-understanding-url-fallback.test.ts index c3362a083ae..62cbc662bf8 100644 --- a/src/media-understanding/media-understanding-url-fallback.test.ts +++ b/src/media-understanding/media-understanding-url-fallback.test.ts @@ -1,6 +1,7 @@ import fs from "node:fs/promises"; import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; +import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js"; import { withTempDir } from "../test-helpers/temp-dir.js"; import { MediaAttachmentCache } from "./attachments.js"; @@ -60,7 +61,9 @@ describe("media understanding attachment URL fallback", () => { }); // getPath should fall through to getBuffer URL fetch, write a temp file, // and return a path to that temp file instead of throwing. - expect(result.path).toEqual(expect.stringMatching(/\S/u)); + expect(path.dirname(result.path)).toBe(resolvePreferredOpenClawTmpDir()); + expect(path.basename(result.path).startsWith("openclaw-media-")).toBe(true); + expect(path.extname(result.path)).toBe(".jpg"); expect(fetchRemoteMediaMock).toHaveBeenCalledTimes(1); const fetchInput = fetchRemoteMediaMock.mock.calls[0]?.[0] as | { url?: unknown; fetchImpl?: unknown; maxBytes?: unknown; ssrfPolicy?: unknown } diff --git a/src/media-understanding/openai-compatible-audio.test.ts b/src/media-understanding/openai-compatible-audio.test.ts index 068e5e15acf..31c51d0cea2 100644 --- a/src/media-understanding/openai-compatible-audio.test.ts +++ b/src/media-understanding/openai-compatible-audio.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from "vitest"; +import { VERSION } from "../version.js"; import { createRequestCaptureJsonFetch, installPinnedHostnameTestHooks, @@ -24,8 +25,8 @@ describe("transcribeOpenAiCompatibleAudio", () => { const headers = new Headers(getRequest().init?.headers); expect(headers.get("originator")).toBe("openclaw"); - expect(headers.get("version")).toEqual(expect.stringMatching(/\S/u)); - expect(headers.get("user-agent")).toMatch(/^openclaw\//); + expect(headers.get("version")).toBe(VERSION); + expect(headers.get("user-agent")).toBe(`openclaw/${VERSION}`); }); it("does not add hidden attribution headers on custom OpenAI-compatible hosts", async () => { diff --git a/src/plugins/hooks.model-override-wiring.test.ts b/src/plugins/hooks.model-override-wiring.test.ts index 7d14a8ae86d..81f44ffde80 100644 --- a/src/plugins/hooks.model-override-wiring.test.ts +++ b/src/plugins/hooks.model-override-wiring.test.ts @@ -258,9 +258,7 @@ describe("model override pipeline wiring", () => { await expect(resultPromise).resolves.toEqual({ prependContext: "fast" }); expect(logger.error).toHaveBeenCalledWith( - expect.stringContaining( - "[hooks] before_prompt_build handler from slow-plugin failed: timed out after 5ms", - ), + "[hooks] before_prompt_build handler from slow-plugin failed: timed out after 5ms", ); } finally { vi.useRealTimers(); diff --git a/src/plugins/provider-auth-input.test.ts b/src/plugins/provider-auth-input.test.ts index 9fd87642d13..83cfde06697 100644 --- a/src/plugins/provider-auth-input.test.ts +++ b/src/plugins/provider-auth-input.test.ts @@ -378,7 +378,11 @@ describe("ensureApiKeyFromEnvOrPrompt", () => { expect(result).toBe("env-key"); expectMinimaxEnvRefCredentialStored(setCredential); expect(note).toHaveBeenCalledWith( - expect.stringContaining("Could not validate provider reference"), + [ + "Could not validate provider reference filemain:/providers/minimax/apiKey.", + "secrets.providers.filemain.path is not readable: /tmp/does-not-exist-secrets.json | ENOENT: no such file or directory, lstat '/tmp/does-not-exist-secrets.json' | secrets.providers.filemain.path is not readable: /tmp/does-not-exist-secrets.json | ENOENT: no such file or directory, lstat '/tmp/does-not-exist-secrets.json'", + "Check your provider configuration and try again.", + ].join("\n"), "Reference check failed", ); }); diff --git a/test/openclaw-npm-postpublish-verify.test.ts b/test/openclaw-npm-postpublish-verify.test.ts index 57fb4f53c74..0774a153922 100644 --- a/test/openclaw-npm-postpublish-verify.test.ts +++ b/test/openclaw-npm-postpublish-verify.test.ts @@ -350,9 +350,10 @@ describe("collectInstalledRootDependencyManifestErrors", () => { mkdirSync(join(packageRoot, "dist"), { recursive: true }); writeFileSync(join(packageRoot, "package.json"), "{not-json\n", "utf8"); - expect(collectInstalledRootDependencyManifestErrors(packageRoot)).toEqual([ - expect.stringMatching(/^installed package\.json could not be parsed:/u), - ]); + const errors = collectInstalledRootDependencyManifestErrors(packageRoot); + expect(errors).toHaveLength(1); + expect(errors[0]?.startsWith("installed package.json could not be parsed:")).toBe(true); + expect(errors[0]?.endsWith(".")).toBe(true); } finally { rmSync(packageRoot, { recursive: true, force: true }); }