Skip to content

Commit cc478a8

Browse files
committed
Add unit tests on search index operations
1 parent 872f4ba commit cc478a8

11 files changed

+191
-16
lines changed

psalm-baseline.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
<code>($value is NativeType ? BSONType : $value)</code>
2929
</MixedInferredReturnType>
3030
</file>
31+
<file src="src/Collection.php">
32+
<MixedInferredReturnType>
33+
<code>Traversable</code>
34+
</MixedInferredReturnType>
35+
<UndefinedClass>
36+
<code>Traversable</code>
37+
</UndefinedClass>
38+
</file>
3139
<file src="src/Command/ListCollections.php">
3240
<MixedAssignment>
3341
<code>$cmd[$option]</code>
@@ -168,6 +176,14 @@
168176
<code><![CDATA[$this->index['name']]]></code>
169177
</MixedReturnStatement>
170178
</file>
179+
<file src="src/Model/SearchIndexInput.php">
180+
<MixedReturnStatement>
181+
<code><![CDATA[$this->index['name']]]></code>
182+
</MixedReturnStatement>
183+
<PossiblyInvalidPropertyFetch>
184+
<code><![CDATA[$index['definition']->mappings]]></code>
185+
</PossiblyInvalidPropertyFetch>
186+
</file>
171187
<file src="src/Operation/Aggregate.php">
172188
<MixedArgument>
173189
<code><![CDATA[$this->options['typeMap']]]></code>
@@ -309,6 +325,11 @@
309325
<code>isInTransaction</code>
310326
</MixedMethodCall>
311327
</file>
328+
<file src="src/Operation/CreateSearchIndexes.php">
329+
<MixedArgumentTypeCoercion>
330+
<code>$index</code>
331+
</MixedArgumentTypeCoercion>
332+
</file>
312333
<file src="src/Operation/DatabaseCommand.php">
313334
<MixedArgument>
314335
<code><![CDATA[$this->options['typeMap']]]></code>
@@ -537,6 +558,14 @@
537558
<code>isInTransaction</code>
538559
</MixedMethodCall>
539560
</file>
561+
<file src="src/Operation/UpdateSearchIndex.php">
562+
<MixedAssignment>
563+
<code><![CDATA[$this->definition]]></code>
564+
</MixedAssignment>
565+
<RedundantConditionGivenDocblockType>
566+
<code>! is_object($definition)</code>
567+
</RedundantConditionGivenDocblockType>
568+
</file>
540569
<file src="src/Operation/Watch.php">
541570
<MixedArgument>
542571
<code><![CDATA[$reply->cursor->firstBatch]]></code>

src/Model/SearchIndexInput.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use function is_array;
2424
use function is_object;
2525
use function is_string;
26+
use function sprintf;
2627

2728
/**
2829
* Search index input model class.
@@ -40,7 +41,7 @@ class SearchIndexInput implements Serializable
4041
private $index;
4142

4243
/**
43-
* @param array{name: string, definition: array|string} $index Search index specification
44+
* @param array{name: string, definition: array|object} $index Search index specification
4445
* @throws InvalidArgumentException
4546
*/
4647
public function __construct(array $index)
@@ -65,6 +66,10 @@ public function __construct(array $index)
6566
throw InvalidArgumentException::invalidType('"definition" option', $index['definition'], 'array or object');
6667
}
6768

69+
if (! isset($index['definition']['mappings']) && ! isset($index['definition']->mappings)) {
70+
throw new InvalidArgumentException(sprintf('Required "mappings" document is missing from the search index definition named "%s".', $index['name']));
71+
}
72+
6873
$this->index = $index;
6974
}
7075

src/Operation/ListSearchIndexes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function __construct(string $databaseName, string $collectionName, $filte
7070

7171
$filter = document_to_array($filter);
7272

73-
if (isset($filter['name']) && ! is_string($options['name'])) {
73+
if (isset($filter['name']) && ! is_string($filter['name'])) {
7474
throw InvalidArgumentException::invalidType('"name" filter', $filter['name'], 'string');
7575
}
7676

tests/Operation/BulkWriteTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,6 @@ public function testDeleteManyCollationOptionTypeCheck($collation): void
9292
]);
9393
}
9494

