Add out-of-the-box Frigate PTZ support.
This commit is contained in:
@@ -23,7 +23,6 @@ import {
|
||||
} from '../test-utils';
|
||||
|
||||
vi.mock('../../src/utils/action.js');
|
||||
vi.mock('../../src/camera-manager/manager.js');
|
||||
|
||||
const createAction = (
|
||||
action: Record<string, unknown>,
|
||||
@@ -708,6 +707,62 @@ describe('ActionsManager.executeAction', () => {
|
||||
expect(api.getViewManager().setViewWithNewDisplayMode).toBeCalledWith('grid');
|
||||
});
|
||||
|
||||
describe('should handle ptz action', () => {
|
||||
it('with selected camera', async () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new ActionsManager(api);
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(
|
||||
createView({ camera: 'camera.office' }),
|
||||
);
|
||||
|
||||
await manager.executeAction(
|
||||
createAction({
|
||||
frigate_card_action: 'ptz',
|
||||
ptz_action: 'left',
|
||||
})!,
|
||||
);
|
||||
|
||||
expect(api.getCameraManager().executePTZAction).toBeCalledWith(
|
||||
'camera.office',
|
||||
'left',
|
||||
{
|
||||
phase: undefined,
|
||||
preset: undefined,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('without selected camera', async () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new ActionsManager(api);
|
||||
|
||||
await manager.executeAction(
|
||||
createAction({
|
||||
frigate_card_action: 'ptz',
|
||||
ptz_action: 'left',
|
||||
})!,
|
||||
);
|
||||
|
||||
expect(api.getCameraManager().executePTZAction).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle show_ptz action', async () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new ActionsManager(api);
|
||||
|
||||
await manager.executeAction(
|
||||
createAction({
|
||||
frigate_card_action: 'show_ptz',
|
||||
show_ptz: true,
|
||||
})!,
|
||||
);
|
||||
|
||||
expect(api.getViewManager().setViewWithNewContext).toBeCalledWith(
|
||||
expect.objectContaining({ live: { ptzVisible: true } }),
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle unknown action', async () => {
|
||||
const manager = new ActionsManager(createCardAPI());
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { CardController } from '../../src/card-controller/controller';
|
||||
import { HASSManager } from '../../src/card-controller/hass-manager';
|
||||
import { CardHASSAPI } from '../../src/card-controller/types';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createCameraManager,
|
||||
@@ -8,12 +8,11 @@ import {
|
||||
createConfig,
|
||||
createHASS,
|
||||
createStateEntity,
|
||||
createStore,
|
||||
createView,
|
||||
} from '../test-utils';
|
||||
|
||||
vi.mock('../../src/camera-manager/manager.js');
|
||||
|
||||
const createAPIWithoutMediaPlayers = (): CardHASSAPI => {
|
||||
const createAPIWithoutMediaPlayers = (): CardController => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getMediaPlayerManager().getMediaPlayers).mockReturnValue([]);
|
||||
return api;
|
||||
@@ -158,20 +157,20 @@ describe('HASSManager', () => {
|
||||
|
||||
describe('should set default view when', () => {
|
||||
it('selected camera trigger entity changes', () => {
|
||||
const cameraManager = createCameraManager({
|
||||
configs: new Map([
|
||||
[
|
||||
'camera.foo',
|
||||
createCameraConfig({
|
||||
const api = createAPIWithoutMediaPlayers();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig({
|
||||
triggers: {
|
||||
entities: ['binary_sensor.motion'],
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
]),
|
||||
});
|
||||
const api = createAPIWithoutMediaPlayers();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
);
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(
|
||||
createView({
|
||||
camera: 'camera.foo',
|
||||
@@ -189,20 +188,20 @@ describe('HASSManager', () => {
|
||||
});
|
||||
|
||||
it('selected camera is unknown', () => {
|
||||
const cameraManager = createCameraManager({
|
||||
configs: new Map([
|
||||
[
|
||||
'camera.foo',
|
||||
createCameraConfig({
|
||||
const api = createAPIWithoutMediaPlayers();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig({
|
||||
triggers: {
|
||||
entities: ['binary_sensor.motion'],
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
]),
|
||||
});
|
||||
const api = createAPIWithoutMediaPlayers();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
);
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(
|
||||
createView({
|
||||
camera: 'camera.UNKNOWN',
|
||||
|
||||
@@ -18,9 +18,37 @@ describe('InitializationManager', () => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
it('should not be initialized', () => {
|
||||
const manager = new InitializationManager(createCardAPI());
|
||||
expect(manager.isInitializedMandatory()).toBeFalsy();
|
||||
describe('should correctly determine when mandatory initialization is required', () => {
|
||||
it('without aspects', () => {
|
||||
const api = createCardAPI();
|
||||
const initializer = mock<Initializer>();
|
||||
const manager = new InitializationManager(api, initializer);
|
||||
|
||||
initializer.isInitializedMultiple.mockReturnValue(false);
|
||||
|
||||
expect(manager.isInitializedMandatory()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('without view', () => {
|
||||
const api = createCardAPI();
|
||||
const initializer = mock<Initializer>();
|
||||
const manager = new InitializationManager(api, initializer);
|
||||
|
||||
initializer.isInitializedMultiple.mockReturnValue(true);
|
||||
|
||||
expect(manager.isInitializedMandatory()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('with aspects and view', () => {
|
||||
const api = createCardAPI();
|
||||
const initializer = mock<Initializer>();
|
||||
const manager = new InitializationManager(api, initializer);
|
||||
|
||||
initializer.isInitializedMultiple.mockReturnValue(true);
|
||||
vi.mocked(api.getViewManager().hasView).mockReturnValue(true);
|
||||
|
||||
expect(manager.isInitializedMandatory()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should initialize mandatory', () => {
|
||||
@@ -41,7 +69,9 @@ describe('InitializationManager', () => {
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
vi.mocked(api.getConfigManager().hasConfig).mockReturnValue(true);
|
||||
vi.mocked(api.getMessageManager().hasMessage).mockReturnValue(false);
|
||||
vi.mocked(api.getQueryStringManager().hasViewRelatedActions).mockReturnValue(false);
|
||||
vi.mocked(api.getQueryStringManager().hasViewRelatedActions).mockReturnValue(
|
||||
false,
|
||||
);
|
||||
const manager = new InitializationManager(api);
|
||||
|
||||
expect(await manager.initializeMandatory()).toBeTruthy();
|
||||
@@ -50,7 +80,6 @@ describe('InitializationManager', () => {
|
||||
expect(sideLoadHomeAssistantElements).toBeCalled();
|
||||
expect(api.getCameraManager().initializeCamerasFromConfig).toBeCalled();
|
||||
expect(api.getViewManager().setViewDefault).toBeCalled();
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
});
|
||||
|
||||
it('successfully with querystring view', async () => {
|
||||
@@ -71,7 +100,9 @@ describe('InitializationManager', () => {
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
vi.mocked(api.getConfigManager().hasConfig).mockReturnValue(true);
|
||||
vi.mocked(api.getMessageManager().hasMessage).mockReturnValue(true);
|
||||
vi.mocked(api.getQueryStringManager().hasViewRelatedActions).mockReturnValue(false);
|
||||
vi.mocked(api.getQueryStringManager().hasViewRelatedActions).mockReturnValue(
|
||||
false,
|
||||
);
|
||||
const manager = new InitializationManager(api);
|
||||
|
||||
expect(await manager.initializeMandatory()).toBeTruthy();
|
||||
@@ -134,7 +165,6 @@ describe('InitializationManager', () => {
|
||||
expect(await manager.initializeBackgroundIfNecessary()).toBeTruthy();
|
||||
expect(api.getMediaPlayerManager().initialize).not.toBeCalled();
|
||||
expect(api.getMicrophoneManager().connect).not.toBeCalled();
|
||||
expect(api.getCardElementManager().update).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('successfully with all inititalizers', async () => {
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
import { MediaPlayerManager } from '../../src/card-controller/media-player-manager';
|
||||
import { MEDIA_PLAYER_SUPPORT_BROWSE_MEDIA } from '../../src/const';
|
||||
import { ExtendedHomeAssistant } from '../../src/types';
|
||||
import { EntityRegistryManager } from '../../src/utils/ha/entity-registry';
|
||||
import {
|
||||
TestViewMedia,
|
||||
createCameraConfig,
|
||||
createCameraManager,
|
||||
createCardAPI,
|
||||
createHASS,
|
||||
createRegistryEntity,
|
||||
createStateEntity,
|
||||
createStore,
|
||||
TestViewMedia,
|
||||
} from '../test-utils';
|
||||
import { MediaPlayerManager } from '../../src/card-controller/media-player-manager';
|
||||
import { ExtendedHomeAssistant } from '../../src/types';
|
||||
import { MEDIA_PLAYER_SUPPORT_BROWSE_MEDIA } from '../../src/const';
|
||||
import { EntityRegistryManager } from '../../src/utils/ha/entity-registry';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
|
||||
vi.mock('../../src/camera-manager/manager.js');
|
||||
|
||||
const createHASSWithMediaPlayers = (): ExtendedHomeAssistant => {
|
||||
const attributesSupported = {
|
||||
@@ -145,9 +144,7 @@ describe('MediaPlayerManager', () => {
|
||||
describe('live', () => {
|
||||
it('without camera config', async () => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getCameraConfig).mockReturnValue(null);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
const manager = new MediaPlayerManager(api);
|
||||
|
||||
@@ -159,28 +156,33 @@ describe('MediaPlayerManager', () => {
|
||||
describe('using standard method', () => {
|
||||
it('successfully', async () => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getCameraConfig).mockReturnValue(
|
||||
createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
}),
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(cameraManager.getCameraMetadata).mockReturnValue({
|
||||
vi.mocked(api.getCameraManager().getCameraMetadata).mockReturnValue({
|
||||
title: 'camera title',
|
||||
icon: 'icon',
|
||||
});
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
const hass = createHASS({
|
||||
'camera.foo': createStateEntity({
|
||||
attributes: {
|
||||
entity_picture: 'http://thumbnail',
|
||||
},
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(
|
||||
createHASS({
|
||||
'camera.foo': createStateEntity({
|
||||
attributes: {
|
||||
entity_picture: 'http://thumbnail',
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(hass);
|
||||
);
|
||||
const manager = new MediaPlayerManager(api);
|
||||
|
||||
await manager.playLive('media_player.foo', 'camera');
|
||||
await manager.playLive('media_player.foo', 'camera.foo');
|
||||
|
||||
expect(api.getHASSManager().getHASS()?.callService).toBeCalledWith(
|
||||
'media_player',
|
||||
@@ -199,32 +201,41 @@ describe('MediaPlayerManager', () => {
|
||||
|
||||
it('without camera_entity', async () => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getCameraConfig).mockReturnValue(
|
||||
createCameraConfig({}),
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig(),
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
const manager = new MediaPlayerManager(api);
|
||||
|
||||
await manager.playLive('media_player.foo', 'camera');
|
||||
await manager.playLive('media_player.foo', 'camera.foo');
|
||||
|
||||
expect(api.getHASSManager().getHASS()?.callService).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('without title and thumbnail', async () => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getCameraConfig).mockReturnValue(
|
||||
createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
}),
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
const manager = new MediaPlayerManager(api);
|
||||
|
||||
await manager.playLive('media_player.foo', 'camera');
|
||||
await manager.playLive('media_player.foo', 'camera.foo');
|
||||
|
||||
expect(api.getHASSManager().getHASS()?.callService).toBeCalledWith(
|
||||
'media_player',
|
||||
@@ -242,25 +253,29 @@ describe('MediaPlayerManager', () => {
|
||||
describe('using dashboard method', () => {
|
||||
it('successfully', async () => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getCameraConfig).mockReturnValue(
|
||||
createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
cast: {
|
||||
method: 'dashboard',
|
||||
dashboard: {
|
||||
dashboard_path: 'dashboard_path',
|
||||
view_path: 'view_path',
|
||||
},
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
cast: {
|
||||
method: 'dashboard',
|
||||
dashboard: {
|
||||
dashboard_path: 'dashboard_path',
|
||||
view_path: 'view_path',
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getQueryStringManager().generateQueryString).mockReturnValue('');
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
const manager = new MediaPlayerManager(api);
|
||||
|
||||
await manager.playLive('media_player.foo', 'camera');
|
||||
await manager.playLive('media_player.foo', 'camera.foo');
|
||||
|
||||
expect(api.getHASSManager().getHASS()?.callService).toBeCalledWith(
|
||||
'cast',
|
||||
@@ -275,24 +290,28 @@ describe('MediaPlayerManager', () => {
|
||||
|
||||
it('without hass', async () => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getCameraConfig).mockReturnValue(
|
||||
createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
cast: {
|
||||
method: 'dashboard',
|
||||
dashboard: {
|
||||
dashboard_path: 'dashboard_path',
|
||||
view_path: 'view_path',
|
||||
},
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
cast: {
|
||||
method: 'dashboard',
|
||||
dashboard: {
|
||||
dashboard_path: 'dashboard_path',
|
||||
view_path: 'view_path',
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(null);
|
||||
const manager = new MediaPlayerManager(api);
|
||||
|
||||
await manager.playLive('media_player.foo', 'camera');
|
||||
await manager.playLive('media_player.foo', 'camera.foo');
|
||||
|
||||
// No actual test can be performed here as nothing observable happens.
|
||||
// This test serves only as code-coverage long-tail.
|
||||
@@ -301,21 +320,25 @@ describe('MediaPlayerManager', () => {
|
||||
|
||||
it('without required configuration', async () => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getCameraConfig).mockReturnValue(
|
||||
createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
cast: {
|
||||
method: 'dashboard',
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.foo',
|
||||
config: createCameraConfig({
|
||||
camera_entity: 'camera.foo',
|
||||
cast: {
|
||||
method: 'dashboard',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
|
||||
const manager = new MediaPlayerManager(api);
|
||||
|
||||
await manager.playLive('media_player.foo', 'camera');
|
||||
await manager.playLive('media_player.foo', 'camera.foo');
|
||||
|
||||
expect(
|
||||
vi.mocked(api.getMessageManager().setMessageIfHigherPriority),
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('MicrophoneManager', () => {
|
||||
const manager = new MicrophoneManager(api);
|
||||
navigatorMock.mediaDevices.getUserMedia.mockRejectedValue(new Error());
|
||||
|
||||
await manager.connect();
|
||||
expect(await manager.connect()).toBeFalsy();
|
||||
|
||||
expect(manager.isConnected()).toBeFalsy();
|
||||
expect(manager.isForbidden()).toBeTruthy();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import add from 'date-fns/add';
|
||||
import { HassEntities } from 'home-assistant-js-websocket';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { ScanOptions } from '../../src/config/types';
|
||||
import { CardController } from '../../src/card-controller/controller';
|
||||
import { TriggersManager } from '../../src/card-controller/triggers-manager';
|
||||
import { ScanOptions } from '../../src/config/types';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createCameraManager,
|
||||
@@ -10,18 +11,17 @@ import {
|
||||
createConfig,
|
||||
createHASS,
|
||||
createStateEntity,
|
||||
createStore,
|
||||
createView,
|
||||
} from '../test-utils';
|
||||
|
||||
vi.mock('../../src/camera-manager/manager.js');
|
||||
|
||||
// Creating and mocking a trigger API is a lot of boilerplate, this convenience
|
||||
// function reduces it.
|
||||
const createTriggerAPI = (options?: {
|
||||
config?: Partial<ScanOptions>;
|
||||
hassStates?: HassEntities;
|
||||
interaction?: boolean;
|
||||
}) => {
|
||||
}): CardController => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
@@ -37,19 +37,18 @@ const createTriggerAPI = (options?: {
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(
|
||||
createHASS(options?.hassStates),
|
||||
);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(
|
||||
createCameraManager({
|
||||
configs: new Map([
|
||||
[
|
||||
'camera_1',
|
||||
createCameraConfig({
|
||||
triggers: {
|
||||
entities: ['binary_sensor.motion'],
|
||||
},
|
||||
}),
|
||||
],
|
||||
]),
|
||||
}),
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera_1',
|
||||
config: createCameraConfig({
|
||||
triggers: {
|
||||
entities: ['binary_sensor.motion'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getInteractionManager().hasInteraction).mockReturnValue(
|
||||
options?.interaction ?? false,
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { QueryType } from '../../src/camera-manager/types';
|
||||
import { FrigateCardView } from '../../src/config/types';
|
||||
import { getAllDependentCameras } from '../../src/utils/camera';
|
||||
import { ViewManager } from '../../src/card-controller/view-manager';
|
||||
import { FrigateCardView } from '../../src/config/types';
|
||||
import { executeMediaQueryForView } from '../../src/utils/media-to-view';
|
||||
import { EventMediaQueries } from '../../src/view/media-queries';
|
||||
import { MediaQueriesResults } from '../../src/view/media-queries-results';
|
||||
import { View } from '../../src/view/view';
|
||||
import {
|
||||
createCameraCapabilities,
|
||||
createCameraConfig,
|
||||
createCameraManager,
|
||||
createCardAPI,
|
||||
createConfig,
|
||||
createHASS,
|
||||
createStore,
|
||||
createView,
|
||||
generateViewMediaArray,
|
||||
generateViewMediaArray
|
||||
} from '../test-utils';
|
||||
|
||||
vi.mock('../../src/camera-manager/manager.js');
|
||||
vi.mock('../../src/utils/camera');
|
||||
vi.mock('../../src/utils/media-to-view');
|
||||
|
||||
describe('ViewManager.setView', () => {
|
||||
it('should set view', () => {
|
||||
@@ -29,6 +33,7 @@ describe('ViewManager.setView', () => {
|
||||
manager.setView(view);
|
||||
|
||||
expect(manager.getView()).toBe(view);
|
||||
expect(manager.hasView()).toBeTruthy();
|
||||
expect(api.getMediaLoadedInfoManager().clear).toBeCalled();
|
||||
expect(api.getCardElementManager().scrollReset).toBeCalled();
|
||||
expect(api.getMessageManager().reset).toBeCalled();
|
||||
@@ -101,6 +106,7 @@ describe('ViewManager.reset', () => {
|
||||
manager.reset();
|
||||
|
||||
expect(manager.getView()).toBeNull();
|
||||
expect(manager.hasView()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -109,6 +115,13 @@ describe('ViewManager.setViewDefault', () => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera',
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
manager.setViewDefault();
|
||||
@@ -130,12 +143,18 @@ describe('ViewManager.setViewDefault', () => {
|
||||
});
|
||||
|
||||
it('should cycle camera when configured', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera_1',
|
||||
},
|
||||
{
|
||||
cameraID: 'camera_2',
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
view: {
|
||||
@@ -160,13 +179,19 @@ describe('ViewManager.setViewDefault', () => {
|
||||
});
|
||||
|
||||
it('should respect parameters', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera.kitchen', 'camera.office']),
|
||||
);
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.office',
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
const manager = new ViewManager(api);
|
||||
|
||||
manager.setViewDefault({
|
||||
@@ -186,60 +211,84 @@ describe('ViewManager.setViewByParameters', () => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager().getCameraCapabilities).mockReturnValue(
|
||||
createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
}),
|
||||
);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
manager.setViewByParameters({
|
||||
cameraID: 'camera',
|
||||
cameraID: 'camera.kitchen',
|
||||
viewName: 'clips',
|
||||
});
|
||||
|
||||
expect(manager.getView()?.view).toBe('clips');
|
||||
expect(manager.getView()?.camera).toBe('camera');
|
||||
expect(manager.getView()?.camera).toBe('camera.kitchen');
|
||||
});
|
||||
|
||||
it('should set view by parameters using existing view if unspecified', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.office',
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager().getCameraCapabilities).mockReturnValue(
|
||||
createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
}),
|
||||
);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
manager.setViewByParameters({
|
||||
cameraID: 'camera_1',
|
||||
cameraID: 'camera.kitchen',
|
||||
viewName: 'clips',
|
||||
});
|
||||
|
||||
manager.setViewByParameters({
|
||||
cameraID: 'camera_2',
|
||||
cameraID: 'camera.office',
|
||||
});
|
||||
|
||||
expect(manager.getView()?.view).toBe('clips');
|
||||
expect(manager.getView()?.camera).toBe('camera_2');
|
||||
expect(manager.getView()?.camera).toBe('camera.office');
|
||||
});
|
||||
|
||||
it('should set view by parameters using config as fallback', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
manager.setViewByParameters({
|
||||
cameraID: 'camera_1',
|
||||
cameraID: 'camera.kitchen',
|
||||
// No prior view, and no specified view. This could happen during query
|
||||
// string based initialization.
|
||||
});
|
||||
|
||||
expect(manager.getView()?.view).toBe('live');
|
||||
expect(manager.getView()?.camera).toBe('camera_1');
|
||||
expect(manager.getView()?.camera).toBe('camera.kitchen');
|
||||
});
|
||||
|
||||
it('should not set view by parameters without config', () => {
|
||||
@@ -253,12 +302,19 @@ describe('ViewManager.setViewByParameters', () => {
|
||||
});
|
||||
|
||||
it('should not set view by parameters without visible cameras', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(new Set());
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
config: createCameraConfig({
|
||||
hide: true,
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
manager.setViewByParameters({
|
||||
@@ -278,6 +334,21 @@ describe('ViewManager.setViewByParameters', () => {
|
||||
])('%s', (viewName: FrigateCardView) => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager().getCameraCapabilities).mockReturnValue(
|
||||
createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
);
|
||||
|
||||
vi.mocked(api.getConfigManager()).getConfig.mockReturnValue(
|
||||
createConfig({
|
||||
media_viewer: {
|
||||
@@ -295,7 +366,7 @@ describe('ViewManager.setViewByParameters', () => {
|
||||
const manager = new ViewManager(api);
|
||||
|
||||
manager.setViewByParameters({
|
||||
cameraID: 'camera',
|
||||
cameraID: 'camera.kitchen',
|
||||
viewName: viewName,
|
||||
});
|
||||
|
||||
@@ -314,43 +385,31 @@ describe('ViewManager.setViewByParameters', () => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getCameraManager().getCameraCapabilities).mockReturnValue(
|
||||
createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
|
||||
manager.setViewByParameters({
|
||||
cameraID: 'camera',
|
||||
cameraID: 'camera.kitchen',
|
||||
viewName: viewName,
|
||||
});
|
||||
|
||||
expect(manager.getView()?.displayMode).toBe('single');
|
||||
});
|
||||
});
|
||||
|
||||
it('should set view by parameters using config as fallback', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(getAllDependentCameras).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_1_hd']),
|
||||
);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
manager.setViewByParameters({
|
||||
cameraID: 'camera_1',
|
||||
viewName: 'live',
|
||||
substream: 'camera_1_hd',
|
||||
});
|
||||
|
||||
expect(manager.getView()?.view).toBe('live');
|
||||
expect(manager.getView()?.camera).toBe('camera_1');
|
||||
expect(manager.getView()?.context?.live?.overrides).toEqual(
|
||||
new Map([['camera_1', 'camera_1_hd']]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// @vitest-environment jsdom
|
||||
@@ -360,6 +419,7 @@ describe('ViewManager.setViewWithNewDisplayMode', () => {
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
manager.setView(createView());
|
||||
|
||||
@@ -380,20 +440,40 @@ describe('ViewManager.setViewWithNewDisplayMode', () => {
|
||||
});
|
||||
|
||||
it('should set display mode to grid and create new query', async () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraCount).mockReturnValue(2);
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.office',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const hass = createHASS();
|
||||
vi.mocked(api.getHASSManager()).getHASS.mockReturnValue(hass);
|
||||
|
||||
const media = generateViewMediaArray({ count: 5 });
|
||||
vi.mocked(cameraManager.executeMediaQueries).mockResolvedValue(media);
|
||||
const mediaArray = generateViewMediaArray({ count: 5 });
|
||||
vi.mocked(executeMediaQueryForView).mockResolvedValue(
|
||||
new View({
|
||||
view: 'clip',
|
||||
camera: 'camera.kitchen',
|
||||
queryResults: new MediaQueriesResults({ results: mediaArray }),
|
||||
}),
|
||||
);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
const query = new EventMediaQueries([
|
||||
@@ -410,39 +490,50 @@ describe('ViewManager.setViewWithNewDisplayMode', () => {
|
||||
|
||||
await manager.setViewWithNewDisplayMode('grid');
|
||||
|
||||
expect(manager.getView()?.queryResults?.getResults()).toBe(media);
|
||||
expect(cameraManager.executeMediaQueries).toBeCalledWith(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
type: 'event-query',
|
||||
cameraIDs: new Set(['camera_1', 'camera_2']),
|
||||
hasClip: true,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
expect(manager.getView()?.queryResults?.getResults()).toBe(mediaArray);
|
||||
});
|
||||
|
||||
it('should set display mode to single and create new query', async () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraCount).mockReturnValue(2);
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.office',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const hass = createHASS();
|
||||
vi.mocked(api.getHASSManager()).getHASS.mockReturnValue(hass);
|
||||
|
||||
const media = generateViewMediaArray({ count: 5 });
|
||||
vi.mocked(cameraManager.executeMediaQueries).mockResolvedValue(media);
|
||||
const mediaArray = generateViewMediaArray({ count: 5 });
|
||||
vi.mocked(executeMediaQueryForView).mockResolvedValue(
|
||||
new View({
|
||||
view: 'clip',
|
||||
camera: 'camera.kitchen',
|
||||
queryResults: new MediaQueriesResults({ results: mediaArray }),
|
||||
}),
|
||||
);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
const query = new EventMediaQueries([
|
||||
{
|
||||
type: QueryType.Event,
|
||||
cameraIDs: new Set(['camera_1', 'camera_2']),
|
||||
cameraIDs: new Set(['camera.kitchen', 'camera.office']),
|
||||
hasClip: true,
|
||||
},
|
||||
]);
|
||||
@@ -450,53 +541,58 @@ describe('ViewManager.setViewWithNewDisplayMode', () => {
|
||||
manager.setView(
|
||||
createView({
|
||||
view: 'clip',
|
||||
camera: 'camera_2',
|
||||
camera: 'camera.office',
|
||||
query: query,
|
||||
}),
|
||||
);
|
||||
|
||||
await manager.setViewWithNewDisplayMode('single');
|
||||
|
||||
expect(manager.getView()?.queryResults?.getResults()).toBe(media);
|
||||
expect(cameraManager.executeMediaQueries).toBeCalledWith(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
type: 'event-query',
|
||||
cameraIDs: new Set(['camera_2']),
|
||||
hasClip: true,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
expect(manager.getView()?.queryResults?.getResults()).toBe(mediaArray);
|
||||
});
|
||||
|
||||
it('should set display mode to single and handle failed new query', async () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraCount).mockReturnValue(2);
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.office',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
const query = new EventMediaQueries([
|
||||
{
|
||||
type: QueryType.Event,
|
||||
cameraIDs: new Set(['camera_1', 'camera_2']),
|
||||
cameraIDs: new Set(['camera.kitchen', 'camera.office']),
|
||||
hasClip: true,
|
||||
},
|
||||
]);
|
||||
|
||||
const originalView = createView({
|
||||
view: 'clip',
|
||||
camera: 'camera_2',
|
||||
camera: 'camera.office',
|
||||
query: query,
|
||||
});
|
||||
manager.setView(originalView);
|
||||
|
||||
// Query execution fails / returns null.
|
||||
vi.mocked(cameraManager.executeMediaQueries).mockRejectedValue(null);
|
||||
vi.mocked(executeMediaQueryForView).mockRejectedValue(null);
|
||||
|
||||
await manager.setViewWithNewDisplayMode('single');
|
||||
|
||||
@@ -504,14 +600,28 @@ describe('ViewManager.setViewWithNewDisplayMode', () => {
|
||||
});
|
||||
|
||||
it('should set display mode and handle empty new query results', async () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraCount).mockReturnValue(2);
|
||||
vi.mocked(cameraManager.getStore().getVisibleCameraIDs).mockReturnValue(
|
||||
new Set(['camera_1', 'camera_2']),
|
||||
);
|
||||
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.office',
|
||||
capabilities: createCameraCapabilities({
|
||||
supportsClips: true,
|
||||
supportsRecordings: true,
|
||||
supportsSnapshots: true,
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
|
||||
|
||||
const manager = new ViewManager(api);
|
||||
@@ -519,20 +629,20 @@ describe('ViewManager.setViewWithNewDisplayMode', () => {
|
||||
const query = new EventMediaQueries([
|
||||
{
|
||||
type: QueryType.Event,
|
||||
cameraIDs: new Set(['camera_1']),
|
||||
cameraIDs: new Set(['camera.kitchen']),
|
||||
hasClip: true,
|
||||
},
|
||||
]);
|
||||
const originalView = createView({
|
||||
view: 'clip',
|
||||
camera: 'camera_2',
|
||||
camera: 'camera.office',
|
||||
query: query,
|
||||
});
|
||||
manager.setView(originalView);
|
||||
|
||||
await manager.setViewWithNewDisplayMode('grid');
|
||||
|
||||
vi.mocked(cameraManager.executeMediaQueries).mockResolvedValue(null);
|
||||
vi.mocked(executeMediaQueryForView).mockResolvedValue(null);
|
||||
|
||||
// Empty queries will not be executed, so view will not be changed.
|
||||
expect(manager.getView()?.displayMode).toBeNull();
|
||||
@@ -541,13 +651,21 @@ describe('ViewManager.setViewWithNewDisplayMode', () => {
|
||||
|
||||
describe('ViewManager.setViewWithSubstream', () => {
|
||||
it('should set new equal view with no dependencies', () => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
},
|
||||
]),
|
||||
);
|
||||
const manager = new ViewManager(api);
|
||||
const view = createView({
|
||||
view: 'live',
|
||||
camera: 'camera',
|
||||
});
|
||||
vi.mocked(getAllDependentCameras).mockReturnValue(new Set(['camera']));
|
||||
|
||||
const manager = new ViewManager(createCardAPI());
|
||||
manager.setView(view);
|
||||
manager.setViewWithSubstream();
|
||||
|
||||
@@ -557,39 +675,71 @@ describe('ViewManager.setViewWithSubstream', () => {
|
||||
});
|
||||
|
||||
it('should set new view with next substream', () => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
config: createCameraConfig({
|
||||
dependencies: {
|
||||
cameras: ['camera.kitchen_hd'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.kitchen_hd',
|
||||
},
|
||||
]),
|
||||
);
|
||||
const manager = new ViewManager(api);
|
||||
const view = createView({
|
||||
view: 'live',
|
||||
camera: 'camera',
|
||||
camera: 'camera.kitchen',
|
||||
});
|
||||
vi.mocked(getAllDependentCameras).mockReturnValue(new Set(['camera', 'camera2']));
|
||||
|
||||
const manager = new ViewManager(createCardAPI());
|
||||
manager.setView(view);
|
||||
manager.setViewWithSubstream();
|
||||
|
||||
expect(manager.getView()?.context?.live?.overrides).toEqual(
|
||||
new Map([['camera', 'camera2']]),
|
||||
new Map([['camera.kitchen', 'camera.kitchen_hd']]),
|
||||
);
|
||||
});
|
||||
|
||||
it('should set new view with next substream when view has invalid substream', () => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
config: createCameraConfig({
|
||||
dependencies: {
|
||||
cameras: ['camera.kitchen_hd'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
cameraID: 'camera.kitchen_hd',
|
||||
},
|
||||
]),
|
||||
);
|
||||
const manager = new ViewManager(api);
|
||||
const view = createView({
|
||||
view: 'live',
|
||||
camera: 'camera',
|
||||
camera: 'camera.kitchen',
|
||||
context: {
|
||||
live: {
|
||||
overrides: new Map([['camera', 'camera-that-does-not-exist']]),
|
||||
overrides: new Map([['camera.kitchen', 'camera-that-does-not-exist']]),
|
||||
},
|
||||
},
|
||||
});
|
||||
vi.mocked(getAllDependentCameras).mockReturnValue(new Set(['camera', 'camera2']));
|
||||
|
||||
const manager = new ViewManager(createCardAPI());
|
||||
manager.setView(view);
|
||||
manager.setViewWithSubstream();
|
||||
|
||||
expect(manager.getView()?.context?.live?.overrides).toEqual(
|
||||
new Map([['camera', 'camera']]),
|
||||
new Map([['camera.kitchen', 'camera.kitchen']]),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -680,17 +830,23 @@ describe('ViewManager.isViewSupportedByCamera', () => {
|
||||
['media' as const, false],
|
||||
])('%s', (viewName: FrigateCardView, expected: boolean) => {
|
||||
const api = createCardAPI();
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getCameraCapabilities).mockReturnValue({
|
||||
canFavoriteEvents: false,
|
||||
canFavoriteRecordings: false,
|
||||
canSeek: false,
|
||||
supportsClips: false,
|
||||
supportsRecordings: false,
|
||||
supportsSnapshots: false,
|
||||
supportsTimeline: false,
|
||||
});
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(cameraManager);
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
capabilities: {
|
||||
canFavoriteEvents: false,
|
||||
canFavoriteRecordings: false,
|
||||
canSeek: false,
|
||||
supportsClips: false,
|
||||
supportsRecordings: false,
|
||||
supportsSnapshots: false,
|
||||
supportsTimeline: false,
|
||||
},
|
||||
},
|
||||
]),
|
||||
);
|
||||
const manager = new ViewManager(api);
|
||||
|
||||
expect(manager.isViewSupportedByCamera('camera', viewName)).toBe(expected);
|
||||
|
||||
Reference in New Issue
Block a user