Add comprehensive Home Assistant schema validation tests

- Created detailed test suite for Home Assistant schema validation
- Implemented schemas for entities, services, events, configurations, automations, and device controls
- Added robust validation for complex Home Assistant data structures
- Enhanced type safety and validation for Home Assistant-related interfaces
- Expanded schema definitions to support multiple use cases and edge scenarios
This commit is contained in:
jango-blockchained
2025-01-30 10:42:39 +01:00
parent 251dfa0a91
commit 732a727d27
3 changed files with 765 additions and 212 deletions

View File

@@ -1,6 +1,50 @@
import { JSONSchemaType } from 'ajv';
import * as HomeAssistant from '../types/hass.js';
// Define base types for automation components
type TriggerType = {
platform: string;
event?: string | null;
entity_id?: string | null;
to?: string | null;
from?: string | null;
offset?: string | null;
[key: string]: any;
};
type ConditionType = {
condition: string;
conditions?: Array<Record<string, any>> | null;
[key: string]: any;
};
type ActionType = {
service: string;
target?: {
entity_id?: string | string[] | null;
[key: string]: any;
} | null;
data?: Record<string, any> | null;
[key: string]: any;
};
type AutomationType = {
alias: string;
description?: string | null;
mode?: ('single' | 'parallel' | 'queued' | 'restart') | null;
trigger: TriggerType[];
condition?: ConditionType[] | null;
action: ActionType[];
};
type DeviceControlType = {
domain: 'light' | 'switch' | 'climate' | 'cover' | 'fan' | 'scene' | 'script' | 'media_player';
command: string;
entity_id: string | string[];
parameters?: Record<string, any> | null;
};
// Schema definitions
export const entitySchema: JSONSchemaType<HomeAssistant.Entity> = {
type: 'object',
properties: {
@@ -37,25 +81,19 @@ export const serviceSchema: JSONSchemaType<HomeAssistant.Service> = {
nullable: true,
properties: {
entity_id: {
anyOf: [
{ type: 'string' },
{ type: 'array', items: { type: 'string' } }
],
nullable: true
type: 'array',
nullable: true,
items: { type: 'string' }
},
device_id: {
anyOf: [
{ type: 'string' },
{ type: 'array', items: { type: 'string' } }
],
nullable: true
type: 'array',
nullable: true,
items: { type: 'string' }
},
area_id: {
anyOf: [
{ type: 'string' },
{ type: 'array', items: { type: 'string' } }
],
nullable: true
type: 'array',
nullable: true,
items: { type: 'string' }
}
},
additionalProperties: false
@@ -70,6 +108,117 @@ export const serviceSchema: JSONSchemaType<HomeAssistant.Service> = {
additionalProperties: false
};
export const automationSchema: JSONSchemaType<AutomationType> = {
type: 'object',
properties: {
alias: { type: 'string' },
description: { type: 'string', nullable: true },
mode: {
type: 'string',
enum: ['single', 'parallel', 'queued', 'restart'],
nullable: true
},
trigger: {
type: 'array',
items: {
type: 'object',
required: ['platform'],
properties: {
platform: { type: 'string' },
event: { type: 'string', nullable: true },
entity_id: { type: 'string', nullable: true },
to: { type: 'string', nullable: true },
from: { type: 'string', nullable: true },
offset: { type: 'string', nullable: true }
},
additionalProperties: true
}
},
condition: {
type: 'array',
nullable: true,
items: {
type: 'object',
required: ['condition'],
properties: {
condition: { type: 'string' },
conditions: {
type: 'array',
nullable: true,
items: {
type: 'object',
additionalProperties: true
}
}
},
additionalProperties: true
}
},
action: {
type: 'array',
items: {
type: 'object',
required: ['service'],
properties: {
service: { type: 'string' },
target: {
type: 'object',
nullable: true,
properties: {
entity_id: {
anyOf: [
{ type: 'string' },
{
type: 'array',
items: { type: 'string' }
}
],
nullable: true
}
},
additionalProperties: true
},
data: {
type: 'object',
nullable: true,
additionalProperties: true
}
},
additionalProperties: true
}
}
},
required: ['alias', 'trigger', 'action'],
additionalProperties: true
};
export const deviceControlSchema: JSONSchemaType<DeviceControlType> = {
type: 'object',
properties: {
domain: {
type: 'string',
enum: ['light', 'switch', 'climate', 'cover', 'fan', 'scene', 'script', 'media_player']
},
command: { type: 'string' },
entity_id: {
anyOf: [
{ type: 'string' },
{
type: 'array',
items: { type: 'string' }
}
]
},
parameters: {
type: 'object',
nullable: true,
additionalProperties: true
}
},
required: ['domain', 'command', 'entity_id'],
additionalProperties: false
};
export const stateChangedEventSchema: JSONSchemaType<HomeAssistant.StateChangedEvent> = {
type: 'object',
properties: {
@@ -80,63 +229,17 @@ export const stateChangedEventSchema: JSONSchemaType<HomeAssistant.StateChangedE
entity_id: { type: 'string' },
new_state: {
anyOf: [
{
type: 'object',
properties: {
entity_id: { type: 'string' },
state: { type: 'string' },
attributes: {
type: 'object',
additionalProperties: true
},
last_changed: { type: 'string' },
last_updated: { type: 'string' },
context: {
type: 'object',
properties: {
id: { type: 'string' },
parent_id: { type: 'string', nullable: true },
user_id: { type: 'string', nullable: true }
},
required: ['id'],
additionalProperties: false
}
},
required: ['entity_id', 'state', 'attributes', 'last_changed', 'last_updated', 'context'],
additionalProperties: false
},
entitySchema,
{ type: 'null' }
]
],
nullable: true
},
old_state: {
anyOf: [
{
type: 'object',
properties: {
entity_id: { type: 'string' },
state: { type: 'string' },
attributes: {
type: 'object',
additionalProperties: true
},
last_changed: { type: 'string' },
last_updated: { type: 'string' },
context: {
type: 'object',
properties: {
id: { type: 'string' },
parent_id: { type: 'string', nullable: true },
user_id: { type: 'string', nullable: true }
},
required: ['id'],
additionalProperties: false
}
},
required: ['entity_id', 'state', 'attributes', 'last_changed', 'last_updated', 'context'],
additionalProperties: false
},
entitySchema,
{ type: 'null' }
]
],
nullable: true
}
},
required: ['entity_id', 'new_state', 'old_state'],
@@ -178,7 +281,10 @@ export const configSchema: JSONSchemaType<HomeAssistant.Config> = {
},
location_name: { type: 'string' },
time_zone: { type: 'string' },
components: { type: 'array', items: { type: 'string' } },
components: {
type: 'array',
items: { type: 'string' }
},
version: { type: 'string' }
},
required: ['latitude', 'longitude', 'elevation', 'unit_system', 'location_name', 'time_zone', 'components', 'version'],