117 lines
5.0 KiB
TypeScript
117 lines
5.0 KiB
TypeScript
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
import { AirgradientClient, AirgradientMapper, type IAirgradientSnapshot } from '../../ts/integrations/airgradient/index.js';
|
|
|
|
const snapshot: IAirgradientSnapshot = {
|
|
connected: true,
|
|
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
devices: [
|
|
{
|
|
host: '192.168.1.75',
|
|
name: 'Living Room AirGradient',
|
|
serialNumber: 'abcdef123456',
|
|
model: 'I-9PSL',
|
|
modelName: 'AirGradient ONE',
|
|
firmwareVersion: '3.1.2',
|
|
latestFirmwareVersion: '3.2.0',
|
|
online: true,
|
|
measures: {
|
|
signalStrength: -49,
|
|
serialNumber: 'abcdef123456',
|
|
bootTime: 4,
|
|
firmwareVersion: '3.1.2',
|
|
model: 'I-9PSL',
|
|
pm01: 2,
|
|
pm02: 6.5,
|
|
rawPm02: 7,
|
|
pm10: 9,
|
|
ambientTemperature: 21.4,
|
|
relativeHumidity: 45,
|
|
rco2: 620,
|
|
totalVolatileOrganicComponentIndex: 3,
|
|
nitrogenIndex: 1,
|
|
pm003Count: 123,
|
|
},
|
|
config: {
|
|
country: 'US',
|
|
pmStandard: 'us-aqi',
|
|
ledBarMode: 'co2',
|
|
co2AutomaticBaselineCalibrationDays: 30,
|
|
temperatureUnit: 'c',
|
|
configurationControl: 'local',
|
|
postDataToAirGradient: true,
|
|
ledBarBrightness: 80,
|
|
displayBrightness: 60,
|
|
noxLearningOffset: 60,
|
|
tvocLearningOffset: 120,
|
|
},
|
|
},
|
|
],
|
|
events: [],
|
|
};
|
|
|
|
tap.test('maps AirGradient measures and config to devices and entities', async () => {
|
|
const devices = AirgradientMapper.toDevices(snapshot);
|
|
const entities = AirgradientMapper.toEntities(snapshot);
|
|
|
|
expect(devices[0].id).toEqual('airgradient.device.abcdef123456');
|
|
expect(devices[0].manufacturer).toEqual('AirGradient');
|
|
expect(devices[0].features.some((featureArg) => featureArg.id === 'co2')).toBeTrue();
|
|
expect(entities.find((entityArg) => entityArg.id === 'sensor.living_room_airgradient_pm2_5')?.state).toEqual(6.5);
|
|
expect(entities.find((entityArg) => entityArg.id === 'sensor.living_room_airgradient_co2')?.state).toEqual(620);
|
|
expect(entities.find((entityArg) => entityArg.uniqueId.endsWith('_display_pm_standard') && entityArg.platform === 'select')?.state).toEqual('us_aqi');
|
|
expect(entities.find((entityArg) => entityArg.uniqueId.endsWith('_display_brightness') && entityArg.platform === 'number')?.state).toEqual(60);
|
|
expect(entities.find((entityArg) => entityArg.uniqueId.endsWith('_update'))?.attributes?.latestVersion).toEqual('3.2.0');
|
|
});
|
|
|
|
tap.test('maps AirGradient services to safe config payloads', async () => {
|
|
const entities = AirgradientMapper.toEntities(snapshot);
|
|
const pmStandardEntity = entities.find((entityArg) => entityArg.uniqueId.endsWith('_display_pm_standard') && entityArg.platform === 'select')!;
|
|
const brightnessEntity = entities.find((entityArg) => entityArg.uniqueId.endsWith('_display_brightness') && entityArg.platform === 'number')!;
|
|
const postDataEntity = entities.find((entityArg) => entityArg.uniqueId.endsWith('_post_data_to_airgradient'))!;
|
|
const ledTestEntity = entities.find((entityArg) => entityArg.uniqueId.endsWith('_led_bar_test'))!;
|
|
|
|
const pmCommand = AirgradientMapper.commandForService(snapshot, {
|
|
domain: 'select',
|
|
service: 'select_option',
|
|
target: { entityId: pmStandardEntity.id },
|
|
data: { option: 'ugm3' },
|
|
});
|
|
const brightnessCommand = AirgradientMapper.commandForService(snapshot, {
|
|
domain: 'number',
|
|
service: 'set_value',
|
|
target: { entityId: brightnessEntity.id },
|
|
data: { value: 42 },
|
|
});
|
|
const switchCommand = AirgradientMapper.commandForService(snapshot, {
|
|
domain: 'switch',
|
|
service: 'turn_off',
|
|
target: { entityId: postDataEntity.id },
|
|
});
|
|
const buttonCommand = AirgradientMapper.commandForService(snapshot, {
|
|
domain: 'button',
|
|
service: 'press',
|
|
target: { entityId: ledTestEntity.id },
|
|
});
|
|
|
|
expect(pmCommand?.type === 'set_config' ? pmCommand.payload : undefined).toEqual({ pmStandard: 'ugm3' });
|
|
expect(brightnessCommand?.type === 'set_config' ? brightnessCommand.payload : undefined).toEqual({ displayBrightness: 42 });
|
|
expect(switchCommand?.type === 'set_config' ? switchCommand.payload : undefined).toEqual({ postDataToAirGradient: false });
|
|
expect(buttonCommand?.type === 'set_config' ? buttonCommand.payload : undefined).toEqual({ ledBarTestRequested: true });
|
|
expect(AirgradientMapper.commandForService(snapshot, { domain: 'airgradient', service: 'set_config', target: {}, data: { field: 'unknown', value: true } })).toBeUndefined();
|
|
});
|
|
|
|
tap.test('does not fake live AirGradient command success for snapshot-only configs', async () => {
|
|
const client = new AirgradientClient({ snapshot });
|
|
const command = AirgradientMapper.commandForService(snapshot, {
|
|
domain: 'number',
|
|
service: 'set_value',
|
|
target: { entityId: 'number.living_room_airgradient_display_brightness' },
|
|
data: { value: 50 },
|
|
})!;
|
|
const result = await client.sendCommand(command);
|
|
expect(result.success).toBeFalse();
|
|
expect(result.error).toContain('requires config.host');
|
|
});
|
|
|
|
export default tap.start();
|