UNPKG

@yyberi/fronius-comm

Version:

Library for communicating with Fronius solar inverters

214 lines 8.77 kB
// 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