Files

94 lines
3.8 KiB
TypeScript
Raw Permalink Normal View History

import { expect, tap } from '@git.zone/tstest/tapbundle';
import { BoschShcIntegration } from '../../ts/integrations/bosch_shc/index.js';
import type { IBoschShcModeledCommand, IBoschShcSnapshot } from '../../ts/integrations/bosch_shc/index.js';
const snapshot: IBoschShcSnapshot = {
host: '192.168.1.10',
devices: [
{ id: 'hdm:ZigBee:plug', rootDeviceId: 'AA:BB:CC:DD:EE:FF', deviceModel: 'PSM', manufacturer: 'BOSCH', serial: 'PSM123', name: 'Kitchen Plug', status: 'AVAILABLE', profile: 'GENERIC', deviceServiceIds: ['PowerSwitch'] },
{ id: 'shutter:living', rootDeviceId: 'AA:BB:CC:DD:EE:FF', deviceModel: 'BBL', manufacturer: 'BOSCH', serial: 'BBL123', name: 'Living Shutter', status: 'AVAILABLE', profile: 'GENERIC', deviceServiceIds: ['ShutterControl'] },
],
services: [
{ id: 'PowerSwitch', deviceId: 'hdm:ZigBee:plug', state: { '@type': 'powerSwitchState', switchState: 'ON', automaticPowerOffTime: 0 } },
{ id: 'ShutterControl', deviceId: 'shutter:living', state: { '@type': 'shutterControlState', operationState: 'STOPPED', level: 0.5, calibrated: true } },
],
};
tap.test('runs modeled Bosch SHC service commands through an injected executor', async () => {
const calls: IBoschShcModeledCommand[] = [];
const runtime = await new BoschShcIntegration().setup({
host: '192.168.1.10',
snapshot,
executor: async (commandArg) => {
calls.push(commandArg);
return { ok: true };
},
}, {});
const result = await runtime.callService?.({
domain: 'switch',
service: 'turn_off',
target: { entityId: 'switch.kitchen_plug' },
});
expect(result?.success).toBeTrue();
expect(calls[0].action).toEqual('put_device_service_state');
expect(calls[0].path).toEqual('/devices/hdm:ZigBee:plug/services/PowerSwitch/state');
expect(calls[0].body).toEqual({ '@type': 'powerSwitchState', switchState: 'OFF' });
const coverResult = await runtime.callService?.({
domain: 'cover',
service: 'set_cover_position',
target: { entityId: 'cover.living_shutter' },
data: { position: 75 },
});
expect(coverResult?.success).toBeTrue();
expect(calls[1].body).toEqual({ '@type': 'shutterControlState', level: 0.75 });
await runtime.destroy();
});
tap.test('returns clear unsupported errors without executor for writes and pairing', async () => {
const runtime = await new BoschShcIntegration().setup({ host: '192.168.1.10', snapshot }, {});
const result = await runtime.callService?.({
domain: 'switch',
service: 'turn_on',
target: { entityId: 'switch.kitchen_plug' },
});
expect(result?.success).toBeFalse();
expect(result?.error).toContain('requires config.snapshot or an injected executor');
const pairResult = await runtime.callService?.({
domain: 'bosch_shc',
service: 'pair_client',
target: {},
data: { system_password: 'secret' },
});
expect(pairResult?.success).toBeFalse();
expect(pairResult?.error).toContain('pairing transport');
await runtime.destroy();
});
tap.test('models Bosch SHC pairing only through an injected executor', async () => {
const calls: IBoschShcModeledCommand[] = [];
const runtime = await new BoschShcIntegration().setup({
host: '192.168.1.10',
executor: async (commandArg) => {
calls.push(commandArg);
return { token: 'token:bosch-shc' };
},
}, {});
const result = await runtime.callService?.({
domain: 'bosch_shc',
service: 'pair_client',
target: {},
data: { system_password: 'secret', client_id: 'homeassistant', client_name: 'HomeAssistant' },
});
expect(result?.success).toBeTrue();
expect(calls[0].action).toEqual('pair_client');
expect(calls[0].sensitiveFields).toEqual(['systemPassword', 'certificatePem']);
expect(calls[0].body?.clientName).toEqual('HomeAssistant');
await runtime.destroy();
});
export default tap.start();