UNPKG

energy-manager-iot

Version:

Library for energy management in IoT devices via MQTT protocol. Documentation: https://jonhvmp.github.io/energy-manager-iot-docs/

194 lines (193 loc) 8.96 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const index_1 = require("../index"); const error_handler_1 = require("../utils/error-handler"); const mqtt = __importStar(require("mqtt")); jest.mock('mqtt', () => { const mockClient = { on: jest.fn().mockReturnThis(), end: jest.fn((_, __, cb) => cb && cb()), publish: jest.fn((_, __, ___, cb) => cb && cb()), subscribe: jest.fn((_, __, cb) => cb && cb()), unsubscribe: jest.fn((_, cb) => cb && cb()), removeAllListeners: jest.fn() }; return { connect: jest.fn().mockReturnValue(mockClient) }; }); /** * Advanced coverage tests for the EnergyManager class * * These tests focus on improving code coverage by testing specific * behaviors and edge cases not covered by the main test suite. */ describe('EnergyManager - Advanced Coverage', () => { let energyManager; let mockMqttClient; beforeEach(() => { jest.clearAllMocks(); energyManager = new index_1.EnergyManager({ topicPrefix: 'advanced/test/', statusInterval: 500 }); mockMqttClient = mqtt.connect('mqtt://localhost:1883'); }); afterEach(() => { if (energyManager['statusCheckInterval']) { clearInterval(energyManager['statusCheckInterval']); } energyManager.removeAllListeners(); }); describe('Topics and IDs', () => { test('should correctly extract device ID from topic', () => { // @ts-ignore - Access private method const deviceId = energyManager['extractDeviceIdFromStatusTopic']('advanced/test/sensor123/status'); expect(deviceId).toBe('sensor123'); }); test('should return null for invalid topics', () => { // @ts-ignore - Access private method const deviceId1 = energyManager['extractDeviceIdFromStatusTopic']('wrong-prefix/sensor123/status'); // @ts-ignore - Access private method const deviceId2 = energyManager['extractDeviceIdFromStatusTopic']('advanced/test/sensor123/command'); expect(deviceId1).toBeNull(); expect(deviceId2).toBeNull(); }); test('should generate unique request IDs', () => { // @ts-ignore - Access private method const requestId = energyManager['generateRequestId'](); expect(requestId).toMatch(/^req_\d+_[a-z0-9]+$/); }); }); describe('Command Errors', () => { test('should throw error when sending command to non-existent device', async () => { // Simulate MQTT connection Object.defineProperty(energyManager['mqtt'], 'isClientConnected', { value: () => true }); await expect(energyManager.sendCommand('non-existent', index_1.CommandType.SLEEP)).rejects.toThrow(error_handler_1.EnergyManagerError); }); test('should handle error when publishing command', async () => { // Register device energyManager.registerDevice('sensor1', 'Sensor', index_1.DeviceType.SENSOR); // Simulate MQTT connection Object.defineProperty(energyManager['mqtt'], 'isClientConnected', { value: () => true }); // Simulate publish error energyManager['mqtt'].publish = jest.fn().mockRejectedValue(new Error('Publish failed')); await expect(energyManager.sendCommand('sensor1', index_1.CommandType.SLEEP)).rejects.toThrow(); }); test('should propagate error when sending command to group', async () => { // Create group and add device energyManager.createGroup('test-group'); energyManager.registerDevice('sensor1', 'Sensor', index_1.DeviceType.SENSOR); energyManager.addDeviceToGroup('sensor1', 'test-group'); // Simulate MQTT connection Object.defineProperty(energyManager['mqtt'], 'isClientConnected', { value: () => true }); // Simulate command error energyManager.sendCommand = jest.fn().mockRejectedValue(new Error('Command failed')); await expect(energyManager.sendCommandToGroup('test-group', index_1.CommandType.SLEEP)).rejects.toThrow(error_handler_1.EnergyManagerError); }); }); describe('MQTT Events', () => { beforeEach(() => { // Simulate MQTT connection to test events const connectPromise = energyManager.connect('mqtt://localhost:1883'); // Simulate connect callback const onConnect = mockMqttClient.on.mock.calls.find((c) => c[0] === 'connect')?.[1]; if (onConnect) onConnect(); return connectPromise; }); test('should emit reconnect event', () => { const reconnectListener = jest.fn(); energyManager.on('reconnecting', reconnectListener); // Simulate reconnect event const onReconnect = mockMqttClient.on.mock.calls.find((c) => c[0] === 'reconnect')?.[1]; if (onReconnect) onReconnect(); expect(reconnectListener).toHaveBeenCalled(); }); test('should emit error event', () => { const errorListener = jest.fn(); energyManager.on('error', errorListener); const testError = new Error('Test error'); // Simulate error event const onError = mockMqttClient.on.mock.calls.find((c) => c[0] === 'error')?.[1]; if (onError) onError(testError); expect(errorListener).toHaveBeenCalledWith(testError); }); }); describe('Topic Subscriptions', () => { test('should subscribe to all device status topics', async () => { // Register devices energyManager.registerDevice('sensor1', 'Sensor 1', index_1.DeviceType.SENSOR); energyManager.registerDevice('sensor2', 'Sensor 2', index_1.DeviceType.SENSOR); // Spy on subscribe method const subscribeSpy = jest.spyOn(energyManager['mqtt'], 'subscribe') .mockResolvedValue(); // Simulate connected state Object.defineProperty(energyManager['mqtt'], 'isClientConnected', { value: () => true }); // @ts-ignore - Access private method await energyManager['subscribeToAllDeviceStatuses'](); // Should call subscribe for each device expect(subscribeSpy).toHaveBeenCalledTimes(2); expect(subscribeSpy).toHaveBeenCalledWith('advanced/test/sensor1/status'); expect(subscribeSpy).toHaveBeenCalledWith('advanced/test/sensor2/status'); }); test('should not attempt to subscribe when disconnected', async () => { // Register device energyManager.registerDevice('sensor1', 'Sensor', index_1.DeviceType.SENSOR); // Spy on subscribe method const subscribeSpy = jest.spyOn(energyManager['mqtt'], 'subscribe') .mockResolvedValue(); // Simulate disconnected state Object.defineProperty(energyManager['mqtt'], 'isClientConnected', { value: () => false }); // @ts-ignore - Access private method await energyManager['subscribeToAllDeviceStatuses'](); // Should not call subscribe expect(subscribeSpy).not.toHaveBeenCalled(); }); }); });