Files
devicemanager/test/test.ts

262 lines
8.0 KiB
TypeScript

import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as devicemanager from '../ts/index.js';
// Test core exports
tap.test('should export DeviceManager', async () => {
expect(devicemanager.DeviceManager).toBeDefined();
expect(typeof devicemanager.DeviceManager).toEqual('function');
});
tap.test('should export UniversalDevice', async () => {
expect(devicemanager.UniversalDevice).toBeDefined();
expect(typeof devicemanager.UniversalDevice).toEqual('function');
});
tap.test('should export Features', async () => {
expect(devicemanager.ScanFeature).toBeDefined();
expect(devicemanager.PrintFeature).toBeDefined();
expect(devicemanager.PlaybackFeature).toBeDefined();
expect(devicemanager.VolumeFeature).toBeDefined();
expect(devicemanager.PowerFeature).toBeDefined();
expect(devicemanager.SnmpFeature).toBeDefined();
});
tap.test('should export device factories', async () => {
expect(devicemanager.createScanner).toBeDefined();
expect(devicemanager.createPrinter).toBeDefined();
expect(devicemanager.createSpeaker).toBeDefined();
expect(devicemanager.createUpsDevice).toBeDefined();
expect(typeof devicemanager.createScanner).toEqual('function');
expect(typeof devicemanager.createPrinter).toEqual('function');
});
tap.test('should export protocol implementations', async () => {
expect(devicemanager.EsclProtocol).toBeDefined();
expect(devicemanager.SaneProtocol).toBeDefined();
expect(devicemanager.IppProtocol).toBeDefined();
expect(devicemanager.SnmpProtocol).toBeDefined();
});
tap.test('should export retry helpers', async () => {
expect(devicemanager.withRetry).toBeDefined();
expect(devicemanager.createRetryable).toBeDefined();
expect(devicemanager.defaultRetryOptions).toBeDefined();
});
// Test DeviceManager creation
tap.test('should create DeviceManager instance', async () => {
const dm = new devicemanager.DeviceManager({
autoDiscovery: false,
});
expect(dm).toBeInstanceOf(devicemanager.DeviceManager);
expect(dm.isDiscovering).toEqual(false);
expect(dm.getScanners()).toEqual([]);
expect(dm.getPrinters()).toEqual([]);
expect(dm.getDevices()).toEqual([]);
});
// Test device selector
tap.test('should support device selection with IDeviceSelector', async () => {
const dm = new devicemanager.DeviceManager({
autoDiscovery: false,
});
// Empty manager should return empty array
expect(dm.getDevices({ hasFeature: 'scan' })).toEqual([]);
expect(dm.getDevices({ name: 'Test' })).toEqual([]);
// selectDevice should throw when no devices match
let error: Error | null = null;
try {
dm.selectDevice({ address: '192.168.1.100' });
} catch (e) {
error = e as Error;
}
expect(error).not.toBeNull();
expect(error?.message).toContain('No device found');
});
// Test retry helper
tap.test('withRetry should succeed on first try', async () => {
let callCount = 0;
const result = await devicemanager.withRetry(async () => {
callCount++;
return 'success';
});
expect(result).toEqual('success');
expect(callCount).toEqual(1);
});
tap.test('withRetry should retry on failure', async () => {
let callCount = 0;
const result = await devicemanager.withRetry(
async () => {
callCount++;
if (callCount < 3) {
throw new Error('Temporary failure');
}
return 'success after retries';
},
{ maxRetries: 5, baseDelay: 10, maxDelay: 100 }
);
expect(result).toEqual('success after retries');
expect(callCount).toEqual(3);
});
tap.test('withRetry should throw after max retries', async () => {
let callCount = 0;
let error: Error | null = null;
try {
await devicemanager.withRetry(
async () => {
callCount++;
throw new Error('Persistent failure');
},
{ maxRetries: 2, baseDelay: 10, maxDelay: 100 }
);
} catch (e) {
error = e as Error;
}
expect(error).not.toBeNull();
expect(error?.message).toEqual('Persistent failure');
expect(callCount).toEqual(3); // Initial + 2 retries
});
// Test discovery (non-blocking)
tap.test('should start and stop discovery', async () => {
const dm = new devicemanager.DeviceManager();
// Track events
let discoveryStarted = false;
let discoveryStopped = false;
dm.on('discovery:started', () => {
discoveryStarted = true;
});
dm.on('discovery:stopped', () => {
discoveryStopped = true;
});
await dm.startDiscovery();
expect(dm.isDiscovering).toEqual(true);
expect(discoveryStarted).toEqual(true);
// Wait a bit for potential device discovery
await new Promise((resolve) => setTimeout(resolve, 2000));
// Log discovered devices using new API
const scanners = dm.getDevices({ hasFeature: 'scan' });
const printers = dm.getDevices({ hasFeature: 'print' });
console.log(`Discovered ${scanners.length} scanner(s) and ${printers.length} printer(s)`);
for (const scanner of scanners) {
const scanFeature = scanner.getFeature<devicemanager.ScanFeature>('scan');
console.log(` Scanner: ${scanner.name} (${scanner.address}) - ${scanFeature?.protocol || 'unknown'}`);
}
for (const printer of printers) {
console.log(` Printer: ${printer.name} (${printer.address})`);
}
await dm.stopDiscovery();
expect(dm.isDiscovering).toEqual(false);
expect(discoveryStopped).toEqual(true);
await dm.shutdown();
});
// Test Scanner creation using factory
tap.test('should create Scanner device using factory', async () => {
const scanner = devicemanager.createScanner({
id: 'test:scanner:1',
name: 'Test Scanner',
address: '192.168.1.100',
port: 443,
protocol: 'escl',
txtRecords: {
'ty': 'HP LaserJet MFP',
'pdl': 'image/jpeg,application/pdf',
'cs': 'color,grayscale',
'is': 'platen,adf',
},
});
expect(scanner).toBeInstanceOf(devicemanager.UniversalDevice);
expect(scanner.name).toEqual('Test Scanner');
expect(scanner.address).toEqual('192.168.1.100');
expect(scanner.hasFeature('scan')).toEqual(true);
const scanFeature = scanner.selectFeature<devicemanager.ScanFeature>('scan');
expect(scanFeature).toBeInstanceOf(devicemanager.ScanFeature);
expect(scanFeature.protocol).toEqual('escl');
});
// Test Printer creation using factory
tap.test('should create Printer device using factory', async () => {
const printer = devicemanager.createPrinter({
id: 'test:printer:1',
name: 'Test Printer',
address: '192.168.1.101',
port: 631,
ippPath: '/ipp/print',
txtRecords: {
'ty': 'Brother HL-L2350DW',
'Color': 'T',
'Duplex': 'T',
},
});
expect(printer).toBeInstanceOf(devicemanager.UniversalDevice);
expect(printer.name).toEqual('Test Printer');
expect(printer.address).toEqual('192.168.1.101');
expect(printer.hasFeature('print')).toEqual(true);
const printFeature = printer.selectFeature<devicemanager.PrintFeature>('print');
expect(printFeature).toBeInstanceOf(devicemanager.PrintFeature);
});
// Test UniversalDevice feature management
tap.test('should manage features on UniversalDevice', async () => {
const device = new devicemanager.UniversalDevice('192.168.1.50', 80, {
name: 'Test Device',
});
expect(device.name).toEqual('Test Device');
expect(device.address).toEqual('192.168.1.50');
expect(device.featureCount).toEqual(0);
expect(device.hasFeature('scan')).toEqual(false);
// selectFeature should throw when feature doesn't exist
let error: Error | null = null;
try {
device.selectFeature('scan');
} catch (e) {
error = e as Error;
}
expect(error).not.toBeNull();
expect(error?.message).toContain("does not have feature 'scan'");
// getFeature should return undefined
expect(device.getFeature('scan')).toBeUndefined();
});
// Test IP helpers
tap.test('should export IP helper utilities', async () => {
expect(devicemanager.isValidIp).toBeDefined();
expect(devicemanager.cidrToIps).toBeDefined();
expect(devicemanager.getLocalSubnet).toBeDefined();
// Test isValidIp
expect(devicemanager.isValidIp('192.168.1.1')).toEqual(true);
expect(devicemanager.isValidIp('invalid')).toEqual(false);
expect(devicemanager.isValidIp('256.1.1.1')).toEqual(false);
});
export default tap.start();