Add unittest coverage for engine-factory.
This commit is contained in:
@@ -7,6 +7,7 @@ package-lock.json
|
|||||||
.envrc
|
.envrc
|
||||||
|
|
||||||
stats.html
|
stats.html
|
||||||
|
/coverage/
|
||||||
|
|
||||||
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
|
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|||||||
Vendored
+2
-1
@@ -8,6 +8,7 @@
|
|||||||
"runem.lit-plugin",
|
"runem.lit-plugin",
|
||||||
"davidanson.vscode-markdownlint",
|
"davidanson.vscode-markdownlint",
|
||||||
"redhat.vscode-yaml",
|
"redhat.vscode-yaml",
|
||||||
"lokalise.i18n-ally"
|
"lokalise.i18n-ally",
|
||||||
|
"zixuanchen.vitest-explorer"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -59,6 +59,7 @@
|
|||||||
"@types/lodash-es": "^4.17.5",
|
"@types/lodash-es": "^4.17.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.36.2",
|
"@typescript-eslint/eslint-plugin": "^5.36.2",
|
||||||
"@typescript-eslint/parser": "^5.36.2",
|
"@typescript-eslint/parser": "^5.36.2",
|
||||||
|
"@vitest/coverage-c8": "^0.29.8",
|
||||||
"eslint": "^8.23.0",
|
"eslint": "^8.23.0",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
@@ -74,14 +75,18 @@
|
|||||||
"rollup-plugin-visualizer": "^5.8.2",
|
"rollup-plugin-visualizer": "^5.8.2",
|
||||||
"sass": "^1.54.9",
|
"sass": "^1.54.9",
|
||||||
"ts-prune": "^0.10.3",
|
"ts-prune": "^0.10.3",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5",
|
||||||
|
"vitest": "^0.29.8",
|
||||||
|
"vitest-mock-extended": "^1.1.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "rollup -c --watch",
|
"start": "rollup -c --watch",
|
||||||
"build": "yarn run lint && yarn run rollup",
|
"build": "yarn run lint && yarn run rollup",
|
||||||
"lint": "eslint 'src/**/*.ts'",
|
"lint": "eslint 'src/**/*.ts'",
|
||||||
"rollup": "rollup -c",
|
"rollup": "rollup -c",
|
||||||
"prune": "ts-prune"
|
"prune": "ts-prune",
|
||||||
|
"test": "vitest run",
|
||||||
|
"coverage": "vitest run --coverage"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "18.14.0",
|
"node": "18.14.0",
|
||||||
|
|||||||
@@ -58,10 +58,6 @@ export class CameraManagerEngineFactory {
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
cameraConfig: CameraConfig,
|
cameraConfig: CameraConfig,
|
||||||
): Promise<Engine | null> {
|
): Promise<Engine | null> {
|
||||||
if (!cameraConfig) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let engine: Engine | null = null;
|
let engine: Engine | null = null;
|
||||||
if (cameraConfig.engine === 'frigate') {
|
if (cameraConfig.engine === 'frigate') {
|
||||||
engine = Engine.Frigate;
|
engine = Engine.Frigate;
|
||||||
|
|||||||
+1
-1
@@ -477,7 +477,7 @@ const cameraConfigDefault = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const cameraConfigSchema = z
|
export const cameraConfigSchema = z
|
||||||
.object({
|
.object({
|
||||||
camera_entity: z.string().optional(),
|
camera_entity: z.string().optional(),
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import { describe, expect, it, vi } from 'vitest';
|
||||||
|
import { mock } from 'vitest-mock-extended';
|
||||||
|
import { EntityRegistryManager } from '../../src/utils/ha/entity-registry';
|
||||||
|
import { EntityCache } from '../../src/utils/ha/entity-registry/cache';
|
||||||
|
import { CameraManagerEngineFactory } from '../../src/camera-manager/engine-factory.js';
|
||||||
|
import { CameraConfig, cameraConfigSchema, CardWideConfig } from '../../src/types.js';
|
||||||
|
import { HomeAssistant } from 'custom-card-helpers';
|
||||||
|
import { Engine } from '../../src/camera-manager/types.js';
|
||||||
|
import { Entity } from '../../src/utils/ha/entity-registry/types.js';
|
||||||
|
import { ResolvedMediaCache } from '../../src/utils/ha/resolved-media';
|
||||||
|
import { GenericCameraManagerEngine } from '../../src/camera-manager/generic/engine-generic';
|
||||||
|
import { FrigateCameraManagerEngine } from '../../src/camera-manager/frigate/engine-frigate';
|
||||||
|
import { MotionEyeCameraManagerEngine } from '../../src/camera-manager/motioneye/engine-motioneye';
|
||||||
|
|
||||||
|
vi.mock('../../src/utils/ha/entity-registry');
|
||||||
|
vi.mock('../../src/utils/ha/entity-registry/cache');
|
||||||
|
|
||||||
|
const createFactory = (options?: {
|
||||||
|
entityRegistryManager?: EntityRegistryManager;
|
||||||
|
resolvedMediaCache?: ResolvedMediaCache;
|
||||||
|
cardWideConfig?: CardWideConfig;
|
||||||
|
}): CameraManagerEngineFactory => {
|
||||||
|
return new CameraManagerEngineFactory(
|
||||||
|
options?.entityRegistryManager ?? new EntityRegistryManager(new EntityCache()),
|
||||||
|
options?.resolvedMediaCache ?? new ResolvedMediaCache(),
|
||||||
|
options?.cardWideConfig ?? {},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const createCameraConfig = (config: Partial<CameraConfig>): CameraConfig => {
|
||||||
|
return cameraConfigSchema.parse(config);
|
||||||
|
};
|
||||||
|
|
||||||
|
const createHASS = (): HomeAssistant => {
|
||||||
|
return mock<HomeAssistant>();
|
||||||
|
};
|
||||||
|
|
||||||
|
const createEntity = (entity: Partial<Entity>): Entity => {
|
||||||
|
return {
|
||||||
|
...entity,
|
||||||
|
config_entry_id: entity.config_entry_id ?? null,
|
||||||
|
device_id: entity.device_id ?? null,
|
||||||
|
disabled_by: entity.disabled_by ?? null,
|
||||||
|
entity_id: entity.entity_id ?? 'entity_id',
|
||||||
|
hidden_by: entity.hidden_by ?? null,
|
||||||
|
platform: entity.platform ?? 'platform',
|
||||||
|
translation_key: entity.translation_key ?? null,
|
||||||
|
unique_id: entity.unique_id ?? 'unique_id',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('getEngineForCamera()', () => {
|
||||||
|
it('config:frigate', async () => {
|
||||||
|
const config = createCameraConfig({ engine: 'frigate' });
|
||||||
|
expect(await createFactory().getEngineForCamera(createHASS(), config)).toBe(
|
||||||
|
Engine.Frigate,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('config:motionEye', async () => {
|
||||||
|
const config = createCameraConfig({ engine: 'motioneye' });
|
||||||
|
expect(await createFactory().getEngineForCamera(createHASS(), config)).toBe(
|
||||||
|
Engine.MotionEye,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('auto:frigate', async () => {
|
||||||
|
const config = createCameraConfig({ engine: 'auto', camera_entity: 'camera.foo' });
|
||||||
|
const entityRegistryManager = new EntityRegistryManager(new EntityCache());
|
||||||
|
|
||||||
|
entityRegistryManager.getEntity = vi
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue(createEntity({ entity_id: 'camera.foo', platform: 'frigate' }));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await createFactory({
|
||||||
|
entityRegistryManager: entityRegistryManager,
|
||||||
|
}).getEngineForCamera(createHASS(), config),
|
||||||
|
).toBe(Engine.Frigate);
|
||||||
|
});
|
||||||
|
it('auto:motioneye', async () => {
|
||||||
|
const config = createCameraConfig({ engine: 'auto', camera_entity: 'camera.foo' });
|
||||||
|
const entityRegistryManager = new EntityRegistryManager(new EntityCache());
|
||||||
|
|
||||||
|
entityRegistryManager.getEntity = vi
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue(
|
||||||
|
createEntity({ entity_id: 'camera.foo', platform: 'motioneye' }),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await createFactory({
|
||||||
|
entityRegistryManager: entityRegistryManager,
|
||||||
|
}).getEngineForCamera(createHASS(), config),
|
||||||
|
).toBe(Engine.MotionEye);
|
||||||
|
});
|
||||||
|
it('auto:motioneye', async () => {
|
||||||
|
const config = createCameraConfig({ engine: 'auto', camera_entity: 'camera.foo' });
|
||||||
|
const entityRegistryManager = new EntityRegistryManager(new EntityCache());
|
||||||
|
|
||||||
|
entityRegistryManager.getEntity = vi
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue(createEntity({ entity_id: 'camera.foo', platform: 'generic' }));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await createFactory({
|
||||||
|
entityRegistryManager: entityRegistryManager,
|
||||||
|
}).getEngineForCamera(createHASS(), config),
|
||||||
|
).toBe(Engine.Generic);
|
||||||
|
});
|
||||||
|
it('config:frigate:camera_name', async () => {
|
||||||
|
const config = createCameraConfig({
|
||||||
|
frigate: { client_id: 'bar', camera_name: 'foo' },
|
||||||
|
});
|
||||||
|
expect(await createFactory().getEngineForCamera(createHASS(), config)).toBe(
|
||||||
|
Engine.Frigate,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('config:frigate:throw', async () => {
|
||||||
|
const config = createCameraConfig({ engine: 'auto', camera_entity: 'camera.foo' });
|
||||||
|
const entityRegistryManager = new EntityRegistryManager(new EntityCache());
|
||||||
|
|
||||||
|
entityRegistryManager.getEntity = vi.fn().mockRejectedValue(new Error());
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
createFactory({
|
||||||
|
entityRegistryManager: entityRegistryManager,
|
||||||
|
}).getEngineForCamera(createHASS(), config),
|
||||||
|
).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('createEngine()', () => {
|
||||||
|
it('generic', async () => {
|
||||||
|
expect(await createFactory().createEngine(Engine.Generic)).toBeInstanceOf(
|
||||||
|
GenericCameraManagerEngine,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('frigate', async () => {
|
||||||
|
expect(await createFactory().createEngine(Engine.Frigate)).toBeInstanceOf(
|
||||||
|
FrigateCameraManagerEngine,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('motioneye', async () => {
|
||||||
|
expect(await createFactory().createEngine(Engine.MotionEye)).toBeInstanceOf(
|
||||||
|
MotionEyeCameraManagerEngine,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user