@@ -478,4 +478,195 @@ describe("util.effect-zod", () => {
478478 expect ( bad . error ! . issues . map ( ( i ) => i . message ) ) . toEqual ( expect . arrayContaining ( [ "not positive" , "not even" ] ) )
479479 } )
480480 } )
481+
482+ describe ( "well-known refinement translation" , ( ) => {
483+ test ( "Schema.isInt emits type: integer in JSON Schema" , ( ) => {
484+ const schema = zod ( Schema . Number . check ( Schema . isInt ( ) ) )
485+ const native = json ( z . number ( ) . int ( ) )
486+ expect ( json ( schema ) ) . toEqual ( native )
487+ expect ( schema . parse ( 3 ) ) . toBe ( 3 )
488+ expect ( schema . safeParse ( 1.5 ) . success ) . toBe ( false )
489+ } )
490+
491+ test ( "Schema.isGreaterThan(0) emits exclusiveMinimum: 0" , ( ) => {
492+ const schema = zod ( Schema . Number . check ( Schema . isGreaterThan ( 0 ) ) )
493+ expect ( ( json ( schema ) as any ) . exclusiveMinimum ) . toBe ( 0 )
494+ expect ( schema . parse ( 1 ) ) . toBe ( 1 )
495+ expect ( schema . safeParse ( 0 ) . success ) . toBe ( false )
496+ expect ( schema . safeParse ( - 1 ) . success ) . toBe ( false )
497+ } )
498+
499+ test ( "Schema.isGreaterThanOrEqualTo(0) emits minimum: 0" , ( ) => {
500+ const schema = zod ( Schema . Number . check ( Schema . isGreaterThanOrEqualTo ( 0 ) ) )
501+ expect ( ( json ( schema ) as any ) . minimum ) . toBe ( 0 )
502+ expect ( schema . parse ( 0 ) ) . toBe ( 0 )
503+ expect ( schema . safeParse ( - 1 ) . success ) . toBe ( false )
504+ } )
505+
506+ test ( "Schema.isLessThan(10) emits exclusiveMaximum: 10" , ( ) => {
507+ const schema = zod ( Schema . Number . check ( Schema . isLessThan ( 10 ) ) )
508+ expect ( ( json ( schema ) as any ) . exclusiveMaximum ) . toBe ( 10 )
509+ expect ( schema . parse ( 9 ) ) . toBe ( 9 )
510+ expect ( schema . safeParse ( 10 ) . success ) . toBe ( false )
511+ } )
512+
513+ test ( "Schema.isLessThanOrEqualTo(10) emits maximum: 10" , ( ) => {
514+ const schema = zod ( Schema . Number . check ( Schema . isLessThanOrEqualTo ( 10 ) ) )
515+ expect ( ( json ( schema ) as any ) . maximum ) . toBe ( 10 )
516+ expect ( schema . parse ( 10 ) ) . toBe ( 10 )
517+ expect ( schema . safeParse ( 11 ) . success ) . toBe ( false )
518+ } )
519+
520+ test ( "Schema.isMultipleOf(5) emits multipleOf: 5" , ( ) => {
521+ const schema = zod ( Schema . Number . check ( Schema . isMultipleOf ( 5 ) ) )
522+ expect ( ( json ( schema ) as any ) . multipleOf ) . toBe ( 5 )
523+ expect ( schema . parse ( 10 ) ) . toBe ( 10 )
524+ expect ( schema . safeParse ( 7 ) . success ) . toBe ( false )
525+ } )
526+
527+ test ( "Schema.isFinite validates at runtime" , ( ) => {
528+ const schema = zod ( Schema . Number . check ( Schema . isFinite ( ) ) )
529+ expect ( schema . parse ( 1 ) ) . toBe ( 1 )
530+ expect ( schema . safeParse ( Infinity ) . success ) . toBe ( false )
531+ expect ( schema . safeParse ( NaN ) . success ) . toBe ( false )
532+ } )
533+
534+ test ( "chained isInt + isGreaterThan(0) matches z.number().int().positive()" , ( ) => {
535+ const schema = zod ( Schema . Number . check ( Schema . isInt ( ) ) . check ( Schema . isGreaterThan ( 0 ) ) )
536+ const native = json ( z . number ( ) . int ( ) . positive ( ) )
537+ expect ( json ( schema ) ) . toEqual ( native )
538+ expect ( schema . parse ( 3 ) ) . toBe ( 3 )
539+ expect ( schema . safeParse ( 0 ) . success ) . toBe ( false )
540+ expect ( schema . safeParse ( 1.5 ) . success ) . toBe ( false )
541+ } )
542+
543+ test ( "chained isInt + isGreaterThanOrEqualTo(0) matches z.number().int().min(0)" , ( ) => {
544+ const schema = zod ( Schema . Number . check ( Schema . isInt ( ) ) . check ( Schema . isGreaterThanOrEqualTo ( 0 ) ) )
545+ const native = json ( z . number ( ) . int ( ) . min ( 0 ) )
546+ expect ( json ( schema ) ) . toEqual ( native )
547+ expect ( schema . parse ( 0 ) ) . toBe ( 0 )
548+ expect ( schema . safeParse ( - 1 ) . success ) . toBe ( false )
549+ } )
550+
551+ test ( "Schema.isBetween emits both bounds" , ( ) => {
552+ const schema = zod ( Schema . Number . check ( Schema . isBetween ( { minimum : 1 , maximum : 10 } ) ) )
553+ const shape = json ( schema ) as any
554+ expect ( shape . minimum ) . toBe ( 1 )
555+ expect ( shape . maximum ) . toBe ( 10 )
556+ expect ( schema . parse ( 5 ) ) . toBe ( 5 )
557+ expect ( schema . safeParse ( 11 ) . success ) . toBe ( false )
558+ expect ( schema . safeParse ( 0 ) . success ) . toBe ( false )
559+ } )
560+
561+ test ( "Schema.isBetween with exclusive bounds emits exclusiveMinimum/Maximum" , ( ) => {
562+ const schema = zod (
563+ Schema . Number . check (
564+ Schema . isBetween ( { minimum : 1 , maximum : 10 , exclusiveMinimum : true , exclusiveMaximum : true } ) ,
565+ ) ,
566+ )
567+ const shape = json ( schema ) as any
568+ expect ( shape . exclusiveMinimum ) . toBe ( 1 )
569+ expect ( shape . exclusiveMaximum ) . toBe ( 10 )
570+ expect ( schema . parse ( 5 ) ) . toBe ( 5 )
571+ expect ( schema . safeParse ( 1 ) . success ) . toBe ( false )
572+ expect ( schema . safeParse ( 10 ) . success ) . toBe ( false )
573+ } )
574+
575+ test ( "Schema.isInt32 (FilterGroup) produces integer bounds" , ( ) => {
576+ const schema = zod ( Schema . Number . check ( Schema . isInt32 ( ) ) )
577+ const shape = json ( schema ) as any
578+ expect ( shape . type ) . toBe ( "integer" )
579+ expect ( shape . minimum ) . toBe ( - 2147483648 )
580+ expect ( shape . maximum ) . toBe ( 2147483647 )
581+ expect ( schema . parse ( 42 ) ) . toBe ( 42 )
582+ expect ( schema . safeParse ( 1.5 ) . success ) . toBe ( false )
583+ expect ( schema . safeParse ( 2147483648 ) . success ) . toBe ( false )
584+ } )
585+
586+ test ( "Schema.isMinLength on string emits minLength" , ( ) => {
587+ const schema = zod ( Schema . String . check ( Schema . isMinLength ( 3 ) ) )
588+ expect ( ( json ( schema ) as any ) . minLength ) . toBe ( 3 )
589+ expect ( schema . parse ( "abc" ) ) . toBe ( "abc" )
590+ expect ( schema . safeParse ( "ab" ) . success ) . toBe ( false )
591+ } )
592+
593+ test ( "Schema.isMaxLength on string emits maxLength" , ( ) => {
594+ const schema = zod ( Schema . String . check ( Schema . isMaxLength ( 5 ) ) )
595+ expect ( ( json ( schema ) as any ) . maxLength ) . toBe ( 5 )
596+ expect ( schema . parse ( "abcde" ) ) . toBe ( "abcde" )
597+ expect ( schema . safeParse ( "abcdef" ) . success ) . toBe ( false )
598+ } )
599+
600+ test ( "Schema.isLengthBetween on string emits both bounds" , ( ) => {
601+ const schema = zod ( Schema . String . check ( Schema . isLengthBetween ( 2 , 4 ) ) )
602+ const shape = json ( schema ) as any
603+ expect ( shape . minLength ) . toBe ( 2 )
604+ expect ( shape . maxLength ) . toBe ( 4 )
605+ expect ( schema . parse ( "abc" ) ) . toBe ( "abc" )
606+ expect ( schema . safeParse ( "a" ) . success ) . toBe ( false )
607+ expect ( schema . safeParse ( "abcde" ) . success ) . toBe ( false )
608+ } )
609+
610+ test ( "Schema.isMinLength on array emits minItems" , ( ) => {
611+ const schema = zod ( Schema . Array ( Schema . String ) . check ( Schema . isMinLength ( 1 ) ) )
612+ expect ( ( json ( schema ) as any ) . minItems ) . toBe ( 1 )
613+ expect ( schema . parse ( [ "x" ] ) ) . toEqual ( [ "x" ] )
614+ expect ( schema . safeParse ( [ ] ) . success ) . toBe ( false )
615+ } )
616+
617+ test ( "Schema.isPattern emits pattern" , ( ) => {
618+ const schema = zod ( Schema . String . check ( Schema . isPattern ( / ^ p e r / ) ) )
619+ expect ( ( json ( schema ) as any ) . pattern ) . toBe ( "^per" )
620+ expect ( schema . parse ( "per_abc" ) ) . toBe ( "per_abc" )
621+ expect ( schema . safeParse ( "abc" ) . success ) . toBe ( false )
622+ } )
623+
624+ test ( "Schema.isStartsWith matches native zod .startsWith() JSON Schema" , ( ) => {
625+ const schema = zod ( Schema . String . check ( Schema . isStartsWith ( "per" ) ) )
626+ const native = json ( z . string ( ) . startsWith ( "per" ) )
627+ expect ( json ( schema ) ) . toEqual ( native )
628+ expect ( schema . parse ( "per_abc" ) ) . toBe ( "per_abc" )
629+ expect ( schema . safeParse ( "abc" ) . success ) . toBe ( false )
630+ } )
631+
632+ test ( "Schema.isEndsWith matches native zod .endsWith() JSON Schema" , ( ) => {
633+ const schema = zod ( Schema . String . check ( Schema . isEndsWith ( ".json" ) ) )
634+ const native = json ( z . string ( ) . endsWith ( ".json" ) )
635+ expect ( json ( schema ) ) . toEqual ( native )
636+ expect ( schema . parse ( "a.json" ) ) . toBe ( "a.json" )
637+ expect ( schema . safeParse ( "a.txt" ) . success ) . toBe ( false )
638+ } )
639+
640+ test ( "Schema.isUUID emits format: uuid" , ( ) => {
641+ const schema = zod ( Schema . String . check ( Schema . isUUID ( ) ) )
642+ expect ( ( json ( schema ) as any ) . format ) . toBe ( "uuid" )
643+ } )
644+
645+ test ( "mix of well-known and anonymous filters translates known and reroutes unknown to superRefine" , ( ) => {
646+ // isInt is well-known (translates to .int()); the anonymous filter falls
647+ // back to superRefine.
648+ const notSeven = Schema . makeFilter ( ( n : number ) => ( n !== 7 ? undefined : "no sevens allowed" ) )
649+ const schema = zod ( Schema . Number . check ( Schema . isInt ( ) ) . check ( notSeven ) )
650+
651+ const shape = json ( schema ) as any
652+ // Well-known translation is preserved — type is integer, not plain number
653+ expect ( shape . type ) . toBe ( "integer" )
654+
655+ // Runtime: both constraints fire
656+ expect ( schema . parse ( 3 ) ) . toBe ( 3 )
657+ expect ( schema . safeParse ( 1.5 ) . success ) . toBe ( false )
658+ const seven = schema . safeParse ( 7 )
659+ expect ( seven . success ) . toBe ( false )
660+ expect ( seven . error ! . issues [ 0 ] . message ) . toBe ( "no sevens allowed" )
661+ } )
662+
663+ test ( "inside a struct field, well-known refinements propagate through" , ( ) => {
664+ // Mirrors config.ts port: z.number().int().positive().optional()
665+ const Port = Schema . optional ( Schema . Number . check ( Schema . isInt ( ) ) . check ( Schema . isGreaterThan ( 0 ) ) )
666+ const schema = zod ( Schema . Struct ( { port : Port } ) )
667+ const shape = json ( schema ) as any
668+ expect ( shape . properties . port . type ) . toBe ( "integer" )
669+ expect ( shape . properties . port . exclusiveMinimum ) . toBe ( 0 )
670+ } )
671+ } )
481672} )
0 commit comments