95-
public function provideInvalidDocumentValues()
96-
{
97-
return $this->wrapValuesForDataProvider($this->getInvalidDocumentValues());
98-
}
99-
10095
public function testDeleteOneFilterArgumentMissing(): void
10196
{
10297
$this->expectException(InvalidArgumentException::class);

tests/Operation/CreateIndexesTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,4 @@ public function testConstructorRequiresIndexSpecificationNameToBeString($name):
9898
$this->expectExceptionMessage('Expected "name" option to have type "string"');
9999
new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [['key' => ['x' => 1], 'name' => $name]]);
100100
}
101-
102-
public function provideInvalidStringValues()
103-
{
104-
return $this->wrapValuesForDataProvider($this->getInvalidStringValues());
105-
}
106101
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Operation;
4+
5+
use MongoDB\Exception\InvalidArgumentException;
6+
use MongoDB\Operation\CreateSearchIndexes;
7+
8+
class CreateSearchIndexesTest extends TestCase
9+
{
10+
public function testConstructorIndexesArgumentMustBeAList(): void
11+
{
12+
$this->expectException(InvalidArgumentException::class);
13+
$this->expectExceptionMessage('$indexes is not a list');
14+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [1 => ['name' => 'index name', 'definition' => ['mappings' => ['dynamic' => true]]]]);
15+
}
16+
17+
public function testConstructorRequiresAtLeastOneIndex(): void
18+
{
19+
$this->expectException(InvalidArgumentException::class);
20+
$this->expectExceptionMessage('$indexes is empty');
21+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), []);
22+
}
23+
24+
/** @dataProvider provideInvalidIndexSpecificationTypes */
25+
public function testConstructorRequiresIndexSpecificationsToBeAnArray($index): void
26+
{
27+
$this->expectException(InvalidArgumentException::class);
28+
$this->expectExceptionMessage('Expected $index[0] to have type "array"');
29+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [$index]);
30+
}
31+
32+
public function testConstructorRequiresSearchIndexName(): void
33+
{
34+
$this->expectException(InvalidArgumentException::class);
35+
$this->expectExceptionMessage('Required "name" string is missing from index specification');
36+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [[]]);
37+
}
38+
39+
/** @dataProvider provideInvalidStringValues */
40+
public function testConstructorRequiresSearchIndexNameToBeAString($name): void
41+
{
42+
$this->expectException(InvalidArgumentException::class);
43+
$this->expectExceptionMessage('Expected "name" option to have type "string"');
44+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [['name' => $name]]);
45+
}
46+
47+
public function testConstructorRequiresSearchIndexDefinitionToBeDefined(): void
48+
{
49+
$this->expectException(InvalidArgumentException::class);
50+
$this->expectExceptionMessage('Required "definition" document is missing from search index specification');
51+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [['name' => 'index name']]);
52+
}
53+
54+
/** @dataProvider provideInvalidDocumentValues */
55+
public function testConstructorRequiresSearchIndexDefinitionToBeAnArray($definition): void
56+
{
57+
$this->expectException(InvalidArgumentException::class);
58+
$this->expectExceptionMessage('Expected "definition" option to have type "array or object"');
59+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [['name' => 'index name', 'definition' => $definition]]);
60+
}
61+
62+
public function testConstructorRequiresSearchIndexDefinitionToContainMappings(): void
63+
{
64+
$this->expectException(InvalidArgumentException::class);
65+
$this->expectExceptionMessage('Required "mappings" document is missing from the search index definition named "index name".');
66+
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [['name' => 'index name', 'definition' => ['foo' => 'bar']]]);
67+
}
68+
69+
public function provideInvalidIndexSpecificationTypes()
70+
{
71+
return $this->wrapValuesForDataProvider($this->getInvalidArrayValues());
72+
}
73+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Operation;
4+
5+
use MongoDB\Exception\InvalidArgumentException;
6+
use MongoDB\Operation\DropSearchIndex;
7+
8+
class DropSearchIndexTest extends TestCase
9+
{
10+
public function testConstructorRequiresANotEmptyIndexName(): void
11+
{
12+
$this->expectException(InvalidArgumentException::class);
13+
new DropSearchIndex($this->getDatabaseName(), $this->getCollectionName(), '');
14+
}
15+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Operation;
4+
5+
use MongoDB\Exception\InvalidArgumentException;
6+
use MongoDB\Operation\ListSearchIndexes;
7+
8+
class ListSearchIndexesTest extends TestCase
9+
{
10+
/** @dataProvider provideInvalidStringValues */
11+
public function testConstructorExpectNameFilterToBeAString($name): void
12+
{
13+
$this->expectException(InvalidArgumentException::class);
14+
$this->expectExceptionMessage('Expected "name" filter to have type "string"');
15+
new ListSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), ['name' => $name]);
16+
}
17+
18+
/** @dataProvider provideInvalidConstructorOptions */
19+
public function testConstructorOptionTypeChecks(array $options): void
20+
{
21+
$this->expectException(InvalidArgumentException::class);
22+
new ListSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [], $options);
23+
}
24+
25+
public function provideInvalidConstructorOptions(): array
26+
{
27+
$options = [];
28+
29+
foreach ($this->getInvalidIntegerValues() as $value) {
30+
$options[][] = ['batchSize' => $value];
31+
}
32+
33+
return $options;
34+
}
35+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Operation;
4+
5+
use MongoDB\Exception\InvalidArgumentException;
6+
use MongoDB\Operation\UpdateSearchIndex;
7+
8+
class UpdateSearchIndexTest extends TestCase
9+
{
10+
public function testConstructorRequiresANotEmptyIndexName(): void
11+
{
12+
$this->expectException(InvalidArgumentException::class);
13+
new UpdateSearchIndex($this->getDatabaseName(), $this->getCollectionName(), '', []);
14+
}
15+
16+
/** @dataProvider provideInvalidDocumentValues */
17+
public function testConstructorRequiresSearchIndexDefinitionToBeADocument($definition): void
18+
{
19+
$this->expectException(InvalidArgumentException::class);
20+
$this->expectExceptionMessage('Expected $definition to have type "array or object"');
21+
new UpdateSearchIndex($this->getDatabaseName(), $this->getCollectionName(), 'index name', $definition);
22+
}
23+
}

