Files
Enelix-Utils/tests/EnergyPieVisualizationTest.cjs
T
2026-10-07 17:16:00 +00:00

147 lines
5.9 KiB
JavaScript

'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const vm = require('node:vm');
function visualization(initialState) {
const elements = new Map();
const element = id => {
if (!elements.has(id)) {
elements.set(id, {
innerHTML: '', textContent: '', value: '', hidden: false,
style: {
setProperty(name, value) { this[name] = value; }
},
addEventListener() {}, classList: { toggle() {} }
});
}
return elements.get(id);
};
const window = { setTimeout() {} };
const document = {
getElementById: element,
documentElement: { style: {} },
addEventListener() {}
};
const html = fs.readFileSync(path.join(__dirname, '../Energiediagramm/module.html'), 'utf8');
const script = html.match(/<script>([\s\S]*?)<\/script>/)[1]
.replace('__ENELIX_INITIAL_STATE__', JSON.stringify(initialState));
vm.runInNewContext(script, {
window, document,
getComputedStyle: () => ({ getPropertyValue: () => '' })
});
return { element, window, document };
}
function payload(overrides = {}) {
return {
range: 'day', date: '2026-10-06', hasData: true,
values: {
Produktion: 10, Hausverbrauch: 5, Netzbezug: 10, Einspeisung: 0,
Eigenverbrauchsquote: null, Autarkiegrad: null
},
...overrides
};
}
test('unavailable shares show neutral rings while preserving energy totals', () => {
const ui = visualization(payload({ sharesAvailable: false, attributionHint: 'Different measurement boundaries.' }));
for (const id of ['self-consumption-chart', 'autarky-chart']) {
const html = ui.element(id).innerHTML;
assert.match(html, /Nicht bestimmbar/);
assert.doesNotMatch(html, /donut-value|0\.0%/);
}
assert.match(ui.element('summary').innerHTML, /Produktion/);
assert.match(ui.element('summary').innerHTML, /10\.00 kWh/);
assert.match(ui.element('summary').innerHTML, /5\.00 kWh/);
assert.equal(ui.element('message').hidden, false);
assert.equal(ui.element('message').textContent, 'Different measurement boundaries.');
});
test('unavailable flag cannot display stale numeric percentages', () => {
const state = payload({ sharesAvailable: false });
state.values.Eigenverbrauchsquote = 75;
state.values.Autarkiegrad = 50;
const ui = visualization(state);
assert.doesNotMatch(ui.element('self-consumption-chart').innerHTML, /75\.0%/);
assert.doesNotMatch(ui.element('autarky-chart').innerHTML, /50\.0%/);
});
test('legacy numeric percentages and later recovery remain compatible', () => {
const ui = visualization(payload({ sharesAvailable: false }));
const state = payload();
state.values.Eigenverbrauchsquote = 75;
state.values.Autarkiegrad = 81.25;
ui.window.handleMessage(JSON.stringify(state));
assert.match(ui.element('self-consumption-chart').innerHTML, /75\.0%/);
assert.match(ui.element('autarky-chart').innerHTML, /81\.3%/);
assert.equal(ui.element('message').hidden, true);
});
test('missing archive values do not hide the attribution limitation', () => {
const ui = visualization(payload({
hasData: false, noDataHint: 'No archive data.',
sharesAvailable: false, attributionHint: 'Different measurement boundaries.'
}));
assert.equal(ui.element('message').textContent,
'No archive data. Different measurement boundaries.');
});
test('old payloads retain the original Energy Pie background', () => {
const ui = visualization(payload());
const style = ui.element('energy-app').style;
assert.equal(style['--card-color'], '#121216');
assert.equal(style['--background-accent-1-rgb'], '99, 179, 255');
assert.equal(style['--background-accent-2-rgb'], '168, 85, 247');
assert.equal(style['--content-color'], '#f5f5f7');
assert.equal(style.colorScheme, 'dark');
});
test('configured backgrounds apply initially and on visualization updates', () => {
const ui = visualization(payload({ colors: {
background: '#FFFFFF', backgroundAccent1: '#DCE169', backgroundAccent2: '#4E8181',
selfConsumption: '#1259A7', autarky: '#178A55'
} }));
const style = ui.element('energy-app').style;
assert.equal(style['--card-color'], '#FFFFFF');
assert.equal(style['--background-accent-1-rgb'], '220, 225, 105');
assert.equal(style['--background-accent-2-rgb'], '78, 129, 129');
assert.equal(style['--content-color'], '#121216');
assert.equal(style.colorScheme, 'light');
assert.equal(ui.document.documentElement.style.colorScheme, undefined);
const state = payload({ colors: {
background: '#000000', backgroundAccent1: '#112233', backgroundAccent2: '#445566',
selfConsumption: '#1259A7', autarky: '#178A55'
} });
state.values.Eigenverbrauchsquote = 75;
state.values.Autarkiegrad = 50;
ui.window.handleMessage(JSON.stringify(state));
assert.equal(style['--card-color'], '#000000');
assert.equal(style['--background-accent-1-rgb'], '17, 34, 51');
assert.equal(style['--background-accent-2-rgb'], '68, 85, 102');
assert.equal(style['--content-color'], '#f5f5f7');
assert.equal(style.colorScheme, 'dark');
assert.match(ui.element('self-consumption-chart').innerHTML, /stroke="#1259A7"/);
assert.match(ui.element('autarky-chart').innerHTML, /stroke="#178A55"/);
ui.window.handleMessage(payload());
assert.equal(style['--card-color'], '#121216');
assert.equal(style['--background-accent-1-rgb'], '99, 179, 255');
});
test('invalid or incomplete background colors fall back independently', () => {
for (const invalid of [null, -1, 16777216, {}, '', '#123', '#123456; color:red', 'url(https://invalid.test/)']) {
const ui = visualization(payload({ hasData: false, colors: {
background: invalid, backgroundAccent1: '#aAbBcC', backgroundAccent2: invalid
} }));
const style = ui.element('energy-app').style;
assert.equal(style['--card-color'], '#121216');
assert.equal(style['--background-accent-1-rgb'], '170, 187, 204');
assert.equal(style['--background-accent-2-rgb'], '168, 85, 247');
}
});