Files
advanced-camera-card/tests/view/test-utils.ts
T

241 lines
7.2 KiB
TypeScript

import {
QueryType,
type EventQuery,
type RecordingQuery,
type ReviewQuery,
} from '../../src/camera-manager/types';
import type { FolderQuery } from '../../src/card-controller/folders/types';
import type { FolderConfig } from '../../src/config/schema/folders';
import { QuerySource } from '../../src/query-source';
import type { Severity } from '../../src/severity';
import {
ViewMedia,
ViewMediaType,
type EventViewMedia,
type ReviewViewMedia,
} from '../../src/view/item';
import { QueryResults } from '../../src/view/query-results';
import { View, type ViewParameters } from '../../src/view/view';
export class TestViewMedia extends ViewMedia implements EventViewMedia, ReviewViewMedia {
private _icon: string | null = null;
private _id: string | null;
private _startTime: Date | null;
private _endTime: Date | null;
private _inProgress: boolean | null;
private _contentID: string | null;
private _title: string | null;
private _thumbnail: string | null;
private _what: string[] | null = null;
private _score: number | null = null;
private _tags: string[] | null = null;
private _where: string[] | null = null;
private _severity: Severity | null = null;
private _reviewed: boolean | null = null;
private _description: string | null = null;
private _favorite: boolean | null = null;
constructor(options?: {
id?: string | null;
startTime?: Date | null;
mediaType?: ViewMediaType;
cameraID?: string | null;
folder?: FolderConfig | null;
endTime?: Date | null;
inProgress?: boolean;
contentID?: string;
title?: string | null;
description?: string | null;
thumbnail?: string | null;
icon?: string | null;
what?: string[] | null;
score?: number | null;
tags?: string[] | null;
where?: string[] | null;
severity?: Severity | null;
reviewed?: boolean | null;
favorite?: boolean | null;
}) {
super(options?.mediaType ?? ViewMediaType.Clip, {
...(options?.cameraID !== null &&
!options?.folder && { cameraID: options?.cameraID ?? 'camera' }),
...(options?.folder && { folder: options.folder }),
});
this._id = options?.id !== undefined ? options.id : 'id';
this._startTime = options?.startTime ?? null;
this._endTime = options?.endTime ?? null;
this._inProgress = options?.inProgress !== undefined ? options.inProgress : false;
this._contentID = options?.contentID ?? null;
this._title = options?.title !== undefined ? options.title : null;
this._description = options?.description !== undefined ? options.description : null;
this._thumbnail = options?.thumbnail !== undefined ? options.thumbnail : null;
this._icon = options?.icon !== undefined ? options.icon : null;
this._what = options?.what !== undefined ? options.what : null;
this._score = options?.score !== undefined ? options.score : null;
this._tags = options?.tags !== undefined ? options.tags : null;
this._where = options?.where !== undefined ? options.where : null;
this._severity = options?.severity !== undefined ? options.severity : null;
this._reviewed = options?.reviewed !== undefined ? options.reviewed : null;
this._favorite = options?.favorite !== undefined ? options.favorite : null;
}
public getIcon(): string | null {
return this._icon;
}
public getID(): string | null {
return this._id;
}
public getStartTime(): Date | null {
return this._startTime;
}
public getEndTime(): Date | null {
return this._endTime;
}
public inProgress(): boolean | null {
return this._inProgress;
}
public getContentID(): string | null {
return this._contentID;
}
public getTitle(): string | null {
return this._title;
}
public getDescription(): string | null {
return this._description;
}
public getThumbnail(): string | null {
return this._thumbnail;
}
public getWhat(): string[] | null {
return this._what;
}
public getScore(): number | null {
return this._score;
}
public getTags(): string[] | null {
return this._tags;
}
public getWhere(): string[] | null {
return this._where;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public isGroupableWith(_that: EventViewMedia): boolean {
return false;
}
public getSeverity(): Severity | null {
return this._severity;
}
public isReviewed(): boolean | null {
return this._reviewed;
}
public setReviewed(reviewed: boolean): void {
this._reviewed = reviewed;
}
public isFavorite(): boolean | null {
return this._favorite;
}
public setFavorite(favorite: boolean): void {
this._favorite = favorite;
}
}
// jsdom does not implement `window.matchMedia`, so it has to be installed
// before a test can control what it returns. Must be called from inside a test
// or a test hook, as the stub is removed once the test finishes.
export const generateViewMediaArray = (options?: {
cameraIDs?: string[];
count?: number;
}): ViewMedia[] => {
const media: ViewMedia[] = [];
for (let i = 0; i < (options?.count ?? 100); ++i) {
for (const cameraID of options?.cameraIDs ?? ['kitchen', 'office']) {
media.push(
new TestViewMedia({
cameraID: cameraID,
id: `id-${cameraID}-${i}`,
}),
);
}
}
return media;
};
// ViewMedia itself has no native way to set startTime and ID that aren't linked
// to an engine.
export const createView = (options?: Partial<ViewParameters>): View => {
return new View({
view: 'live',
camera: 'camera',
...options,
});
};
export const createViewWithMedia = (options?: Partial<ViewParameters>): View => {
const media = generateViewMediaArray({ count: 5 });
return createView({
queryResults: new QueryResults({
results: media,
selectedIndex: 0,
}),
...options,
});
};
export const createEventQuery = (
cameraID: string,
options?: Partial<EventQuery>,
): EventQuery => ({
source: QuerySource.Camera,
type: QueryType.Event,
cameraIDs: new Set([cameraID]),
...options,
});
export const createRecordingQuery = (
cameraID: string,
options?: Partial<RecordingQuery>,
): RecordingQuery => ({
source: QuerySource.Camera,
type: QueryType.Recording,
cameraIDs: new Set([cameraID]),
...options,
});
export const createReviewQuery = (
cameraID: string,
options?: Partial<ReviewQuery>,
): ReviewQuery => ({
source: QuerySource.Camera,
type: QueryType.Review,
cameraIDs: new Set([cameraID]),
...options,
});
export const createFolderQuery = (folderId: string): FolderQuery => ({
source: QuerySource.Folder,
folder: { id: folderId, type: 'ha', title: folderId },
path: [{ ha: { id: 'Root' } }],
});
export const isEventQuery = (node: {
source: QuerySource;
type?: QueryType;
}): node is EventQuery =>
node.source === QuerySource.Camera && node.type === QueryType.Event;
export const isRecordingQuery = (node: {
source: QuerySource;
type?: QueryType;
}): node is RecordingQuery =>
node.source === QuerySource.Camera && node.type === QueryType.Recording;
export const isReviewQuery = (node: {
source: QuerySource;
type?: QueryType;
}): node is ReviewQuery =>
node.source === QuerySource.Camera && node.type === QueryType.Review;
export const isFolderQuery = (node: { source: QuerySource }): node is FolderQuery =>
node.source === QuerySource.Folder;