chore: Update ha-nunjucks to 1.6.2 (#2549)

- Replaces:
https://github.com/dermotduffy/advanced-camera-card/pull/2515
This commit is contained in:
Dermot Duffy
2026-06-30 17:45:13 -07:00
committed by dermotduffy
parent 015fb1876d
commit c3d3dd3934
15 changed files with 113 additions and 14 deletions
@@ -8,8 +8,15 @@ import type {
BrowseMediaMetadata,
RichBrowseMedia,
} from '../../../../src/ha/browse-media/types';
import { createHASS, createMockTemplateRenderer } from '../../../test-utils';
import {
createHASS,
createMockTemplateRenderer,
stubConnectedHomeAssistant,
} from '../../../test-utils';
// The `with template matcher` test loads the real ha-nunjucks engine, which
// reads `window`/`document` at import, so this suite needs a DOM environment.
// @vitest-environment jsdom
describe('MediaMatcher', () => {
// A mock renderer for the matcher plumbing, which never renders templates.
// The `value_template` suite below uses its own real, loaded engine.
@@ -153,6 +160,7 @@ describe('MediaMatcher', () => {
// renderer (rather than the shared mock).
const templateManager = new TemplateManager();
beforeAll(async () => {
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
});
+12 -2
View File
@@ -1,9 +1,19 @@
import { describe, expect, it, vi } from 'vitest';
import { beforeAll, describe, expect, it, vi } from 'vitest';
import { TemplateManager } from '../../../src/card-controller/templates/index';
import { createConfig, createHASS, createStateEntity } from '../../test-utils';
import {
createConfig,
createHASS,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../test-utils';
// ha-nunjucks reads `window`/`document` at import and renders via a
// `window.haNunjucks` global, so the renderer needs a DOM environment.
// @vitest-environment jsdom
describe('TemplateManager', () => {
beforeAll(() => stubConnectedHomeAssistant());
describe('loadRenderer', () => {
it('should render a template raw before the engine is loaded', () => {
const manager = new TemplateManager();
@@ -6,6 +6,7 @@ import {
createHASS,
createMockTemplateRenderer,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../test-utils';
// @vitest-environment jsdom
@@ -66,6 +67,7 @@ describe('renderTimePeriodToSeconds', () => {
const templateManager = new TemplateManager();
beforeAll(async () => {
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
});
@@ -7,6 +7,7 @@ import {
createHASS,
createMockTemplateRenderer,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../test-utils';
// A mock renderer for the orchestration tests, which never render templates.
@@ -198,6 +199,7 @@ describe('ConditionsManager', () => {
// loaded for the synchronous renderer (rather than the shared mock).
const templateManager = new TemplateManager();
beforeAll(async () => {
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
});
@@ -6,6 +6,7 @@ import {
createHASS,
createMockTemplateRenderer,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../../test-utils';
import { createEvaluatorContext } from './test-utils';
@@ -131,6 +132,7 @@ describe('numeric state condition', () => {
// This case renders a real value_template, so load the lazily-imported
// engine for the synchronous renderer.
const templateManager = new TemplateManager();
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
const evaluator = createConditionEvaluator(
@@ -2,7 +2,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { TemplateManager } from '../../../../src/card-controller/templates';
import { createConditionEvaluator } from '../../../../src/condition-trigger/conditions/factory';
import { createHASS, createStateEntity } from '../../../test-utils';
import {
createHASS,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../../test-utils';
import { createEvaluatorContext } from './test-utils';
// @vitest-environment jsdom
@@ -340,6 +344,7 @@ describe('state condition', () => {
// This case renders a real templated `for`, so load the lazily-imported
// engine for the synchronous renderer.
const templateManager = new TemplateManager();
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
const evaluator = createConditionEvaluator(
@@ -2,13 +2,18 @@ import { beforeAll, describe, expect, it } from 'vitest';
import { TemplateManager } from '../../../../src/card-controller/templates';
import { createConditionEvaluator } from '../../../../src/condition-trigger/conditions/factory';
import { createHASS, createStateEntity } from '../../../test-utils';
import {
createHASS,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../../test-utils';
import { createEvaluatorContext } from './test-utils';
// @vitest-environment jsdom
describe('template condition', () => {
const templateManager = new TemplateManager();
beforeAll(async () => {
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
});
@@ -9,6 +9,7 @@ import {
createHASSManager,
createMockTemplateRenderer,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../test-utils';
const templateManager = createMockTemplateRenderer();
@@ -126,6 +127,7 @@ describe('TriggersManager', () => {
// loaded for the synchronous renderer (rather than the shared mock).
const templateManager = new TemplateManager();
beforeAll(async () => {
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
});
@@ -8,7 +8,11 @@ import {
import { ConditionStateManager } from '../../../../src/condition-trigger/conditions/state-manager';
import { NumericStateTrigger } from '../../../../src/condition-trigger/triggers/triggers/numeric-state';
import type { TriggerOfType } from '../../../../src/condition-trigger/triggers/triggers/types';
import { createHASS, createStateEntity } from '../../../test-utils';
import {
createHASS,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../../test-utils';
import { createTriggerEvaluatorContext } from './test-utils';
const SENSOR = 'sensor.temperature';
@@ -163,6 +167,7 @@ describe('NumericStateTrigger', () => {
it('should match the rendered value_template', async () => {
const templateManager = new TemplateManager();
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
const { trigger, stateManager, callback } = create(
@@ -13,11 +13,16 @@ import { TemplateManager } from '../../../../src/card-controller/templates';
import { ConditionStateManager } from '../../../../src/condition-trigger/conditions/state-manager';
import { TemplateTrigger } from '../../../../src/condition-trigger/triggers/triggers/template';
import type { TriggerOfType } from '../../../../src/condition-trigger/triggers/triggers/types';
import { createHASS, createStateEntity } from '../../../test-utils';
import {
createHASS,
createStateEntity,
stubConnectedHomeAssistant,
} from '../../../test-utils';
import { createTriggerEvaluatorContext } from './test-utils';
const templateManager = new TemplateManager();
beforeAll(async () => {
stubConnectedHomeAssistant();
await templateManager.loadRenderer();
});
+30
View File
@@ -758,6 +758,36 @@ export const createMockTemplateRenderer = (): TemplateManager => {
return renderer;
};
// At import the real ha-nunjucks engine waits for a connected `home-assistant`
// element before finishing initialization, retrying on a timer that can outlive
// the test (and throw `document is not defined` once the environment is torn
// down). Test suites that load the real engine call this first, in a jsdom
// environment, so it initializes immediately as it does in a real Home
// Assistant frontend. Idempotent.
//
// Workaround for an upstream bug; remove once it is fixed:
// https://github.com/Nerwyn/ha-nunjucks/issues/11
export const stubConnectedHomeAssistant = (): void => {
if (document.querySelector('home-assistant')) {
return;
}
const ha = document.createElement('home-assistant');
Object.assign(ha, {
hass: {
// The readiness gate the engine polls for.
connected: true,
connection: {
connected: true,
// Awaited by the engine's label-registry fetch during init.
sendMessagePromise: () => Promise.resolve([]),
},
language: 'en',
states: {},
},
});
document.body.appendChild(ha);
};
export const createCardAPI = (): CardController => {
const api = mock<CardController>();