diff --git a/src/camera-manager/frigate/camera.ts b/src/camera-manager/frigate/camera.ts index ce1eabda..3111b673 100644 --- a/src/camera-manager/frigate/camera.ts +++ b/src/camera-manager/frigate/camera.ts @@ -327,14 +327,14 @@ export class FrigateCamera extends Camera { if (panTilt.length || zoom.length || presets?.length) { return { - ...(panTilt && { + ...(panTilt.length && { left: panTilt, right: panTilt, up: panTilt, down: panTilt, }), - ...(zoom && { zoomIn: zoom, zoomOut: zoom }), - ...(presets && { presets: presets }), + ...(zoom.length && { zoomIn: zoom, zoomOut: zoom }), + ...(presets?.length && { presets: presets }), }; } return null; diff --git a/tests/camera-manager/frigate/camera.test.ts b/tests/camera-manager/frigate/camera.test.ts index 96b23b1c..6ccd4757 100644 --- a/tests/camera-manager/frigate/camera.test.ts +++ b/tests/camera-manager/frigate/camera.test.ts @@ -292,16 +292,82 @@ describe('FrigateCamera', () => { }); expect(camera.getCapabilities()?.has('ptz')).toBeTruthy(); expect(camera.getCapabilities()?.getPTZCapabilities()).toEqual({ - left: [], - right: [], - up: [], - down: [], - zoomIn: [], - zoomOut: [], + // pt-r and zoom-r don't match 'pt' and 'zoom', so only presets presets: ['preset01'], }); expect(camera.getCapabilities()?.hasPTZCapability()).toBeTruthy(); }); + + it('when getPTZInfo returns only zoom capabilities', async () => { + vi.spyOn(global.console, 'warn').mockReturnValue(undefined); + + const camera = new FrigateCamera( + createCameraConfig({ + frigate: { + camera_name: 'front_door', + }, + }), + mock(), + ); + vi.mocked(getPTZInfo).mockResolvedValue({ + features: ['zoom'], + name: 'front_door', + presets: [], + }); + + await camera.initialize({ + hass: createHASS(), + entityRegistryManager: mock(), + stateWatcher: mock(), + frigateEventWatcher: mock(), + }); + + expect(camera.getCapabilities()?.has('ptz')).toBeTruthy(); + + // Should only have zoom capabilities, not empty pan/tilt arrays + expect(camera.getCapabilities()?.getPTZCapabilities()).toEqual({ + zoomIn: ['continuous'], + zoomOut: ['continuous'], + }); + + expect(camera.getCapabilities()?.hasPTZCapability()).toBeTruthy(); + }); + + it('when getPTZInfo returns only pan/tilt capabilities', async () => { + vi.spyOn(global.console, 'warn').mockReturnValue(undefined); + + const camera = new FrigateCamera( + createCameraConfig({ + frigate: { + camera_name: 'front_door', + }, + }), + mock(), + ); + vi.mocked(getPTZInfo).mockResolvedValue({ + features: ['pt'], + name: 'front_door', + presets: [], + }); + + await camera.initialize({ + hass: createHASS(), + entityRegistryManager: mock(), + stateWatcher: mock(), + frigateEventWatcher: mock(), + }); + expect(camera.getCapabilities()?.has('ptz')).toBeTruthy(); + + // Should only have pan/tilt capabilities, not empty zoom arrays + expect(camera.getCapabilities()?.getPTZCapabilities()).toEqual({ + left: ['continuous'], + right: ['continuous'], + up: ['continuous'], + down: ['continuous'], + }); + + expect(camera.getCapabilities()?.hasPTZCapability()).toBeTruthy(); + }); }); });