feat: Add support for Frigate reviews / detections [initial PR] (#2315)
- Add support for Frigate reviews / detections. - Add support for GenAI metadata. - Significant internal refactor to more flexible "UnifiedQuery" to allow mixing cameras with simple metadata and review metadata (e.g. a timeline view of a Frigate camera with reviews, and a Reolink camera with simple metadata). - Add support for folder media as camera media. There are a few more PRs to commit prior to this going live, but commiting this for now due to the scale of the change. BREAKING CHANGE: `media_type` and `events_type` are retired under `live`, `viewer` and `timeline` configuration sections, instead media type is associated (once) with the camera under `media`.
This commit is contained in:
@@ -4,6 +4,7 @@ import { FoldersExecutor } from '../../../src/card-controller/folders/executor';
|
||||
import { HAFoldersEngine } from '../../../src/card-controller/folders/ha/engine';
|
||||
import { FolderQuery } from '../../../src/card-controller/folders/types';
|
||||
import { FolderConfig } from '../../../src/config/schema/folders';
|
||||
import { QuerySource } from '../../../src/query-source';
|
||||
import { Endpoint } from '../../../src/types';
|
||||
import { ViewFolder } from '../../../src/view/item';
|
||||
import { createFolder, createHASS, TestViewMedia } from '../../test-utils';
|
||||
@@ -53,6 +54,34 @@ describe('FoldersExecutor', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefaultQueryParameters', () => {
|
||||
it('should return null for non-existent folder engine', () => {
|
||||
const folder: FolderConfig = {
|
||||
type: 'UNKNOWN',
|
||||
} as unknown as FolderConfig;
|
||||
const executor = new FoldersExecutor();
|
||||
|
||||
expect(executor.getDefaultQueryParameters(folder)).toBeNull();
|
||||
});
|
||||
|
||||
it('should get default query parameters for HA folder engine', () => {
|
||||
const folder = createFolder();
|
||||
const haFolderEngine = mock<HAFoldersEngine>();
|
||||
const expectedQuery: FolderQuery = {
|
||||
source: QuerySource.Folder,
|
||||
folder: folder,
|
||||
path: [{}],
|
||||
};
|
||||
haFolderEngine.getDefaultQueryParameters.mockReturnValue(expectedQuery);
|
||||
|
||||
const executor = new FoldersExecutor({
|
||||
ha: haFolderEngine,
|
||||
});
|
||||
|
||||
expect(executor.getDefaultQueryParameters(folder)).toEqual(expectedQuery);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDownloadPath', () => {
|
||||
it('should not get download path for non-existent folder engine', async () => {
|
||||
const folder: FolderConfig = {
|
||||
@@ -105,39 +134,15 @@ describe('FoldersExecutor', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateDefaultFolderQuery', () => {
|
||||
it('should generate default folder query', () => {
|
||||
const folder: FolderConfig = createFolder();
|
||||
const query: FolderQuery = {
|
||||
folder,
|
||||
path: [{ ha: { id: 'media-source://' } }],
|
||||
};
|
||||
|
||||
const haFolderEngine = mock<HAFoldersEngine>();
|
||||
haFolderEngine.generateDefaultFolderQuery.mockReturnValue(query);
|
||||
const executor = new FoldersExecutor({ ha: haFolderEngine });
|
||||
|
||||
expect(executor.generateDefaultFolderQuery(folder)).toEqual(query);
|
||||
});
|
||||
|
||||
it('should return null for non-existent folder engine', () => {
|
||||
const folder: FolderConfig = {
|
||||
type: 'UNKNOWN',
|
||||
} as unknown as FolderConfig;
|
||||
const executor = new FoldersExecutor();
|
||||
|
||||
expect(executor.generateDefaultFolderQuery(folder)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateChildFolderQuery', () => {
|
||||
it('should generate child folder query', () => {
|
||||
const folder: FolderConfig = createFolder();
|
||||
const query: FolderQuery = {
|
||||
source: QuerySource.Folder,
|
||||
folder,
|
||||
path: [{ ha: { id: 'media-source://' } }],
|
||||
};
|
||||
const viewFolder = new ViewFolder(folder);
|
||||
const viewFolder = new ViewFolder(folder, []);
|
||||
|
||||
const haFolderEngine = mock<HAFoldersEngine>();
|
||||
haFolderEngine.generateChildFolderQuery.mockReturnValue(query);
|
||||
@@ -152,10 +157,11 @@ describe('FoldersExecutor', () => {
|
||||
type: 'UNKNOWN',
|
||||
} as unknown as FolderConfig;
|
||||
const query: FolderQuery = {
|
||||
source: QuerySource.Folder,
|
||||
folder,
|
||||
path: [{ ha: { id: 'media-source://' } }],
|
||||
};
|
||||
const viewFolder = new ViewFolder(folder);
|
||||
const viewFolder = new ViewFolder(folder, []);
|
||||
const executor = new FoldersExecutor();
|
||||
|
||||
expect(executor.generateChildFolderQuery(query, viewFolder)).toBeNull();
|
||||
@@ -176,6 +182,7 @@ describe('FoldersExecutor', () => {
|
||||
it('should expand folder', async () => {
|
||||
const folder = createFolder();
|
||||
const query: FolderQuery = {
|
||||
source: QuerySource.Folder,
|
||||
folder,
|
||||
path: [{ ha: { id: 'media-source://' } }],
|
||||
};
|
||||
@@ -184,7 +191,7 @@ describe('FoldersExecutor', () => {
|
||||
folder,
|
||||
startTime: new Date('2023-04-29T14:27'),
|
||||
});
|
||||
const folderItem = new ViewFolder(folder);
|
||||
const folderItem = new ViewFolder(folder, []);
|
||||
|
||||
const haFolderEngine = mock<HAFoldersEngine>();
|
||||
haFolderEngine.expandFolder.mockResolvedValue([folderItem, mediaItem, folderItem]);
|
||||
@@ -201,4 +208,30 @@ describe('FoldersExecutor', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('areResultsFresh', () => {
|
||||
it('should return true for non-existent engine', () => {
|
||||
const folder: FolderConfig = {
|
||||
type: 'UNKNOWN',
|
||||
} as unknown as FolderConfig;
|
||||
const query: FolderQuery = { source: QuerySource.Folder, folder, path: [{}] };
|
||||
const executor = new FoldersExecutor();
|
||||
|
||||
expect(executor.areResultsFresh(new Date(), query)).toBe(true);
|
||||
});
|
||||
|
||||
it('should get results from HA engine', () => {
|
||||
const folder = createFolder();
|
||||
const query: FolderQuery = { source: QuerySource.Folder, folder, path: [{}] };
|
||||
const haFolderEngine = mock<HAFoldersEngine>();
|
||||
haFolderEngine.areResultsFresh.mockReturnValue(false);
|
||||
|
||||
const executor = new FoldersExecutor({
|
||||
ha: haFolderEngine,
|
||||
});
|
||||
|
||||
expect(executor.areResultsFresh(new Date(), query)).toBe(false);
|
||||
expect(haFolderEngine.areResultsFresh).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user