Skip to content

Commit ac961a7

Browse files
authored
Merge pull request #60463 from nextcloud/jtr/test-carddav-search
test(carddav): refactor testSearch to use clearer assertions and unique UIDs
2 parents 3ab181d + 4a9022a commit ac961a7

1 file changed

Lines changed: 110 additions & 86 deletions

File tree

apps/dav/tests/unit/CardDAV/CardDavBackendTest.php

Lines changed: 110 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)