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();