import { describe, it, expect, vi, beforeEach } from 'vitest' // Mock the mongodb provider before importing the model const mockCollection = { findOne: vi.fn(), find: vi.fn().mockReturnValue({ sort: vi.fn().mockReturnValue({ skip: vi.fn().mockReturnValue({ limit: vi.fn().mockReturnValue({ toArray: vi.fn().mockResolvedValue([]) }) }) }), toArray: vi.fn().mockResolvedValue([]) }), countDocuments: vi.fn(), findOneAndUpdate: vi.fn(), updateOne: vi.fn(), updateMany: vi.fn(), distinct: vi.fn().mockResolvedValue([]), aggregate: vi.fn().mockReturnValue({ toArray: vi.fn().mockResolvedValue([]) }), skip: vi.fn().mockReturnThis(), limit: vi.fn().mockReturnThis(), sort: vi.fn().mockReturnThis(), toArray: vi.fn().mockResolvedValue([]), } const mockDb = { collection: vi.fn().mockReturnValue(mockCollection), } vi.mock('#providers/mongodb_provider', () => ({ getMongoDb: () => mockDb, })) import DeviceModel from '../../../app/models/device.js' describe('DeviceModel', () => { beforeEach(() => { vi.clearAllMocks() mockCollection.toArray.mockResolvedValue([]) }) it('findByIdentifier calls findOne with identifier', async () => { mockCollection.findOne.mockResolvedValue({ identifier: 'abc', deviceId: {} }) const result = await DeviceModel.findByIdentifier('abc') expect(mockCollection.findOne).toHaveBeenCalledWith({ identifier: 'abc' }) expect(result).toEqual({ identifier: 'abc', deviceId: {} }) }) it('findByIdentifier returns null when not found', async () => { mockCollection.findOne.mockResolvedValue(null) const result = await DeviceModel.findByIdentifier('xyz') expect(result).toBeNull() }) it('findByDeviceId queries by all 4 fields', async () => { const { DeviceId } = await import('../../../app/domain/device/device_id.js') const deviceId = new DeviceId('Mfr', 'OUI', 'PC', 'SN') mockCollection.findOne.mockResolvedValue(null) await DeviceModel.findByDeviceId(deviceId) expect(mockCollection.findOne).toHaveBeenCalledWith({ 'deviceId.manufacturer': 'Mfr', 'deviceId.oui': 'OUI', 'deviceId.productClass': 'PC', 'deviceId.serialNumber': 'SN', }) }) it('createOrUpdate upserts by deviceId', async () => { const device = { deviceId: { manufacturer: 'M', oui: 'O', productClass: 'P', serialNumber: 'S' }, properties: [] } mockCollection.findOneAndUpdate.mockResolvedValue(device) const result = await DeviceModel.createOrUpdate(device as any) expect(mockCollection.findOneAndUpdate).toHaveBeenCalled() expect(result).toEqual(device) }) it('createOrUpdate upserts by identifier', async () => { const device = { identifier: 'hash123', properties: [] } mockCollection.findOneAndUpdate.mockResolvedValue(device) await DeviceModel.createOrUpdate(device as any) expect(mockCollection.findOneAndUpdate).toHaveBeenCalledWith( { identifier: 'hash123' }, expect.any(Object), expect.any(Object) ) }) it('createOrUpdate throws if no identifier or deviceId', async () => { await expect(DeviceModel.createOrUpdate({} as any)).rejects.toThrow('Either identifier or deviceId must be provided') }) it('updateCompliance calls updateOne', async () => { mockCollection.updateOne.mockResolvedValue({ modifiedCount: 1 }) await DeviceModel.updateCompliance('id1', { status: 'compliant' } as any) expect(mockCollection.updateOne).toHaveBeenCalled() }) it('updateProvisioningCode calls updateOne', async () => { mockCollection.updateOne.mockResolvedValue({ modifiedCount: 1 }) await DeviceModel.updateProvisioningCode('id1', 'code-123') expect(mockCollection.updateOne).toHaveBeenCalled() }) it('resetComplianceForConfiguration updates many', async () => { mockCollection.updateMany.mockResolvedValue({ modifiedCount: 3 }) await DeviceModel.resetComplianceForConfiguration('cfg-1') expect(mockCollection.updateMany).toHaveBeenCalled() }) })