fix: Timeline should should show folder media even without camera support (#2216)
- Closes #2205
This commit is contained in:
@@ -253,7 +253,7 @@ describe('getViewByParameters', () => {
|
||||
view: 'snapshots',
|
||||
},
|
||||
}),
|
||||
).toThrowError(/The selected camera does not support this view/);
|
||||
).toThrowError(/The selected camera or media does not support this view/);
|
||||
});
|
||||
|
||||
it('should choose live view with failsafe', () => {
|
||||
|
||||
@@ -11,18 +11,11 @@ import {
|
||||
} from '../../../src/card-controller/view/types';
|
||||
import { ViewManager } from '../../../src/card-controller/view/view-manager';
|
||||
import { ViewQueryExecutor } from '../../../src/card-controller/view/view-query-executor';
|
||||
import { AdvancedCameraCardView } from '../../../src/config/schema/common/const';
|
||||
import { ViewMedia, ViewMediaType } from '../../../src/view/item';
|
||||
import { EventMediaQuery } from '../../../src/view/query';
|
||||
import { QueryResults } from '../../../src/view/query-results';
|
||||
import { View } from '../../../src/view/view';
|
||||
import {
|
||||
createCameraManager,
|
||||
createCapabilities,
|
||||
createCardAPI,
|
||||
createStore,
|
||||
createView,
|
||||
} from '../../test-utils';
|
||||
import { createCardAPI, createView } from '../../test-utils';
|
||||
|
||||
const createInitializedCardAPI = (initialized?: boolean): CardController => {
|
||||
const api = createCardAPI();
|
||||
@@ -301,44 +294,6 @@ describe('should handle exceptions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isViewSupportedByCamera', () => {
|
||||
it.each([
|
||||
['live' as const, false],
|
||||
['image' as const, true],
|
||||
['diagnostics' as const, true],
|
||||
['clip' as const, false],
|
||||
['clips' as const, false],
|
||||
['snapshot' as const, false],
|
||||
['snapshots' as const, false],
|
||||
['recording' as const, false],
|
||||
['recordings' as const, false],
|
||||
['timeline' as const, false],
|
||||
['media' as const, true],
|
||||
])('%s', (viewName: AdvancedCameraCardView, expected: boolean) => {
|
||||
const api = createInitializedCardAPI();
|
||||
vi.mocked(api.getCameraManager).mockReturnValue(createCameraManager());
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera.kitchen',
|
||||
capabilities: createCapabilities({
|
||||
live: false,
|
||||
'favorite-events': false,
|
||||
'favorite-recordings': false,
|
||||
seek: false,
|
||||
clips: false,
|
||||
recordings: false,
|
||||
snapshots: false,
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
const manager = new ViewManager(api);
|
||||
|
||||
expect(manager.isViewSupportedByCamera('camera', viewName)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasMajorMediaChange', () => {
|
||||
it('should consider undefined views as major', () => {
|
||||
const manager = new ViewManager(createCardAPI());
|
||||
|
||||
@@ -23,6 +23,10 @@ import { createGeneralAction, createViewAction } from '../../src/utils/action.js
|
||||
import { ViewMedia, ViewMediaType } from '../../src/view/item.js';
|
||||
import { QueryResults } from '../../src/view/query-results.js';
|
||||
import { FolderViewQuery } from '../../src/view/query.js';
|
||||
import {
|
||||
getCameraIDsForViewName,
|
||||
isViewSupportedByCamera,
|
||||
} from '../../src/view/view-support.js';
|
||||
import { View } from '../../src/view/view.js';
|
||||
import {
|
||||
createCameraConfig,
|
||||
@@ -39,6 +43,7 @@ import {
|
||||
TestViewMedia,
|
||||
} from '../test-utils.js';
|
||||
|
||||
vi.mock('../../src/view/view-support.js');
|
||||
vi.mock('../../src/utils/media-player-controller.js');
|
||||
vi.mock('../../src/card-controller/microphone-manager.js');
|
||||
|
||||
@@ -498,7 +503,7 @@ describe('MenuButtonController', () => {
|
||||
describe('should have live menu button', () => {
|
||||
it('when in live view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'live' }),
|
||||
viewManager: viewManager,
|
||||
@@ -517,7 +522,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not in live view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'clips' }),
|
||||
viewManager: viewManager,
|
||||
@@ -536,7 +541,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not supported', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(false);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(false);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -552,7 +557,7 @@ describe('MenuButtonController', () => {
|
||||
describe('should have clips menu button', () => {
|
||||
it('when in clips view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'clips' }),
|
||||
viewManager: viewManager,
|
||||
@@ -572,7 +577,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not in clips view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -591,7 +596,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not supported', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(false);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(false);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -605,7 +610,7 @@ describe('MenuButtonController', () => {
|
||||
describe('should have snapshots menu button', () => {
|
||||
it('when in snapshots view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'snapshots' }),
|
||||
viewManager: viewManager,
|
||||
@@ -631,7 +636,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not in snapshots view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -656,7 +661,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not supported', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(false);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(false);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -672,7 +677,7 @@ describe('MenuButtonController', () => {
|
||||
describe('should have recordings menu button', () => {
|
||||
it('when in recordings view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'recordings' }),
|
||||
viewManager: viewManager,
|
||||
@@ -698,7 +703,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not in recordings view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -723,7 +728,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not supported', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(false);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(false);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -739,7 +744,7 @@ describe('MenuButtonController', () => {
|
||||
describe('should have image menu button', () => {
|
||||
it('when in image view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'image' }),
|
||||
@@ -759,7 +764,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not in image view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'live' }),
|
||||
@@ -779,7 +784,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not supported', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(false);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(false);
|
||||
const buttons = calculateButtons(controller, {
|
||||
viewManager: viewManager,
|
||||
});
|
||||
@@ -795,7 +800,7 @@ describe('MenuButtonController', () => {
|
||||
describe('should have timeline button', () => {
|
||||
it('when in timeline view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'timeline' }),
|
||||
viewManager: viewManager,
|
||||
@@ -817,7 +822,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not in timeline view', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(true);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(true);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'live' }),
|
||||
viewManager: viewManager,
|
||||
@@ -839,7 +844,7 @@ describe('MenuButtonController', () => {
|
||||
|
||||
it('when not supported', () => {
|
||||
const viewManager = mock<ViewManager>();
|
||||
vi.mocked(viewManager.isViewSupportedByCamera).mockReturnValue(false);
|
||||
vi.mocked(isViewSupportedByCamera).mockReturnValue(false);
|
||||
const buttons = calculateButtons(controller, {
|
||||
view: createView({ view: 'live' }),
|
||||
viewManager: viewManager,
|
||||
@@ -1476,6 +1481,10 @@ describe('MenuButtonController', () => {
|
||||
]),
|
||||
);
|
||||
|
||||
vi.mocked(getCameraIDsForViewName).mockReturnValue(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
|
||||
expect(
|
||||
calculateButtons(controller, { cameraManager: cameraManager, view: view }),
|
||||
).toContainEqual({
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { QueryType } from '../../src/camera-manager/types';
|
||||
import { AdvancedCameraCardView } from '../../src/config/schema/common/const';
|
||||
import { CapabilityKey } from '../../src/types';
|
||||
import { getCameraIDsForViewName } from '../../src/view/view-to-cameras';
|
||||
import { EventMediaQuery } from '../../src/view/query';
|
||||
import { QueryResults } from '../../src/view/query-results';
|
||||
import {
|
||||
getCameraIDsForViewName,
|
||||
isViewSupportedByCamera,
|
||||
isViewSupportedByQueryOnly,
|
||||
} from '../../src/view/view-support';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createCameraManager,
|
||||
createCapabilities,
|
||||
createStore,
|
||||
generateViewMediaArray,
|
||||
} from '../test-utils';
|
||||
|
||||
describe('getCameraIDsForViewName', () => {
|
||||
@@ -29,13 +37,13 @@ describe('getCameraIDsForViewName', () => {
|
||||
]),
|
||||
);
|
||||
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName)).toEqual(
|
||||
expect(getCameraIDsForViewName(viewName, cameraManager)).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-1')).toEqual(
|
||||
expect(getCameraIDsForViewName(viewName, cameraManager, 'camera-1')).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-2')).toEqual(
|
||||
expect(getCameraIDsForViewName(viewName, cameraManager, 'camera-2')).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
});
|
||||
@@ -62,7 +70,7 @@ describe('getCameraIDsForViewName', () => {
|
||||
]),
|
||||
);
|
||||
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName)).toEqual(
|
||||
expect(getCameraIDsForViewName(viewName, cameraManager)).toEqual(
|
||||
new Set(['camera-2']),
|
||||
);
|
||||
});
|
||||
@@ -89,15 +97,81 @@ describe('getCameraIDsForViewName', () => {
|
||||
]),
|
||||
);
|
||||
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName)).toEqual(
|
||||
expect(getCameraIDsForViewName(viewName, cameraManager)).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-1')).toEqual(
|
||||
expect(getCameraIDsForViewName(viewName, cameraManager, 'camera-1')).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-2')).toEqual(
|
||||
expect(getCameraIDsForViewName(viewName, cameraManager, 'camera-2')).toEqual(
|
||||
new Set(['camera-2']),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isViewSupportedByCamera', () => {
|
||||
it('should return true for supported view', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera-1',
|
||||
capabilities: createCapabilities({ live: true }),
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
expect(isViewSupportedByCamera('live', cameraManager, 'camera-1')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for unsupported view', () => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera-1',
|
||||
capabilities: createCapabilities({ live: false }),
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
expect(isViewSupportedByCamera('live', cameraManager, 'camera-1')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isViewSupportedByQueryOnly', () => {
|
||||
it.each([
|
||||
['live' as const],
|
||||
['image' as const],
|
||||
['diagnostics' as const],
|
||||
['clip' as const],
|
||||
['clips' as const],
|
||||
['snapshot' as const],
|
||||
['snapshots' as const],
|
||||
['recording' as const],
|
||||
['recordings' as const],
|
||||
['media' as const],
|
||||
])('%s', (viewName: AdvancedCameraCardView) => {
|
||||
expect(isViewSupportedByQueryOnly(viewName)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for timeline without query', () => {
|
||||
expect(isViewSupportedByQueryOnly('timeline')).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for timeline with query and query results', () => {
|
||||
const query = new EventMediaQuery([
|
||||
{
|
||||
type: QueryType.Event,
|
||||
cameraIDs: new Set(['camera-1']),
|
||||
},
|
||||
]);
|
||||
const queryResults = new QueryResults({
|
||||
results: generateViewMediaArray({ count: 5 }),
|
||||
selectedIndex: 0,
|
||||
});
|
||||
|
||||
expect(isViewSupportedByQueryOnly('timeline', query, queryResults)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user