feat: Add event-based automation triggers (#2537)
This commit is contained in:
committed by
dermotduffy
parent
b701366762
commit
a31816c168
+150
-218
@@ -13,6 +13,8 @@ import {
|
||||
createCameraConfig,
|
||||
createCapabilities,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createHASSEvent,
|
||||
createInitializedCamera,
|
||||
createRegistryEntity,
|
||||
createStateEntity,
|
||||
@@ -25,10 +27,7 @@ describe('Camera', () => {
|
||||
const config = createCameraConfig();
|
||||
const camera = new Camera(
|
||||
config,
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getConfig()).toBe(config);
|
||||
});
|
||||
@@ -38,10 +37,7 @@ describe('Camera', () => {
|
||||
const capabilities = createCapabilities();
|
||||
const camera = await createInitializedCamera(
|
||||
createCameraConfig(),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
capabilities,
|
||||
);
|
||||
expect(camera.getCapabilities()).toBe(capabilities);
|
||||
@@ -50,20 +46,14 @@ describe('Camera', () => {
|
||||
it('when unpopulated', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig(),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getCapabilities()).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('should get engine', async () => {
|
||||
const engine = new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
);
|
||||
const engine = new GenericCameraManagerEngine(createHASSManager());
|
||||
const camera = new Camera(createCameraConfig(), engine);
|
||||
expect(camera.getEngine()).toBe(engine);
|
||||
});
|
||||
@@ -71,10 +61,7 @@ describe('Camera', () => {
|
||||
it('should set and get id', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig(),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
camera.setID('foo');
|
||||
expect(camera.getID()).toBe('foo');
|
||||
@@ -84,10 +71,7 @@ describe('Camera', () => {
|
||||
it('should throw without id', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig(),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(() => camera.getID()).toThrowError(
|
||||
'Could not determine camera id for the following ' +
|
||||
@@ -107,17 +91,12 @@ describe('Camera', () => {
|
||||
entities: ['camera.foo'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
const stateWatcher = mock<StateWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: stateWatcher,
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager({ stateWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
@@ -130,6 +109,26 @@ describe('Camera', () => {
|
||||
expect(stateWatcher.unsubscribe).toBeCalled();
|
||||
});
|
||||
|
||||
it('should skip initialization when hass is unavailable', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig({
|
||||
triggers: {
|
||||
entities: ['camera.foo'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
const stateWatcher = mock<StateWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hassManager: createHASSManager({ hass: null, stateWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
expect(stateWatcher.subscribe).not.toBeCalled();
|
||||
expect(camera.getCapabilities()).toBeNull();
|
||||
});
|
||||
|
||||
it('should set capabilities and use go2rtc metadata endpoint', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig({
|
||||
@@ -138,18 +137,13 @@ describe('Camera', () => {
|
||||
stream: 'stream',
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
vi.mocked(liveProviderSupports2WayAudio).mockResolvedValue(true);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).toHaveBeenCalledWith(
|
||||
@@ -180,18 +174,13 @@ describe('Camera', () => {
|
||||
stream: 'stream',
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
vi.mocked(liveProviderSupports2WayAudio).mockResolvedValue(false);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(camera.getCapabilities()?.has('2-way-audio')).toBe(false);
|
||||
@@ -206,18 +195,13 @@ describe('Camera', () => {
|
||||
metadata_fetch_timeout_seconds: 20,
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
vi.mocked(liveProviderSupports2WayAudio).mockResolvedValue(true);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).toHaveBeenCalledWith(
|
||||
@@ -240,10 +224,7 @@ describe('Camera', () => {
|
||||
live: true,
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
vi.mocked(liveProviderSupports2WayAudio).mockResolvedValue(true);
|
||||
@@ -252,9 +233,7 @@ describe('Camera', () => {
|
||||
hass.config.components = ['hass_web_proxy'];
|
||||
|
||||
await camera.initialize({
|
||||
hass,
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager({ hass }),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).toHaveBeenCalledWith(
|
||||
@@ -281,10 +260,7 @@ describe('Camera', () => {
|
||||
createCameraConfig({
|
||||
proxy: { live: true },
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getLiveProxyConfig()).toEqual(
|
||||
expect.objectContaining({ enabled: true, enforce: true }),
|
||||
@@ -296,10 +272,7 @@ describe('Camera', () => {
|
||||
createCameraConfig({
|
||||
proxy: { media: true },
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getMediaProxyConfig()).toEqual(
|
||||
expect.objectContaining({ enabled: true, enforce: true }),
|
||||
@@ -312,10 +285,7 @@ describe('Camera', () => {
|
||||
live_provider: 'go2rtc',
|
||||
go2rtc: { url: 'http://go2rtc' },
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getLiveProxyConfig()).toEqual(
|
||||
expect.objectContaining({ enabled: true, enforce: false }),
|
||||
@@ -327,10 +297,7 @@ describe('Camera', () => {
|
||||
createCameraConfig({
|
||||
proxy: { media: 'auto' },
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getMediaProxyConfig()).toEqual(
|
||||
expect.objectContaining({ enabled: false, enforce: false }),
|
||||
@@ -344,16 +311,11 @@ describe('Camera', () => {
|
||||
force: ['2-way-audio'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).not.toHaveBeenCalled();
|
||||
@@ -368,16 +330,11 @@ describe('Camera', () => {
|
||||
force: ['2-way-audio'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).not.toHaveBeenCalled();
|
||||
@@ -392,16 +349,11 @@ describe('Camera', () => {
|
||||
force: ['2-way-audio'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).not.toHaveBeenCalled();
|
||||
@@ -415,16 +367,11 @@ describe('Camera', () => {
|
||||
disable: ['2-way-audio'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).not.toHaveBeenCalled();
|
||||
@@ -438,16 +385,11 @@ describe('Camera', () => {
|
||||
disable_except: ['substream'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).not.toHaveBeenCalled();
|
||||
@@ -461,17 +403,12 @@ describe('Camera', () => {
|
||||
disable_except: ['substream', '2-way-audio'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
vi.mocked(liveProviderSupports2WayAudio).mockResolvedValue(true);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).toHaveBeenCalled();
|
||||
@@ -485,17 +422,12 @@ describe('Camera', () => {
|
||||
disable_except: [],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
vi.mocked(liveProviderSupports2WayAudio).mockResolvedValue(true);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(liveProviderSupports2WayAudio).toHaveBeenCalled();
|
||||
@@ -510,16 +442,11 @@ describe('Camera', () => {
|
||||
});
|
||||
const camera = new Camera(
|
||||
createCameraConfig({ camera_entity: 'camera.front_door' }),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
entityRegistryManager: new EntityRegistryManagerMock([cameraEntity]),
|
||||
});
|
||||
|
||||
@@ -529,16 +456,11 @@ describe('Camera', () => {
|
||||
it('should leave entity null when camera_entity is unset', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig(),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
entityRegistryManager: new EntityRegistryManagerMock(),
|
||||
});
|
||||
|
||||
@@ -548,16 +470,11 @@ describe('Camera', () => {
|
||||
it('should leave entity null when entityRegistryManager is not provided', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig({ camera_entity: 'camera.front_door' }),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager(),
|
||||
});
|
||||
|
||||
expect(camera.getEntity()).toBeNull();
|
||||
@@ -594,10 +511,7 @@ describe('Camera', () => {
|
||||
...(options?.userEntities && { entities: options.userEntities }),
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
const stateWatcher = mock<StateWatcherSubscriptionInterface>();
|
||||
const hass = createHASS(
|
||||
@@ -609,9 +523,7 @@ describe('Camera', () => {
|
||||
},
|
||||
);
|
||||
await camera.initialize({
|
||||
hass,
|
||||
stateWatcher,
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager({ hass, stateWatcher }),
|
||||
...(!options?.omitRegistryManager && {
|
||||
entityRegistryManager: new EntityRegistryManagerMock(
|
||||
options?.registryEntities ?? [cameraEntity, doorbellEntity],
|
||||
@@ -737,10 +649,7 @@ describe('Camera', () => {
|
||||
entities: ['binary_sensor.foo'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
{
|
||||
eventCallback: eventCallback,
|
||||
},
|
||||
@@ -748,9 +657,7 @@ describe('Camera', () => {
|
||||
|
||||
const stateWatcher = mock<StateWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: stateWatcher,
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager({ stateWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
@@ -780,27 +687,25 @@ describe('Camera', () => {
|
||||
events: [{ event_type: 'zha_event' }],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
{ eventCallback },
|
||||
);
|
||||
|
||||
const eventWatcher = mock<EventWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher,
|
||||
hassManager: createHASSManager({ eventWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
expect(eventWatcher.subscribe).toBeCalledTimes(1);
|
||||
const request = vi.mocked(eventWatcher.subscribe).mock.calls[0][1];
|
||||
const request = vi.mocked(eventWatcher.subscribe).mock.calls[0][0];
|
||||
expect(request.event_type).toBe('zha_event');
|
||||
expect(request.matcher).toBeUndefined();
|
||||
|
||||
callEventWatcherCallback(eventWatcher, { command: 'press' });
|
||||
callEventWatcherCallback(
|
||||
eventWatcher,
|
||||
createHASSEvent('zha_event', { command: 'press' }),
|
||||
);
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
cameraID: 'camera_1',
|
||||
@@ -812,6 +717,63 @@ describe('Camera', () => {
|
||||
expect(eventWatcher.unsubscribe).toBeCalled();
|
||||
});
|
||||
|
||||
it('should attach a context-only matcher when only a context filter is set', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig({
|
||||
id: 'camera_1',
|
||||
triggers: {
|
||||
events: [{ event_type: 'zha_event', context: { user_id: 'u-1' } }],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
const eventWatcher = mock<EventWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hassManager: createHASSManager({ eventWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
const matcher = vi.mocked(eventWatcher.subscribe).mock.calls[0][0].matcher;
|
||||
expect(matcher).toBeDefined();
|
||||
expect(
|
||||
matcher?.(
|
||||
createHASSEvent('zha_event', {}, { id: 'i', user_id: 'u-1', parent_id: null }),
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
matcher?.(
|
||||
createHASSEvent('zha_event', {}, { id: 'i', user_id: 'u-2', parent_id: null }),
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should expand list-form event_type into one subscription per type', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig({
|
||||
id: 'camera_1',
|
||||
triggers: {
|
||||
events: [{ event_type: ['zha_event', 'deconz_event'] }],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
const eventWatcher = mock<EventWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hassManager: createHASSManager({ eventWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
expect(eventWatcher.subscribe).toBeCalledTimes(2);
|
||||
expect(vi.mocked(eventWatcher.subscribe).mock.calls[0][0].event_type).toBe(
|
||||
'zha_event',
|
||||
);
|
||||
expect(vi.mocked(eventWatcher.subscribe).mock.calls[1][0].event_type).toBe(
|
||||
'deconz_event',
|
||||
);
|
||||
});
|
||||
|
||||
it('should attach a matcher when triggers.events entry has data filter', async () => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig({
|
||||
@@ -820,24 +782,23 @@ describe('Camera', () => {
|
||||
events: [{ event_type: 'zha_event', event_data: { command: 'press' } }],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
const eventWatcher = mock<EventWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher,
|
||||
hassManager: createHASSManager({ eventWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
const matcher = vi.mocked(eventWatcher.subscribe).mock.calls[0][1].matcher;
|
||||
const matcher = vi.mocked(eventWatcher.subscribe).mock.calls[0][0].matcher;
|
||||
expect(matcher).toBeDefined();
|
||||
expect(matcher?.({ command: 'press', extra: 1 })).toBe(true);
|
||||
expect(matcher?.({ command: 'release' })).toBe(false);
|
||||
expect(
|
||||
matcher?.(createHASSEvent('zha_event', { command: 'press', extra: 1 })),
|
||||
).toBe(true);
|
||||
expect(matcher?.(createHASSEvent('zha_event', { command: 'release' }))).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('should not subscribe to events when trigger capability is disabled', async () => {
|
||||
@@ -848,17 +809,12 @@ describe('Camera', () => {
|
||||
events: [{ event_type: 'zha_event' }],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
const eventWatcher = mock<EventWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: mock<StateWatcherSubscriptionInterface>(),
|
||||
eventWatcher,
|
||||
hassManager: createHASSManager({ eventWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: false }) },
|
||||
});
|
||||
|
||||
@@ -876,10 +832,7 @@ describe('Camera', () => {
|
||||
entities: ['event.front_door_doorbell'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
{
|
||||
eventCallback: eventCallback,
|
||||
},
|
||||
@@ -887,9 +840,7 @@ describe('Camera', () => {
|
||||
|
||||
const stateWatcher = mock<StateWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: stateWatcher,
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager({ stateWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
@@ -913,10 +864,7 @@ describe('Camera', () => {
|
||||
entities: ['event.front_door_doorbell'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
{
|
||||
eventCallback: eventCallback,
|
||||
},
|
||||
@@ -924,9 +872,7 @@ describe('Camera', () => {
|
||||
|
||||
const stateWatcher = mock<StateWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: stateWatcher,
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager({ stateWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
@@ -953,10 +899,7 @@ describe('Camera', () => {
|
||||
entities: ['binary_sensor.foo'],
|
||||
},
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
{
|
||||
eventCallback: eventCallback,
|
||||
},
|
||||
@@ -964,9 +907,7 @@ describe('Camera', () => {
|
||||
|
||||
const stateWatcher = mock<StateWatcherSubscriptionInterface>();
|
||||
await camera.initialize({
|
||||
hass: createHASS(),
|
||||
stateWatcher: stateWatcher,
|
||||
eventWatcher: mock<EventWatcherSubscriptionInterface>(),
|
||||
hassManager: createHASSManager({ stateWatcher }),
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: false }) },
|
||||
});
|
||||
|
||||
@@ -1128,10 +1069,7 @@ describe('Camera', () => {
|
||||
(_name: string, cameraConfig: unknown, expectedResult: CameraProxyConfig) => {
|
||||
const camera = new Camera(
|
||||
createCameraConfig(cameraConfig),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getProxyConfig()).toEqual(expectedResult);
|
||||
},
|
||||
@@ -1145,10 +1083,7 @@ describe('Camera', () => {
|
||||
go2rtc: { stream: '' },
|
||||
camera_entity: '',
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(camera.getEndpoints()).toBeNull();
|
||||
});
|
||||
@@ -1162,10 +1097,7 @@ describe('Camera', () => {
|
||||
},
|
||||
camera_entity: 'camera.foo',
|
||||
}),
|
||||
new GenericCameraManagerEngine(
|
||||
mock<StateWatcherSubscriptionInterface>(),
|
||||
mock<EventWatcherSubscriptionInterface>(),
|
||||
),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
|
||||
expect(camera.getEndpoints()).toEqual({
|
||||
|
||||
Reference in New Issue
Block a user