tests/TestCase.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,21 +164,26 @@ public function dataDescription(): string
164164
return is_string($dataName) ? $dataName : '';
165165
}
166166

167-
public function provideInvalidArrayValues()
167+
public function provideInvalidArrayValues(): array
168168
{
169169
return $this->wrapValuesForDataProvider($this->getInvalidArrayValues());
170170
}
171171

172-
public function provideInvalidDocumentValues()
172+
public function provideInvalidDocumentValues(): array
173173
{
174174
return $this->wrapValuesForDataProvider($this->getInvalidDocumentValues());
175175
}
176176

177-
public function provideInvalidIntegerValues()
177+
public function provideInvalidIntegerValues(): array
178178
{
179179
return $this->wrapValuesForDataProvider($this->getInvalidIntegerValues());
180180
}
181181

182+
public function provideInvalidStringValues(): array
183+
{
184+
return $this->wrapValuesForDataProvider($this->getInvalidStringValues());
185+
}
186+
182187
protected function assertDeprecated(callable $execution): void
183188
{
184189
$errors = [];

tests/UnifiedSpecTests/Operation.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ private function executeForCollection(Collection $collection)
563563
return $collection->updateSearchIndex($args['name'], $args['definition']);
564564

565565
case 'listSearchIndexes':
566-
return $collection->listSearchIndexes($args['name'] ?? '', document_to_array($args['aggregationOptions'] ?? []), document_to_array(($args['listIndexOptions'] ?? [])));
566+
return $collection->listSearchIndexes($args['name'] ?? '', document_to_array($args['aggregationOptions'] ?? []));
567567

568568
default:
569569
Assert::fail('Unsupported collection operation: ' . $this->name);

0 commit comments

Comments
 (0)