@@ -17,6 +17,10 @@ const mockCollection = {
1717 toArray : jest . fn ( ) . mockResolvedValue ( [ ] ) ,
1818 findOne : jest . fn ( ) . mockResolvedValue ( null ) ,
1919 insertOne : jest . fn ( ) . mockResolvedValue ( { insertedId : '123' } ) ,
20+ insertMany : jest . fn ( ) . mockResolvedValue ( {
21+ insertedIds : { 0 : 'id1' , 1 : 'id2' } ,
22+ insertedCount : 2
23+ } ) ,
2024 updateOne : jest . fn ( ) . mockResolvedValue ( { modifiedCount : 1 } ) ,
2125 deleteOne : jest . fn ( ) . mockResolvedValue ( { deletedCount : 1 } ) ,
2226 countDocuments : jest . fn ( ) . mockResolvedValue ( 10 )
@@ -34,7 +38,10 @@ const mockClient = {
3438jest . mock ( 'mongodb' , ( ) => {
3539 return {
3640 MongoClient : jest . fn ( ) . mockImplementation ( ( ) => mockClient ) ,
37- ObjectId : jest . fn ( id => id )
41+ ObjectId : jest . fn ( ) . mockImplementation ( ( id ?: string ) => ( {
42+ toHexString : ( ) => id || 'generated-object-id' ,
43+ toString : ( ) => id || 'generated-object-id'
44+ } ) )
3845 } ;
3946} ) ;
4047
@@ -328,4 +335,246 @@ describe('MongoDriver', () => {
328335 ) ;
329336 } ) ;
330337
338+ describe ( 'DriverInterface v4.0 methods' , ( ) => {
339+ describe ( 'executeQuery' , ( ) => {
340+ it ( 'should execute a simple QueryAST query' , async ( ) => {
341+ const ast = {
342+ object : 'users' ,
343+ fields : [ 'name' , 'email' ] ,
344+ filters : {
345+ type : 'comparison' as const ,
346+ field : 'status' ,
347+ operator : '=' ,
348+ value : 'active'
349+ } ,
350+ top : 10 ,
351+ skip : 0
352+ } ;
353+
354+ mockCollection . toArray . mockResolvedValue ( [
355+ { name : 'User 1' , email : 'user1@example.com' } ,
356+ { name : 'User 2' , email : 'user2@example.com' }
357+ ] ) ;
358+
359+ const result = await driver . executeQuery ( ast ) ;
360+
361+ expect ( result . value ) . toHaveLength ( 2 ) ;
362+ expect ( result . count ) . toBe ( 2 ) ;
363+ expect ( mockCollection . find ) . toHaveBeenCalled ( ) ;
364+ } ) ;
365+
366+ it ( 'should handle complex QueryAST with AND filters' , async ( ) => {
367+ const ast = {
368+ object : 'users' ,
369+ filters : {
370+ type : 'and' as const ,
371+ children : [
372+ {
373+ type : 'comparison' as const ,
374+ field : 'status' ,
375+ operator : '=' ,
376+ value : 'active'
377+ } ,
378+ {
379+ type : 'comparison' as const ,
380+ field : 'age' ,
381+ operator : '>' ,
382+ value : 18
383+ }
384+ ]
385+ }
386+ } ;
387+
388+ mockCollection . toArray . mockResolvedValue ( [ ] ) ;
389+
390+ const result = await driver . executeQuery ( ast ) ;
391+
392+ expect ( result . value ) . toEqual ( [ ] ) ;
393+ expect ( mockCollection . find ) . toHaveBeenCalled ( ) ;
394+ } ) ;
395+
396+ it ( 'should handle QueryAST with sort' , async ( ) => {
397+ const ast = {
398+ object : 'users' ,
399+ sort : [
400+ { field : 'name' , order : 'asc' as const }
401+ ]
402+ } ;
403+
404+ mockCollection . toArray . mockResolvedValue ( [ ] ) ;
405+
406+ await driver . executeQuery ( ast ) ;
407+
408+ expect ( mockCollection . find ) . toHaveBeenCalledWith (
409+ { } ,
410+ expect . objectContaining ( {
411+ sort : { name : 1 }
412+ } )
413+ ) ;
414+ } ) ;
415+ } ) ;
416+
417+ describe ( 'executeCommand' , ( ) => {
418+ it ( 'should execute create command' , async ( ) => {
419+ const command = {
420+ type : 'create' as const ,
421+ object : 'users' ,
422+ data : { name : 'New User' , email : 'new@example.com' }
423+ } ;
424+
425+ mockCollection . insertOne . mockResolvedValue ( {
426+ insertedId : 'new123' ,
427+ acknowledged : true
428+ } as any ) ;
429+
430+ const result = await driver . executeCommand ( command ) ;
431+
432+ expect ( result . success ) . toBe ( true ) ;
433+ expect ( result . affected ) . toBe ( 1 ) ;
434+ expect ( result . data ) . toBeDefined ( ) ;
435+ expect ( mockCollection . insertOne ) . toHaveBeenCalled ( ) ;
436+ } ) ;
437+
438+ it ( 'should execute update command' , async ( ) => {
439+ const command = {
440+ type : 'update' as const ,
441+ object : 'users' ,
442+ id : '123' ,
443+ data : { name : 'Updated User' }
444+ } ;
445+
446+ mockCollection . updateOne . mockResolvedValue ( {
447+ modifiedCount : 1 ,
448+ acknowledged : true
449+ } as any ) ;
450+ mockCollection . findOne . mockResolvedValue ( {
451+ _id : '123' ,
452+ name : 'Updated User'
453+ } ) ;
454+
455+ const result = await driver . executeCommand ( command ) ;
456+
457+ expect ( result . success ) . toBe ( true ) ;
458+ expect ( result . affected ) . toBe ( 1 ) ;
459+ expect ( mockCollection . updateOne ) . toHaveBeenCalled ( ) ;
460+ } ) ;
461+
462+ it ( 'should execute delete command' , async ( ) => {
463+ const command = {
464+ type : 'delete' as const ,
465+ object : 'users' ,
466+ id : '123'
467+ } ;
468+
469+ mockCollection . deleteOne . mockResolvedValue ( {
470+ deletedCount : 1 ,
471+ acknowledged : true
472+ } as any ) ;
473+
474+ const result = await driver . executeCommand ( command ) ;
475+
476+ expect ( result . success ) . toBe ( true ) ;
477+ expect ( result . affected ) . toBe ( 1 ) ;
478+ expect ( mockCollection . deleteOne ) . toHaveBeenCalled ( ) ;
479+ } ) ;
480+
481+ it ( 'should execute bulkCreate command' , async ( ) => {
482+ const command = {
483+ type : 'bulkCreate' as const ,
484+ object : 'users' ,
485+ records : [
486+ { name : 'User 1' , email : 'user1@example.com' } ,
487+ { name : 'User 2' , email : 'user2@example.com' }
488+ ]
489+ } ;
490+
491+ mockCollection . insertOne . mockResolvedValue ( {
492+ insertedId : 'id1' ,
493+ acknowledged : true
494+ } as any ) ;
495+
496+ const result = await driver . executeCommand ( command ) ;
497+
498+ expect ( result . success ) . toBe ( true ) ;
499+ expect ( result . affected ) . toBe ( 2 ) ;
500+ expect ( result . data ) . toHaveLength ( 2 ) ;
501+ } ) ;
502+
503+ it ( 'should execute bulkUpdate command' , async ( ) => {
504+ const command = {
505+ type : 'bulkUpdate' as const ,
506+ object : 'users' ,
507+ updates : [
508+ { id : '1' , data : { name : 'Updated 1' } } ,
509+ { id : '2' , data : { name : 'Updated 2' } }
510+ ]
511+ } ;
512+
513+ mockCollection . updateOne . mockResolvedValue ( {
514+ modifiedCount : 1 ,
515+ acknowledged : true
516+ } as any ) ;
517+ mockCollection . findOne . mockResolvedValue ( { _id : '1' , name : 'Updated 1' } ) ;
518+
519+ const result = await driver . executeCommand ( command ) ;
520+
521+ expect ( result . success ) . toBe ( true ) ;
522+ expect ( result . affected ) . toBe ( 2 ) ;
523+ } ) ;
524+
525+ it ( 'should execute bulkDelete command' , async ( ) => {
526+ const command = {
527+ type : 'bulkDelete' as const ,
528+ object : 'users' ,
529+ ids : [ '1' , '2' , '3' ]
530+ } ;
531+
532+ mockCollection . deleteOne . mockResolvedValue ( {
533+ deletedCount : 1 ,
534+ acknowledged : true
535+ } as any ) ;
536+
537+ const result = await driver . executeCommand ( command ) ;
538+
539+ expect ( result . success ) . toBe ( true ) ;
540+ expect ( result . affected ) . toBe ( 3 ) ;
541+ } ) ;
542+
543+ it ( 'should handle command errors gracefully' , async ( ) => {
544+ const command = {
545+ type : 'create' as const ,
546+ object : 'users' ,
547+ data : undefined // Invalid data
548+ } ;
549+
550+ const result = await driver . executeCommand ( command ) ;
551+
552+ expect ( result . success ) . toBe ( false ) ;
553+ expect ( result . error ) . toBeDefined ( ) ;
554+ expect ( result . affected ) . toBe ( 0 ) ;
555+ } ) ;
556+
557+ it ( 'should reject unknown command types' , async ( ) => {
558+ const command = {
559+ type : 'invalidCommand' as any ,
560+ object : 'users'
561+ } ;
562+
563+ const result = await driver . executeCommand ( command ) ;
564+
565+ expect ( result . success ) . toBe ( false ) ;
566+ expect ( result . error ) . toContain ( 'Unknown command type' ) ;
567+ expect ( result . error ) . toContain ( 'Valid types are' ) ;
568+ } ) ;
569+ } ) ;
570+
571+ describe ( 'execute' , ( ) => {
572+ it ( 'should throw error as MongoDB does not support raw command execution' , async ( ) => {
573+ await expect ( driver . execute ( 'SELECT * FROM users' ) ) . rejects . toThrow (
574+ 'MongoDB driver does not support raw command execution'
575+ ) ;
576+ } ) ;
577+ } ) ;
578+ } ) ;
579+
331580} ) ;
0 commit comments