@@ -657,18 +657,20 @@ public function testGetCardIdFailed(): void {
657657 }
658658
659659 #[\PHPUnit \Framework \Attributes \DataProvider(methodName: 'dataTestSearch ' )]
660- public function testSearch (string $ pattern , array $ properties , array $ options , array $ expected ): void {
661- /** @var VCard $vCards */
660+ public function testSearch (string $ pattern , array $ properties , array $ options , array $ expectedUris , array $ expectedNeedles ): void {
662661 $ vCards = [];
662+
663663 $ vCards [0 ] = new VCard ();
664- $ vCards [0 ]->add (new Text ($ vCards [0 ], 'UID ' , 'uid ' ));
664+ $ vCards [0 ]->add (new Text ($ vCards [0 ], 'UID ' , 'uid-0 ' ));
665665 $ vCards [0 ]->add (new Text ($ vCards [0 ], 'FN ' , 'John Doe ' ));
666666 $ vCards [0 ]->add (new Text ($ vCards [0 ], 'CLOUD ' , 'john@nextcloud.com ' ));
667+
667668 $ vCards [1 ] = new VCard ();
668- $ vCards [1 ]->add (new Text ($ vCards [1 ], 'UID ' , 'uid ' ));
669+ $ vCards [1 ]->add (new Text ($ vCards [1 ], 'UID ' , 'uid-1 ' ));
669670 $ vCards [1 ]->add (new Text ($ vCards [1 ], 'FN ' , 'John M. Doe ' ));
671+
670672 $ vCards [2 ] = new VCard ();
671- $ vCards [2 ]->add (new Text ($ vCards [2 ], 'UID ' , 'uid ' ));
673+ $ vCards [2 ]->add (new Text ($ vCards [2 ], 'UID ' , 'uid-2 ' ));
672674 $ vCards [2 ]->add (new Text ($ vCards [2 ], 'FN ' , 'find without options ' ));
673675 $ vCards [2 ]->add (new Text ($ vCards [2 ], 'CLOUD ' , 'peter_pan@nextcloud.com ' ));
674676
@@ -690,95 +692,117 @@ public function testSearch(string $pattern, array $properties, array $options, a
690692 $ vCardIds [] = $ query ->getLastInsertId ();
691693 }
692694
693- $ query = $ this ->db ->getQueryBuilder ();
694- $ query ->insert ($ this ->dbCardsPropertiesTable )
695- ->values (
696- [
697- 'addressbookid ' => $ query ->createNamedParameter (0 ),
698- 'cardid ' => $ query ->createNamedParameter ($ vCardIds [0 ]),
699- 'name ' => $ query ->createNamedParameter ('FN ' ),
700- 'value ' => $ query ->createNamedParameter ('John Doe ' ),
701- 'preferred ' => $ query ->createNamedParameter (0 )
702- ]
703- );
704- $ query ->executeStatement ();
705- $ query = $ this ->db ->getQueryBuilder ();
706- $ query ->insert ($ this ->dbCardsPropertiesTable )
707- ->values (
708- [
709- 'addressbookid ' => $ query ->createNamedParameter (0 ),
710- 'cardid ' => $ query ->createNamedParameter ($ vCardIds [0 ]),
711- 'name ' => $ query ->createNamedParameter ('CLOUD ' ),
712- 'value ' => $ query ->createNamedParameter ('John@nextcloud.com ' ),
713- 'preferred ' => $ query ->createNamedParameter (0 )
714- ]
715- );
716- $ query ->executeStatement ();
717- $ query = $ this ->db ->getQueryBuilder ();
718- $ query ->insert ($ this ->dbCardsPropertiesTable )
719- ->values (
720- [
721- 'addressbookid ' => $ query ->createNamedParameter (0 ),
722- 'cardid ' => $ query ->createNamedParameter ($ vCardIds [1 ]),
723- 'name ' => $ query ->createNamedParameter ('FN ' ),
724- 'value ' => $ query ->createNamedParameter ('John M. Doe ' ),
725- 'preferred ' => $ query ->createNamedParameter (0 )
726- ]
727- );
728- $ query ->executeStatement ();
729- $ query = $ this ->db ->getQueryBuilder ();
730- $ query ->insert ($ this ->dbCardsPropertiesTable )
731- ->values (
732- [
733- 'addressbookid ' => $ query ->createNamedParameter (0 ),
734- 'cardid ' => $ query ->createNamedParameter ($ vCardIds [2 ]),
735- 'name ' => $ query ->createNamedParameter ('FN ' ),
736- 'value ' => $ query ->createNamedParameter ('find without options ' ),
737- 'preferred ' => $ query ->createNamedParameter (0 )
738- ]
739- );
740- $ query ->executeStatement ();
741- $ query = $ this ->db ->getQueryBuilder ();
742- $ query ->insert ($ this ->dbCardsPropertiesTable )
743- ->values (
744- [
745- 'addressbookid ' => $ query ->createNamedParameter (0 ),
746- 'cardid ' => $ query ->createNamedParameter ($ vCardIds [2 ]),
747- 'name ' => $ query ->createNamedParameter ('CLOUD ' ),
748- 'value ' => $ query ->createNamedParameter ('peter_pan@nextcloud.com ' ),
749- 'preferred ' => $ query ->createNamedParameter (0 )
750- ]
751- );
752- $ query ->executeStatement ();
695+ $ propertyRows = [
696+ [$ vCardIds [0 ], 'FN ' , 'John Doe ' ],
697+ [$ vCardIds [0 ], 'CLOUD ' , 'John@nextcloud.com ' ],
698+ [$ vCardIds [1 ], 'FN ' , 'John M. Doe ' ],
699+ [$ vCardIds [2 ], 'FN ' , 'find without options ' ],
700+ [$ vCardIds [2 ], 'CLOUD ' , 'peter_pan@nextcloud.com ' ],
701+ ];
702+
703+ foreach ($ propertyRows as [$ cardId , $ name , $ value ]) {
704+ $ query = $ this ->db ->getQueryBuilder ();
705+ $ query ->insert ($ this ->dbCardsPropertiesTable )
706+ ->values (
707+ [
708+ 'addressbookid ' => $ query ->createNamedParameter (0 ),
709+ 'cardid ' => $ query ->createNamedParameter ($ cardId ),
710+ 'name ' => $ query ->createNamedParameter ($ name ),
711+ 'value ' => $ query ->createNamedParameter ($ value ),
712+ 'preferred ' => $ query ->createNamedParameter (0 ),
713+ ]
714+ );
715+ $ query ->executeStatement ();
716+ }
753717
754718 $ result = $ this ->backend ->search (0 , $ pattern , $ properties , $ options );
755719
756- // check result
757- $ this ->assertSame (count ($ expected ), count ($ result ));
758- $ found = [];
759- foreach ($ result as $ r ) {
760- foreach ($ expected as $ exp ) {
761- if ($ r ['uri ' ] === $ exp [0 ] && strpos ($ r ['carddata ' ], $ exp [1 ]) > 0 ) {
762- $ found [$ exp [1 ]] = true ;
763- break ;
764- }
765- }
766- }
720+ $ this ->assertCount (count ($ expectedUris ), $ result );
721+
722+ $ actualUris = array_map (static fn (array $ row ): string => $ row ['uri ' ], $ result );
723+ sort ($ actualUris );
724+ $ expectedSortedUris = $ expectedUris ;
725+ sort ($ expectedSortedUris );
726+
727+ $ this ->assertSame ($ expectedSortedUris , $ actualUris , 'Search returned unexpected URIs ' );
767728
768- $ this ->assertSame (count ($ expected ), count ($ found ));
729+ $ expectedByUri = array_combine ($ expectedUris , $ expectedNeedles );
730+ $ this ->assertIsArray ($ expectedByUri );
731+
732+ foreach ($ result as $ row ) {
733+ $ this ->assertArrayHasKey ($ row ['uri ' ], $ expectedByUri , 'Unexpected URI in search result ' );
734+ $ this ->assertNotFalse (
735+ strpos ($ row ['carddata ' ], $ expectedByUri [$ row ['uri ' ]]),
736+ 'Returned carddata does not contain expected fragment for ' . $ row ['uri ' ]
737+ );
738+ }
769739 }
770740
771741 public static function dataTestSearch (): array {
772742 return [
773- ['John ' , ['FN ' ], [], [['uri0 ' , 'John Doe ' ], ['uri1 ' , 'John M. Doe ' ]]],
774- ['M. Doe ' , ['FN ' ], [], [['uri1 ' , 'John M. Doe ' ]]],
775- ['Do ' , ['FN ' ], [], [['uri0 ' , 'John Doe ' ], ['uri1 ' , 'John M. Doe ' ]]],
776- 'check if duplicates are handled correctly ' => ['John ' , ['FN ' , 'CLOUD ' ], [], [['uri0 ' , 'John Doe ' ], ['uri1 ' , 'John M. Doe ' ]]],
777- 'case insensitive ' => ['john ' , ['FN ' ], [], [['uri0 ' , 'John Doe ' ], ['uri1 ' , 'John M. Doe ' ]]],
778- 'limit ' => ['john ' , ['FN ' ], ['limit ' => 1 ], [['uri0 ' , 'John Doe ' ]]],
779- 'limit and offset ' => ['john ' , ['FN ' ], ['limit ' => 1 , 'offset ' => 1 ], [['uri1 ' , 'John M. Doe ' ]]],
780- 'find "_" escaped ' => ['_ ' , ['CLOUD ' ], [], [['uri2 ' , 'find without options ' ]]],
781- 'find not empty CLOUD ' => ['%_% ' , ['CLOUD ' ], ['escape_like_param ' => false ], [['uri0 ' , 'John Doe ' ], ['uri2 ' , 'find without options ' ]]],
743+ 'basic FN match ' => [
744+ 'pattern ' => 'John ' ,
745+ 'properties ' => ['FN ' ],
746+ 'options ' => [],
747+ 'expectedUris ' => ['uri0 ' , 'uri1 ' ],
748+ 'expectedNeedles ' => ['John Doe ' , 'John M. Doe ' ],
749+ ],
750+ 'partial FN match ' => [
751+ 'pattern ' => 'M. Doe ' ,
752+ 'properties ' => ['FN ' ],
753+ 'options ' => [],
754+ 'expectedUris ' => ['uri1 ' ],
755+ 'expectedNeedles ' => ['John M. Doe ' ],
756+ ],
757+ 'substring FN match ' => [
758+ 'pattern ' => 'Do ' ,
759+ 'properties ' => ['FN ' ],
760+ 'options ' => [],
761+ 'expectedUris ' => ['uri0 ' , 'uri1 ' ],
762+ 'expectedNeedles ' => ['John Doe ' , 'John M. Doe ' ],
763+ ],
764+ 'search across multiple properties returns one result per card ' => [
765+ 'pattern ' => 'John ' ,
766+ 'properties ' => ['FN ' , 'CLOUD ' ],
767+ 'options ' => [],
768+ 'expectedUris ' => ['uri0 ' , 'uri1 ' ],
769+ 'expectedNeedles ' => ['John Doe ' , 'John M. Doe ' ],
770+ ],
771+ 'case-insensitive search ' => [
772+ 'pattern ' => 'john ' ,
773+ 'properties ' => ['FN ' ],
774+ 'options ' => [],
775+ 'expectedUris ' => ['uri0 ' , 'uri1 ' ],
776+ 'expectedNeedles ' => ['John Doe ' , 'John M. Doe ' ],
777+ ],
778+ 'limit ' => [
779+ 'pattern ' => 'john ' ,
780+ 'properties ' => ['FN ' ],
781+ 'options ' => ['limit ' => 1 ],
782+ 'expectedUris ' => ['uri0 ' ],
783+ 'expectedNeedles ' => ['John Doe ' ],
784+ ],
785+ 'limit with offset ' => [
786+ 'pattern ' => 'john ' ,
787+ 'properties ' => ['FN ' ],
788+ 'options ' => ['limit ' => 1 , 'offset ' => 1 ],
789+ 'expectedUris ' => ['uri1 ' ],
790+ 'expectedNeedles ' => ['John M. Doe ' ],
791+ ],
792+ 'underscore is escaped by default ' => [
793+ 'pattern ' => '_ ' ,
794+ 'properties ' => ['CLOUD ' ],
795+ 'options ' => [],
796+ 'expectedUris ' => ['uri2 ' ],
797+ 'expectedNeedles ' => ['find without options ' ],
798+ ],
799+ 'underscore wildcard search when escape_like_param is false ' => [
800+ 'pattern ' => '%_% ' ,
801+ 'properties ' => ['CLOUD ' ],
802+ 'options ' => ['escape_like_param ' => false ],
803+ 'expectedUris ' => ['uri0 ' , 'uri2 ' ],
804+ 'expectedNeedles ' => ['John Doe ' , 'find without options ' ],
805+ ],
782806 ];
783807 }
784808
0 commit comments