UNPKG

node-switchbot

Version:

The node-switchbot is a Node.js module which allows you to control your Switchbot Devices through Bluetooth (BLE).

152 lines 8.4 kB
import { Buffer } from 'node:buffer'; import { describe, expect, it } from 'vitest'; import { ErrorUtils, LogLevel, ValidationUtils } from './device.js'; describe('validationUtils', () => { describe('validatePercentage', () => { it('should accept valid percentages', () => { expect(() => ValidationUtils.validatePercentage(0)).not.toThrow(); expect(() => ValidationUtils.validatePercentage(50)).not.toThrow(); expect(() => ValidationUtils.validatePercentage(100)).not.toThrow(); }); it('should reject invalid percentages', () => { expect(() => ValidationUtils.validatePercentage(-1)).toThrow('must be between 0 and 100'); expect(() => ValidationUtils.validatePercentage(101)).toThrow('must be between 0 and 100'); expect(() => ValidationUtils.validatePercentage(Number.NaN)).toThrow('must be a valid number'); }); it('should reject non-numbers', () => { expect(() => ValidationUtils.validatePercentage('50')).toThrow('must be a valid number'); expect(() => ValidationUtils.validatePercentage(null)).toThrow('must be a valid number'); }); }); describe('validateRGB', () => { it('should accept valid RGB values', () => { expect(() => ValidationUtils.validateRGB(0)).not.toThrow(); expect(() => ValidationUtils.validateRGB(128)).not.toThrow(); expect(() => ValidationUtils.validateRGB(255)).not.toThrow(); }); it('should reject invalid RGB values', () => { expect(() => ValidationUtils.validateRGB(-1)).toThrow('must be an integer between 0 and 255'); expect(() => ValidationUtils.validateRGB(256)).toThrow('must be an integer between 0 and 255'); expect(() => ValidationUtils.validateRGB(128.5)).toThrow('must be an integer between 0 and 255'); }); }); describe('validateBuffer', () => { it('should accept valid buffers', () => { const buffer = Buffer.from([1, 2, 3]); expect(() => ValidationUtils.validateBuffer(buffer)).not.toThrow(); expect(() => ValidationUtils.validateBuffer(buffer, 3)).not.toThrow(); }); it('should reject non-buffers', () => { expect(() => ValidationUtils.validateBuffer('not a buffer')).toThrow('must be a Buffer instance'); expect(() => ValidationUtils.validateBuffer(null)).toThrow('must be a Buffer instance'); }); it('should validate buffer length', () => { const buffer = Buffer.from([1, 2, 3]); expect(() => ValidationUtils.validateBuffer(buffer, 2)).toThrow('must have exactly 2 bytes'); expect(() => ValidationUtils.validateBuffer(buffer, 4)).toThrow('must have exactly 4 bytes'); }); }); describe('validateString', () => { it('should accept valid strings', () => { expect(() => ValidationUtils.validateString('hello')).not.toThrow(); expect(() => ValidationUtils.validateString('test', 'param', 1, 10)).not.toThrow(); }); it('should reject non-strings', () => { expect(() => ValidationUtils.validateString(123)).toThrow('must be a string'); expect(() => ValidationUtils.validateString(null)).toThrow('must be a string'); }); it('should validate string length', () => { expect(() => ValidationUtils.validateString('')).toThrow('must have at least 1 character'); expect(() => ValidationUtils.validateString('too long', 'param', 1, 5)).toThrow('must have at most 5 character'); }); }); describe('validateRange', () => { it('should accept values in range', () => { expect(() => ValidationUtils.validateRange(5, 0, 10)).not.toThrow(); expect(() => ValidationUtils.validateRange(0, 0, 10)).not.toThrow(); expect(() => ValidationUtils.validateRange(10, 0, 10)).not.toThrow(); }); it('should reject values out of range', () => { expect(() => ValidationUtils.validateRange(-1, 0, 10)).toThrow('must be between 0 and 10'); expect(() => ValidationUtils.validateRange(11, 0, 10)).toThrow('must be between 0 and 10'); }); it('should validate integers when required', () => { expect(() => ValidationUtils.validateRange(5, 0, 10, 'value', true)).not.toThrow(); expect(() => ValidationUtils.validateRange(5.5, 0, 10, 'value', true)).toThrow('must be an integer'); }); }); describe('validateMacAddress', () => { it('should accept valid MAC addresses', () => { expect(() => ValidationUtils.validateMacAddress('AA:BB:CC:DD:EE:FF')).not.toThrow(); expect(() => ValidationUtils.validateMacAddress('aa:bb:cc:dd:ee:ff')).not.toThrow(); expect(() => ValidationUtils.validateMacAddress('AA-BB-CC-DD-EE-FF')).not.toThrow(); expect(() => ValidationUtils.validateMacAddress('aabbccddeeff')).not.toThrow(); }); it('should reject invalid MAC addresses', () => { expect(() => ValidationUtils.validateMacAddress('invalid')).toThrow('must be a valid MAC address format'); expect(() => ValidationUtils.validateMacAddress('GG:BB:CC:DD:EE:FF')).toThrow('must be a valid MAC address format'); }); }); describe('validateEnum', () => { it('should accept valid enum values', () => { const allowed = ['red', 'green', 'blue']; expect(() => ValidationUtils.validateEnum('red', allowed)).not.toThrow(); expect(() => ValidationUtils.validateEnum('green', allowed)).not.toThrow(); }); it('should reject invalid enum values', () => { const allowed = ['red', 'green', 'blue']; expect(() => ValidationUtils.validateEnum('yellow', allowed)).toThrow('must be one of: red, green, blue'); }); }); }); describe('errorUtils', () => { describe('createTimeoutError', () => { it('should create descriptive timeout errors', () => { const error = ErrorUtils.createTimeoutError('connect', 5000); expect(error.message).toBe('Operation \'connect\' timed out after 5000ms'); }); }); describe('createConnectionError', () => { it('should create connection errors with device context', () => { const error = ErrorUtils.createConnectionError('device123'); expect(error.message).toBe('Failed to connect to device device123'); }); it('should include cause if provided', () => { const cause = new Error('Network unavailable'); const error = ErrorUtils.createConnectionError('device123', cause); expect(error.message).toBe('Failed to connect to device device123: Network unavailable'); }); }); describe('createCommandError', () => { it('should create command errors with context', () => { const error = ErrorUtils.createCommandError('turnOn', 'device123'); expect(error.message).toBe('Command \'turnOn\' failed for device device123'); }); }); describe('withTimeout', () => { it('should resolve when operation completes within timeout', async () => { const fastOperation = Promise.resolve('success'); const result = await ErrorUtils.withTimeout(fastOperation, 1000, 'test'); expect(result).toBe('success'); }); it('should reject when operation exceeds timeout', async () => { const slowOperation = new Promise(resolve => setTimeout(resolve, 100)); await expect(ErrorUtils.withTimeout(slowOperation, 50, 'test')) .rejects .toThrow('Operation \'test\' timed out after 50ms'); }); }); }); describe('logLevel', () => { it('should export all log levels', () => { expect(LogLevel.SUCCESS).toBe('success'); expect(LogLevel.DEBUGSUCCESS).toBe('debugsuccess'); expect(LogLevel.WARN).toBe('warn'); expect(LogLevel.DEBUGWARN).toBe('debugwarn'); expect(LogLevel.ERROR).toBe('error'); expect(LogLevel.DEBUGERROR).toBe('debugerror'); expect(LogLevel.DEBUG).toBe('debug'); expect(LogLevel.INFO).toBe('info'); }); }); //# sourceMappingURL=device.test.js.map