1+ using System . Text . RegularExpressions ;
2+ using NetDaemon . Client . HomeAssistant . Model ;
3+ using NetDaemon . HassModel . CodeGenerator ;
4+ using NetDaemon . HassModel . CodeGenerator . CodeGeneration ;
5+
6+ namespace NetDaemon . HassModel . Tests . CodeGenerator ;
7+
8+ public class HelpersGeneratorTest
9+ {
10+ [ Fact ]
11+ public void AddHomeAssistantGenerated_ShouldNotRegisterDuplicateEntityClasses ( )
12+ {
13+ // Arrange: Create test data that would lead to duplicate SensorEntities registrations
14+ var states = new HassState [ ]
15+ {
16+ // Non-numeric sensor (no unit_of_measurement)
17+ new ( ) { EntityId = "sensor.simple_text" , Attributes = new Dictionary < string , object > ( ) } ,
18+
19+ // Numeric sensor (has unit_of_measurement)
20+ new ( ) { EntityId = "sensor.temperature" , Attributes = new Dictionary < string , object > { [ "unit_of_measurement" ] = "°C" } }
21+ } ;
22+
23+ // Act: Generate metadata which creates both numeric and non-numeric sensor domains
24+ var metaData = EntityMetaDataGenerator . GetEntityDomainMetaData ( states ) ;
25+
26+ // Both should have the same EntitiesForDomainClassName
27+ var sensorDomains = metaData . Domains . Where ( d => d . Domain == "sensor" ) . ToList ( ) ;
28+ sensorDomains . Should ( ) . HaveCount ( 2 , "there should be both numeric and non-numeric sensor domains" ) ;
29+ sensorDomains . Should ( ) . AllSatisfy ( d => d . EntitiesForDomainClassName . Should ( ) . Be ( "SensorEntities" ) ) ;
30+
31+ // Generate the extension method code
32+ var generatedMembers = HelpersGenerator . Generate ( metaData . Domains , [ ] ) . ToList ( ) ;
33+ var generatedCode = generatedMembers . First ( ) . ToString ( ) ;
34+
35+ // Assert: The generated code should not contain duplicate SensorEntities registrations
36+ var sensorEntitiesMatches = Regex . Matches (
37+ generatedCode ,
38+ @"serviceCollection\.AddTransient<SensorEntities>\(\);" ) ;
39+
40+ sensorEntitiesMatches . Should ( ) . HaveCount ( 1 , "SensorEntities should only be registered once, not duplicated" ) ;
41+ }
42+
43+ [ Fact ]
44+ public void AddHomeAssistantGenerated_ShouldRegisterAllUniqueEntityClasses ( )
45+ {
46+ // Arrange: Create test data with different domains
47+ var states = new HassState [ ]
48+ {
49+ new ( ) { EntityId = "sensor.temperature" , Attributes = new Dictionary < string , object > { [ "unit_of_measurement" ] = "°C" } } ,
50+ new ( ) { EntityId = "light.living_room" , Attributes = new Dictionary < string , object > ( ) } ,
51+ new ( ) { EntityId = "switch.kitchen" , Attributes = new Dictionary < string , object > ( ) }
52+ } ;
53+
54+ // Act: Generate metadata
55+ var metaData = EntityMetaDataGenerator . GetEntityDomainMetaData ( states ) ;
56+
57+ // Generate the extension method code
58+ var generatedMembers = HelpersGenerator . Generate ( metaData . Domains , [ ] ) . ToList ( ) ;
59+ var generatedCode = generatedMembers . First ( ) . ToString ( ) ;
60+
61+ // Assert: Each domain should be registered exactly once
62+ generatedCode . Should ( ) . Contain ( "serviceCollection.AddTransient<SensorEntities>();" ) ;
63+ generatedCode . Should ( ) . Contain ( "serviceCollection.AddTransient<LightEntities>();" ) ;
64+ generatedCode . Should ( ) . Contain ( "serviceCollection.AddTransient<SwitchEntities>();" ) ;
65+
66+ // Verify no duplicates
67+ var sensorMatches = Regex . Matches ( generatedCode , @"serviceCollection\.AddTransient<SensorEntities>\(\);" ) ;
68+ var lightMatches = Regex . Matches ( generatedCode , @"serviceCollection\.AddTransient<LightEntities>\(\);" ) ;
69+ var switchMatches = Regex . Matches ( generatedCode , @"serviceCollection\.AddTransient<SwitchEntities>\(\);" ) ;
70+
71+ sensorMatches . Should ( ) . HaveCount ( 1 ) ;
72+ lightMatches . Should ( ) . HaveCount ( 1 ) ;
73+ switchMatches . Should ( ) . HaveCount ( 1 ) ;
74+ }
75+ }
0 commit comments