Skip to content

Commit a5e8a52

Browse files
committed
Add fake document manager
1 parent c86582e commit a5e8a52

4 files changed

Lines changed: 296 additions & 4 deletions

File tree

src/Documents/DocumentManager.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* @see https://docs.opensearch.org/latest/api-reference/document-apis/delete-by-query/
1313
* @see https://docs.opensearch.org/latest/api-reference/search-apis/search/
1414
*/
15-
class DocumentManager
15+
class DocumentManager implements DocumentManagerInterface
1616
{
1717
/**
1818
* Create a new document manager instance.
@@ -28,7 +28,7 @@ public function __construct(
2828
*
2929
* @throws BulkRequestException
3030
*/
31-
public function index(string $index, array $documents, bool $refresh = false, ?DocumentRouting $routing = null): self
31+
public function index(string $index, array $documents, bool $refresh = false, ?DocumentRouting $routing = null): static
3232
{
3333
$params = [
3434
'index' => $index,
@@ -59,7 +59,7 @@ public function index(string $index, array $documents, bool $refresh = false, ?D
5959
*
6060
* @throws BulkRequestException
6161
*/
62-
public function delete(string $index, array $ids, bool $refresh = false, ?DocumentRouting $routing = null): self
62+
public function delete(string $index, array $ids, bool $refresh = false, ?DocumentRouting $routing = null): static
6363
{
6464
$params = [
6565
'index' => $index,
@@ -91,7 +91,7 @@ public function delete(string $index, array $ids, bool $refresh = false, ?Docume
9191
*
9292
* @param array<string, mixed> $query
9393
*/
94-
public function deleteByQuery(string $index, array $query, bool $refresh = false): self
94+
public function deleteByQuery(string $index, array $query, bool $refresh = false): static
9595
{
9696
$this->client->deleteByQuery([
9797
'index' => $index,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace DirectoryTree\OpenSearchAdapter\Documents;
4+
5+
use DirectoryTree\OpenSearchAdapter\Exceptions\BulkRequestException;
6+
use DirectoryTree\OpenSearchAdapter\Search\SearchRequest;
7+
use DirectoryTree\OpenSearchAdapter\Search\SearchResponse;
8+
9+
/**
10+
* Manages OpenSearch documents.
11+
*/
12+
interface DocumentManagerInterface
13+
{
14+
/**
15+
* Index the given documents into OpenSearch.
16+
*
17+
* @param array<int, Document> $documents
18+
*
19+
* @throws BulkRequestException
20+
*/
21+
public function index(string $index, array $documents, bool $refresh = false, ?DocumentRouting $routing = null): static;
22+
23+
/**
24+
* Delete the given documents from OpenSearch.
25+
*
26+
* @param array<int, string> $ids
27+
*
28+
* @throws BulkRequestException
29+
*/
30+
public function delete(string $index, array $ids, bool $refresh = false, ?DocumentRouting $routing = null): static;
31+
32+
/**
33+
* Delete documents that match the given OpenSearch query.
34+
*
35+
* @param array<string, mixed> $query
36+
*/
37+
public function deleteByQuery(string $index, array $query, bool $refresh = false): static;
38+
39+
/**
40+
* Search an index using the given search request.
41+
*/
42+
public function search(string $index, SearchRequest $request): SearchResponse;
43+
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<?php
2+
3+
namespace DirectoryTree\OpenSearchAdapter\Testing\Fakes;
4+
5+
use DirectoryTree\OpenSearchAdapter\Documents\Document;
6+
use DirectoryTree\OpenSearchAdapter\Documents\DocumentManagerInterface;
7+
use DirectoryTree\OpenSearchAdapter\Documents\DocumentRouting;
8+
use DirectoryTree\OpenSearchAdapter\Search\SearchRequest;
9+
use DirectoryTree\OpenSearchAdapter\Search\SearchResponse;
10+
use PHPUnit\Framework\Assert as PHPUnit;
11+
12+
/**
13+
* Fakes OpenSearch document operations for tests.
14+
*/
15+
class FakeDocumentManager implements DocumentManagerInterface
16+
{
17+
/**
18+
* The indexed document operations.
19+
*
20+
* @var array<int, array{index: string, documents: array<int, Document>, refresh: bool, routing: DocumentRouting|null}>
21+
*/
22+
protected array $indexed = [];
23+
24+
/**
25+
* The deleted document operations.
26+
*
27+
* @var array<int, array{index: string, ids: array<int, string>, refresh: bool, routing: DocumentRouting|null}>
28+
*/
29+
protected array $deleted = [];
30+
31+
/**
32+
* The delete by query operations.
33+
*
34+
* @var array<int, array{index: string, query: array<string, mixed>, refresh: bool}>
35+
*/
36+
protected array $deletedByQuery = [];
37+
38+
/**
39+
* The search operations.
40+
*
41+
* @var array<int, array{index: string, request: SearchRequest}>
42+
*/
43+
protected array $searched = [];
44+
45+
/**
46+
* The response that should be returned for searches.
47+
*/
48+
protected SearchResponse $response;
49+
50+
/**
51+
* Create a new fake document manager instance.
52+
*/
53+
public function __construct()
54+
{
55+
$this->response = new SearchResponse([
56+
'hits' => [
57+
'hits' => [],
58+
],
59+
]);
60+
}
61+
62+
/**
63+
* Set the search response returned by the fake.
64+
*/
65+
public function respondWith(SearchResponse $response): static
66+
{
67+
$this->response = $response;
68+
69+
return $this;
70+
}
71+
72+
/**
73+
* Index the given documents into OpenSearch.
74+
*
75+
* @param array<int, Document> $documents
76+
*/
77+
public function index(string $index, array $documents, bool $refresh = false, ?DocumentRouting $routing = null): static
78+
{
79+
$this->indexed[] = compact('index', 'documents', 'refresh', 'routing');
80+
81+
return $this;
82+
}
83+
84+
/**
85+
* Delete the given documents from OpenSearch.
86+
*
87+
* @param array<int, string> $ids
88+
*/
89+
public function delete(string $index, array $ids, bool $refresh = false, ?DocumentRouting $routing = null): static
90+
{
91+
$this->deleted[] = compact('index', 'ids', 'refresh', 'routing');
92+
93+
return $this;
94+
}
95+
96+
/**
97+
* Delete documents that match the given OpenSearch query.
98+
*
99+
* @param array<string, mixed> $query
100+
*/
101+
public function deleteByQuery(string $index, array $query, bool $refresh = false): static
102+
{
103+
$this->deletedByQuery[] = compact('index', 'query', 'refresh');
104+
105+
return $this;
106+
}
107+
108+
/**
109+
* Search an index using the given search request.
110+
*/
111+
public function search(string $index, SearchRequest $request): SearchResponse
112+
{
113+
$this->searched[] = compact('index', 'request');
114+
115+
return $this->response;
116+
}
117+
118+
/**
119+
* Assert that the given documents were indexed.
120+
*
121+
* @param array<int, Document> $documents
122+
*/
123+
public function assertIndexed(string $index, array $documents, bool $refresh = false, ?DocumentRouting $routing = null): static
124+
{
125+
PHPUnit::assertContainsEquals(compact('index', 'documents', 'refresh', 'routing'), $this->indexed);
126+
127+
return $this;
128+
}
129+
130+
/**
131+
* Assert that the given document IDs were deleted.
132+
*
133+
* @param array<int, string> $ids
134+
*/
135+
public function assertDeleted(string $index, array $ids, bool $refresh = false, ?DocumentRouting $routing = null): static
136+
{
137+
PHPUnit::assertContainsEquals(compact('index', 'ids', 'refresh', 'routing'), $this->deleted);
138+
139+
return $this;
140+
}
141+
142+
/**
143+
* Assert that the given query was deleted.
144+
*
145+
* @param array<string, mixed> $query
146+
*/
147+
public function assertDeletedByQuery(string $index, array $query, bool $refresh = false): static
148+
{
149+
PHPUnit::assertContainsEquals(compact('index', 'query', 'refresh'), $this->deletedByQuery);
150+
151+
return $this;
152+
}
153+
154+
/**
155+
* Assert that the given index was searched.
156+
*/
157+
public function assertSearched(string $index, SearchRequest $request): static
158+
{
159+
PHPUnit::assertContainsEquals(compact('index', 'request'), $this->searched);
160+
161+
return $this;
162+
}
163+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
use DirectoryTree\OpenSearchAdapter\Documents\Document;
4+
use DirectoryTree\OpenSearchAdapter\Documents\DocumentManagerInterface;
5+
use DirectoryTree\OpenSearchAdapter\Documents\DocumentRouting;
6+
use DirectoryTree\OpenSearchAdapter\Search\SearchRequest;
7+
use DirectoryTree\OpenSearchAdapter\Search\SearchResponse;
8+
use DirectoryTree\OpenSearchAdapter\Testing\Fakes\FakeDocumentManager;
9+
10+
test('fake document manager implements the document manager contract', function () {
11+
expect(new FakeDocumentManager)->toBeInstanceOf(DocumentManagerInterface::class);
12+
});
13+
14+
test('fake document manager records indexed documents', function () {
15+
$documents = [
16+
new Document('1', ['title' => 'First']),
17+
new Document('2', ['title' => 'Second']),
18+
];
19+
20+
$routing = DocumentRouting::make('1', 'tenant-1')
21+
->add('2', 'tenant-2');
22+
23+
$documentsManager = new FakeDocumentManager;
24+
25+
$documentsManager->index('posts', $documents, true, $routing);
26+
27+
$documentsManager->assertIndexed('posts', $documents, true, $routing);
28+
});
29+
30+
test('fake document manager records deleted documents', function () {
31+
$routing = DocumentRouting::make('1', 'tenant-1')
32+
->add('2', 'tenant-2');
33+
34+
$documents = new FakeDocumentManager;
35+
36+
$documents->delete('posts', ['1', '2'], true, $routing);
37+
38+
$documents->assertDeleted('posts', ['1', '2'], true, $routing);
39+
});
40+
41+
test('fake document manager records delete by query operations', function () {
42+
$documents = new FakeDocumentManager;
43+
44+
$documents->deleteByQuery('posts', $query = [
45+
'term' => [
46+
'status' => 'draft',
47+
],
48+
], true);
49+
50+
$documents->assertDeletedByQuery('posts', $query, true);
51+
});
52+
53+
test('fake document manager records searches and returns configured responses', function () {
54+
$documents = new FakeDocumentManager;
55+
$request = new SearchRequest([
56+
'match' => [
57+
'title' => 'OpenSearch',
58+
],
59+
]);
60+
61+
$response = new SearchResponse([
62+
'hits' => [
63+
'total' => [
64+
'value' => 1,
65+
'relation' => 'eq',
66+
],
67+
'hits' => [
68+
[
69+
'_id' => '1',
70+
'_index' => 'posts',
71+
'_source' => [
72+
'title' => 'OpenSearch',
73+
],
74+
],
75+
],
76+
],
77+
]);
78+
79+
$result = $documents
80+
->respondWith($response)
81+
->search('posts', $request);
82+
83+
expect($result)->toBe($response);
84+
85+
$documents->assertSearched('posts', $request);
86+
});

0 commit comments

Comments
 (0)