@yyberi/fronius-comm
Version:
Library for communicating with Fronius solar inverters
214 lines • 8.77 kB
JavaScript
// tests/fronius-comm.test.ts
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
import { FroniusClient } from '@yyberi/fronius-comm';
import * as http from "http";
// Mockataan http.get heti alussa
vi.mock("http", () => ({
get: vi.fn()
}));
describe("FroniusClient", () => {
let client;
beforeEach(() => {
client = new FroniusClient("1.2.3.4", "scope", "deviceId", "deviceClass");
});
afterEach(() => {
vi.clearAllMocks();
});
/* ------------------------------------------------------------------
* getRealtimeData -testit
* ----------------------------------------------------------------*/
function makeMockResponse(json) {
return {
on(event, cb) {
if (event === "data")
cb(json);
if (event === "end")
cb();
return this;
}
};
}
function makeMockRequest(options) {
return {
on(event, cb) {
if (event === "timeout" && options?.timeout)
cb();
if (event === "error" && options?.error)
cb(options.error);
return this;
}
};
}
describe("getRealtimeData()", () => {
it("resolves with parsed values when response contains Value fields", async () => {
const body = {
Body: {
Data: {
TOTAL_ENERGY: { Value: 100 },
YEAR_ENERGY: { Value: 200 },
DAY_ENERGY: { Value: 10 },
PAC: { Value: 5 },
}
}
};
const json = JSON.stringify(body);
const mockRes = makeMockResponse(json);
const mockReq = makeMockRequest();
http.get.mockImplementation((opts, cb) => {
cb(mockRes);
return mockReq;
});
const result = await client.getRealtimeData();
expect(result).toEqual({
totalEnergy: 100,
yearEnergy: 200,
dayEnergy: 10,
actPower: 5
});
});
it("resolves with parsed values when response contains Values fields", async () => {
const body = {
Body: {
Data: {
TOTAL_ENERGY: { Values: { "0": 300 } },
YEAR_ENERGY: { Values: { "0": 400 } },
DAY_ENERGY: { Values: { "0": 20 } },
PAC: { Values: { "0": 8 } },
}
}
};
const json = JSON.stringify(body);
const mockRes = makeMockResponse(json);
const mockReq = makeMockRequest();
http.get.mockImplementation((opts, cb) => {
cb(mockRes);
return mockReq;
});
const result = await client.getRealtimeData();
expect(result).toEqual({
totalEnergy: 300,
yearEnergy: 400,
dayEnergy: 20,
actPower: 8
});
});
it("resolves with partial values when some params are missing or invalid", async () => {
const body = {
Body: {
Data: {
TOTAL_ENERGY: { Value: 50 },
YEAR_ENERGY: {}, // missing
DAY_ENERGY: null, // invalid
PAC: { Value: null } // invalid
}
}
};
const json = JSON.stringify(body);
const mockRes = makeMockResponse(json);
const mockReq = makeMockRequest();
http.get.mockImplementation((opts, cb) => {
cb(mockRes);
return mockReq;
});
const result = await client.getRealtimeData();
expect(result).toEqual({ totalEnergy: 50 });
});
it("rejects on JSON parse error", async () => {
const invalid = "not a json";
const mockRes = makeMockResponse(invalid);
const mockReq = makeMockRequest();
http.get.mockImplementation((opts, cb) => {
cb(mockRes);
return mockReq;
});
await expect(client.getRealtimeData())
.rejects.toThrow("Failed to parse inverter data");
});
it("rejects on timeout", async () => {
const mockReq = makeMockRequest({ timeout: true });
http.get.mockImplementation(() => mockReq);
await expect(client.getRealtimeData())
.rejects.toThrow("Timeout while connecting to inverter");
});
it("rejects on connection error", async () => {
const mockReq = makeMockRequest({ error: new Error("fail") });
http.get.mockImplementation(() => mockReq);
await expect(client.getRealtimeData())
.rejects.toThrow("Connection error: fail");
});
});
/* ------------------------------------------------------------------
* parseEnergyReal_WAC_Sum_Produced_* -testit
* ----------------------------------------------------------------*/
describe("parseEnergyReal_WAC_Sum_Produced_5min()", () => {
const startIso = "2022-01-01T00:00:00Z";
// arvojen avaimet sekunteina: 0, 300, 600, ..., 3600
const sampleValues = Array.from({ length: 13 }, (_, i) => i)
.reduce((acc, i) => ({ ...acc, [String(i * 300)]: i }), {});
beforeEach(() => {
// Stubataan private getProductionData
vi.spyOn(client, "getProductionData")
.mockResolvedValue({ start: startIso, values: sampleValues });
});
it("tuottaa 5-minuutin datan oikein", async () => {
const data5 = await client.parseEnergyReal_WAC_Sum_Produced_5min("2022-01-01");
// skip sec=0 => 12 entryä
expect(data5).toHaveLength(12);
// Ensimmäinen on sec=300 => arvo 1, aika 00:05:00
expect(data5[0]).toEqual({
time: "2022-01-01T00:05:00.000Z",
value: 1
});
// Viimeinen on sec=3600 => arvo 12, aika 01:00:00
expect(data5[11]).toEqual({
time: "2022-01-01T01:00:00.000Z",
value: 12
});
});
});
describe("parseEnergyReal_WAC_Sum_Produced_15min()", () => {
const startIso = "2022-01-01T00:00:00Z";
const sampleValues = Array.from({ length: 13 }, (_, i) => i)
.reduce((acc, i) => ({ ...acc, [String(i * 300)]: i }), {});
beforeEach(() => {
vi.spyOn(client, "getProductionData")
.mockResolvedValue({ start: startIso, values: sampleValues });
});
it("tuottaa 15-minuutin ryhmittelyn oikein", async () => {
const { data15min } = await client.parseEnergyReal_WAC_Sum_Produced_15min("2022-01-01");
// 13 values => skip 0 => 12 values => 4 ryhmää kolmen välein
expect(data15min).toHaveLength(4);
// Ensimmäinen ryhmä: 1+2+3 = 6, aika 00:15:00
expect(data15min[0]).toEqual({
time: "2022-01-01T00:15:00.000Z",
value: 1 + 2 + 3
});
// Viimeinen ryhmä: 10+11+12 = 33, aika 01:00:00
expect(data15min[3]).toEqual({
time: "2022-01-01T01:00:00.000Z",
value: 10 + 11 + 12
});
});
});
describe("parseEnergyReal_WAC_Sum_Produced_All()", () => {
const startIso = "2022-01-01T00:00:00Z";
const sampleValues = Array.from({ length: 13 }, (_, i) => i)
.reduce((acc, i) => ({ ...acc, [String(i * 300)]: i }), {});
beforeEach(() => {
vi.spyOn(client, "getProductionData")
.mockResolvedValue({ start: startIso, values: sampleValues });
});
it("tuottaa 60-minuutin kokonaisryhmittelyn oikein", async () => {
const { data60min } = await client.parseEnergyReal_WAC_Sum_Produced_All("2022-01-01");
// 12 arvoa => yksi 60-min ryhmä
expect(data60min).toHaveLength(1);
// Summa 1+...+12 = 78, aika 01:00:00
expect(data60min[0]).toEqual({
time: "2022-01-01T01:00:00.000Z",
value: Array.from({ length: 12 }, (_, i) => i + 1)
.reduce((sum, v) => sum + v, 0)
});
});
});
});
//# sourceMappingURL=fronius-comm.test.js.map