Files
Enelix-EMS/services/license/changes/20261006-heat-pump-header/tests/system-wizard.test.mjs
T
2026-10-06 14:35:17 +00:00

142 lines
5.5 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
consumerFields,
normalizeSystemConfiguration,
publicWizardCatalog
} from "../portal-domain.mjs";
import { buildSymconPackage } from "../symcon-package.mjs";
const emptyDevices = () => ({
battery: { quantity: 0, items: [] },
buffer_storage: { quantity: 0, items: [] },
ev_charger: { quantity: 0, items: [] },
consumer_single: { quantity: 0, items: [] },
boiler_multi: { quantity: 0, items: [] },
heat_pump: { quantity: 0, items: [] }
});
const baseConfiguration = () => ({
name: "Testsystem",
location: "Zürich",
manager: { properties: {} },
gridMeasurement: { profile: "manual", sourceVariableId: 42 },
pvSystem: { enabled: false },
devices: emptyDevices()
});
test("wizard catalog contains complete manager, consumer and integration schemas", () => {
const catalog = publicWizardCatalog();
assert.equal(catalog.schemaVersion, 4);
assert.equal(catalog.managerFields.length, 11);
assert.deepEqual(Object.keys(catalog.consumerFields).sort(), Object.keys(emptyDevices()).sort());
assert.equal(catalog.evVariants.length, 2);
assert.ok(catalog.integrations.energy.some(profile => profile.id === "fronius_solar_api_v1"));
assert.ok(catalog.integrations.energy.some(profile => profile.id === "huawei_sun2000_modbus"));
assert.ok(catalog.integrations.energy.some(profile => profile.id === "sma_sunspec_modbus"));
assert.ok(catalog.integrations.energy.some(profile => profile.id === "goodwe_et_modbus"));
assert.ok(catalog.integrations.energy.some(profile => profile.id === "solaredge_sunspec_modbus"));
assert.ok(catalog.integrations.storage.some(profile => profile.id === "sigenergy_sigenstor"));
assert.ok(catalog.integrations.actuator.some(profile => profile.id === "shelly_pro_4pm"));
assert.ok(consumerFields.battery.length > 20);
});
test("normalizes individual device properties and integration metadata", () => {
const configuration = baseConfiguration();
configuration.manager.properties.MesswertMaxAlter = 15;
configuration.devices.consumer_single = {
quantity: 1,
items: [{
name: "Wärmepumpe",
integration: { profile: "shelly_pro_4pm", topicPrefix: "shellypro4pm-test", channel: 3 },
properties: { Nennleistung: 4200, PrioritaetPV: 2 }
}]
};
const result = normalizeSystemConfiguration(configuration);
assert.equal(result.manager.properties.MesswertMaxAlter, 15);
assert.equal(result.devices.consumer_single.items[0].integration.channel, 3);
assert.equal(result.devices.consumer_single.items[0].properties.Nennleistung, 4200);
assert.equal(result.devices.consumer_single.items[0].properties.PrioritaetPV, 2);
});
test("derives battery type and enables charging by default", () => {
const configuration = baseConfiguration();
configuration.devices.battery = {
quantity: 2,
items: [{
name: "Hausspeicher",
integration: { profile: "goodwe_lynx", host: "192.0.2.10" },
properties: { Batterietyp: 0 }
}, {
name: "Gewerbespeicher",
integration: { profile: "sigenergy_sigenstor", host: "192.0.2.11" },
properties: { Batterietyp: 0 }
}]
};
configuration.devices.ev_charger = {
quantity: 2,
items: [{ name: "Direkt", variant: "standalone", properties: {} },
{ name: "Gateway", variant: "gateway", properties: {} }]
};
const result = normalizeSystemConfiguration(configuration);
assert.equal(result.devices.battery.items[0].properties.Batterietyp, 2);
assert.equal(result.devices.battery.items[1].properties.Batterietyp, 4);
assert.equal(result.devices.ev_charger.items[0].properties.Ladefreigabe, true);
assert.equal(result.devices.ev_charger.items[1].properties.Ladefreigabe, true);
});
test("package wires gateway, Shelly feedback, levels, sensors and visualisation", () => {
const configuration = baseConfiguration();
configuration.devices.ev_charger = {
quantity: 1,
items: [{ name: "Garage", variant: "gateway", properties: { Ladestationskennung: "EH123" } }]
};
configuration.devices.consumer_single = {
quantity: 1,
items: [{ name: "Heizstab", integration: { profile: "shelly_plus_1pm", topicPrefix: "shelly/heizstab" }, properties: {} }]
};
configuration.devices.boiler_multi = {
quantity: 1,
items: [{
name: "Boiler",
properties: {},
powerLevels: [{ Stufe: 1, Leistung: 3000, integration: { profile: "shelly_pro_2pm", topicPrefix: "shelly/boiler", channel: 1 } }],
schedule: [{ Uhrzeit: "06:30", Solltemperatur: 55 }],
sensor: { profile: "shelly_addon_temperature", topicPrefix: "shelly/boiler" }
}]
};
const archive = buildSymconPackage(configuration).toString("utf8");
assert.match(archive, /RueckmeldungVariableID/);
assert.match(archive, /Boilerfuehler_PT1/);
assert.match(archive, /IPS_ConnectInstance/);
assert.match(archive, /Energie-Kreisdiagramm/);
});
test("requires a host for network profiles", () => {
const configuration = baseConfiguration();
configuration.gridMeasurement = { profile: "sma_sunspec_modbus" };
assert.throws(
() => normalizeSystemConfiguration(configuration),
error => error.message === "integration_host_missing"
);
});
test("requires an MQTT topic for Shelly profiles", () => {
const configuration = baseConfiguration();
configuration.devices.consumer_single = {
quantity: 1,
items: [{
name: "Heizstab",
integration: { profile: "shelly_plus_1pm" },
properties: {}
}]
};
assert.throws(
() => normalizeSystemConfiguration(configuration),
error => error.message === "integration_topic_missing"
);
});