Skip to content

Commit 4d01cfc

Browse files
Copilothotlong
andcommitted
Add comprehensive tests for executeQuery and executeCommand methods
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 3fff3c1 commit 4d01cfc

1 file changed

Lines changed: 250 additions & 1 deletion

File tree

packages/drivers/mongo/test/index.test.ts

Lines changed: 250 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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 = {
3438
jest.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

Comments
 (0)