71 lines
3.8 KiB
TypeScript
71 lines
3.8 KiB
TypeScript
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
import { DaikinConfigFlow, DaikinMapper, createDaikinDiscoveryDescriptor, type IDaikinRawData } from '../../ts/integrations/daikin/index.js';
|
|
|
|
tap.test('matches Daikin zeroconf records and creates config flow output', async () => {
|
|
const descriptor = createDaikinDiscoveryDescriptor();
|
|
const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'daikin-zeroconf-match');
|
|
const result = await matcher!.matches({ type: '_dkapi._tcp.local.', name: 'Living Daikin._dkapi._tcp.local.', host: 'daikin.local', port: 80, properties: { mac: 'AABBCCDDEEFF', name: 'Living Daikin' } }, {});
|
|
|
|
expect(result.matched).toBeTrue();
|
|
expect(result.candidate?.integrationDomain).toEqual('daikin');
|
|
expect(result.candidate?.host).toEqual('daikin.local');
|
|
expect(result.candidate?.macAddress).toEqual('aa:bb:cc:dd:ee:ff');
|
|
|
|
const done = await (await new DaikinConfigFlow().start(result.candidate!, {})).submit!({});
|
|
expect(done.kind).toEqual('done');
|
|
expect(done.config?.host).toEqual('daikin.local');
|
|
expect(done.config?.port).toEqual(80);
|
|
expect(done.config?.macAddress).toEqual('aa:bb:cc:dd:ee:ff');
|
|
});
|
|
|
|
tap.test('matches UDP discovery payloads from pydaikin basic_info', async () => {
|
|
const descriptor = createDaikinDiscoveryDescriptor();
|
|
const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'daikin-udp-match');
|
|
const result = await matcher!.matches({ host: '192.0.2.10', port: 30050, data: 'ret=OK,type=aircon,name=Office%20Daikin,mac=112233445566,ver=1_0_0' }, {});
|
|
|
|
expect(result.matched).toBeTrue();
|
|
expect(result.normalizedDeviceId).toEqual('11:22:33:44:55:66');
|
|
expect(result.candidate?.host).toEqual('192.0.2.10');
|
|
expect(result.candidate?.port).toEqual(80);
|
|
expect(result.candidate?.metadata?.discoveryProtocol).toEqual('udp');
|
|
});
|
|
|
|
tap.test('matches manual snapshots without requiring live HTTP credentials', async () => {
|
|
const rawData: Partial<IDaikinRawData> = {
|
|
basicInfo: { name: 'Manual%20Daikin', mac: 'AABBCCDDEEFF' },
|
|
controlInfo: { pow: '0', mode: '3', stemp: '22' },
|
|
sensorInfo: { htemp: '20' },
|
|
};
|
|
const snapshot = DaikinMapper.toSnapshot({ config: { name: 'Manual Daikin' }, rawData, online: true, source: 'manual' });
|
|
const descriptor = createDaikinDiscoveryDescriptor();
|
|
const manualMatcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'daikin-manual-match');
|
|
const match = await manualMatcher!.matches({ name: 'Manual Daikin', snapshot }, {});
|
|
|
|
expect(match.matched).toBeTrue();
|
|
expect(match.candidate?.metadata?.snapshot).toEqual(snapshot);
|
|
const validation = await descriptor.getValidators()[0].validate(match.candidate!, {});
|
|
expect(validation.matched).toBeTrue();
|
|
|
|
const done = await (await new DaikinConfigFlow().start(match.candidate!, {})).submit!({});
|
|
expect(done.kind).toEqual('done');
|
|
expect(done.config?.snapshot?.climate.hvacMode).toEqual('off');
|
|
});
|
|
|
|
tap.test('rejects mixed API key and password authentication', async () => {
|
|
const done = await (await new DaikinConfigFlow().start({ source: 'manual', integrationDomain: 'daikin', host: 'daikin.local' }, {})).submit!({ apiKey: 'key', password: 'pass' });
|
|
expect(done.kind).toEqual('error');
|
|
expect(done.error).toContain('either API key or password');
|
|
});
|
|
|
|
tap.test('rejects candidates without Daikin hints or usable data', async () => {
|
|
const descriptor = createDaikinDiscoveryDescriptor();
|
|
const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'daikin-manual-match');
|
|
const result = await matcher!.matches({ name: 'Generic service' }, {});
|
|
expect(result.matched).toBeFalse();
|
|
|
|
const validation = await descriptor.getValidators()[0].validate({ source: 'manual', name: 'Daikin without host' }, {});
|
|
expect(validation.matched).toBeFalse();
|
|
});
|
|
|
|
export default tap.start();
|