import { describe, it, expect, vi } from 'vitest' const mockCollection = { find: vi.fn().mockReturnThis(), findOne: vi.fn(), insertOne: vi.fn(), insertMany: vi.fn(), updateOne: vi.fn(), updateMany: vi.fn(), deleteOne: vi.fn(), deleteMany: vi.fn(), countDocuments: vi.fn(), sort: vi.fn().mockReturnThis(), skip: vi.fn().mockReturnThis(), limit: vi.fn().mockReturnThis(), toArray: vi.fn(), } const mockDb = { collection: vi.fn().mockReturnValue(mockCollection) } vi.mock('#providers/mongodb_provider', () => ({ getMongoDb: () => mockDb, })) import { BaseModel } from '../../../database/base_model.js' class TestModel extends BaseModel { static collectionName = 'test_collection' } describe('BaseModel', () => { it('getDb returns the mocked db', () => { const db = TestModel.getDb() expect(db).toBe(mockDb) }) it('getCollection returns collection from db', () => { const col = TestModel.getCollection() expect(mockDb.collection).toHaveBeenCalledWith('test_collection') expect(col).toBe(mockCollection) }) it('find calls collection.find', async () => { mockCollection.toArray.mockResolvedValue([{ name: 'a' }]) const results = await TestModel.find({ name: 'a' }) expect(mockCollection.find).toHaveBeenCalledWith({ name: 'a' }) expect(results).toEqual([{ name: 'a' }]) }) it('findOne calls collection.findOne', async () => { mockCollection.findOne.mockResolvedValue({ x: 1 }) const result = await TestModel.findOne({ x: 1 }) expect(result).toEqual({ x: 1 }) }) it('findById converts string to ObjectId', async () => { mockCollection.findOne.mockResolvedValue({ _id: 'abc' }) await TestModel.findById('507f1f77bcf86cd799439011') expect(mockCollection.findOne).toHaveBeenCalled() }) it('create inserts with timestamps', async () => { mockCollection.insertOne.mockResolvedValue({ insertedId: 'new-id' }) const result = await TestModel.create({ name: 'test' }) expect(result.name).toBe('test') expect(result.createdAt).toBeDefined() expect(result.updatedAt).toBeDefined() expect(result._id).toBe('new-id') }) it('createMany inserts multiple docs', async () => { mockCollection.insertMany.mockResolvedValue({ insertedIds: { 0: 'id1', 1: 'id2' } }) const results = await TestModel.createMany([{ a: 1 }, { a: 2 }]) expect(results).toHaveLength(2) }) it('updateOne with $set passes through', async () => { mockCollection.updateOne.mockResolvedValue({ modifiedCount: 1 }) await TestModel.updateOne({ name: 'x' }, { $set: { val: 2 } }) expect(mockCollection.updateOne).toHaveBeenCalledWith({ name: 'x' }, { $set: { val: 2 } }) }) it('updateOne without $set wraps in $set', async () => { mockCollection.updateOne.mockResolvedValue({ modifiedCount: 1 }) await TestModel.updateOne({ name: 'x' }, { val: 3 }) expect(mockCollection.updateOne).toHaveBeenCalledWith( { name: 'x' }, expect.objectContaining({ $set: expect.objectContaining({ val: 3 }) }) ) }) it('updateMany works', async () => { mockCollection.updateMany.mockResolvedValue({ modifiedCount: 5 }) await TestModel.updateMany({ type: 'a' }, { $set: { active: false } }) expect(mockCollection.updateMany).toHaveBeenCalled() }) it('deleteOne returns boolean', async () => { mockCollection.deleteOne.mockResolvedValue({ deletedCount: 1 }) const result = await TestModel.deleteOne({ name: 'x' }) expect(result).toBe(true) }) it('deleteOne returns false when not found', async () => { mockCollection.deleteOne.mockResolvedValue({ deletedCount: 0 }) const result = await TestModel.deleteOne({ name: 'nonexistent' }) expect(result).toBe(false) }) it('deleteMany returns count', async () => { mockCollection.deleteMany.mockResolvedValue({ deletedCount: 3 }) const count = await TestModel.deleteMany({ old: true }) expect(count).toBe(3) }) it('paginate returns paginated data', async () => { mockCollection.countDocuments.mockResolvedValue(50) mockCollection.toArray.mockResolvedValue([{ id: 1 }, { id: 2 }]) const result = await TestModel.paginate(2, 10, {}) expect(result.total).toBe(50) expect(result.page).toBe(2) expect(result.perPage).toBe(10) expect(result.lastPage).toBe(5) expect(result.data).toHaveLength(2) expect(mockCollection.skip).toHaveBeenCalledWith(10) // (2-1) * 10 expect(mockCollection.limit).toHaveBeenCalledWith(10) }) })