feat: ValueMatcher 支持 primitive 原始值简写,等价于 { equals: value }
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { isEmptyObject, isEqual, isNil, isPlainObject } from "es-toolkit";
|
||||
|
||||
import type { CheckFailure, JsonValue } from "../types";
|
||||
import type { ExpectResult, ValueMatcher } from "./types";
|
||||
import type { ExpectResult, ValueMatcher, ValueMatcherInput } from "./types";
|
||||
|
||||
import { mismatchFailure } from "./failure";
|
||||
|
||||
@@ -66,18 +66,19 @@ export function checkExpectValue(actual: unknown, expected: JsonValue | ValueMat
|
||||
|
||||
export function checkValueMatcher(
|
||||
actual: unknown,
|
||||
matcher: undefined | ValueMatcher,
|
||||
matcher: undefined | ValueMatcherInput,
|
||||
options: { message?: string; path: string; phase: CheckFailure["phase"]; stringifyNonString?: boolean },
|
||||
): ExpectResult {
|
||||
if (matcher === undefined) return { failure: null, matched: true };
|
||||
if (applyMatcher(actual, matcher, { stringifyNonString: options.stringifyNonString })) {
|
||||
const normalized = isValueMatcherObject(matcher) ? matcher : { equals: matcher };
|
||||
if (applyMatcher(actual, normalized, { stringifyNonString: options.stringifyNonString })) {
|
||||
return { failure: null, matched: true };
|
||||
}
|
||||
return {
|
||||
failure: mismatchFailure(
|
||||
options.phase,
|
||||
options.path,
|
||||
matcher,
|
||||
normalized,
|
||||
actual,
|
||||
options.message ?? `${options.path} mismatch`,
|
||||
),
|
||||
|
||||
22
src/server/checker/expect/normalize.ts
Normal file
22
src/server/checker/expect/normalize.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { ValueMatcherPrimitive } from "./types";
|
||||
|
||||
import { isValueMatcherObject } from "./matcher";
|
||||
|
||||
export function isValueMatcherPrimitive(value: unknown): value is ValueMatcherPrimitive {
|
||||
return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
||||
}
|
||||
|
||||
export function normalizeExpectMatchers(expect: Record<string, unknown>, keys: string[]): void {
|
||||
for (const key of keys) {
|
||||
if (key in expect) {
|
||||
expect[key] = normalizeValueMatcher(expect[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeValueMatcher(value: unknown): unknown {
|
||||
if (value === undefined) return undefined;
|
||||
if (isValueMatcherObject(value)) return value;
|
||||
if (isValueMatcherPrimitive(value)) return { equals: value };
|
||||
return value;
|
||||
}
|
||||
@@ -39,3 +39,7 @@ export interface ValueMatcher {
|
||||
lte?: number;
|
||||
regex?: string;
|
||||
}
|
||||
|
||||
export type ValueMatcherInput = ValueMatcher | ValueMatcherPrimitive;
|
||||
|
||||
export type ValueMatcherPrimitive = boolean | null | number | string;
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { ConfigValidationIssue } from "../schema/issues";
|
||||
import type { JsonValue } from "../types";
|
||||
|
||||
import { issue, joinPath } from "../schema/issues";
|
||||
import { isValueMatcherPrimitive } from "./normalize";
|
||||
import { isUnsafeRegex } from "./redos";
|
||||
|
||||
export const MatcherKeys = ["contains", "empty", "equals", "exists", "gt", "gte", "lt", "lte", "regex"] as const;
|
||||
@@ -72,7 +73,9 @@ export function validateValueMatcher(
|
||||
options: { requireAtLeastOne?: boolean } = {},
|
||||
): ConfigValidationIssue[] {
|
||||
const requireAtLeastOne = options.requireAtLeastOne ?? true;
|
||||
if (!isPlainRecord(matcher)) return [issue("invalid-type", path, "必须为 matcher 对象", targetName)];
|
||||
if (isValueMatcherPrimitive(matcher)) return [];
|
||||
if (!isPlainRecord(matcher))
|
||||
return [issue("invalid-type", path, "必须为 primitive 原始值或 matcher 对象", targetName)];
|
||||
|
||||
const issues: ConfigValidationIssue[] = [];
|
||||
let found = 0;
|
||||
|
||||
Reference in New Issue
Block a user