




















@@ -49,6 +49,19 @@ function compileManifestConfigSchema() {
4949return ajv.compile(manifest.configSchema);
5050}
515152+function requireRecord(value: unknown, label: string): Record<string, unknown> {
53+expect(value, label).toBeTypeOf("object");
54+expect(value, label).not.toBeNull();
55+return value as Record<string, unknown>;
56+}
57+58+function expectFields(value: unknown, fields: Record<string, unknown>) {
59+const record = requireRecord(value, "record");
60+for (const [key, expected] of Object.entries(fields)) {
61+expect(record[key]).toEqual(expected);
62+}
63+}
64+5265describe("resolveDiffsPluginDefaults", () => {
5366it("returns built-in defaults when config is missing", () => {
5467expect(resolveDiffsPluginDefaults(undefined)).toEqual(DEFAULT_DIFFS_TOOL_DEFAULTS);
@@ -63,77 +76,83 @@ describe("resolveDiffsPluginDefaults", () => {
6376});
64776578it("clamps and falls back for invalid line spacing and indicators", () => {
66-expect(
79+expectFields(
6780resolveDiffsPluginDefaults({
6881defaults: {
6982lineSpacing: -5,
7083diffIndicators: "unknown",
7184},
7285}),
73-).toMatchObject({
74-lineSpacing: 1,
75-diffIndicators: "bars",
76-});
86+{
87+lineSpacing: 1,
88+diffIndicators: "bars",
89+},
90+);
779178-expect(
92+expectFields(
7993resolveDiffsPluginDefaults({
8094defaults: {
8195lineSpacing: 9,
8296},
8397}),
84-).toMatchObject({
85-lineSpacing: 3,
86-});
98+{
99+lineSpacing: 3,
100+},
101+);
8710288-expect(
103+expectFields(
89104resolveDiffsPluginDefaults({
90105defaults: {
91106lineSpacing: Number.NaN,
92107},
93108}),
94-).toMatchObject({
95-lineSpacing: DEFAULT_DIFFS_TOOL_DEFAULTS.lineSpacing,
96-});
109+{
110+lineSpacing: DEFAULT_DIFFS_TOOL_DEFAULTS.lineSpacing,
111+},
112+);
97113});
9811499115it("derives file defaults from quality preset and clamps explicit overrides", () => {
100-expect(
116+expectFields(
101117resolveDiffsPluginDefaults({
102118defaults: {
103119fileQuality: "print",
104120},
105121}),
106-).toMatchObject({
107-fileQuality: "print",
108-fileScale: 3,
109-fileMaxWidth: 1400,
110-});
122+{
123+fileQuality: "print",
124+fileScale: 3,
125+fileMaxWidth: 1400,
126+},
127+);
111128112-expect(
129+expectFields(
113130resolveDiffsPluginDefaults({
114131defaults: {
115132fileQuality: "hq",
116133fileScale: 99,
117134fileMaxWidth: 99999,
118135},
119136}),
120-).toMatchObject({
121-fileQuality: "hq",
122-fileScale: 4,
123-fileMaxWidth: 2400,
124-});
137+{
138+fileQuality: "hq",
139+fileScale: 4,
140+fileMaxWidth: 2400,
141+},
142+);
125143});
126144127145it("falls back to png for invalid file format defaults", () => {
128-expect(
146+expectFields(
129147resolveDiffsPluginDefaults({
130148defaults: {
131149fileFormat: "invalid" as "png",
132150},
133151}),
134-).toMatchObject({
135-fileFormat: "png",
136-});
152+{
153+fileFormat: "png",
154+},
155+);
137156});
138157139158it("resolves file render format from defaults and explicit overrides", () => {
@@ -149,19 +168,20 @@ describe("resolveDiffsPluginDefaults", () => {
149168});
150169151170it("accepts format as a config alias for fileFormat", () => {
152-expect(
171+expectFields(
153172resolveDiffsPluginDefaults({
154173defaults: {
155174format: "pdf",
156175},
157176}),
158-).toMatchObject({
159-fileFormat: "pdf",
160-});
177+{
178+fileFormat: "pdf",
179+},
180+);
161181});
162182163183it("accepts image* config aliases for backward compatibility", () => {
164-expect(
184+expectFields(
165185resolveDiffsPluginDefaults({
166186defaults: {
167187imageFormat: "pdf",
@@ -170,34 +190,37 @@ describe("resolveDiffsPluginDefaults", () => {
170190imageMaxWidth: 1024,
171191},
172192}),
173-).toMatchObject({
174-fileFormat: "pdf",
175-fileQuality: "hq",
176-fileScale: 2.2,
177-fileMaxWidth: 1024,
178-});
193+{
194+fileFormat: "pdf",
195+fileQuality: "hq",
196+fileScale: 2.2,
197+fileMaxWidth: 1024,
198+},
199+);
179200});
180201181202it("accepts plugin-wide artifact TTL defaults", () => {
182-expect(
203+expectFields(
183204resolveDiffsPluginDefaults({
184205defaults: {
185206ttlSeconds: 21_600,
186207},
187208}),
188-).toMatchObject({
189-ttlSeconds: 21_600,
190-});
209+{
210+ttlSeconds: 21_600,
211+},
212+);
191213192-expect(
214+expectFields(
193215resolveDiffsPluginDefaults({
194216defaults: {
195217ttlSeconds: 99_999,
196218},
197219}),
198-).toMatchObject({
199-ttlSeconds: 21_600,
200-});
220+{
221+ttlSeconds: 21_600,
222+},
223+);
201224});
202225203226it("keeps loader-applied schema defaults from shadowing aliases and quality-derived defaults", () => {
@@ -210,7 +233,7 @@ describe("resolveDiffsPluginDefaults", () => {
210233},
211234};
212235expect(validate(aliasOnly)).toBe(true);
213-expect(resolveDiffsPluginDefaults(aliasOnly)).toMatchObject({
236+expectFields(resolveDiffsPluginDefaults(aliasOnly), {
214237fileFormat: "pdf",
215238fileQuality: "hq",
216239fileScale: 2.5,
@@ -223,7 +246,7 @@ describe("resolveDiffsPluginDefaults", () => {
223246},
224247};
225248expect(validate(qualityOnly)).toBe(true);
226-expect(resolveDiffsPluginDefaults(qualityOnly)).toMatchObject({
249+expectFields(resolveDiffsPluginDefaults(qualityOnly), {
227250fileQuality: "hq",
228251fileScale: 2.5,
229252fileMaxWidth: 1200,
@@ -268,7 +291,7 @@ describe("diffs plugin schema surfaces", () => {
268291});
269292270293it("preserves defaults and security for direct safeParse callers", () => {
271-expect(
294+const parsed = requireRecord(
272295diffsPluginConfigSchema.safeParse?.({
273296viewerBaseUrl: "https://example.com/openclaw/",
274297defaults: {
@@ -279,71 +302,64 @@ describe("diffs plugin schema surfaces", () => {
279302allowRemoteViewer: true,
280303},
281304}),
282-).toMatchObject({
283-success: true,
284-data: {
285-viewerBaseUrl: "https://example.com/openclaw",
286-defaults: {
287-fontFamily: "Fira Code",
288-fontSize: 15,
289-lineSpacing: 1.6,
290-layout: "unified",
291-showLineNumbers: true,
292-diffIndicators: "bars",
293-wordWrap: true,
294-background: true,
295-theme: "light",
296-fileFormat: "png",
297-fileQuality: "standard",
298-fileScale: 2,
299-fileMaxWidth: 960,
300-mode: "both",
301-ttlSeconds: 21_600,
302-},
303-security: {
304-allowRemoteViewer: true,
305-},
306-},
305+"parse result",
306+);
307+expect(parsed.success).toBe(true);
308+const data = requireRecord(parsed.data, "parse data");
309+expect(data.viewerBaseUrl).toBe("https://example.com/openclaw");
310+expectFields(data.defaults, {
311+fontFamily: "Fira Code",
312+fontSize: 15,
313+lineSpacing: 1.6,
314+layout: "unified",
315+showLineNumbers: true,
316+diffIndicators: "bars",
317+wordWrap: true,
318+background: true,
319+theme: "light",
320+fileFormat: "png",
321+fileQuality: "standard",
322+fileScale: 2,
323+fileMaxWidth: 960,
324+mode: "both",
325+ttlSeconds: 21_600,
307326});
327+expectFields(data.security, { allowRemoteViewer: true });
308328});
309329310330it("canonicalizes alias-driven defaults for direct safeParse callers", () => {
311-expect(
331+const parsed = requireRecord(
312332diffsPluginConfigSchema.safeParse?.({
313333defaults: {
314334format: "pdf",
315335imageQuality: "hq",
316336},
317337}),
318-).toMatchObject({
319-success: true,
320-data: {
321-defaults: {
322-fileFormat: "pdf",
323-fileQuality: "hq",
324-fileScale: 2.5,
325-fileMaxWidth: 1200,
326-},
327-},
338+"parse result",
339+);
340+expect(parsed.success).toBe(true);
341+const data = requireRecord(parsed.data, "parse data");
342+expectFields(data.defaults, {
343+fileFormat: "pdf",
344+fileQuality: "hq",
345+fileScale: 2.5,
346+fileMaxWidth: 1200,
328347});
329348});
330349331350it("rejects invalid viewerBaseUrl config values", () => {
332-expect(
351+const parsed = requireRecord(
333352diffsPluginConfigSchema.safeParse?.({
334353viewerBaseUrl: "javascript:alert(1)",
335354}),
336-).toMatchObject({
337-success: false,
338-error: {
339-issues: [
340-{
341-path: ["viewerBaseUrl"],
342-message: "viewerBaseUrl must use http or https: javascript:alert(1)",
343-},
344-],
345-},
346-});
355+"parse result",
356+);
357+expect(parsed.success).toBe(false);
358+const error = requireRecord(parsed.error, "parse error");
359+const issues = error.issues as Array<{ path?: unknown; message?: unknown }>;
360+expect(issues).toHaveLength(1);
361+expect(issues[0]?.path).toEqual(["viewerBaseUrl"]);
362+expect(issues[0]?.message).toBe("viewerBaseUrl must use http or https: javascript:alert(1)");
347363});
348364349365it("keeps the runtime json schema in sync with the manifest config schema", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。