test: share redact and approval fixtures

This commit is contained in:
Peter Steinberger
2026-03-26 15:23:12 +00:00
parent 5e78232bc5
commit 65a1afb9df
5 changed files with 91 additions and 195 deletions

View File

@@ -4,44 +4,9 @@ import {
redactConfigSnapshot,
restoreRedactedValues as restoreRedactedValues_orig,
} from "./redact-snapshot.js";
import { makeSnapshot, restoreRedactedValues } from "./redact-snapshot.test-helpers.js";
import { redactSnapshotTestHints as mainSchemaHints } from "./redact-snapshot.test-hints.js";
import type { ConfigUiHints } from "./schema.js";
import type { ConfigFileSnapshot } from "./types.openclaw.js";
type TestSnapshot<TConfig extends Record<string, unknown>> = ConfigFileSnapshot & {
parsed: TConfig;
resolved: TConfig;
config: TConfig;
};
function makeSnapshot<TConfig extends Record<string, unknown>>(
config: TConfig,
raw?: string,
): TestSnapshot<TConfig> {
return {
path: "/home/user/.openclaw/config.json5",
exists: true,
raw: raw ?? JSON.stringify(config),
parsed: config,
resolved: config as ConfigFileSnapshot["resolved"],
valid: true,
config: config as ConfigFileSnapshot["config"],
hash: "abc123",
issues: [],
warnings: [],
legacyIssues: [],
} as unknown as TestSnapshot<TConfig>;
}
function restoreRedactedValues<TOriginal>(
incoming: unknown,
original: TOriginal,
hints?: ConfigUiHints,
): TOriginal {
const result = restoreRedactedValues_orig(incoming, original, hints);
expect(result.ok).toBe(true);
return result.result as TOriginal;
}
describe("restoreRedactedValues", () => {
it("restores redacted URL endpoint fields on round-trip", () => {

View File

@@ -1,47 +1,7 @@
import { describe, expect, it } from "vitest";
import {
REDACTED_SENTINEL,
redactConfigSnapshot,
restoreRedactedValues as restoreRedactedValues_orig,
} from "./redact-snapshot.js";
import { REDACTED_SENTINEL, redactConfigSnapshot } from "./redact-snapshot.js";
import { makeSnapshot, restoreRedactedValues } from "./redact-snapshot.test-helpers.js";
import { redactSnapshotTestHints as mainSchemaHints } from "./redact-snapshot.test-hints.js";
import type { ConfigUiHints } from "./schema.js";
import type { ConfigFileSnapshot } from "./types.openclaw.js";
type TestSnapshot<TConfig extends Record<string, unknown>> = ConfigFileSnapshot & {
parsed: TConfig;
resolved: TConfig;
config: TConfig;
};
function makeSnapshot<TConfig extends Record<string, unknown>>(
config: TConfig,
raw?: string,
): TestSnapshot<TConfig> {
return {
path: "/home/user/.openclaw/config.json5",
exists: true,
raw: raw ?? JSON.stringify(config),
parsed: config,
resolved: config as ConfigFileSnapshot["resolved"],
valid: true,
config: config as ConfigFileSnapshot["config"],
hash: "abc123",
issues: [],
warnings: [],
legacyIssues: [],
} as unknown as TestSnapshot<TConfig>;
}
function restoreRedactedValues<TOriginal>(
incoming: unknown,
original: TOriginal,
hints?: ConfigUiHints,
): TOriginal {
const result = restoreRedactedValues_orig(incoming, original, hints);
expect(result.ok).toBe(true);
return result.result as TOriginal;
}
describe("realredactConfigSnapshot_real", () => {
it("main schema redact works (samples)", () => {

View File

@@ -0,0 +1,39 @@
import { expect } from "vitest";
import { restoreRedactedValues as restoreRedactedValues_orig } from "./redact-snapshot.js";
import type { ConfigUiHints } from "./schema.js";
import type { ConfigFileSnapshot } from "./types.openclaw.js";
export type TestSnapshot<TConfig extends Record<string, unknown>> = ConfigFileSnapshot & {
parsed: TConfig;
resolved: TConfig;
config: TConfig;
};
export function makeSnapshot<TConfig extends Record<string, unknown>>(
config: TConfig,
raw?: string,
): TestSnapshot<TConfig> {
return {
path: "/home/user/.openclaw/config.json5",
exists: true,
raw: raw ?? JSON.stringify(config),
parsed: config,
resolved: config as ConfigFileSnapshot["resolved"],
valid: true,
config: config as ConfigFileSnapshot["config"],
hash: "abc123",
issues: [],
warnings: [],
legacyIssues: [],
} as unknown as TestSnapshot<TConfig>;
}
export function restoreRedactedValues<TOriginal>(
incoming: unknown,
original: TOriginal,
hints?: ConfigUiHints,
): TOriginal {
const result = restoreRedactedValues_orig(incoming, original, hints);
expect(result.ok).toBe(true);
return result.result as TOriginal;
}

View File

@@ -1,49 +1,15 @@
import JSON5 from "json5";
import { describe, expect, it } from "vitest";
import { REDACTED_SENTINEL, redactConfigSnapshot } from "./redact-snapshot.js";
import {
REDACTED_SENTINEL,
redactConfigSnapshot,
restoreRedactedValues as restoreRedactedValues_orig,
} from "./redact-snapshot.js";
makeSnapshot,
restoreRedactedValues,
type TestSnapshot,
} from "./redact-snapshot.test-helpers.js";
import { redactSnapshotTestHints as mainSchemaHints } from "./redact-snapshot.test-hints.js";
import type { ConfigUiHints } from "./schema.js";
import type { ConfigFileSnapshot } from "./types.openclaw.js";
type TestSnapshot<TConfig extends Record<string, unknown>> = ConfigFileSnapshot & {
parsed: TConfig;
resolved: TConfig;
config: TConfig;
};
function makeSnapshot<TConfig extends Record<string, unknown>>(
config: TConfig,
raw?: string,
): TestSnapshot<TConfig> {
return {
path: "/home/user/.openclaw/config.json5",
exists: true,
raw: raw ?? JSON.stringify(config),
parsed: config,
resolved: config as ConfigFileSnapshot["resolved"],
valid: true,
config: config as ConfigFileSnapshot["config"],
hash: "abc123",
issues: [],
warnings: [],
legacyIssues: [],
} as unknown as TestSnapshot<TConfig>;
}
function restoreRedactedValues<TOriginal>(
incoming: unknown,
original: TOriginal,
hints?: ConfigUiHints,
): TOriginal {
var result = restoreRedactedValues_orig(incoming, original, hints);
expect(result.ok).toBe(true);
return result.result as TOriginal;
}
function expectNestedLevelPairValue(
source: Record<string, Record<string, Record<string, unknown>>>,
field: string,

View File

@@ -10,47 +10,51 @@ type ExecApprovalSurfaceModule = typeof import("./exec-approval-surface.js");
let hasConfiguredExecApprovalDmRoute: ExecApprovalSurfaceModule["hasConfiguredExecApprovalDmRoute"];
let resolveExecApprovalInitiatingSurfaceState: ExecApprovalSurfaceModule["resolveExecApprovalInitiatingSurfaceState"];
async function loadExecApprovalSurfaceModule() {
vi.resetModules();
loadConfigMock.mockReset();
getChannelPluginMock.mockReset();
listChannelPluginsMock.mockReset();
normalizeMessageChannelMock.mockReset();
normalizeMessageChannelMock.mockImplementation((value?: string | null) =>
typeof value === "string" ? value.trim().toLowerCase() : undefined,
);
vi.doMock("../config/config.js", () => ({
loadConfig: (...args: unknown[]) => loadConfigMock(...args),
}));
vi.doMock("../channels/plugins/index.js", () => ({
getChannelPlugin: (...args: unknown[]) => getChannelPluginMock(...args),
listChannelPlugins: (...args: unknown[]) => listChannelPluginsMock(...args),
}));
vi.doMock("../../extensions/discord/src/channel.js", () => ({
discordPlugin: {},
}));
vi.doMock("../../extensions/telegram/src/channel.js", () => ({
telegramPlugin: {},
}));
vi.doMock("../../extensions/slack/src/channel.js", () => ({
slackPlugin: {},
}));
vi.doMock("../../extensions/whatsapp/src/channel.js", () => ({
whatsappPlugin: {},
}));
vi.doMock("../../extensions/signal/src/channel.js", () => ({
signalPlugin: {},
}));
vi.doMock("../../extensions/imessage/src/channel.js", () => ({
imessagePlugin: {},
}));
vi.doMock("../utils/message-channel.js", () => ({
INTERNAL_MESSAGE_CHANNEL: "web",
normalizeMessageChannel: (...args: unknown[]) => normalizeMessageChannelMock(...args),
}));
({ hasConfiguredExecApprovalDmRoute, resolveExecApprovalInitiatingSurfaceState } =
await import("./exec-approval-surface.js"));
}
describe("resolveExecApprovalInitiatingSurfaceState", () => {
beforeEach(async () => {
vi.resetModules();
loadConfigMock.mockReset();
getChannelPluginMock.mockReset();
listChannelPluginsMock.mockReset();
normalizeMessageChannelMock.mockReset();
normalizeMessageChannelMock.mockImplementation((value?: string | null) =>
typeof value === "string" ? value.trim().toLowerCase() : undefined,
);
vi.doMock("../config/config.js", () => ({
loadConfig: (...args: unknown[]) => loadConfigMock(...args),
}));
vi.doMock("../channels/plugins/index.js", () => ({
getChannelPlugin: (...args: unknown[]) => getChannelPluginMock(...args),
listChannelPlugins: (...args: unknown[]) => listChannelPluginsMock(...args),
}));
vi.doMock("../../extensions/discord/src/channel.js", () => ({
discordPlugin: {},
}));
vi.doMock("../../extensions/telegram/src/channel.js", () => ({
telegramPlugin: {},
}));
vi.doMock("../../extensions/slack/src/channel.js", () => ({
slackPlugin: {},
}));
vi.doMock("../../extensions/whatsapp/src/channel.js", () => ({
whatsappPlugin: {},
}));
vi.doMock("../../extensions/signal/src/channel.js", () => ({
signalPlugin: {},
}));
vi.doMock("../../extensions/imessage/src/channel.js", () => ({
imessagePlugin: {},
}));
vi.doMock("../utils/message-channel.js", () => ({
INTERNAL_MESSAGE_CHANNEL: "web",
normalizeMessageChannel: (...args: unknown[]) => normalizeMessageChannelMock(...args),
}));
({ hasConfiguredExecApprovalDmRoute, resolveExecApprovalInitiatingSurfaceState } =
await import("./exec-approval-surface.js"));
await loadExecApprovalSurfaceModule();
});
it("treats web UI, terminal UI, and missing channels as enabled", () => {
@@ -149,45 +153,7 @@ describe("resolveExecApprovalInitiatingSurfaceState", () => {
describe("hasConfiguredExecApprovalDmRoute", () => {
beforeEach(async () => {
vi.resetModules();
loadConfigMock.mockReset();
getChannelPluginMock.mockReset();
listChannelPluginsMock.mockReset();
normalizeMessageChannelMock.mockReset();
normalizeMessageChannelMock.mockImplementation((value?: string | null) =>
typeof value === "string" ? value.trim().toLowerCase() : undefined,
);
vi.doMock("../config/config.js", () => ({
loadConfig: (...args: unknown[]) => loadConfigMock(...args),
}));
vi.doMock("../channels/plugins/index.js", () => ({
getChannelPlugin: (...args: unknown[]) => getChannelPluginMock(...args),
listChannelPlugins: (...args: unknown[]) => listChannelPluginsMock(...args),
}));
vi.doMock("../../extensions/discord/src/channel.js", () => ({
discordPlugin: {},
}));
vi.doMock("../../extensions/telegram/src/channel.js", () => ({
telegramPlugin: {},
}));
vi.doMock("../../extensions/slack/src/channel.js", () => ({
slackPlugin: {},
}));
vi.doMock("../../extensions/whatsapp/src/channel.js", () => ({
whatsappPlugin: {},
}));
vi.doMock("../../extensions/signal/src/channel.js", () => ({
signalPlugin: {},
}));
vi.doMock("../../extensions/imessage/src/channel.js", () => ({
imessagePlugin: {},
}));
vi.doMock("../utils/message-channel.js", () => ({
INTERNAL_MESSAGE_CHANNEL: "web",
normalizeMessageChannel: (...args: unknown[]) => normalizeMessageChannelMock(...args),
}));
({ hasConfiguredExecApprovalDmRoute, resolveExecApprovalInitiatingSurfaceState } =
await import("./exec-approval-surface.js"));
await loadExecApprovalSurfaceModule();
});
it("returns true when any enabled account routes approvals to DM or both", () => {