@@ -32,6 +32,8 @@ public function testImmutability(): void
3232 self ::assertNotSame ($ schema , $ schema ->minItems (1 ));
3333 self ::assertNotSame ($ schema , $ schema ->maxItems (1 ));
3434 self ::assertNotSame ($ schema , $ schema ->contains ('test ' ));
35+ self ::assertNotSame ($ schema , $ schema ->minContains ('test ' , 1 ));
36+ self ::assertNotSame ($ schema , $ schema ->maxContains ('test ' , 1 ));
3537 self ::assertNotSame ($ schema , $ schema ->uniqueItems ());
3638 self ::assertNotSame ($ schema , $ schema ->filter (static fn (mixed $ value ) => true ));
3739 self ::assertNotSame ($ schema , $ schema ->map (static fn (mixed $ value ) => $ value ));
@@ -550,6 +552,208 @@ public function testParseWithInvalidContains(): void
550552 }
551553 }
552554
555+ public function testParseWithValidMinContains (): void
556+ {
557+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
558+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
559+
560+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime2 ];
561+
562+ $ schema = (new ArraySchema (new DateTimeSchema ()))->minContains ($ dateTime2 , 2 );
563+
564+ self ::assertSame ($ input , $ schema ->parse ($ input ));
565+ }
566+
567+ public function testParseWithValidMinContainsWithEqualButNotSame (): void
568+ {
569+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
570+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
571+
572+ $ dateTime2Equal = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
573+
574+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime2Equal ];
575+
576+ $ schema = (new ArraySchema (new DateTimeSchema ()))->minContains ($ dateTime2Equal , 2 , false );
577+
578+ self ::assertSame ($ input , $ schema ->parse ($ input ));
579+ }
580+
581+ public function testParseWithInvalidMinContainsWithEqualButNotSameAndStrictFalse (): void
582+ {
583+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
584+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
585+
586+ $ dateTime2Equal = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
587+
588+ $ dateTime2Equal2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
589+
590+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime2Equal2 ];
591+
592+ $ schema = (new ArraySchema (new DateTimeSchema ()))->minContains ($ dateTime2Equal , 2 , false );
593+
594+ try {
595+ (new ArraySchema (new DateTimeSchema ()))->minContains ($ dateTime2Equal , 2 )->parse ($ input );
596+
597+ throw new \Exception ('code should not be reached ' );
598+ } catch (ErrorsException $ errorsException ) {
599+ self ::assertSame (
600+ [
601+ [
602+ 'path ' => '' ,
603+ 'error ' => [
604+ 'code ' => 'array.minContains ' ,
605+ 'template ' => '{{given}} contains {{contains}} {{containsCount}} times, min {{minContains}} required ' ,
606+ 'variables ' => [
607+ 'contains ' => json_decode (json_encode ($ dateTime2Equal ), true ),
608+ 'containsCount ' => 0 ,
609+ 'given ' => json_decode (json_encode ($ input ), true ),
610+ 'minContains ' => 2 ,
611+ ],
612+ ],
613+ ],
614+ ],
615+ $ errorsException ->errors ->jsonSerialize ()
616+ );
617+ }
618+
619+ self ::assertSame ($ input , $ schema ->parse ($ input ));
620+ }
621+
622+ public function testParseWithInvalidMinContains (): void
623+ {
624+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
625+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
626+
627+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime1 ];
628+
629+ $ schema = (new ArraySchema (new DateTimeSchema ()))->minContains ($ dateTime2 , 2 );
630+
631+ try {
632+ $ schema ->parse ($ input );
633+
634+ throw new \Exception ('code should not be reached ' );
635+ } catch (ErrorsException $ errorsException ) {
636+ self ::assertSame (
637+ [
638+ [
639+ 'path ' => '' ,
640+ 'error ' => [
641+ 'code ' => 'array.minContains ' ,
642+ 'template ' => '{{given}} contains {{contains}} {{containsCount}} times, min {{minContains}} required ' ,
643+ 'variables ' => [
644+ 'contains ' => json_decode (json_encode ($ dateTime2 ), true ),
645+ 'containsCount ' => 1 ,
646+ 'given ' => json_decode (json_encode ($ input ), true ),
647+ 'minContains ' => 2 ,
648+ ],
649+ ],
650+ ],
651+ ],
652+ $ errorsException ->errors ->jsonSerialize ()
653+ );
654+ }
655+ }
656+
657+ public function testParseWithValidMaxContains (): void
658+ {
659+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
660+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
661+
662+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime2 ];
663+
664+ $ schema = (new ArraySchema (new DateTimeSchema ()))->maxContains ($ dateTime2 , 2 );
665+
666+ self ::assertSame ($ input , $ schema ->parse ($ input ));
667+ }
668+
669+ public function testParseWithValidMaxContainsWithEqualButNotSame (): void
670+ {
671+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
672+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
673+
674+ $ dateTime2Equal = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
675+
676+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime2Equal ];
677+
678+ $ schema = (new ArraySchema (new DateTimeSchema ()))->maxContains ($ dateTime2Equal , 2 , false );
679+
680+ self ::assertSame ($ input , $ schema ->parse ($ input ));
681+ }
682+
683+ public function testParseWithInvalidMaxContainsWithEqualButNotSameAndStrictFalse (): void
684+ {
685+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
686+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
687+
688+ $ dateTime2Equal = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
689+
690+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime2Equal ];
691+
692+ $ schema = (new ArraySchema (new DateTimeSchema ()))->maxContains ($ dateTime2Equal , 1 , false );
693+
694+ self ::assertSame ($ input , (new ArraySchema (new DateTimeSchema ()))->maxContains ($ dateTime2Equal , 1 )->parse ($ input ));
695+
696+ try {
697+ $ schema ->parse ($ input );
698+
699+ throw new \Exception ('code should not be reached ' );
700+ } catch (ErrorsException $ errorsException ) {
701+ self ::assertSame (
702+ [
703+ [
704+ 'path ' => '' ,
705+ 'error ' => [
706+ 'code ' => 'array.maxContains ' ,
707+ 'template ' => '{{given}} contains {{contains}} {{containsCount}} times, max {{maxContains}} allowed ' ,
708+ 'variables ' => [
709+ 'contains ' => json_decode (json_encode ($ dateTime2Equal ), true ),
710+ 'containsCount ' => 2 ,
711+ 'given ' => json_decode (json_encode ($ input ), true ),
712+ 'maxContains ' => 1 ,
713+ ],
714+ ],
715+ ],
716+ ],
717+ $ errorsException ->errors ->jsonSerialize ()
718+ );
719+ }
720+ }
721+
722+ public function testParseWithInvalidMaxContains (): void
723+ {
724+ $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
725+ $ dateTime2 = new \DateTimeImmutable ('2024-01-21T09:15:00+00:00 ' );
726+
727+ $ input = [$ dateTime1 , $ dateTime2 , $ dateTime2 , $ dateTime2 , $ dateTime2 ];
728+
729+ $ schema = (new ArraySchema (new DateTimeSchema ()))->maxContains ($ dateTime2 , 2 );
730+
731+ try {
732+ $ schema ->parse ($ input );
733+
734+ throw new \Exception ('code should not be reached ' );
735+ } catch (ErrorsException $ errorsException ) {
736+ self ::assertSame (
737+ [
738+ [
739+ 'path ' => '' ,
740+ 'error ' => [
741+ 'code ' => 'array.maxContains ' ,
742+ 'template ' => '{{given}} contains {{contains}} {{containsCount}} times, max {{maxContains}} allowed ' ,
743+ 'variables ' => [
744+ 'contains ' => json_decode (json_encode ($ dateTime2 ), true ),
745+ 'containsCount ' => 4 ,
746+ 'given ' => json_decode (json_encode ($ input ), true ),
747+ 'maxContains ' => 2 ,
748+ ],
749+ ],
750+ ],
751+ ],
752+ $ errorsException ->errors ->jsonSerialize ()
753+ );
754+ }
755+ }
756+
553757 public function testParseWithValidIncludes (): void
554758 {
555759 $ dateTime1 = new \DateTimeImmutable ('2024-01-20T09:15:00+00:00 ' );
0 commit comments