Skip to content

Commit

Permalink
fix: check input length in skipValidate functions
Browse files Browse the repository at this point in the history
  • Loading branch information
lawvs committed Aug 7, 2024
1 parent ee4de0e commit e0f5632
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
7 changes: 7 additions & 0 deletions .changeset/dull-ants-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@fn-sphere/core": patch
---

Fix `isValidRule` incorrectly returned `false` for functions with `skipValidate` enabled

Now, even if `skipValidate` is enabled, the input data is still checked for length.
84 changes: 82 additions & 2 deletions packages/core/src/filter/validation.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { describe, expect, it } from "vitest";
import { z } from "zod";
import { booleanFilter, stringFilter } from "../presets.js";
import { defineGenericFn, defineTypedFn } from "../fn-sphere.js";
import type { FnSchema } from "../types.js";
import type { FilterId, SingleFilter } from "./types.js";
import { isValidRule } from "./validation.js";

describe("isValidRule", () => {
const filterFnList: FnSchema[] = [...booleanFilter, ...stringFilter];
const filterFnList: FnSchema[] = [
defineTypedFn({
name: "Starts with",
define: z.function().args(z.string(), z.string()).returns(z.boolean()),
implement: (value, target) => value.startsWith(target),
skipValidate: true,
}),
defineTypedFn({
name: "Is checked",
define: z.function().args(z.boolean()).returns(z.boolean()),
implement: (value) => value === true,
skipValidate: true,
}),
];

const mockDataSchema = z.object({
name: z.string(),
Expand Down Expand Up @@ -119,4 +132,71 @@ describe("isValidRule", () => {

expect(result).toBe(true);
});

it("should return false when no input for skip validate standard fn", () => {
const rule: SingleFilter = {
id: "1" as FilterId,
type: "Filter",
name: "Equals",
path: ["name"],
args: [],
};

const standardFn = defineTypedFn({
name: "Equals",
define: z.function().args(z.string(), z.string()).returns(z.boolean()),
implement: (value, target) => value === target,
skipValidate: true,
});

const result = isValidRule({
filterFnList: [standardFn],
dataSchema: mockDataSchema,
rule,
});

expect(result).toBe(false);

rule.args = ["data"];
const newResult = isValidRule({
filterFnList: [standardFn],
dataSchema: mockDataSchema,
rule,
});
expect(newResult).toBe(true);
});

it("should return false when no input for skip validate generic fn", () => {
const rule: SingleFilter = {
id: "1" as FilterId,
type: "Filter",
name: "Equals",
path: ["name"],
args: [],
};

const genericFn = defineGenericFn({
name: "Equals",
genericLimit: (t): t is z.ZodString | z.ZodNumber => true,
define: (t) => z.function().args(t, t).returns(z.boolean()),
implement: (value: z.Primitive, target: z.Primitive) => value === target,
skipValidate: true,
});

const result = isValidRule({
filterFnList: [genericFn],
dataSchema: mockDataSchema,
rule,
});

expect(result).toBe(false);

rule.args = ["data"];
const newResult = isValidRule({
filterFnList: [genericFn],
dataSchema: mockDataSchema,
rule,
});
expect(newResult).toBe(true);
});
});
10 changes: 10 additions & 0 deletions packages/core/src/filter/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ const validateStandardFnRule = ({
}

const requiredParameters = getParametersExceptFirst(fnSchema);

if (requiredParameters.length !== rule.args.length) {
return {
success: false,
error: new Error(
`rule.args length not match required parameters length, ${rule.args.length} !== ${requiredParameters.length}`,
),
};
}

if (!fnSchema.skipValidate) {
const parseResult = z.tuple(requiredParameters).safeParse(rule.args);
return parseResult;
Expand Down

0 comments on commit e0f5632

Please sign in to comment.