7
7
use DateTimeImmutable ;
8
8
use Illuminate \Database \Eloquent \Collection as EloquentCollection ;
9
9
use Laravel \Scout \Builder ;
10
+ use Laravel \Scout \Engines \MeilisearchEngine ;
11
+ use Laravel \Scout \Jobs \RemoveFromSearch ;
12
+ use Laravel \Scout \Tests \Unit \AlgoliaEngineTest ;
10
13
use Mockery as m ;
11
14
use MongoDB \BSON \Document ;
12
15
use MongoDB \BSON \Regex ;
20
23
use MongoDB \Model \BSONDocument ;
21
24
use PHPUnit \Framework \Attributes \DataProvider ;
22
25
26
+ use function serialize ;
27
+ use function unserialize ;
28
+
23
29
/** Unit tests that do not require an Atlas Search cluster */
24
30
class ScoutEngineTest extends TestCase
25
31
{
32
+ private const EXPECTED_SEARCH_OPTIONS = ['allowDiskUse ' => true , 'typeMap ' => ['root ' => 'object ' , 'document ' => 'array ' , 'array ' => 'array ' ]];
33
+
26
34
/** @param callable(): Builder $builder */
27
35
#[DataProvider('provideSearchPipelines ' )]
28
36
public function testSearch (Closure $ builder , array $ expectedPipeline ): void
@@ -36,8 +44,7 @@ public function testSearch(Closure $builder, array $expectedPipeline): void
36
44
$ cursor = m::mock (CursorInterface::class);
37
45
$ cursor ->shouldReceive ('toArray ' )->once ()->with ()->andReturn ($ data );
38
46
39
- $ options = ['allowDiskUse ' => true , 'typeMap ' => ['root ' => 'object ' , 'document ' => 'array ' , 'array ' => 'array ' ]];
40
- $ collection ->shouldReceive ('aggregate ' )->once ()->with ($ expectedPipeline , $ options )->andReturn ($ cursor );
47
+ $ collection ->shouldReceive ('aggregate ' )->once ()->with ($ expectedPipeline , self ::EXPECTED_SEARCH_OPTIONS )->andReturn ($ cursor );
41
48
42
49
$ engine = new ScoutEngine ($ database , softDelete: false , prefix: '' );
43
50
$ result = $ engine ->search ($ builder ());
@@ -157,6 +164,66 @@ function () {
157
164
158
165
public function testPaginate ()
159
166
{
167
+ $ perPage = 5 ;
168
+ $ page = 3 ;
169
+
170
+ $ database = m::mock (Database::class);
171
+ $ collection = m::mock (Collection::class);
172
+ $ cursor = m::mock (CursorInterface::class);
173
+ $ database ->shouldReceive ('selectCollection ' )
174
+ ->with ('table_searchable ' )
175
+ ->andReturn ($ collection );
176
+ $ collection ->shouldReceive ('aggregate ' )
177
+ ->once ()
178
+ ->withArgs (function (...$ args ) {
179
+ self ::assertSame ([
180
+ [
181
+ '$search ' => [
182
+ 'index ' => 'scout ' ,
183
+ 'text ' => [
184
+ 'query ' => 'mustang ' ,
185
+ 'path ' => [
186
+ 'wildcard ' => '* ' ,
187
+ ],
188
+ 'fuzzy ' => [
189
+ 'maxEdits ' => 2 ,
190
+ ],
191
+ ],
192
+ 'count ' => [
193
+ 'type ' => 'lowerBound ' ,
194
+ ],
195
+ 'sort ' => [
196
+ 'name ' => -1 ,
197
+ ],
198
+ ],
199
+ ],
200
+ [
201
+ '$addFields ' => [
202
+ 'search_meta ' => '$$SEARCH_META ' ,
203
+ ],
204
+ ],
205
+ [
206
+ '$limit ' => 5 ,
207
+ ],
208
+ [
209
+ '$skip ' => 10 ,
210
+ ],
211
+ ], $ args [0 ]);
212
+
213
+ $ this ->assertSame (self ::EXPECTED_SEARCH_OPTIONS , $ args [1 ]);
214
+
215
+ return true ;
216
+ })
217
+ ->andReturn ($ cursor );
218
+ $ cursor ->shouldReceive ('toArray ' )
219
+ ->once ()
220
+ ->with ()
221
+ ->andReturn ([['_id ' => 'key_1 ' ], ['_id ' => 'key_2 ' ]]);
222
+
223
+ $ engine = new ScoutEngine ($ database , softDelete: false , prefix: '' );
224
+ $ builder = new Builder (new SearchableModel (), 'mustang ' );
225
+ $ builder ->orderBy ('name ' , 'desc ' );
226
+ $ engine ->paginate ($ builder , $ perPage , $ page );
160
227
}
161
228
162
229
#[DataProvider('provideResultsForMapIds ' )]
@@ -254,18 +321,17 @@ public function testUpdateWithSoftDelete(): void
254
321
[
255
322
'updateOne ' => [
256
323
['_id ' => 'key_1 ' ],
257
- ['$setOnInsert ' => ['_id ' => 'key_1 ' ], '$set ' => ['id ' => 1 , ' date ' => new UTCDateTime ( $ date ) ]],
324
+ ['$setOnInsert ' => ['_id ' => 'key_1 ' ], '$set ' => ['id ' => 1 ]],
258
325
['upsert ' => true ],
259
326
],
260
327
],
261
328
]);
262
329
330
+ $ model = new SearchableModel (['id ' => 1 ]);
331
+ $ model ->delete ();
332
+
263
333
$ engine = new ScoutEngine ($ database , softDelete: false , prefix: '' );
264
- $ engine ->update (EloquentCollection::make ([
265
- (new SearchableModel ([
266
- 'id ' => 1 ,
267
- ])),
268
- ]));
334
+ $ engine ->update (EloquentCollection::make ([$ model ]));
269
335
}
270
336
271
337
public function testDelete (): void
@@ -286,6 +352,28 @@ public function testDelete(): void
286
352
]));
287
353
}
288
354
355
+ /** @see AlgoliaEngineTest::test_delete_with_removeable_scout_collection_using_custom_search_key */
356
+ public function testDeleteWithRemoveableScoutCollection (): void
357
+ {
358
+ $ job = new RemoveFromSearch (EloquentCollection::make ([
359
+ new SearchableModel (['id ' => 5 , 'scout_key ' => 'key_5 ' ]),
360
+ ]));
361
+
362
+ $ job = unserialize (serialize ($ job ));
363
+
364
+ $ database = m::mock (Database::class);
365
+ $ collection = m::mock (Collection::class);
366
+ $ database ->shouldReceive ('selectCollection ' )
367
+ ->with ('table_indexable ' )
368
+ ->andReturn ($ collection );
369
+ $ collection ->shouldReceive ('deleteMany ' )
370
+ ->once ()
371
+ ->with (['_id ' => ['$in ' => ['key_5 ' ]]]);
372
+
373
+ $ engine = new ScoutEngine ($ database , softDelete: false , prefix: 'ignored_prefix_ ' );
374
+ $ engine ->delete ($ job ->models );
375
+ }
376
+
289
377
public function testDeleteAll (): void
290
378
{
291
379
$ collectionNames = ['scout-prefix-table1 ' , 'scout-prefix-table2 ' ];
0 commit comments