1
1
/* eslint-disable @typescript-eslint/no-unused-vars */
2
2
import { expect } from 'chai' ;
3
- import { ChangeStream , Document , InsertOneOptions , MongoError } from '../../../src' ;
3
+ import { Collection , Db } from '../../../src' ;
4
+ import { ChangeStream , Document , InsertOneOptions } from '../../../src' ;
5
+ import { BulkWriteResult } from '../../../src/bulk/common' ;
4
6
import { EventCollector } from '../../tools/utils' ;
5
7
import { EntitiesMap } from './entities' ;
6
- import { expectResultCheck } from './match' ;
8
+ import { expectErrorCheck , expectResultCheck } from './match' ;
7
9
import type * as uni from './schema' ;
8
10
9
- export class UnifiedOperation {
10
- name : string ;
11
- constructor ( op : uni . OperationDescription ) {
12
- this . name = op . name ;
13
- }
14
- }
15
-
16
11
async function abortTransactionOperation (
17
12
entities : EntitiesMap ,
18
13
op : uni . OperationDescription
@@ -23,7 +18,22 @@ async function aggregateOperation(
23
18
entities : EntitiesMap ,
24
19
op : uni . OperationDescription
25
20
) : Promise < Document > {
26
- throw new Error ( 'not implemented.' ) ;
21
+ const dbOrCollection = entities . get ( op . object ) as Db | Collection ;
22
+ if ( ! ( dbOrCollection instanceof Db || dbOrCollection instanceof Collection ) ) {
23
+ throw new Error ( `Operation object '${ op . object } ' must be a db or collection` ) ;
24
+ }
25
+ return dbOrCollection
26
+ . aggregate ( op . arguments . pipeline , {
27
+ allowDiskUse : op . arguments . allowDiskUse ,
28
+ batchSize : op . arguments . batchSize ,
29
+ bypassDocumentValidation : op . arguments . bypassDocumentValidation ,
30
+ maxTimeMS : op . arguments . maxTimeMS ,
31
+ maxAwaitTimeMS : op . arguments . maxAwaitTimeMS ,
32
+ collation : op . arguments . collation ,
33
+ hint : op . arguments . hint ,
34
+ out : op . arguments . out
35
+ } )
36
+ . toArray ( ) ;
27
37
}
28
38
async function assertCollectionExistsOperation (
29
39
entities : EntitiesMap ,
@@ -94,14 +104,16 @@ async function assertSessionTransactionStateOperation(
94
104
async function bulkWriteOperation (
95
105
entities : EntitiesMap ,
96
106
op : uni . OperationDescription
97
- ) : Promise < Document > {
98
- throw new Error ( 'not implemented.' ) ;
107
+ ) : Promise < BulkWriteResult > {
108
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
109
+ return collection . bulkWrite ( op . arguments . requests ) ;
99
110
}
100
111
async function commitTransactionOperation (
101
112
entities : EntitiesMap ,
102
113
op : uni . OperationDescription
103
114
) : Promise < Document > {
104
- throw new Error ( 'not implemented.' ) ;
115
+ const session = entities . getEntity ( 'session' , op . object ) ;
116
+ return session . commitTransaction ( ) ;
105
117
}
106
118
async function createChangeStreamOperation (
107
119
entities : EntitiesMap ,
@@ -148,7 +160,8 @@ async function deleteOneOperation(
148
160
entities : EntitiesMap ,
149
161
op : uni . OperationDescription
150
162
) : Promise < Document > {
151
- throw new Error ( 'not implemented.' ) ;
163
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
164
+ return collection . deleteOne ( op . arguments . filter ) ;
152
165
}
153
166
async function dropCollectionOperation (
154
167
entities : EntitiesMap ,
@@ -168,19 +181,24 @@ async function findOperation(
168
181
) : Promise < Document > {
169
182
const collection = entities . getEntity ( 'collection' , op . object ) ;
170
183
const { filter, sort, batchSize, limit } = op . arguments ;
171
- return await collection . find ( filter , { sort, batchSize, limit } ) . toArray ( ) ;
184
+ return collection . find ( filter , { sort, batchSize, limit } ) . toArray ( ) ;
172
185
}
173
186
async function findOneAndReplaceOperation (
174
187
entities : EntitiesMap ,
175
188
op : uni . OperationDescription
176
189
) : Promise < Document > {
177
- throw new Error ( 'not implemented.' ) ;
190
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
191
+ return collection . findOneAndReplace ( op . arguments . filter , op . arguments . replacement ) ;
178
192
}
179
193
async function findOneAndUpdateOperation (
180
194
entities : EntitiesMap ,
181
195
op : uni . OperationDescription
182
196
) : Promise < Document > {
183
- throw new Error ( 'not implemented.' ) ;
197
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
198
+ const returnOriginal = op . arguments . returnDocument === 'Before' ;
199
+ return (
200
+ await collection . findOneAndUpdate ( op . arguments . filter , op . arguments . update , { returnOriginal } )
201
+ ) . value ;
184
202
}
185
203
async function failPointOperation (
186
204
entities : EntitiesMap ,
@@ -201,7 +219,7 @@ async function insertOneOperation(
201
219
session
202
220
} as InsertOneOptions ;
203
221
204
- return await collection . insertOne ( op . arguments . document , options ) ;
222
+ return collection . insertOne ( op . arguments . document , options ) ;
205
223
}
206
224
async function insertManyOperation (
207
225
entities : EntitiesMap ,
@@ -216,7 +234,7 @@ async function insertManyOperation(
216
234
ordered : op . arguments . ordered ?? true
217
235
} ;
218
236
219
- return await collection . insertMany ( op . arguments . documents , options ) ;
237
+ return collection . insertMany ( op . arguments . documents , options ) ;
220
238
}
221
239
async function iterateUntilDocumentOrErrorOperation (
222
240
entities : EntitiesMap ,
@@ -239,13 +257,20 @@ async function replaceOneOperation(
239
257
entities : EntitiesMap ,
240
258
op : uni . OperationDescription
241
259
) : Promise < Document > {
242
- throw new Error ( 'not implemented.' ) ;
260
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
261
+ return collection . replaceOne ( op . arguments . filter , op . arguments . replacement , {
262
+ bypassDocumentValidation : op . arguments . bypassDocumentValidation ,
263
+ collation : op . arguments . collation ,
264
+ hint : op . arguments . hint ,
265
+ upsert : op . arguments . upsert
266
+ } ) ;
243
267
}
244
268
async function startTransactionOperation (
245
269
entities : EntitiesMap ,
246
270
op : uni . OperationDescription
247
- ) : Promise < Document > {
248
- throw new Error ( 'not implemented.' ) ;
271
+ ) : Promise < void > {
272
+ const session = entities . getEntity ( 'session' , op . object ) ;
273
+ session . startTransaction ( ) ;
249
274
}
250
275
async function targetedFailPointOperation (
251
276
entities : EntitiesMap ,
@@ -277,8 +302,67 @@ async function withTransactionOperation(
277
302
) : Promise < Document > {
278
303
throw new Error ( 'not implemented.' ) ;
279
304
}
305
+ async function countDocumentsOperation (
306
+ entities : EntitiesMap ,
307
+ op : uni . OperationDescription
308
+ ) : Promise < number > {
309
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
310
+ return collection . countDocuments ( op . arguments . filter as Document ) ;
311
+ }
312
+ async function deleteManyOperation (
313
+ entities : EntitiesMap ,
314
+ op : uni . OperationDescription
315
+ ) : Promise < Document > {
316
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
317
+ return collection . deleteMany ( op . arguments . filter ) ;
318
+ }
319
+ async function distinctOperation (
320
+ entities : EntitiesMap ,
321
+ op : uni . OperationDescription
322
+ ) : Promise < Document > {
323
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
324
+ return collection . distinct ( op . arguments . fieldName as string , op . arguments . filter as Document ) ;
325
+ }
326
+ async function estimatedDocumentCountOperation (
327
+ entities : EntitiesMap ,
328
+ op : uni . OperationDescription
329
+ ) : Promise < number > {
330
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
331
+ return collection . estimatedDocumentCount ( ) ;
332
+ }
333
+ async function findOneAndDeleteOperation (
334
+ entities : EntitiesMap ,
335
+ op : uni . OperationDescription
336
+ ) : Promise < Document > {
337
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
338
+ return collection . findOneAndDelete ( op . arguments . filter ) ;
339
+ }
340
+ async function runCommandOperation (
341
+ entities : EntitiesMap ,
342
+ op : uni . OperationDescription
343
+ ) : Promise < Document > {
344
+ const db = entities . getEntity ( 'db' , op . object ) ;
345
+ return db . command ( op . arguments . command ) ;
346
+ }
347
+ async function updateManyOperation (
348
+ entities : EntitiesMap ,
349
+ op : uni . OperationDescription
350
+ ) : Promise < Document > {
351
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
352
+ return collection . updateMany ( op . arguments . filter , op . arguments . update ) ;
353
+ }
354
+ async function updateOneOperation (
355
+ entities : EntitiesMap ,
356
+ op : uni . OperationDescription
357
+ ) : Promise < Document > {
358
+ const collection = entities . getEntity ( 'collection' , op . object ) ;
359
+ return collection . updateOne ( op . arguments . filter , op . arguments . update ) ;
360
+ }
280
361
281
- type RunOperationFn = ( entities : EntitiesMap , op : uni . OperationDescription ) => Promise < Document > ;
362
+ type RunOperationFn = (
363
+ entities : EntitiesMap ,
364
+ op : uni . OperationDescription
365
+ ) => Promise < Document | number | void > ;
282
366
export const operations = new Map < string , RunOperationFn > ( ) ;
283
367
284
368
operations . set ( 'abortTransaction' , abortTransactionOperation ) ;
@@ -321,6 +405,16 @@ operations.set('download', downloadOperation);
321
405
operations . set ( 'upload' , uploadOperation ) ;
322
406
operations . set ( 'withTransaction' , withTransactionOperation ) ;
323
407
408
+ // Versioned API adds these:
409
+ operations . set ( 'countDocuments' , countDocumentsOperation ) ;
410
+ operations . set ( 'deleteMany' , deleteManyOperation ) ;
411
+ operations . set ( 'distinct' , distinctOperation ) ;
412
+ operations . set ( 'estimatedDocumentCount' , estimatedDocumentCountOperation ) ;
413
+ operations . set ( 'findOneAndDelete' , findOneAndDeleteOperation ) ;
414
+ operations . set ( 'runCommand' , runCommandOperation ) ;
415
+ operations . set ( 'updateMany' , updateManyOperation ) ;
416
+ operations . set ( 'updateOne' , updateOneOperation ) ;
417
+
324
418
export async function executeOperationAndCheck (
325
419
operation : uni . OperationDescription ,
326
420
entities : EntitiesMap
@@ -333,9 +427,12 @@ export async function executeOperationAndCheck(
333
427
try {
334
428
result = await opFunc ( entities , operation ) ;
335
429
} catch ( error ) {
430
+ // FIXME: Remove when project is done:
431
+ if ( error . message === 'not implemented.' ) {
432
+ throw error ;
433
+ }
336
434
if ( operation . expectError ) {
337
- expect ( error ) . to . be . instanceof ( MongoError ) ;
338
- // expectErrorCheck(error, operation.expectError);
435
+ expectErrorCheck ( error , operation . expectError , entities ) ;
339
436
} else {
340
437
expect . fail ( `Operation ${ operation . name } failed with ${ error . message } ` ) ;
341
438
}
0 commit comments