Allow camera capabilities to be configured.

This commit is contained in:
Dermot Duffy
2024-03-26 21:00:15 -07:00
parent 0c7260d95a
commit 95c44adcf1
63 changed files with 2308 additions and 1447 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
import { describe, expect, it, vi } from 'vitest';
import { describe, expect, it } from 'vitest';
import { getCameraID } from '../../src/utils/camera.js';
import { createCameraConfig } from '../test-utils.js';
+85
View File
@@ -0,0 +1,85 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import { getEndpointAddressOrDispatchError } from '../../src/utils/endpoint';
import { homeAssistantSignPath } from '../../src/utils/ha';
import { createHASS } from '../test-utils';
vi.mock('../../src/utils/ha');
// @vitest-environment jsdom
describe('getEndpointAddressOrDispatchError', () => {
it('without signing', async () => {
expect(
await getEndpointAddressOrDispatchError(
document.createElement('div'),
createHASS(),
{
endpoint: 'http://example.com',
sign: false,
},
),
).toBe('http://example.com');
});
describe('with signing', () => {
afterEach(() => {
vi.clearAllMocks();
});
it('successful', async () => {
vi.mocked(homeAssistantSignPath).mockResolvedValue('http://signed.com');
expect(
await getEndpointAddressOrDispatchError(
document.createElement('div'),
createHASS(),
{
endpoint: 'http://example.com',
sign: true,
},
),
).toBe('ws://signed.com');
});
it('with null response', async () => {
const element = document.createElement('div');
const listener = vi.fn();
element.addEventListener('frigate-card:message', listener);
vi.mocked(homeAssistantSignPath).mockResolvedValue(null);
expect(
await getEndpointAddressOrDispatchError(element, createHASS(), {
endpoint: 'http://example.com',
sign: true,
}),
).toBeNull();
expect(listener).toBeCalledWith(
expect.objectContaining({
detail: expect.objectContaining({
message: 'Could not sign Home Assistant URL',
}),
}),
);
});
it('with exception on signing', async () => {
const consoleSpy = vi.spyOn(global.console, 'warn').mockReturnValue(undefined);
const element = document.createElement('div');
const listener = vi.fn();
element.addEventListener('frigate-card:message', listener);
vi.mocked(homeAssistantSignPath).mockRejectedValue(new Error());
expect(
await getEndpointAddressOrDispatchError(element, createHASS(), {
endpoint: 'http://example.com',
sign: true,
}),
).toBeNull();
expect(consoleSpy).toBeCalled();
});
});
});
+18 -5
View File
@@ -1,6 +1,6 @@
import add from 'date-fns/add';
import sub from 'date-fns/sub';
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
import { beforeEach, describe, expect, it, Mock, MockedFunction, vi } from 'vitest';
import { QueryType } from '../../src/camera-manager/types';
import {
changeViewToRecentEventsForCameraAndDependents,
@@ -13,6 +13,7 @@ import { ViewMedia } from '../../src/view/media';
import { EventMediaQueries } from '../../src/view/media-queries';
import {
createCameraManager,
createCapabilities,
createPerformanceConfig,
createStore,
createView,
@@ -21,8 +22,8 @@ import {
const createElementListenForView = (): {
element: HTMLElement;
viewHandler: Mock<any, any>;
messageHandler: Mock<any, any>;
viewHandler: EventListener;
messageHandler: EventListener;
} => {
const element = document.createElement('div');
@@ -114,6 +115,7 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ clips: true }),
},
]),
);
@@ -138,7 +140,9 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
},
);
expect(elementHandler.viewHandler).toBeCalled();
expect(getMediaFromHandlerCall(elementHandler.viewHandler)).toBe(mediaArray);
expect(getMediaFromHandlerCall(vi.mocked(elementHandler.viewHandler))).toBe(
mediaArray,
);
});
it('should dispatch error message on fail', async () => {
@@ -150,6 +154,7 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ clips: true }),
},
]),
);
@@ -177,6 +182,7 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ clips: true }),
},
]),
);
@@ -208,6 +214,7 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ clips: true }),
},
]),
);
@@ -246,6 +253,7 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ [mediaType]: true }),
},
]),
);
@@ -440,6 +448,7 @@ describe('changeViewToRecentRecordingForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ recordings: true }),
},
]),
);
@@ -464,7 +473,9 @@ describe('changeViewToRecentRecordingForCameraAndDependents', () => {
},
);
expect(elementHandler.viewHandler).toBeCalled();
expect(getMediaFromHandlerCall(elementHandler.viewHandler)).toBe(mediaArray);
expect(getMediaFromHandlerCall(vi.mocked(elementHandler.viewHandler))).toBe(
mediaArray,
);
});
it('should respect media chunk size', async () => {
@@ -473,6 +484,7 @@ describe('changeViewToRecentRecordingForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ recordings: true }),
},
]),
);
@@ -504,6 +516,7 @@ describe('changeViewToRecentRecordingForCameraAndDependents', () => {
createStore([
{
cameraID: 'camera',
capabilities: createCapabilities({ recordings: true }),
},
]),
);
+7 -5
View File
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest';
import { FrigateCardPTZConfig, frigateCardPTZSchema } from '../../src/config/types';
import { hasUsablePTZ } from '../../src/utils/ptz';
import { createCameraCapabilities } from '../test-utils';
import { createCapabilities } from '../test-utils';
const createPTZConfig = (
config?: Partial<FrigateCardPTZConfig>,
@@ -13,7 +13,7 @@ describe('hasUsablePTZ', () => {
it('should return true with manual actions', () => {
expect(
hasUsablePTZ(
createCameraCapabilities(),
createCapabilities(),
createPTZConfig({
actions_left: {},
}),
@@ -23,14 +23,16 @@ describe('hasUsablePTZ', () => {
it('should return true with capabilities', () => {
expect(
hasUsablePTZ(
createCameraCapabilities({
ptz: {},
createCapabilities({
ptz: {
panTilt: ['continuous'],
},
}),
createPTZConfig(),
),
).toBeTruthy();
});
it('should return false with manual actions or capabilities', () => {
expect(hasUsablePTZ(createCameraCapabilities(), createPTZConfig())).toBeFalsy();
expect(hasUsablePTZ(createCapabilities(), createPTZConfig())).toBeFalsy();
});
});