























@@ -1,9 +1,12 @@
1-import type { ErrorObject } from "ajv";
1+import AjvPkg, { type ErrorObject } from "ajv";
22import { describe, expect, it } from "vitest";
33import { TALK_TEST_PROVIDER_ID } from "../../test-utils/talk-test-provider.js";
4+import * as protocol from "./index.js";
45import {
56formatValidationErrors,
67validateChatEvent,
8+validateCommandsListParams,
9+validateConnectParams,
710validateModelsListParams,
811validateNodeEventResult,
912validateNodePairRequestParams,
@@ -35,6 +38,71 @@ const makeError = (overrides: Partial<ErrorObject>): ErrorObject => ({
3538 ...overrides,
3639});
374041+type CompileMethod = (schema: unknown, meta?: boolean) => unknown;
42+type ProtocolValidator = (value: unknown) => boolean;
43+44+describe("lazy protocol validators", () => {
45+it("compiles on first use and reuses the compiled validator", () => {
46+const ajvPrototype = (AjvPkg as unknown as { prototype: { compile: CompileMethod } }).prototype;
47+const originalCompile = ajvPrototype.compile;
48+let compileCalls = 0;
49+50+ajvPrototype.compile = function (this: unknown, schema: unknown, meta?: boolean) {
51+compileCalls += 1;
52+return originalCompile.call(this, schema, meta);
53+};
54+55+try {
56+expect(compileCalls).toBe(0);
57+expect(validateCommandsListParams({})).toBe(true);
58+expect(compileCalls).toBe(1);
59+expect(validateCommandsListParams({ includeArgs: true })).toBe(true);
60+expect(compileCalls).toBe(1);
61+} finally {
62+ajvPrototype.compile = originalCompile;
63+}
64+});
65+66+it("keeps validation errors readable on the exported validator", () => {
67+expect(validateConnectParams({})).toBe(false);
68+expect(formatValidationErrors(validateConnectParams.errors)).toContain("must have required");
69+70+expect(
71+validateConnectParams({
72+minProtocol: 1,
73+maxProtocol: 1,
74+client: {
75+id: "test",
76+version: "1.0.0",
77+platform: "test",
78+mode: "test",
79+},
80+}),
81+).toBe(true);
82+expect(validateConnectParams.errors).toBeNull();
83+});
84+85+it("can still compile every exported protocol validator", () => {
86+const failures: string[] = [];
87+const validators: Array<[string, ProtocolValidator]> = [];
88+for (const [name, value] of Object.entries(protocol)) {
89+if (name.startsWith("validate") && typeof value === "function") {
90+validators.push([name, value as ProtocolValidator]);
91+}
92+}
93+94+expect(validators.length).toBeGreaterThan(150);
95+for (const [name, validate] of validators) {
96+try {
97+validate(undefined);
98+} catch (err) {
99+failures.push(`${name}: ${err instanceof Error ? err.message : String(err)}`);
100+}
101+}
102+expect(failures).toEqual([]);
103+});
104+});
105+38106describe("formatValidationErrors", () => {
39107it("returns unknown validation error when missing errors", () => {
40108expect(formatValidationErrors(undefined)).toBe("unknown validation error");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。