970 lines
28 KiB
TypeScript
970 lines
28 KiB
TypeScript
import endOfDay from 'date-fns/endOfDay';
|
|
import startOfDay from 'date-fns/startOfDay';
|
|
import sub from 'date-fns/sub';
|
|
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { Capabilities } from '../../src/camera-manager/capabilities';
|
|
import { CameraManagerStore } from '../../src/camera-manager/store';
|
|
import { QueryType } from '../../src/camera-manager/types';
|
|
import {
|
|
MediaFilterController,
|
|
MediaFilterCoreDefaults,
|
|
MediaFilterCoreFavoriteSelection,
|
|
MediaFilterCoreWhen,
|
|
MediaFilterMediaType,
|
|
} from '../../src/components-lib/media-filter-controller';
|
|
import { executeMediaQueryForViewWithErrorDispatching } from '../../src/utils/media-to-view';
|
|
import {
|
|
EventMediaQueries,
|
|
MediaQueries,
|
|
RecordingMediaQueries,
|
|
} from '../../src/view/media-queries';
|
|
import {
|
|
createCameraConfig,
|
|
createCameraManager,
|
|
createCapabilities,
|
|
createLitElement,
|
|
createPerformanceConfig,
|
|
createStore,
|
|
createView,
|
|
} from '../test-utils';
|
|
|
|
vi.mock('../../src/utils/media-to-view');
|
|
|
|
const createCameraStore = (options?: {
|
|
capabilities: Capabilities;
|
|
}): CameraManagerStore => {
|
|
return createStore([
|
|
{
|
|
cameraID: 'camera.kitchen',
|
|
config: createCameraConfig({
|
|
camera_entity: 'camera.kitchen',
|
|
}),
|
|
capabilities:
|
|
options?.capabilities ??
|
|
new Capabilities({
|
|
clips: true,
|
|
snapshots: true,
|
|
recordings: true,
|
|
}),
|
|
},
|
|
]);
|
|
};
|
|
|
|
// @vitest-environment jsdom
|
|
describe('MediaFilterController', () => {
|
|
beforeEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe('should have correct default options', () => {
|
|
it('media type', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getMediaTypeOptions()).toEqual([
|
|
{
|
|
value: MediaFilterMediaType.Clips,
|
|
label: 'Clips',
|
|
},
|
|
{
|
|
value: MediaFilterMediaType.Snapshots,
|
|
label: 'Snapshots',
|
|
},
|
|
{
|
|
value: MediaFilterMediaType.Recordings,
|
|
label: 'Recordings',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('favorite', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getFavoriteOptions()).toEqual([
|
|
{
|
|
value: MediaFilterCoreFavoriteSelection.Favorite,
|
|
label: 'Favorite',
|
|
},
|
|
{
|
|
value: MediaFilterCoreFavoriteSelection.NotFavorite,
|
|
label: 'Not Favorite',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('when', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getWhenOptions()).toEqual([
|
|
{
|
|
value: MediaFilterCoreWhen.Today,
|
|
label: 'Today',
|
|
},
|
|
{
|
|
value: MediaFilterCoreWhen.Yesterday,
|
|
label: 'Yesterday',
|
|
},
|
|
{
|
|
value: MediaFilterCoreWhen.PastWeek,
|
|
label: 'Past Week',
|
|
},
|
|
{
|
|
value: MediaFilterCoreWhen.PastMonth,
|
|
label: 'Past Month',
|
|
},
|
|
{
|
|
value: MediaFilterCoreWhen.Custom,
|
|
label: 'Custom',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('cameras', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getCameraOptions()).toEqual([]);
|
|
});
|
|
|
|
it('what', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getWhatOptions()).toEqual([]);
|
|
});
|
|
|
|
it('where', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getWhereOptions()).toEqual([]);
|
|
});
|
|
|
|
it('tags', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getTagsOptions()).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('should calculate correct dynamic options', () => {
|
|
describe('cameras', () => {
|
|
it('with valid camera', () => {
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getCameraMetadata).mockReturnValue({
|
|
title: 'Kitchen Camera',
|
|
icon: 'mdi:camera',
|
|
});
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
controller.computeCameraOptions(cameraManager);
|
|
expect(controller.getCameraOptions()).toEqual([
|
|
{
|
|
label: 'Kitchen Camera',
|
|
value: 'camera.kitchen',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('with camera that does not support media', () => {
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getCameraMetadata).mockReturnValue({
|
|
title: 'Kitchen Camera',
|
|
icon: 'mdi:camera',
|
|
});
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(
|
|
createCameraStore({
|
|
capabilities: new Capabilities({
|
|
clips: false,
|
|
snapshots: false,
|
|
recordings: false,
|
|
}),
|
|
}),
|
|
);
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
controller.computeCameraOptions(cameraManager);
|
|
expect(controller.getCameraOptions()).toEqual([]);
|
|
});
|
|
|
|
it('without camera metadata', () => {
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getCameraMetadata).mockReturnValue(null);
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
controller.computeCameraOptions(cameraManager);
|
|
expect(controller.getCameraOptions()).toEqual([
|
|
{
|
|
label: 'camera.kitchen',
|
|
value: 'camera.kitchen',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('metadata', () => {
|
|
it('with failed getMediaMetadata call', async () => {
|
|
vi.spyOn(global.console, 'warn').mockReturnValue(undefined);
|
|
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getMediaMetadata).mockRejectedValue(new Error('error'));
|
|
|
|
const host = createLitElement();
|
|
const controller = new MediaFilterController(host);
|
|
await controller.computeMetadataOptions(cameraManager);
|
|
expect(host.requestUpdate).not.toBeCalled();
|
|
});
|
|
|
|
it('with metadata for what', async () => {
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getMediaMetadata).mockResolvedValue({
|
|
what: new Set(['person', 'car']),
|
|
});
|
|
|
|
const host = createLitElement();
|
|
const controller = new MediaFilterController(host);
|
|
await controller.computeMetadataOptions(cameraManager);
|
|
expect(controller.getWhatOptions()).toEqual([
|
|
{
|
|
value: 'car',
|
|
label: 'Car',
|
|
},
|
|
{
|
|
value: 'person',
|
|
label: 'Person',
|
|
},
|
|
]);
|
|
expect(host.requestUpdate).toBeCalled();
|
|
});
|
|
|
|
it('with metadata for where', async () => {
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getMediaMetadata).mockResolvedValue({
|
|
where: new Set(['front_door', 'back_yard']),
|
|
});
|
|
|
|
const host = createLitElement();
|
|
const controller = new MediaFilterController(host);
|
|
await controller.computeMetadataOptions(cameraManager);
|
|
expect(controller.getWhereOptions()).toEqual([
|
|
{
|
|
value: 'back_yard',
|
|
label: 'Back Yard',
|
|
},
|
|
{
|
|
value: 'front_door',
|
|
label: 'Front Door',
|
|
},
|
|
]);
|
|
expect(host.requestUpdate).toBeCalled();
|
|
});
|
|
|
|
it('with metadata for tags', async () => {
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getMediaMetadata).mockResolvedValue({
|
|
tags: new Set(['tag-1', 'tag-2']),
|
|
});
|
|
|
|
const host = createLitElement();
|
|
const controller = new MediaFilterController(host);
|
|
await controller.computeMetadataOptions(cameraManager);
|
|
expect(controller.getTagsOptions()).toEqual([
|
|
{
|
|
value: 'tag-1',
|
|
label: 'Tag-1',
|
|
},
|
|
{
|
|
value: 'tag-2',
|
|
label: 'Tag-2',
|
|
},
|
|
]);
|
|
expect(host.requestUpdate).toBeCalled();
|
|
});
|
|
|
|
it('with metadata for days', async () => {
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getMediaMetadata).mockResolvedValue({
|
|
days: new Set(['2024-02-04', '2024-02-05']),
|
|
});
|
|
|
|
const host = createLitElement();
|
|
const controller = new MediaFilterController(host);
|
|
await controller.computeMetadataOptions(cameraManager);
|
|
|
|
expect(controller.getWhenOptions()).toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({
|
|
value: '2024-02-01,2024-02-29',
|
|
label: 'February 2024',
|
|
}),
|
|
]),
|
|
);
|
|
expect(host.requestUpdate).toBeCalled();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('should get correct controls to show', () => {
|
|
it('view with events', () => {
|
|
const view = createView({ query: new EventMediaQueries() });
|
|
const cameraManager = createCameraManager();
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getControlsToShow(cameraManager, view)).toMatchObject({
|
|
events: true,
|
|
recordings: false,
|
|
});
|
|
});
|
|
|
|
it('view with recordings', () => {
|
|
const view = createView({ query: new RecordingMediaQueries() });
|
|
const cameraManager = createCameraManager();
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getControlsToShow(cameraManager, view)).toMatchObject({
|
|
events: false,
|
|
recordings: true,
|
|
});
|
|
});
|
|
|
|
it('can favorite events', () => {
|
|
const view = createView({ query: new EventMediaQueries() });
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getAggregateCameraCapabilities).mockReturnValue(
|
|
createCapabilities({ 'favorite-events': true }),
|
|
);
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getControlsToShow(cameraManager, view)).toMatchObject({
|
|
favorites: true,
|
|
});
|
|
});
|
|
|
|
it('can favorite recordings', () => {
|
|
const view = createView({ query: new RecordingMediaQueries() });
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getAggregateCameraCapabilities).mockReturnValue(
|
|
createCapabilities({ 'favorite-recordings': true }),
|
|
);
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getControlsToShow(cameraManager, view)).toMatchObject({
|
|
favorites: true,
|
|
});
|
|
});
|
|
|
|
it('can not favorite without a query', () => {
|
|
const view = createView();
|
|
const cameraManager = createCameraManager();
|
|
|
|
const controller = new MediaFilterController(createLitElement());
|
|
expect(controller.getControlsToShow(cameraManager, view)).toMatchObject({
|
|
favorites: false,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('should handle value change', () => {
|
|
it('must have visible cameras', async () => {
|
|
const host = createLitElement();
|
|
const controller = new MediaFilterController(host);
|
|
await controller.valueChangeHandler(
|
|
createCameraManager(),
|
|
createView(),
|
|
{},
|
|
{ when: {} },
|
|
);
|
|
|
|
expect(host.requestUpdate).not.toBeCalled();
|
|
});
|
|
|
|
describe('with events media type', () => {
|
|
it.each([['clips' as const], ['snapshots' as const]])(
|
|
'%s',
|
|
async (viewName: 'clips' | 'snapshots') => {
|
|
const eventListener = vi.fn();
|
|
const host = createLitElement();
|
|
host.addEventListener('frigate-card:view:change', eventListener);
|
|
|
|
const controller = new MediaFilterController(host);
|
|
const cameraManager = createCameraManager();
|
|
const view = createView();
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
vi.mocked(executeMediaQueryForViewWithErrorDispatching).mockResolvedValueOnce(
|
|
view,
|
|
);
|
|
|
|
const from = new Date('2024-02-06T21:59');
|
|
const to = new Date('2024-02-06T22:00');
|
|
|
|
await controller.valueChangeHandler(
|
|
cameraManager,
|
|
view,
|
|
{
|
|
performance: createPerformanceConfig({
|
|
features: {
|
|
media_chunk_size: 11,
|
|
},
|
|
}),
|
|
},
|
|
{
|
|
mediaType:
|
|
viewName === 'clips'
|
|
? MediaFilterMediaType.Clips
|
|
: MediaFilterMediaType.Snapshots,
|
|
when: {
|
|
to: to,
|
|
from: from,
|
|
},
|
|
tags: ['tag-1', 'tag-2'],
|
|
what: ['what-1', 'what-2'],
|
|
where: ['where-1', 'where-2'],
|
|
favorite: MediaFilterCoreFavoriteSelection.Favorite,
|
|
},
|
|
);
|
|
|
|
expect(vi.mocked(executeMediaQueryForViewWithErrorDispatching)).toBeCalledWith(
|
|
host,
|
|
cameraManager,
|
|
view,
|
|
expect.anything(),
|
|
{
|
|
targetCameraID: 'camera.kitchen',
|
|
targetView: viewName,
|
|
},
|
|
);
|
|
expect(
|
|
vi
|
|
.mocked(executeMediaQueryForViewWithErrorDispatching)
|
|
.mock.calls[0][3].getQueries(),
|
|
).toEqual([
|
|
{
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
...(viewName === 'clips' && { hasClip: true }),
|
|
...(viewName === 'snapshots' && { hasSnapshot: true }),
|
|
type: 'event-query',
|
|
tags: new Set(['tag-1', 'tag-2']),
|
|
what: new Set(['what-1', 'what-2']),
|
|
where: new Set(['where-1', 'where-2']),
|
|
favorite: true,
|
|
start: from,
|
|
end: to,
|
|
limit: 11,
|
|
},
|
|
]);
|
|
|
|
expect(eventListener).toBeCalled();
|
|
expect(host.requestUpdate).toBeCalled();
|
|
},
|
|
);
|
|
});
|
|
|
|
it('with recordings media type', async () => {
|
|
const eventListener = vi.fn();
|
|
const host = createLitElement();
|
|
host.addEventListener('frigate-card:view:change', eventListener);
|
|
|
|
const controller = new MediaFilterController(host);
|
|
const cameraManager = createCameraManager();
|
|
const view = createView();
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
vi.mocked(executeMediaQueryForViewWithErrorDispatching).mockResolvedValueOnce(
|
|
view,
|
|
);
|
|
|
|
const from = new Date('2024-02-06T21:59');
|
|
const to = new Date('2024-02-06T22:00');
|
|
|
|
await controller.valueChangeHandler(
|
|
cameraManager,
|
|
view,
|
|
{
|
|
performance: createPerformanceConfig({
|
|
features: {
|
|
media_chunk_size: 11,
|
|
},
|
|
}),
|
|
},
|
|
{
|
|
mediaType: MediaFilterMediaType.Recordings,
|
|
when: {
|
|
to: to,
|
|
from: from,
|
|
},
|
|
favorite: MediaFilterCoreFavoriteSelection.Favorite,
|
|
},
|
|
);
|
|
|
|
expect(vi.mocked(executeMediaQueryForViewWithErrorDispatching)).toBeCalledWith(
|
|
host,
|
|
cameraManager,
|
|
view,
|
|
expect.anything(),
|
|
{
|
|
targetCameraID: 'camera.kitchen',
|
|
targetView: 'recordings',
|
|
},
|
|
);
|
|
expect(
|
|
vi
|
|
.mocked(executeMediaQueryForViewWithErrorDispatching)
|
|
.mock.calls[0][3].getQueries(),
|
|
).toEqual([
|
|
{
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
type: 'recording-query',
|
|
favorite: true,
|
|
start: from,
|
|
end: to,
|
|
limit: 11,
|
|
},
|
|
]);
|
|
|
|
expect(eventListener).toBeCalled();
|
|
expect(host.requestUpdate).toBeCalled();
|
|
});
|
|
|
|
it('without favorites', async () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
|
|
await controller.valueChangeHandler(
|
|
cameraManager,
|
|
createView(),
|
|
{},
|
|
{
|
|
mediaType: MediaFilterMediaType.Recordings,
|
|
when: {},
|
|
},
|
|
);
|
|
|
|
expect(
|
|
vi
|
|
.mocked(executeMediaQueryForViewWithErrorDispatching)
|
|
.mock.calls[0][3].getQueries(),
|
|
).toEqual([
|
|
{
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
type: 'recording-query',
|
|
},
|
|
]);
|
|
});
|
|
|
|
describe('with fixed when selection', () => {
|
|
const date = new Date('2024-10-01T17:14');
|
|
|
|
beforeAll(() => {
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(date);
|
|
});
|
|
|
|
afterAll(() => {
|
|
vi.useFakeTimers();
|
|
});
|
|
|
|
it.each([
|
|
[MediaFilterCoreWhen.Today, startOfDay(date), endOfDay(date)],
|
|
[
|
|
MediaFilterCoreWhen.Yesterday,
|
|
startOfDay(sub(date, { days: 1 })),
|
|
endOfDay(sub(date, { days: 1 })),
|
|
],
|
|
[
|
|
MediaFilterCoreWhen.PastWeek,
|
|
startOfDay(sub(date, { days: 7 })),
|
|
endOfDay(date),
|
|
],
|
|
[
|
|
MediaFilterCoreWhen.PastMonth,
|
|
startOfDay(sub(date, { months: 1 })),
|
|
endOfDay(date),
|
|
],
|
|
[
|
|
'2024-02-01,2024-02-29',
|
|
new Date('2024-02-01T00:00:00'),
|
|
new Date('2024-02-29T23:59:59.999'),
|
|
],
|
|
])('%s', async (value: MediaFilterCoreWhen | string, from: Date, to: Date) => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
|
|
await controller.valueChangeHandler(
|
|
cameraManager,
|
|
createView(),
|
|
{},
|
|
{
|
|
mediaType: MediaFilterMediaType.Recordings,
|
|
when: {
|
|
selected: value,
|
|
},
|
|
},
|
|
);
|
|
|
|
expect(
|
|
vi
|
|
.mocked(executeMediaQueryForViewWithErrorDispatching)
|
|
.mock.calls[0][3].getQueries(),
|
|
).toEqual([
|
|
{
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
type: 'recording-query',
|
|
start: from,
|
|
end: to,
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('custom without values', async () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
|
|
await controller.valueChangeHandler(
|
|
cameraManager,
|
|
createView(),
|
|
{},
|
|
{
|
|
mediaType: MediaFilterMediaType.Recordings,
|
|
when: {
|
|
selected: MediaFilterCoreWhen.Custom,
|
|
},
|
|
},
|
|
);
|
|
|
|
expect(
|
|
vi
|
|
.mocked(executeMediaQueryForViewWithErrorDispatching)
|
|
.mock.calls[0][3].getQueries(),
|
|
).toEqual([
|
|
{
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
type: 'recording-query',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('should calculate correct defaults', () => {
|
|
it('with no queries', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
|
|
controller.computeInitialDefaultsFromView(createCameraManager(), createView());
|
|
|
|
expect(controller.getDefaults()).toBeNull();
|
|
});
|
|
|
|
it('with no cameras', () => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
|
|
controller.computeInitialDefaultsFromView(
|
|
createCameraManager(),
|
|
createView({
|
|
query: new EventMediaQueries([
|
|
{ type: QueryType.Event, cameraIDs: new Set(['camera.kitchen']) },
|
|
]),
|
|
}),
|
|
);
|
|
|
|
expect(controller.getDefaults()).toBeNull();
|
|
});
|
|
|
|
describe('for queries', () => {
|
|
it.each([
|
|
[
|
|
'same cameras' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen', 'camera.living_room']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen', 'camera.living_room']),
|
|
},
|
|
]),
|
|
{
|
|
cameraIDs: ['camera.kitchen', 'camera.living_room'],
|
|
},
|
|
],
|
|
[
|
|
'different cameras' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.living_room']),
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'all cameras' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'different favorites ' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
favorite: true,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
favorite: undefined,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
favorite: false,
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'all favorites' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
favorite: true,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
favorite: true,
|
|
},
|
|
]),
|
|
{
|
|
favorite: MediaFilterCoreFavoriteSelection.Favorite,
|
|
},
|
|
],
|
|
[
|
|
'all not favorites' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
favorite: false,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
favorite: false,
|
|
},
|
|
]),
|
|
{
|
|
favorite: MediaFilterCoreFavoriteSelection.NotFavorite,
|
|
},
|
|
],
|
|
[
|
|
'same hasClip' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasClip: true,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasClip: true,
|
|
},
|
|
]),
|
|
{
|
|
mediaType: MediaFilterMediaType.Clips,
|
|
},
|
|
],
|
|
[
|
|
'different hasClip' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasClip: true,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasClip: false,
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'same hasSnapshot' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasSnapshot: true,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasSnapshot: true,
|
|
},
|
|
]),
|
|
{
|
|
mediaType: MediaFilterMediaType.Snapshots,
|
|
},
|
|
],
|
|
[
|
|
'different hasSnapshot' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasSnapshot: true,
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
hasSnapshot: false,
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'same what' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
what: new Set(['person']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
what: new Set(['person']),
|
|
},
|
|
]),
|
|
{
|
|
what: ['person' as const],
|
|
},
|
|
],
|
|
[
|
|
'different what' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
what: new Set(['person']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
what: new Set(['car']),
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'same where' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
where: new Set(['front_door']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
where: new Set(['front_door']),
|
|
},
|
|
]),
|
|
{
|
|
where: ['front_door' as const],
|
|
},
|
|
],
|
|
[
|
|
'different where' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
where: new Set(['front_door']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
where: new Set(['back_steps']),
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'same tags' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
tags: new Set(['tag-1']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
tags: new Set(['tag-1']),
|
|
},
|
|
]),
|
|
{
|
|
tags: ['tag-1' as const],
|
|
},
|
|
],
|
|
[
|
|
'different tags' as const,
|
|
new EventMediaQueries([
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
tags: new Set(['tag-1']),
|
|
},
|
|
{
|
|
type: QueryType.Event,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
tags: new Set(['tag-2']),
|
|
},
|
|
]),
|
|
{},
|
|
],
|
|
[
|
|
'recordings' as const,
|
|
new RecordingMediaQueries([
|
|
{
|
|
type: QueryType.Recording,
|
|
cameraIDs: new Set(['camera.kitchen']),
|
|
},
|
|
]),
|
|
{
|
|
mediaType: MediaFilterMediaType.Recordings,
|
|
},
|
|
],
|
|
])(
|
|
'%s',
|
|
(
|
|
_name: string,
|
|
mediaQueries: MediaQueries,
|
|
defaults: MediaFilterCoreDefaults | null,
|
|
) => {
|
|
const controller = new MediaFilterController(createLitElement());
|
|
const cameraManager = createCameraManager();
|
|
vi.mocked(cameraManager.getStore).mockReturnValue(createCameraStore());
|
|
|
|
controller.computeInitialDefaultsFromView(
|
|
cameraManager,
|
|
createView({
|
|
query: mediaQueries,
|
|
}),
|
|
);
|
|
|
|
expect(controller.getDefaults()).toEqual(defaults);
|
|
},
|
|
);
|
|
});
|
|
});
|
|
});
|