test: Split test utilities to improve test times (#2622)
This commit is contained in:
@@ -13,8 +13,9 @@ import { BrowseMediaWalker } from '../../../src/ha/browse-media/walker';
|
||||
import { ResolvedMediaCache } from '../../../src/ha/resolved-media';
|
||||
import { QuerySource } from '../../../src/query-source';
|
||||
import type { ViewMedia } from '../../../src/view/item';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import { createCameraConfig, createHASS, createHASSManager } from '../../test-utils';
|
||||
import { createHASS, createHASSManager } from '../../test-utils';
|
||||
|
||||
const createEngine = (): BrowseMediaCameraManagerEngine => {
|
||||
return new BrowseMediaCameraManagerEngine(
|
||||
|
||||
@@ -8,19 +8,18 @@ import type { EventWatcherSubscriptionInterface } from '../../src/card-controlle
|
||||
import type { StateWatcherSubscriptionInterface } from '../../src/card-controller/hass/state-watcher.js';
|
||||
import { liveProviderSupports2WayAudio } from '../../src/utils/live-provider.js';
|
||||
import type * as LiveProviderUtils from '../../src/utils/live-provider.js';
|
||||
import { createCameraConfig } from '../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../ha/registry/entity/mock.js';
|
||||
import {
|
||||
callEventWatcherCallback,
|
||||
callStateWatcherCallback,
|
||||
createCameraConfig,
|
||||
createCapabilities,
|
||||
createHASS,
|
||||
createHASSEvent,
|
||||
createHASSManager,
|
||||
createInitializedCamera,
|
||||
createRegistryEntity,
|
||||
createStateEntity,
|
||||
} from '../test-utils.js';
|
||||
import { createCapabilities, createInitializedCamera } from './test-utils';
|
||||
|
||||
// Partially mock to keep the real pure helpers (e.g. `isGo2RTCLiveProvider`
|
||||
// used by `getProxyConfig`) while mocking the async metadata fetch.
|
||||
@@ -80,7 +79,7 @@ describe('Camera', () => {
|
||||
createCameraConfig(),
|
||||
new GenericCameraManagerEngine(createHASSManager()),
|
||||
);
|
||||
expect(() => camera.getID()).toThrowError(
|
||||
expect(() => camera.getID()).toThrow(
|
||||
'Could not determine camera id for the following ' +
|
||||
"camera, may need to set 'id' parameter manually",
|
||||
);
|
||||
@@ -109,13 +108,13 @@ describe('Camera', () => {
|
||||
});
|
||||
|
||||
expect(camera.isInitialized()).toBe(true);
|
||||
expect(stateWatcher.subscribe).toBeCalledWith(expect.any(Function), [
|
||||
expect(stateWatcher.subscribe).toHaveBeenCalledWith(expect.any(Function), [
|
||||
'camera.foo',
|
||||
]);
|
||||
|
||||
await camera.destroy();
|
||||
|
||||
expect(stateWatcher.unsubscribe).toBeCalled();
|
||||
expect(stateWatcher.unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should skip initialization when hass is unavailable', async () => {
|
||||
@@ -134,7 +133,7 @@ describe('Camera', () => {
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
expect(stateWatcher.subscribe).not.toBeCalled();
|
||||
expect(stateWatcher.subscribe).not.toHaveBeenCalled();
|
||||
expect(camera.getCapabilities()).toBeNull();
|
||||
expect(camera.isInitialized()).toBe(false);
|
||||
});
|
||||
@@ -630,7 +629,7 @@ describe('Camera', () => {
|
||||
|
||||
it('should subscribe to discovered doorbell entities for state changes', async () => {
|
||||
const { stateWatcher } = await initializeDoorbellCamera();
|
||||
expect(stateWatcher.subscribe).toBeCalledWith(expect.any(Function), [
|
||||
expect(stateWatcher.subscribe).toHaveBeenCalledWith(expect.any(Function), [
|
||||
'event.front_door_doorbell',
|
||||
]);
|
||||
});
|
||||
@@ -671,7 +670,7 @@ describe('Camera', () => {
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
expect(stateWatcher.subscribe).toBeCalled();
|
||||
expect(stateWatcher.subscribe).toHaveBeenCalled();
|
||||
|
||||
const diff = {
|
||||
entityID: 'sensor.force_update',
|
||||
@@ -680,7 +679,7 @@ describe('Camera', () => {
|
||||
};
|
||||
callStateWatcherCallback(stateWatcher, diff);
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
cameraID: 'camera_1',
|
||||
id: 'sensor.force_update',
|
||||
type: eventType,
|
||||
@@ -707,7 +706,7 @@ describe('Camera', () => {
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
expect(eventWatcher.subscribe).toBeCalledTimes(1);
|
||||
expect(eventWatcher.subscribe).toHaveBeenCalledTimes(1);
|
||||
const request = vi.mocked(eventWatcher.subscribe).mock.calls[0][0];
|
||||
expect(request.event_type).toBe('zha_event');
|
||||
expect(request.matcher).toBeUndefined();
|
||||
@@ -717,14 +716,14 @@ describe('Camera', () => {
|
||||
createHASSEvent('zha_event', { command: 'press' }),
|
||||
);
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
cameraID: 'camera_1',
|
||||
id: 'event:zha_event',
|
||||
type: 'momentary',
|
||||
});
|
||||
|
||||
await camera.destroy();
|
||||
expect(eventWatcher.unsubscribe).toBeCalled();
|
||||
expect(eventWatcher.unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should attach a context-only matcher when only a context filter is set', async () => {
|
||||
@@ -775,7 +774,7 @@ describe('Camera', () => {
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
|
||||
expect(eventWatcher.subscribe).toBeCalledTimes(2);
|
||||
expect(eventWatcher.subscribe).toHaveBeenCalledTimes(2);
|
||||
expect(vi.mocked(eventWatcher.subscribe).mock.calls[0][0].event_type).toBe(
|
||||
'zha_event',
|
||||
);
|
||||
@@ -828,7 +827,7 @@ describe('Camera', () => {
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: false }) },
|
||||
});
|
||||
|
||||
expect(eventWatcher.subscribe).not.toBeCalled();
|
||||
expect(eventWatcher.subscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not dispatch when the helper returns null', async () => {
|
||||
@@ -860,7 +859,7 @@ describe('Camera', () => {
|
||||
newState: createStateEntity({ state: '2026-05-24T12:00:05.123+00:00' }),
|
||||
});
|
||||
|
||||
expect(eventCallback).not.toBeCalled();
|
||||
expect(eventCallback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should dispatch a momentary event for an event entity fire', async () => {
|
||||
@@ -892,8 +891,8 @@ describe('Camera', () => {
|
||||
newState: createStateEntity({ state: '2026-05-24T12:00:05.123+00:00' }),
|
||||
});
|
||||
|
||||
expect(eventCallback).toBeCalledTimes(1);
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledTimes(1);
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
cameraID: 'camera_1',
|
||||
id: 'event.front_door_doorbell',
|
||||
type: 'momentary',
|
||||
@@ -921,7 +920,7 @@ describe('Camera', () => {
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: false }) },
|
||||
});
|
||||
|
||||
expect(stateWatcher.subscribe).not.toBeCalled();
|
||||
expect(stateWatcher.subscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ import type { CardWideConfig } from '../../src/config/schema/types.js';
|
||||
import type { DeviceRegistryManager } from '../../src/ha/registry/device';
|
||||
import type { EntityRegistryManager } from '../../src/ha/registry/entity/types.js';
|
||||
import type { ResolvedMediaCache } from '../../src/ha/resolved-media.js';
|
||||
import { createCameraConfig } from '../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../ha/registry/entity/mock.js';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createRegistryEntity,
|
||||
|
||||
@@ -26,15 +26,15 @@ import type {
|
||||
EntityRegistryManager,
|
||||
} from '../../../src/ha/registry/entity/types';
|
||||
import { ViewMediaType } from '../../../src/view/item';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createCapabilities,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createRegistryEntity,
|
||||
createStateEntity,
|
||||
} from '../../test-utils';
|
||||
import { createCapabilities } from '../test-utils';
|
||||
|
||||
vi.mock('../../../src/camera-manager/frigate/requests');
|
||||
|
||||
@@ -98,7 +98,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: mock<FrigateEventWatcher>(),
|
||||
frigateReviewWatcher: mock<FrigateReviewWatcher>(),
|
||||
}),
|
||||
).rejects.toThrowError(/Could not find camera entity/);
|
||||
).rejects.toThrow(/Could not find camera entity/);
|
||||
});
|
||||
|
||||
it('with a valid camera_entity', async () => {
|
||||
@@ -315,7 +315,7 @@ describe('FrigateCamera', () => {
|
||||
expect(camera.getCapabilities()?.has('snapshots')).toBeTruthy();
|
||||
expect(camera.getCapabilities()?.has('recordings')).toBeTruthy();
|
||||
expect(camera.getCapabilities()?.has('trigger')).toBeTruthy();
|
||||
expect(vi.mocked(getPTZInfo)).toBeCalled();
|
||||
expect(vi.mocked(getPTZInfo)).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('basic birdseye', async () => {
|
||||
@@ -342,7 +342,7 @@ describe('FrigateCamera', () => {
|
||||
expect(camera.getCapabilities()?.has('snapshots')).toBeFalsy();
|
||||
expect(camera.getCapabilities()?.has('recordings')).toBeFalsy();
|
||||
expect(camera.getCapabilities()?.has('trigger')).toBeTruthy();
|
||||
expect(vi.mocked(getPTZInfo)).not.toBeCalled();
|
||||
expect(vi.mocked(getPTZInfo)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('with ptz', () => {
|
||||
@@ -368,7 +368,7 @@ describe('FrigateCamera', () => {
|
||||
|
||||
expect(camera.getCapabilities()?.has('ptz')).toBeFalsy();
|
||||
expect(camera.getCapabilities()?.hasPTZCapability()).toBeFalsy();
|
||||
expect(consoleSpy).toBeCalled();
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('when getPTZInfo call succeeds with continuous motion', async () => {
|
||||
@@ -824,7 +824,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: eventWatcher,
|
||||
frigateReviewWatcher: mock<FrigateReviewWatcher>(),
|
||||
});
|
||||
expect(eventWatcher.subscribe).toBeCalledWith(
|
||||
expect(eventWatcher.subscribe).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
instanceID: 'CLIENT_ID',
|
||||
}),
|
||||
@@ -853,7 +853,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: eventWatcher,
|
||||
frigateReviewWatcher: mock<FrigateReviewWatcher>(),
|
||||
});
|
||||
expect(eventWatcher.subscribe).not.toBeCalled();
|
||||
expect(eventWatcher.subscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not subscribe without trigger capability', async () => {
|
||||
@@ -878,7 +878,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: eventWatcher,
|
||||
frigateReviewWatcher: mock<FrigateReviewWatcher>(),
|
||||
});
|
||||
expect(eventWatcher.subscribe).not.toBeCalled();
|
||||
expect(eventWatcher.subscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not subscribe with no camera name', async () => {
|
||||
@@ -902,7 +902,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: eventWatcher,
|
||||
frigateReviewWatcher: mock<FrigateReviewWatcher>(),
|
||||
});
|
||||
expect(eventWatcher.subscribe).not.toBeCalled();
|
||||
expect(eventWatcher.subscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unsubscribe on destroy', async () => {
|
||||
@@ -926,10 +926,10 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: eventWatcher,
|
||||
frigateReviewWatcher: mock<FrigateReviewWatcher>(),
|
||||
});
|
||||
expect(eventWatcher.unsubscribe).not.toBeCalled();
|
||||
expect(eventWatcher.unsubscribe).not.toHaveBeenCalled();
|
||||
|
||||
await camera.destroy();
|
||||
expect(eventWatcher.unsubscribe).toBeCalled();
|
||||
expect(eventWatcher.unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not subscribe when destroyed while base initialization is pending', async () => {
|
||||
@@ -965,22 +965,22 @@ describe('FrigateCamera', () => {
|
||||
frigateReviewWatcher: reviewWatcher,
|
||||
capabilityOptions: { capabilities: createCapabilities({ trigger: true }) },
|
||||
});
|
||||
await vi.waitFor(() => expect(entityRegistryManager.getEntity).toBeCalled());
|
||||
await vi.waitFor(() => expect(entityRegistryManager.getEntity).toHaveBeenCalled());
|
||||
|
||||
await camera.destroy();
|
||||
|
||||
// `_destroyed` short-circuits initialize() after the pending await, so
|
||||
// neither watcher is ever subscribed.
|
||||
expect(eventWatcher.subscribe).not.toBeCalled();
|
||||
expect(reviewWatcher.subscribe).not.toBeCalled();
|
||||
expect(eventWatcher.subscribe).not.toHaveBeenCalled();
|
||||
expect(reviewWatcher.subscribe).not.toHaveBeenCalled();
|
||||
|
||||
resolveEntity();
|
||||
await initializePromise;
|
||||
|
||||
expect(eventWatcher.subscribe).not.toBeCalled();
|
||||
expect(eventWatcher.unsubscribe).not.toBeCalled();
|
||||
expect(reviewWatcher.subscribe).not.toBeCalled();
|
||||
expect(reviewWatcher.unsubscribe).not.toBeCalled();
|
||||
expect(eventWatcher.subscribe).not.toHaveBeenCalled();
|
||||
expect(eventWatcher.unsubscribe).not.toHaveBeenCalled();
|
||||
expect(reviewWatcher.subscribe).not.toHaveBeenCalled();
|
||||
expect(reviewWatcher.unsubscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('should call handler correctly', () => {
|
||||
@@ -1097,7 +1097,7 @@ describe('FrigateCamera', () => {
|
||||
});
|
||||
|
||||
if (call) {
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
type: 'new',
|
||||
cameraID: 'CAMERA_1',
|
||||
id: 'event-1',
|
||||
@@ -1106,7 +1106,7 @@ describe('FrigateCamera', () => {
|
||||
fidelity: 'high',
|
||||
});
|
||||
} else {
|
||||
expect(eventCallback).not.toBeCalled();
|
||||
expect(eventCallback).not.toHaveBeenCalled();
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -1170,7 +1170,7 @@ describe('FrigateCamera', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
type: 'end',
|
||||
cameraID: 'CAMERA_1',
|
||||
id: 'event-1',
|
||||
@@ -1378,7 +1378,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: mock<FrigateEventWatcher>(),
|
||||
frigateReviewWatcher: reviewWatcher,
|
||||
});
|
||||
expect(reviewWatcher.subscribe).toBeCalledWith(
|
||||
expect(reviewWatcher.subscribe).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
instanceID: 'CLIENT_ID',
|
||||
}),
|
||||
@@ -1409,7 +1409,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: mock<FrigateEventWatcher>(),
|
||||
frigateReviewWatcher: reviewWatcher,
|
||||
});
|
||||
expect(reviewWatcher.subscribe).not.toBeCalled();
|
||||
expect(reviewWatcher.subscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not subscribe to reviews with description only (no severities)', async () => {
|
||||
@@ -1438,7 +1438,7 @@ describe('FrigateCamera', () => {
|
||||
frigateReviewWatcher: reviewWatcher,
|
||||
});
|
||||
// Severities are required - description alone is not enough
|
||||
expect(reviewWatcher.subscribe).not.toBeCalled();
|
||||
expect(reviewWatcher.subscribe).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('should call handler correctly', () => {
|
||||
@@ -1495,7 +1495,7 @@ describe('FrigateCamera', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
type: 'new',
|
||||
cameraID: 'CAMERA_1',
|
||||
id: '123',
|
||||
@@ -1566,7 +1566,7 @@ describe('FrigateCamera', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
type: 'update',
|
||||
cameraID: 'CAMERA_1',
|
||||
id: '123',
|
||||
@@ -1637,7 +1637,7 @@ describe('FrigateCamera', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
type: 'update',
|
||||
cameraID: 'CAMERA_1',
|
||||
id: '123',
|
||||
@@ -1995,7 +1995,7 @@ describe('FrigateCamera', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(eventCallback).toBeCalledWith({
|
||||
expect(eventCallback).toHaveBeenCalledWith({
|
||||
type: 'end',
|
||||
cameraID: 'CAMERA_1',
|
||||
id: '123',
|
||||
@@ -2123,7 +2123,7 @@ describe('FrigateCamera', () => {
|
||||
frigateEventWatcher: mock<FrigateEventWatcher>(),
|
||||
frigateReviewWatcher: mock<FrigateReviewWatcher>(),
|
||||
}),
|
||||
).rejects.toThrowError(/Could not find camera entity/);
|
||||
).rejects.toThrow(/Could not find camera entity/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2284,7 +2284,7 @@ describe('FrigateCamera', () => {
|
||||
const executor = mock<ActionsExecutor>();
|
||||
await camera.executePTZAction(executor, 'preset');
|
||||
|
||||
expect(executor.executeActions).not.toBeCalled();
|
||||
expect(executor.executeActions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should ignore actions with configured action', async () => {
|
||||
@@ -2316,7 +2316,7 @@ describe('FrigateCamera', () => {
|
||||
const executor = mock<ActionsExecutor>();
|
||||
await camera.executePTZAction(executor, 'left', { phase: 'start' });
|
||||
|
||||
expect(executor.executeActions).toBeCalledTimes(1);
|
||||
expect(executor.executeActions).toHaveBeenCalledTimes(1);
|
||||
expect(executor.executeActions).toHaveBeenLastCalledWith({
|
||||
actions: {
|
||||
action: 'perform-action',
|
||||
|
||||
@@ -38,17 +38,17 @@ import type { RawAdvancedCameraCardConfig } from '../../../src/config/types';
|
||||
import { QuerySource } from '../../../src/query-source';
|
||||
import type { Severity } from '../../../src/severity';
|
||||
import { ViewMedia, ViewMediaType } from '../../../src/view/item';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createFrigateEvent,
|
||||
createFrigateRecording,
|
||||
createFrigateReview,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createStore,
|
||||
TestViewMedia,
|
||||
} from '../../test-utils';
|
||||
import { TestViewMedia } from '../../view/test-utils';
|
||||
import { createStore } from '../test-utils';
|
||||
|
||||
vi.mock('../../../src/camera-manager/frigate/requests');
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
FrigateViewMediaFactory,
|
||||
} from '../../../src/camera-manager/frigate/media';
|
||||
import { ViewMediaType } from '../../../src/view/item';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createFrigateEvent,
|
||||
createFrigateRecording,
|
||||
createFrigateReview,
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('frigate requests', () => {
|
||||
expect(await getRecordingsSummary(hass, 'clientID', 'camera.office')).toBe(
|
||||
recordingSummary,
|
||||
);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
recordingSummarySchema,
|
||||
expect.objectContaining({
|
||||
@@ -77,7 +77,7 @@ describe('frigate requests', () => {
|
||||
before: 0,
|
||||
}),
|
||||
).toBe(recordingSegments);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
recordingSegmentsSchema,
|
||||
expect.objectContaining({
|
||||
@@ -101,7 +101,7 @@ describe('frigate requests', () => {
|
||||
const hass = createHASS();
|
||||
retainEvent(hass, 'clientID', 'eventID', true);
|
||||
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
retainResultSchema,
|
||||
expect.objectContaining({
|
||||
@@ -121,10 +121,10 @@ describe('frigate requests', () => {
|
||||
});
|
||||
|
||||
const hass = createHASS();
|
||||
await expect(retainEvent(hass, 'clientID', 'eventID', true)).rejects.toThrowError(
|
||||
await expect(retainEvent(hass, 'clientID', 'eventID', true)).rejects.toThrow(
|
||||
/Could not retain event/,
|
||||
);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
retainResultSchema,
|
||||
expect.objectContaining({
|
||||
@@ -157,7 +157,7 @@ describe('frigate requests', () => {
|
||||
favorites: true,
|
||||
}),
|
||||
).toBe(events);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
frigateEventsSchema,
|
||||
expect.objectContaining({
|
||||
@@ -193,7 +193,7 @@ describe('frigate requests', () => {
|
||||
|
||||
vi.mocked(homeAssistantWSRequest).mockResolvedValue(eventSummary);
|
||||
expect(await getEventSummary(hass, 'clientID')).toBe(eventSummary);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
eventSummarySchema,
|
||||
expect.objectContaining({
|
||||
@@ -216,7 +216,7 @@ describe('frigate requests', () => {
|
||||
const hass = createHASS();
|
||||
vi.mocked(homeAssistantWSRequest).mockResolvedValue(ptzInfo);
|
||||
expect(await getPTZInfo(hass, 'clientID', 'camera.office')).toBe(ptzInfo);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
ptzInfoSchema,
|
||||
expect.objectContaining({
|
||||
@@ -259,7 +259,7 @@ describe('frigate requests', () => {
|
||||
reviewed: false,
|
||||
}),
|
||||
).toBe(reviews);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
frigateReviewsSchema,
|
||||
expect.objectContaining({
|
||||
@@ -288,7 +288,7 @@ describe('frigate requests', () => {
|
||||
const hass = createHASS();
|
||||
setReviewsReviewed(hass, 'clientID', ['review_id'], true);
|
||||
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
reviewResultSchema,
|
||||
expect.objectContaining({
|
||||
@@ -309,8 +309,8 @@ describe('frigate requests', () => {
|
||||
const hass = createHASS();
|
||||
await expect(
|
||||
setReviewsReviewed(hass, 'clientID', ['review_id'], true),
|
||||
).rejects.toThrowError(/Failed to receive response from Home Assistant/);
|
||||
expect(homeAssistantWSRequest).toBeCalledWith(
|
||||
).rejects.toThrow(/Failed to receive response from Home Assistant/);
|
||||
expect(homeAssistantWSRequest).toHaveBeenCalledWith(
|
||||
hass,
|
||||
reviewResultSchema,
|
||||
expect.objectContaining({
|
||||
|
||||
@@ -15,8 +15,8 @@ import {
|
||||
getReviewTitle,
|
||||
} from '../../../src/camera-manager/frigate/util';
|
||||
import type { CameraConfig } from '../../../src/config/schema/cameras';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createFrigateEvent,
|
||||
createFrigateRecording,
|
||||
createFrigateReview,
|
||||
|
||||
@@ -93,7 +93,7 @@ describe('FrigateEventWatcher', () => {
|
||||
watcher.subscribe({ instanceID: 'frigate', callback: vi.fn() });
|
||||
await flushPromises();
|
||||
|
||||
expect(hass.connection.subscribeMessage).toBeCalledWith(
|
||||
expect(hass.connection.subscribeMessage).toHaveBeenCalledWith(
|
||||
expect.any(Function),
|
||||
expect.objectContaining({
|
||||
type: 'frigate/events/subscribe',
|
||||
@@ -116,7 +116,7 @@ describe('FrigateEventWatcher', () => {
|
||||
watcher.unsubscribe(request);
|
||||
await flushPromises();
|
||||
|
||||
expect(unsub).toBeCalledTimes(1);
|
||||
expect(unsub).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should drop messages from an old-connection subscription after a swap', async () => {
|
||||
@@ -140,7 +140,7 @@ describe('FrigateEventWatcher', () => {
|
||||
await flushPromises();
|
||||
|
||||
oldDispatcher(JSON.stringify(createEventChange()));
|
||||
expect(callback).not.toBeCalled();
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('should call handler', () => {
|
||||
@@ -156,8 +156,8 @@ describe('FrigateEventWatcher', () => {
|
||||
await flushPromises();
|
||||
fireMessage(hass, 'NOT_JSON');
|
||||
|
||||
expect(callback).not.toBeCalled();
|
||||
expect(spy).toBeCalledWith(
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'Received non-JSON payload from subscription: frigate/events/subscribe',
|
||||
'NOT_JSON',
|
||||
);
|
||||
@@ -176,8 +176,8 @@ describe('FrigateEventWatcher', () => {
|
||||
const data = JSON.stringify({});
|
||||
fireMessage(hass, data);
|
||||
|
||||
expect(callback).not.toBeCalled();
|
||||
expect(spy).toBeCalledWith(
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'Received malformed message from subscription: frigate/events/subscribe',
|
||||
data,
|
||||
);
|
||||
@@ -194,7 +194,7 @@ describe('FrigateEventWatcher', () => {
|
||||
const eventChange = createEventChange();
|
||||
fireMessage(hass, JSON.stringify(eventChange));
|
||||
|
||||
expect(callback).toBeCalledWith(eventChange);
|
||||
expect(callback).toHaveBeenCalledWith(eventChange);
|
||||
});
|
||||
|
||||
it('with a matcher', async () => {
|
||||
@@ -219,8 +219,8 @@ describe('FrigateEventWatcher', () => {
|
||||
const eventChange = createEventChange();
|
||||
fireMessage(hass, JSON.stringify(eventChange));
|
||||
|
||||
expect(non_matching_callback).not.toBeCalledWith(eventChange);
|
||||
expect(matching_callback).toBeCalledWith(eventChange);
|
||||
expect(non_matching_callback).not.toHaveBeenCalledWith(eventChange);
|
||||
expect(matching_callback).toHaveBeenCalledWith(eventChange);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -239,7 +239,7 @@ describe('FrigateReviewWatcher', () => {
|
||||
watcher.subscribe({ instanceID: 'frigate', callback });
|
||||
await flushPromises();
|
||||
|
||||
expect(hass.connection.subscribeMessage).toBeCalledWith(
|
||||
expect(hass.connection.subscribeMessage).toHaveBeenCalledWith(
|
||||
expect.any(Function),
|
||||
expect.objectContaining({
|
||||
type: 'frigate/reviews/subscribe',
|
||||
@@ -249,6 +249,6 @@ describe('FrigateReviewWatcher', () => {
|
||||
const reviewChange = createReviewChange();
|
||||
fireMessage(hass, JSON.stringify(reviewChange));
|
||||
|
||||
expect(callback).toBeCalledWith(reviewChange);
|
||||
expect(callback).toHaveBeenCalledWith(reviewChange);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,14 +5,10 @@ import { Engine, QueryResultsType, QueryType } from '../../../src/camera-manager
|
||||
import type { CameraConfig } from '../../../src/config/schema/cameras';
|
||||
import type { RawAdvancedCameraCardConfig } from '../../../src/config/types';
|
||||
import { QuerySource } from '../../../src/query-source';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createStateEntity,
|
||||
createStore,
|
||||
TestViewMedia,
|
||||
} from '../../test-utils';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { createHASS, createHASSManager, createStateEntity } from '../../test-utils';
|
||||
import { TestViewMedia } from '../../view/test-utils';
|
||||
import { createStore } from '../test-utils';
|
||||
|
||||
const createEngine = (): GenericCameraManagerEngine => {
|
||||
return new GenericCameraManagerEngine(createHASSManager());
|
||||
|
||||
@@ -36,17 +36,10 @@ import { QuerySource } from '../../src/query-source.js';
|
||||
import { PTZMovementType, type Endpoint } from '../../src/types.js';
|
||||
import { ViewFolder, type ViewItem, type ViewMedia } from '../../src/view/item.js';
|
||||
import type { ViewItemCapabilities } from '../../src/view/types.js';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createCapabilities,
|
||||
createCardAPI,
|
||||
createConfig,
|
||||
createFolder,
|
||||
createHASS,
|
||||
createInitializedCamera,
|
||||
generateViewMediaArray,
|
||||
TestViewMedia,
|
||||
} from '../test-utils.js';
|
||||
import { createCameraConfig, createConfig } from '../config/test-utils';
|
||||
import { createCardAPI, createFolder, createHASS } from '../test-utils.js';
|
||||
import { generateViewMediaArray, TestViewMedia } from '../view/test-utils';
|
||||
import { createCapabilities, createInitializedCamera } from './test-utils';
|
||||
|
||||
describe('QueryClassifier', () => {
|
||||
it('should classify event query', () => {
|
||||
@@ -481,7 +474,7 @@ describe('CameraManager', () => {
|
||||
type: 'new',
|
||||
};
|
||||
eventCallback?.(cameraEvent);
|
||||
expect(api.getCameraTriggersManager().handleCameraEvent).toBeCalledWith(
|
||||
expect(api.getCameraTriggersManager().handleCameraEvent).toHaveBeenCalledWith(
|
||||
cameraEvent,
|
||||
);
|
||||
});
|
||||
@@ -505,7 +498,7 @@ describe('CameraManager', () => {
|
||||
]);
|
||||
|
||||
await manager.initializeCamerasFromConfig();
|
||||
expect(api.getEntityRegistryManager().fetchEntityList).toBeCalled();
|
||||
expect(api.getEntityRegistryManager().fetchEntityList).toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
|
||||
@@ -516,7 +509,7 @@ describe('CameraManager', () => {
|
||||
const manager = createCameraManager(api);
|
||||
|
||||
await manager.initializeCamerasFromConfig();
|
||||
expect(api.getEntityRegistryManager().fetchEntityList).not.toBeCalled();
|
||||
expect(api.getEntityRegistryManager().fetchEntityList).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -710,7 +703,7 @@ describe('CameraManager', () => {
|
||||
const results = new Map([[baseEventQuery, baseEventQueryResults]]);
|
||||
engine.getEvents.mockResolvedValue(results);
|
||||
expect(await manager.getEvents(baseEventQuery, engineOptions)).toEqual(results);
|
||||
expect(engine.getEvents).toBeCalledWith(
|
||||
expect(engine.getEvents).toHaveBeenCalledWith(
|
||||
hass,
|
||||
expect.anything(),
|
||||
baseEventQuery,
|
||||
@@ -743,7 +736,12 @@ describe('CameraManager', () => {
|
||||
|
||||
await manager.reviewMedia(media, true);
|
||||
|
||||
expect(engine.reviewMedia).toBeCalledWith(hass, expect.anything(), media, true);
|
||||
expect(engine.reviewMedia).toHaveBeenCalledWith(
|
||||
hass,
|
||||
expect.anything(),
|
||||
media,
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1210,7 +1208,7 @@ describe('CameraManager', () => {
|
||||
const manager = createCameraManager(createCardAPI(), engine);
|
||||
manager.favoriteMedia(new TestViewMedia(), true);
|
||||
|
||||
expect(engine.favoriteMedia).not.toBeCalled();
|
||||
expect(engine.favoriteMedia).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should succeed', async () => {
|
||||
@@ -1225,7 +1223,12 @@ describe('CameraManager', () => {
|
||||
|
||||
const media = new TestViewMedia({ cameraID: 'id' });
|
||||
manager.favoriteMedia(media, true);
|
||||
expect(engine.favoriteMedia).toBeCalledWith(hass, expect.anything(), media, true);
|
||||
expect(engine.favoriteMedia).toHaveBeenCalledWith(
|
||||
hass,
|
||||
expect.anything(),
|
||||
media,
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1396,7 +1399,7 @@ describe('CameraManager', () => {
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(null);
|
||||
manager.executePTZAction('another', 'left');
|
||||
|
||||
expect(api.getActionsManager().executeActions).toBeCalledWith({
|
||||
expect(api.getActionsManager().executeActions).toHaveBeenCalledWith({
|
||||
actions: action,
|
||||
});
|
||||
});
|
||||
@@ -1425,7 +1428,9 @@ describe('CameraManager', () => {
|
||||
|
||||
manager.executePTZAction('another', 'left');
|
||||
|
||||
expect(api.getActionsManager().executeActions).toBeCalledWith({ actions: action });
|
||||
expect(api.getActionsManager().executeActions).toHaveBeenCalledWith({
|
||||
actions: action,
|
||||
});
|
||||
});
|
||||
|
||||
describe('with rotation', () => {
|
||||
@@ -1544,7 +1549,7 @@ describe('CameraManager', () => {
|
||||
preset: presetAction,
|
||||
};
|
||||
|
||||
expect(api.getActionsManager().executeActions).toBeCalledWith({
|
||||
expect(api.getActionsManager().executeActions).toHaveBeenCalledWith({
|
||||
actions: expectedActionMap[expectedAction],
|
||||
});
|
||||
},
|
||||
@@ -1657,7 +1662,7 @@ describe('CameraManager', () => {
|
||||
});
|
||||
expect(await manager.getMediaSeekTime(media, middleTime)).toBe(42);
|
||||
|
||||
expect(engine.getMediaSeekTime).toBeCalledWith(
|
||||
expect(engine.getMediaSeekTime).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
media,
|
||||
|
||||
@@ -3,12 +3,9 @@ import { mock } from 'vitest-mock-extended';
|
||||
|
||||
import type { CameraManagerEngine } from '../../../src/camera-manager/engine';
|
||||
import { MotionEyeCamera } from '../../../src/camera-manager/motioneye/camera';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASSManager,
|
||||
createRegistryEntity,
|
||||
} from '../../test-utils';
|
||||
import { createHASSManager, createRegistryEntity } from '../../test-utils';
|
||||
|
||||
const cameraEntity = createRegistryEntity({
|
||||
entity_id: 'camera.motioneye',
|
||||
|
||||
@@ -22,9 +22,9 @@ import {
|
||||
import type { Entity } from '../../../src/ha/registry/entity/types';
|
||||
import { ResolvedMediaCache } from '../../../src/ha/resolved-media';
|
||||
import { QuerySource } from '../../../src/query-source';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createRegistryEntity,
|
||||
|
||||
@@ -7,9 +7,9 @@ import type { CameraProxyConfig } from '../../../src/camera-manager/types';
|
||||
import type { ActionsExecutor } from '../../../src/card-controller/actions/types';
|
||||
import type { DeviceRegistryManager } from '../../../src/ha/registry/device';
|
||||
import type { EntityRegistryManagerLive } from '../../../src/ha/registry/entity';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createRegistryEntity,
|
||||
@@ -107,7 +107,7 @@ describe('ReolinkCamera', () => {
|
||||
entityRegistryManager: mock<EntityRegistryManagerLive>(),
|
||||
deviceRegistryManager: mock<DeviceRegistryManager>(),
|
||||
}),
|
||||
).rejects.toThrowError('Could not find camera entity');
|
||||
).rejects.toThrow('Could not find camera entity');
|
||||
});
|
||||
|
||||
it('without a unique_id', async () => {
|
||||
@@ -130,7 +130,7 @@ describe('ReolinkCamera', () => {
|
||||
entityRegistryManager,
|
||||
deviceRegistryManager: mock<DeviceRegistryManager>(),
|
||||
}),
|
||||
).rejects.toThrowError('Could not initialize Reolink camera');
|
||||
).rejects.toThrow('Could not initialize Reolink camera');
|
||||
});
|
||||
|
||||
it('without a valid unique_id', async () => {
|
||||
@@ -153,7 +153,7 @@ describe('ReolinkCamera', () => {
|
||||
entityRegistryManager,
|
||||
deviceRegistryManager: mock<DeviceRegistryManager>(),
|
||||
}),
|
||||
).rejects.toThrowError('Could not initialize Reolink camera');
|
||||
).rejects.toThrow('Could not initialize Reolink camera');
|
||||
});
|
||||
|
||||
it('successfully with a directly connected camera', async () => {
|
||||
@@ -729,7 +729,7 @@ describe('ReolinkCamera', () => {
|
||||
await camera.executePTZAction(executor, 'left');
|
||||
await camera.executePTZAction(executor, 'left', { phase: 'start' });
|
||||
|
||||
expect(executor.executeActions).not.toBeCalled();
|
||||
expect(executor.executeActions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should ignore actions with configured action', async () => {
|
||||
@@ -758,7 +758,7 @@ describe('ReolinkCamera', () => {
|
||||
const executor = mock<ActionsExecutor>();
|
||||
await camera.executePTZAction(executor, 'left', { phase: 'start' });
|
||||
|
||||
expect(executor.executeActions).toBeCalledTimes(1);
|
||||
expect(executor.executeActions).toHaveBeenCalledTimes(1);
|
||||
expect(executor.executeActions).toHaveBeenLastCalledWith({
|
||||
actions: {
|
||||
action: 'perform-action',
|
||||
|
||||
@@ -31,15 +31,10 @@ import type { EntityRegistryManager } from '../../../src/ha/registry/entity/type
|
||||
import { ResolvedMediaCache } from '../../../src/ha/resolved-media';
|
||||
import { homeAssistantWSRequest } from '../../../src/ha/ws-request';
|
||||
import { QuerySource } from '../../../src/query-source';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createInitializedCamera,
|
||||
createRegistryEntity,
|
||||
createStore,
|
||||
} from '../../test-utils';
|
||||
import { createHASS, createHASSManager, createRegistryEntity } from '../../test-utils';
|
||||
import { createInitializedCamera, createStore } from '../test-utils';
|
||||
|
||||
vi.mock('../../../src/ha/ws-request');
|
||||
|
||||
|
||||
@@ -9,12 +9,10 @@ import { Engine } from '../../src/camera-manager/types.js';
|
||||
import type { DeviceRegistryManager } from '../../src/ha/registry/device/index.js';
|
||||
import type { EntityRegistryManager } from '../../src/ha/registry/entity/types.js';
|
||||
import type { ResolvedMediaCache } from '../../src/ha/resolved-media.js';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASSManager,
|
||||
createInitializedCamera,
|
||||
TestViewMedia,
|
||||
} from '../test-utils.js';
|
||||
import { createCameraConfig } from '../config/test-utils';
|
||||
import { createHASSManager } from '../test-utils.js';
|
||||
import { TestViewMedia } from '../view/test-utils';
|
||||
import { createInitializedCamera } from './test-utils';
|
||||
|
||||
describe('CameraManagerStore', async () => {
|
||||
const configVisible = createCameraConfig({
|
||||
@@ -144,7 +142,7 @@ describe('CameraManagerStore', async () => {
|
||||
|
||||
expect(store.getCameraCount()).toBe(0);
|
||||
for (const camera of cameras) {
|
||||
expect(camera.destroy).toBeCalled();
|
||||
expect(camera.destroy).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -381,10 +379,10 @@ describe('CameraManagerStore', async () => {
|
||||
expect(store.getCamera('camera-3')).toBe(camera_3_new);
|
||||
expect(store.getCamera('camera-4')).toBe(camera_4);
|
||||
|
||||
expect(camera_1.destroy).toBeCalled();
|
||||
expect(camera_2.destroy).not.toBeCalled();
|
||||
expect(camera_3.destroy).toBeCalled();
|
||||
expect(camera_3_new.destroy).not.toBeCalled();
|
||||
expect(camera_4.destroy).not.toBeCalled();
|
||||
expect(camera_1.destroy).toHaveBeenCalled();
|
||||
expect(camera_2.destroy).not.toHaveBeenCalled();
|
||||
expect(camera_3.destroy).toHaveBeenCalled();
|
||||
expect(camera_3_new.destroy).not.toHaveBeenCalled();
|
||||
expect(camera_4.destroy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import { vi } from 'vitest';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
|
||||
import { Camera } from '../../src/camera-manager/camera';
|
||||
import { Capabilities } from '../../src/camera-manager/capabilities';
|
||||
import type { CameraManagerEngine } from '../../src/camera-manager/engine';
|
||||
import { GenericCameraManagerEngine } from '../../src/camera-manager/generic/engine-generic';
|
||||
import type { CameraManager } from '../../src/camera-manager/manager';
|
||||
import { CameraManagerStore } from '../../src/camera-manager/store';
|
||||
import { type CameraEventCallback } from '../../src/camera-manager/types';
|
||||
import type { StateWatcherSubscriptionInterface } from '../../src/card-controller/hass/state-watcher';
|
||||
import { type CameraConfig } from '../../src/config/schema/cameras';
|
||||
import type { EntityRegistryManager } from '../../src/ha/registry/entity/types';
|
||||
import type { CapabilitiesRaw } from '../../src/types';
|
||||
import { createCameraConfig } from '../config/test-utils';
|
||||
import { createHASSManager } from '../test-utils';
|
||||
|
||||
export const createCapabilities = (capabilities?: CapabilitiesRaw): Capabilities => {
|
||||
return new Capabilities({
|
||||
'favorite-events': false,
|
||||
'favorite-recordings': false,
|
||||
'remote-control-entity': true,
|
||||
clips: false,
|
||||
live: false,
|
||||
recordings: false,
|
||||
seek: false,
|
||||
snapshots: false,
|
||||
trigger: true,
|
||||
...capabilities,
|
||||
});
|
||||
};
|
||||
|
||||
export const createInitializedCamera = async (
|
||||
config: CameraConfig,
|
||||
engine: CameraManagerEngine,
|
||||
capabilities?: Capabilities,
|
||||
stateWatcher?: StateWatcherSubscriptionInterface,
|
||||
): Promise<Camera> => {
|
||||
const camera = new Camera(config, engine);
|
||||
await camera.initialize({
|
||||
hassManager: createHASSManager({ stateWatcher }),
|
||||
...(capabilities ? { capabilityOptions: { capabilities } } : {}),
|
||||
});
|
||||
return camera;
|
||||
};
|
||||
|
||||
export const createStore = (
|
||||
cameras?: {
|
||||
cameraID: string;
|
||||
engine?: CameraManagerEngine;
|
||||
config?: CameraConfig;
|
||||
capabilities?: Capabilities | null;
|
||||
eventCallback?: CameraEventCallback;
|
||||
}[],
|
||||
): CameraManagerStore => {
|
||||
const store = new CameraManagerStore();
|
||||
for (const cameraProps of cameras ?? []) {
|
||||
const eventCallback = cameraProps.eventCallback ?? vi.fn();
|
||||
const capabilities =
|
||||
cameraProps.capabilities === undefined
|
||||
? createCapabilities()
|
||||
: cameraProps.capabilities ?? undefined;
|
||||
const camera = new Camera(
|
||||
cameraProps.config ?? createCameraConfig(),
|
||||
cameraProps.engine ??
|
||||
new GenericCameraManagerEngine(
|
||||
createHASSManager(),
|
||||
mock<EntityRegistryManager>(),
|
||||
eventCallback,
|
||||
),
|
||||
{ eventCallback, capabilities },
|
||||
);
|
||||
camera.setID(cameraProps.cameraID);
|
||||
store.addCamera(camera);
|
||||
}
|
||||
return store;
|
||||
};
|
||||
|
||||
export const createCameraManager = (store?: CameraManagerStore): CameraManager => {
|
||||
const cameraStore = store ?? createStore();
|
||||
const cameraManager = mock<CameraManager>();
|
||||
vi.mocked(cameraManager.getStore).mockReturnValue(cameraStore);
|
||||
vi.mocked(cameraManager.getCameraCapabilities).mockImplementation(
|
||||
(cameraID: string): Capabilities | null => {
|
||||
return cameraStore.getCamera(cameraID)?.getCapabilities() ?? null;
|
||||
},
|
||||
);
|
||||
|
||||
return cameraManager;
|
||||
};
|
||||
@@ -4,12 +4,9 @@ import { mock } from 'vitest-mock-extended';
|
||||
import type { CameraManagerEngine } from '../../../src/camera-manager/engine';
|
||||
import { TPLinkCamera } from '../../../src/camera-manager/tplink/camera';
|
||||
import type { ActionsExecutor } from '../../../src/card-controller/actions/types';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASSManager,
|
||||
createRegistryEntity,
|
||||
} from '../../test-utils';
|
||||
import { createHASSManager, createRegistryEntity } from '../../test-utils';
|
||||
|
||||
describe('TPLinkCamera', () => {
|
||||
// Entity patterns from: https://github.com/dermotduffy/advanced-camera-card/issues/2183
|
||||
@@ -83,7 +80,7 @@ describe('TPLinkCamera', () => {
|
||||
hassManager: createHASSManager(),
|
||||
entityRegistryManager: new EntityRegistryManagerMock(),
|
||||
}),
|
||||
).rejects.toThrowError('Could not find camera entity');
|
||||
).rejects.toThrow('Could not find camera entity');
|
||||
});
|
||||
|
||||
it('without a matching entity in registry', async () => {
|
||||
@@ -98,7 +95,7 @@ describe('TPLinkCamera', () => {
|
||||
hassManager: createHASSManager(),
|
||||
entityRegistryManager: new EntityRegistryManagerMock(),
|
||||
}),
|
||||
).rejects.toThrowError('Could not find camera entity');
|
||||
).rejects.toThrow('Could not find camera entity');
|
||||
});
|
||||
|
||||
it('successfully with webrtc_card.entity fallback', async () => {
|
||||
@@ -204,7 +201,7 @@ describe('TPLinkCamera', () => {
|
||||
await camera.executePTZAction(executor, 'left', { phase: 'start' }),
|
||||
).toBeFalsy();
|
||||
|
||||
expect(executor.executeActions).not.toBeCalled();
|
||||
expect(executor.executeActions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should ignore zoom actions (not supported by TPLink)', async () => {
|
||||
@@ -226,7 +223,7 @@ describe('TPLinkCamera', () => {
|
||||
await camera.executePTZAction(executor, 'zoom_out', { phase: 'start' }),
|
||||
).toBeFalsy();
|
||||
|
||||
expect(executor.executeActions).not.toBeCalled();
|
||||
expect(executor.executeActions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should ignore preset actions (not supported by TPLink)', async () => {
|
||||
@@ -245,7 +242,7 @@ describe('TPLinkCamera', () => {
|
||||
await camera.executePTZAction(executor, 'preset', { preset: 'home' }),
|
||||
).toBeFalsy();
|
||||
|
||||
expect(executor.executeActions).not.toBeCalled();
|
||||
expect(executor.executeActions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle stop phase (no-op for TPLink)', async () => {
|
||||
@@ -265,7 +262,7 @@ describe('TPLinkCamera', () => {
|
||||
await camera.executePTZAction(executor, 'left', { phase: 'stop' }),
|
||||
).toBeTruthy();
|
||||
|
||||
expect(executor.executeActions).not.toBeCalled();
|
||||
expect(executor.executeActions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -353,7 +350,7 @@ describe('TPLinkCamera', () => {
|
||||
const executor = mock<ActionsExecutor>();
|
||||
await camera.executePTZAction(executor, 'left', { phase: 'start' });
|
||||
|
||||
expect(executor.executeActions).toBeCalledTimes(1);
|
||||
expect(executor.executeActions).toHaveBeenCalledTimes(1);
|
||||
expect(executor.executeActions).toHaveBeenLastCalledWith({
|
||||
actions: {
|
||||
action: 'perform-action',
|
||||
|
||||
@@ -2,13 +2,9 @@ import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { TPLinkCameraManagerEngine } from '../../../src/camera-manager/tplink/engine-tplink';
|
||||
import { Engine } from '../../../src/camera-manager/types';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||
import {
|
||||
createCameraConfig,
|
||||
createHASS,
|
||||
createHASSManager,
|
||||
createRegistryEntity,
|
||||
} from '../../test-utils';
|
||||
import { createHASS, createHASSManager, createRegistryEntity } from '../../test-utils';
|
||||
|
||||
const createEngine = (options?: {
|
||||
entityRegistryManager?: EntityRegistryManagerMock;
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
getGo2RTCMetadataEndpoint,
|
||||
getGo2RTCStreamEndpoint,
|
||||
} from '../../../src/camera-manager/utils/go2rtc/endpoint.js';
|
||||
import { createCameraConfig } from '../../test-utils.js';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
|
||||
describe('getGo2RTCStreamEndpoint', () => {
|
||||
it('with local configuration', () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from '../../../src/camera-manager/utils/ptz';
|
||||
import type { PTZAction } from '../../../src/config/schema/actions/custom/ptz';
|
||||
import { PTZMovementType } from '../../../src/types';
|
||||
import { createCameraConfig } from '../../test-utils';
|
||||
import { createCameraConfig } from '../../config/test-utils';
|
||||
|
||||
const action = {
|
||||
action: 'perform-action' as const,
|
||||
|
||||
Reference in New Issue
Block a user