node-red-contrib-power-saver
Version:
A module for Node-RED that you can use to turn on and off a switch based on power prices
176 lines (170 loc) • 5.97 kB
JavaScript
const expect = require("chai").expect;
const helper = require("node-red-node-test-helper");
const bestSave = require("../src/strategy-best-save.js");
const { DateTime } = require("luxon");
const prices = require("./data/converted-prices.json");
const result = require("./data/best-save-result.json");
const reconfigResult = require("./data/reconfigResult");
const { testPlan, equalPlan } = require("./test-utils");
const { makeFlow, makePayload } = require("./strategy-best-save-test-utils");
const cloneDeep = require("lodash.clonedeep");
helper.init(require.resolve("node-red"));
describe("send config as input", () => {
beforeEach(function (done) {
helper.startServer(done);
});
afterEach(function (done) {
helper.unload().then(function () {
helper.stopServer(done);
});
});
it("should send new schedule on output 3", function (done) {
const flow = makeFlow(3, 2);
let pass = 1;
helper.load(bestSave, flow, function () {
const n1 = helper.getNode("n1");
const n2 = helper.getNode("n2");
n2.on("input", function (msg) {
switch (pass) {
case 1:
pass++;
expect(equalPlan(result, msg.payload)).to.equal(true);
n1.receive({ payload: { config: { minSaving: 1.0 } } });
break;
case 2:
pass++;
expect(msg.payload.schedule.length).to.equal(2);
n1.receive({ payload: makePayload(prices, testPlan.time) });
break;
case 3:
pass++;
expect(msg.payload.schedule.length).to.equal(2);
done();
}
});
n1.receive({ payload: makePayload(prices, testPlan.time) });
});
});
it("should use another minHoursOnAfterMaxSequenceSaved", function (done) {
const flow = makeFlow(3, 2);
const changeTime = DateTime.fromISO("2021-06-20T01:50:00.045+02:00");
let pass = 1;
helper.load(bestSave, flow, function () {
const n1 = helper.getNode("n1");
const n2 = helper.getNode("n2");
n2.on("input", function (msg) {
switch (pass) {
case 1:
pass++;
expect(equalPlan(result, msg.payload)).to.equal(true);
n1.receive({
payload: {
config: { minHoursOnAfterMaxSequenceSaved: 5 },
time: changeTime,
},
});
break;
case 2:
pass++;
reconfigResult.config.minHoursOnAfterMaxSequenceSaved = 5;
expect(equalPlan(reconfigResult, msg.payload)).to.equal(true);
const payload = makePayload(prices, testPlan.time);
payload.time = changeTime;
n1.receive({ payload });
break;
case 3:
pass++;
expect(equalPlan(reconfigResult, msg.payload)).to.equal(true);
done();
}
});
n1.receive({ payload: makePayload(prices, testPlan.time) });
});
});
it("should accept config and price-data together", function (done) {
const flow = makeFlow(3, 2);
let pass = 1;
helper.load(bestSave, flow, function () {
const n1 = helper.getNode("n1");
const n2 = helper.getNode("n2");
n2.on("input", function (msg) {
switch (pass) {
case 1:
pass++;
expect(equalPlan(result, msg.payload)).to.equal(true);
n1.receive({ payload: makePayloadWithConfigAndPrices(prices, testPlan.time) });
break;
case 2:
pass++;
const priceSum = prices.priceData.reduce((prev, p) => {
return prev + p.value;
}, 0);
const planSum = msg.payload.hours.reduce((prev, h) => {
return prev + h.price;
}, 0);
expect(Math.round(planSum)).to.equal(Math.round(priceSum * 2));
done();
}
});
n1.receive({ payload: makePayload(prices, testPlan.time) });
});
});
it("can override", function (done) {
const flow = makeFlow(3, 2, false);
const time = prices.priceData[0].start;
helper.load(bestSave, flow, function () {
const n1 = helper.getNode("n1");
const n2 = helper.getNode("n2");
const n3 = helper.getNode("n3");
const n4 = helper.getNode("n4");
let countOn = 0;
let countOff = 0;
let pass = 0;
n2.on("input", function (msg) {
pass++;
n1.warn.should.not.be.called;
if (pass === 1) {
setTimeout(() => {
console.log("countOn = " + countOn + ", countOff = " + countOff);
expect(countOn).to.equal(2);
expect(countOff).to.equal(2);
n1.status.should.be.calledWithExactly({ fill: "yellow", shape: "dot", text: "Override on" });
done();
}, 900);
}
});
n3.on("input", function (msg) {
countOn++;
expect(msg).to.have.deep.property("payload", true);
if (countOn === 2) {
n1.receive({ payload: { config: { override: "on" }, time } });
}
});
n4.on("input", function (msg) {
countOff++;
expect(msg).to.have.deep.property("payload", false);
if (countOff === 1) {
n1.receive({ payload: { config: { override: "on" }, name: "wrong name" }, time });
}
if (countOff === 2) {
n1.receive({ payload: { config: { override: "on" }, time } });
}
});
n1.receive({ payload: makePayload(prices, time) });
});
});
});
function makePayloadWithConfigAndPrices(prices, time) {
const payload = cloneDeep(prices);
payload.priceData.forEach((e) => {
e.value = e.value * 2;
});
payload.time = time;
let entryTime = DateTime.fromISO(payload.time);
payload.priceData.forEach((e) => {
e.start = entryTime.toISO();
entryTime = entryTime.plus({ milliseconds: 10 });
});
payload.config = { minSaving: 0.01 };
return payload;
}