From 91ffe0656bb0316d3940d26f912b96a68eecaaea Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Mon, 26 Aug 2024 14:35:16 -0700 Subject: [PATCH] Don't run automations prior to initialization . --- src/card-controller/automations-manager.ts | 15 ++++--- src/card-controller/hass/hass-manager.ts | 4 ++ src/card-controller/types.ts | 1 + .../automations-manager.test.ts | 41 ++++++++++++++++--- .../card-controller/hass/hass-manager.test.ts | 10 +++++ 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/card-controller/automations-manager.ts b/src/card-controller/automations-manager.ts index dbc38abb..367a7f5c 100644 --- a/src/card-controller/automations-manager.ts +++ b/src/card-controller/automations-manager.ts @@ -27,11 +27,16 @@ export class AutomationsManager { } public execute(): void { - const hass = this._api.getHASSManager().getHASS(); - - // Never execute automations if there's an error (as our automation loop - // avoidance -- which shows as an error -- would not work!). - if (!hass || this._api.getMessageManager().hasErrorMessage()) { + if ( + !this._api.getHASSManager().hasHASS() || + // Never execute automations if the card hasn't finished initializing, as + // it could cause a view change when camera loads are not finished. + // See: https://github.com/dermotduffy/frigate-hass-card/issues/1407 + !this._api.getInitializationManager().isInitializedMandatory() || + // Never execute automations if there's an error (as our automation loop + // avoidance -- which shows as an error -- would not work!). + this._api.getMessageManager().hasErrorMessage() + ) { return; } diff --git a/src/card-controller/hass/hass-manager.ts b/src/card-controller/hass/hass-manager.ts index a0ea929f..86ce88eb 100644 --- a/src/card-controller/hass/hass-manager.ts +++ b/src/card-controller/hass/hass-manager.ts @@ -17,6 +17,10 @@ export class HASSManager { return this._hass; } + public hasHASS(): boolean { + return !!this._hass; + } + public getStateWatcher(): StateWatcherSubscriptionInterface { return this._stateWatcher; } diff --git a/src/card-controller/types.ts b/src/card-controller/types.ts index 5dd754d6..834d7f8a 100644 --- a/src/card-controller/types.ts +++ b/src/card-controller/types.ts @@ -59,6 +59,7 @@ export interface CardAutomationsAPI { getCardElementManager(): CardElementManager; getConditionsManager(): ConditionsManager; getHASSManager(): HASSManager; + getInitializationManager(): InitializationManager; getMessageManager(): MessageManager; } diff --git a/tests/card-controller/automations-manager.test.ts b/tests/card-controller/automations-manager.test.ts index a60fa696..2f9d6d41 100644 --- a/tests/card-controller/automations-manager.test.ts +++ b/tests/card-controller/automations-manager.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; import { AutomationsManager } from '../../src/card-controller/automations-manager.js'; -import { createCardAPI, createHASS } from '../test-utils.js'; +import { createCardAPI } from '../test-utils.js'; import { ActionType } from '../../src/config/types.js'; import { AuxillaryActionConfig } from '../../src/card-controller/actions/types.js'; @@ -34,9 +34,25 @@ describe('AutomationsManager', () => { expect(api.getActionsManager().executeActions).not.toBeCalled(); }); + it('should do nothing without being initialized', () => { + const api = createCardAPI(); + vi.mocked(api.getHASSManager().hasHASS).mockReturnValue(true); + vi.mocked(api.getInitializationManager().isInitializedMandatory).mockReturnValue( + false, + ); + + const automationsManager = new AutomationsManager(api); + automationsManager.execute(); + + expect(api.getActionsManager().executeActions).not.toBeCalled(); + }); + it('should do nothing without automations', () => { const api = createCardAPI(); - vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS()); + vi.mocked(api.getHASSManager().hasHASS).mockReturnValue(true); + vi.mocked(api.getInitializationManager().isInitializedMandatory).mockReturnValue( + true, + ); const automationsManager = new AutomationsManager(api); automationsManager.execute(); @@ -46,7 +62,10 @@ describe('AutomationsManager', () => { it('should execute actions', () => { const api = createCardAPI(); - vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS()); + vi.mocked(api.getHASSManager().hasHASS).mockReturnValue(true); + vi.mocked(api.getInitializationManager().isInitializedMandatory).mockReturnValue( + true, + ); const automationsManager = new AutomationsManager(api); automationsManager.addAutomations([automation]); @@ -77,7 +96,11 @@ describe('AutomationsManager', () => { it('should execute actions_not', () => { const api = createCardAPI(); - vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS()); + vi.mocked(api.getHASSManager().hasHASS).mockReturnValue(true); + vi.mocked(api.getInitializationManager().isInitializedMandatory).mockReturnValue( + true, + ); + vi.mocked(api.getConditionsManager().evaluateConditions).mockReturnValue(false); const automationsManager = new AutomationsManager(api); @@ -90,7 +113,10 @@ describe('AutomationsManager', () => { it('should prevent automation loops', () => { const api = createCardAPI(); - vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS()); + vi.mocked(api.getHASSManager().hasHASS).mockReturnValue(true); + vi.mocked(api.getInitializationManager().isInitializedMandatory).mockReturnValue( + true, + ); const automationsManager = new AutomationsManager(api); automationsManager.addAutomations([automation, not_automation]); @@ -130,7 +156,10 @@ describe('AutomationsManager', () => { it('should delete automations', () => { const api = createCardAPI(); - vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS()); + vi.mocked(api.getHASSManager().hasHASS).mockReturnValue(true); + vi.mocked(api.getInitializationManager().isInitializedMandatory).mockReturnValue( + true, + ); const automationsManager = new AutomationsManager(api); automationsManager.addAutomations([automation]); diff --git a/tests/card-controller/hass/hass-manager.test.ts b/tests/card-controller/hass/hass-manager.test.ts index f4051d31..181a2799 100644 --- a/tests/card-controller/hass/hass-manager.test.ts +++ b/tests/card-controller/hass/hass-manager.test.ts @@ -21,6 +21,7 @@ describe('HASSManager', () => { it('should have null hass on construction', () => { const manager = new HASSManager(createCardAPI()); expect(manager.getHASS()).toBeNull(); + expect(manager.hasHASS()).toBeFalsy(); }); it('should get state watcher', () => { @@ -28,6 +29,15 @@ describe('HASSManager', () => { expect(manager.getStateWatcher()).toEqual(expect.any(StateWatcher)); }); + it('should get hass after set', () => { + const manager = new HASSManager(createCardAPI()); + const hass = createHASS(); + manager.setHASS(hass); + + expect(manager.getHASS()).toBe(hass); + expect(manager.hasHASS()).toBeTruthy(); + }); + it('should set light or dark mode upon setting hass', () => { const api = createCardAPI(); const manager = new HASSManager(api);