feat: Add support for inbound "calls" from triggers (#2500)

This commit is contained in:
Dermot Duffy
2026-06-30 17:45:13 -07:00
committed by dermotduffy
parent f4c686c298
commit 15e335a647
39 changed files with 2915 additions and 133 deletions
@@ -291,6 +291,55 @@ describe('TriggersManager', () => {
expect(api.getViewManager().setViewDefaultWithNewQuery).not.toBeCalled();
expect(api.getViewManager().setViewByParametersWithNewQuery).not.toBeCalled();
});
it('should handle trigger action set to call', async () => {
const api = createTriggerAPI({
config: {
actions: { trigger: 'call' },
},
});
const manager = new TriggersManager(api);
await manager.handleCameraEvent({
cameraID: 'camera_1',
id: 'event-1',
type: 'new',
});
expect(manager.isTriggered()).toBeTruthy();
// `start()` is called with the triggered camera and the inbound flag --
// view navigation is delegated to CallManager itself.
expect(api.getCallManager().start).toBeCalledWith({
cameraID: 'camera_1',
inbound: true,
});
expect(api.getViewManager().setViewByParametersWithNewQuery).not.toBeCalled();
});
it('should start a call on a high-fidelity event with no media', async () => {
// The high-fidelity-no-media skip-guard intentionally lets `call`
// through -- calls don't depend on a new media item being available.
const api = createTriggerAPI({
config: {
actions: { trigger: 'call' },
},
});
const manager = new TriggersManager(api);
await manager.handleCameraEvent({
cameraID: 'camera_1',
id: 'event-1',
type: 'new',
fidelity: 'high',
});
expect(api.getCallManager().start).toBeCalledWith({
cameraID: 'camera_1',
inbound: true,
});
});
});
describe('untrigger actions', () => {
@@ -361,6 +410,38 @@ describe('TriggersManager', () => {
expect(api.getViewManager().setViewDefaultWithNewQuery).toBeCalled();
});
it('should handle untrigger action set to call', async () => {
const api = createTriggerAPI({
config: {
actions: { trigger: 'none', untrigger: 'call' },
},
});
const manager = new TriggersManager(api);
await manager.handleCameraEvent({
cameraID: 'camera_1',
id: 'event-1',
type: 'new',
});
await manager.handleCameraEvent({
cameraID: 'camera_1',
id: 'event-1',
type: 'end',
});
vi.setSystemTime(add(start, { seconds: 10 }));
vi.runOnlyPendingTimers();
await flushPromises();
expect(manager.isTriggered()).toBeFalsy();
expect(api.getCallManager().endIf).toBeCalledWith({
cameraID: 'camera_1',
inbound: true,
answered: false,
});
expect(api.getViewManager().setViewDefaultWithNewQuery).not.toBeCalled();
});
it('should handle untrigger call with no state', async () => {
const api = createTriggerAPI();
const manager = new TriggersManager(api);