fix(test): repair readonly case table typing

This commit is contained in:
Peter Steinberger
2026-02-22 00:09:06 +01:00
parent 8394f0e30e
commit 843a037532
4 changed files with 45 additions and 12 deletions

View File

@@ -1,11 +1,19 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
import { typedCases } from "../test-utils/typed-cases.js";
import { buildSubagentSystemPrompt } from "./subagent-announce.js"; import { buildSubagentSystemPrompt } from "./subagent-announce.js";
import { buildAgentSystemPrompt, buildRuntimeLine } from "./system-prompt.js"; import { buildAgentSystemPrompt, buildRuntimeLine } from "./system-prompt.js";
describe("buildAgentSystemPrompt", () => { describe("buildAgentSystemPrompt", () => {
it("formats owner section for plain, hash, and missing owner lists", () => { it("formats owner section for plain, hash, and missing owner lists", () => {
const cases = [ const cases = typedCases<{
name: string;
params: Parameters<typeof buildAgentSystemPrompt>[0];
expectAuthorizedSection: boolean;
contains: string[];
notContains: string[];
hashMatch?: RegExp;
}>([
{ {
name: "plain owner numbers", name: "plain owner numbers",
params: { params: {
@@ -16,14 +24,14 @@ describe("buildAgentSystemPrompt", () => {
contains: [ contains: [
"Authorized senders: +123, +456. These senders are allowlisted; do not assume they are the owner.", "Authorized senders: +123, +456. These senders are allowlisted; do not assume they are the owner.",
], ],
notContains: [] as string[], notContains: [],
}, },
{ {
name: "hashed owner numbers", name: "hashed owner numbers",
params: { params: {
workspaceDir: "/tmp/openclaw", workspaceDir: "/tmp/openclaw",
ownerNumbers: ["+123", "+456", ""], ownerNumbers: ["+123", "+456", ""],
ownerDisplay: "hash" as const, ownerDisplay: "hash",
}, },
expectAuthorizedSection: true, expectAuthorizedSection: true,
contains: ["Authorized senders:"], contains: ["Authorized senders:"],
@@ -36,10 +44,10 @@ describe("buildAgentSystemPrompt", () => {
workspaceDir: "/tmp/openclaw", workspaceDir: "/tmp/openclaw",
}, },
expectAuthorizedSection: false, expectAuthorizedSection: false,
contains: [] as string[], contains: [],
notContains: ["## Authorized Senders", "Authorized senders:"], notContains: ["## Authorized Senders", "Authorized senders:"],
}, },
] as const; ]);
for (const testCase of cases) { for (const testCase of cases) {
const prompt = buildAgentSystemPrompt(testCase.params); const prompt = buildAgentSystemPrompt(testCase.params);

View File

@@ -12,6 +12,7 @@ import type { OpenClawConfig } from "../../config/config.js";
import { updateSessionStore } from "../../config/sessions.js"; import { updateSessionStore } from "../../config/sessions.js";
import * as internalHooks from "../../hooks/internal-hooks.js"; import * as internalHooks from "../../hooks/internal-hooks.js";
import { clearPluginCommands, registerPluginCommand } from "../../plugins/commands.js"; import { clearPluginCommands, registerPluginCommand } from "../../plugins/commands.js";
import { typedCases } from "../../test-utils/typed-cases.js";
import type { MsgContext } from "../templating.js"; import type { MsgContext } from "../templating.js";
import { resetBashChatCommandForTests } from "./bash-command.js"; import { resetBashChatCommandForTests } from "./bash-command.js";
import { handleCompactCommand } from "./commands-compact.js"; import { handleCompactCommand } from "./commands-compact.js";
@@ -138,7 +139,12 @@ function buildParams(commandBody: string, cfg: OpenClawConfig, ctxOverrides?: Pa
describe("handleCommands gating", () => { describe("handleCommands gating", () => {
it("blocks /bash when disabled or not elevated-allowlisted", async () => { it("blocks /bash when disabled or not elevated-allowlisted", async () => {
resetBashChatCommandForTests(); resetBashChatCommandForTests();
const cases = [ const cases = typedCases<{
name: string;
cfg: OpenClawConfig;
applyParams?: (params: ReturnType<typeof buildParams>) => void;
expectedText: string;
}>([
{ {
name: "disabled bash command", name: "disabled bash command",
cfg: { cfg: {
@@ -162,7 +168,7 @@ describe("handleCommands gating", () => {
}, },
expectedText: "elevated is not available", expectedText: "elevated is not available",
}, },
] as const; ]);
for (const testCase of cases) { for (const testCase of cases) {
const params = buildParams("/bash echo hi", testCase.cfg); const params = buildParams("/bash echo hi", testCase.cfg);
testCase.applyParams?.(params); testCase.applyParams?.(params);

View File

@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import type { MsgContext } from "../auto-reply/templating.js"; import type { MsgContext } from "../auto-reply/templating.js";
import { typedCases } from "../test-utils/typed-cases.js";
import { import {
type ChannelMatchSource, type ChannelMatchSource,
buildChannelKeyCandidates, buildChannelKeyCandidates,
@@ -42,7 +43,18 @@ describe("resolveChannelEntryMatch", () => {
}); });
describe("resolveChannelEntryMatchWithFallback", () => { describe("resolveChannelEntryMatchWithFallback", () => {
const fallbackCases = [ const fallbackCases = typedCases<{
name: string;
entries: Record<string, { allow: boolean }>;
args: {
keys: string[];
parentKeys?: string[];
wildcardKey?: string;
};
expectedEntryKey: string;
expectedSource: ChannelMatchSource;
expectedMatchKey: string;
}>([
{ {
name: "prefers direct matches over parent and wildcard", name: "prefers direct matches over parent and wildcard",
entries: { a: { allow: true }, parent: { allow: false }, "*": { allow: false } }, entries: { a: { allow: true }, parent: { allow: false }, "*": { allow: false } },
@@ -67,7 +79,7 @@ describe("resolveChannelEntryMatchWithFallback", () => {
expectedSource: "wildcard", expectedSource: "wildcard",
expectedMatchKey: "*", expectedMatchKey: "*",
}, },
] as const; ]);
for (const testCase of fallbackCases) { for (const testCase of fallbackCases) {
it(testCase.name, () => { it(testCase.name, () => {

View File

@@ -51,7 +51,14 @@ function createProps(overrides: Partial<ChatProps> = {}): ChatProps {
describe("chat view", () => { describe("chat view", () => {
it("renders/hides compaction and fallback indicators across recency states", () => { it("renders/hides compaction and fallback indicators across recency states", () => {
const cases = [ const cases: Array<{
name: string;
nowMs?: number;
props: Partial<ChatProps>;
selector: string;
missing?: boolean;
expectedText?: string;
}> = [
{ {
name: "active compaction", name: "active compaction",
props: { props: {
@@ -134,7 +141,7 @@ describe("chat view", () => {
selector: ".compaction-indicator--fallback-cleared", selector: ".compaction-indicator--fallback-cleared",
expectedText: "Fallback cleared: fireworks/minimax-m2p5", expectedText: "Fallback cleared: fireworks/minimax-m2p5",
}, },
] as const; ];
for (const testCase of cases) { for (const testCase of cases) {
const nowSpy = const nowSpy =
@@ -146,7 +153,7 @@ describe("chat view", () => {
expect(indicator, testCase.name).toBeNull(); expect(indicator, testCase.name).toBeNull();
} else { } else {
expect(indicator, testCase.name).not.toBeNull(); expect(indicator, testCase.name).not.toBeNull();
expect(indicator?.textContent, testCase.name).toContain(testCase.expectedText); expect(indicator?.textContent, testCase.name).toContain(testCase.expectedText ?? "");
} }
nowSpy?.mockRestore(); nowSpy?.mockRestore();
} }