using Evergreen.Health.Application.Health.Devices; using Evergreen.Health.Application.Health.Devices.Discovery; using Evergreen.Health.Application.Health.Devices.Mattress; using Evergreen.Health.Application.Health.Integrations.HomeAssistant; using Evergreen.Health.Application.Health.Scenes; using Microsoft.Extensions.Options; using System.Text.Json; using Xunit; namespace Admin.NET.Test.Health; public sealed class SystemServiceFilteringTests { private static HomeAssistantDeviceCatalog Catalog() => new(Options.Create(new HomeAssistantOptions()), new DeviceModuleRegistry([])); [Fact] public void RegistryDeserializationRetainsSystemServiceMarker() { var device = JsonSerializer.Deserialize( """{"id":"system-sun","name":"Sun","entry_type":"service"}"""); Assert.NotNull(device); Assert.Equal("service", device.EntryType); } [Fact] public void SystemServicesAreExcludedFromListAndAllDeviceCounts() { var registry = new HomeAssistantRegistries { Devices = [new() { Id = "sun", Name = "Sun", EntryType = "service" }, new() { Id = "backup", Name = "Backup", EntryType = "service" }], Entities = [new() { DeviceId = "sun", EntityId = "sensor.sun_next_rising", Platform = "sun" }, new() { DeviceId = "backup", EntityId = "sensor.backup_backup_manager_state", Platform = "backup" }] }; var states = new Dictionary { ["sensor.sun_next_rising"] = new() { EntityId = "sensor.sun_next_rising", State = "2026-10-10T06:00:00Z" }, ["sensor.backup_backup_manager_state"] = new() { EntityId = "sensor.backup_backup_manager_state", State = "idle" } }; for (var i = 0; i < 9; i++) { var deviceId = $"furniture-{i}"; var entityId = i == 0 ? "cover.curtain" : $"switch.furniture_{i}"; registry.Devices.Add(new() { Id = deviceId, Name = $"家具{i}" }); registry.Entities.Add(new() { DeviceId = deviceId, EntityId = entityId, Platform = "xiaomi_home" }); states[entityId] = new() { EntityId = entityId, State = i == 0 ? "unavailable" : "on" }; } var devices = Catalog().BuildDiscoveredDevices(registry, states); Assert.Equal(9, devices.Count); Assert.DoesNotContain(devices, device => device.DeviceId is "sun" or "backup"); Assert.Contains(devices, device => device.DeviceId == "furniture-0" && !device.Online); var summary = HomeAssistantDeviceCatalog.BuildSummary(devices); Assert.Equal(9, summary.TotalDevices); Assert.Equal(8, summary.OnlineDevices); Assert.Equal(1, summary.OfflineDevices); Assert.Equal(9, summary.TotalEntities); Assert.Equal(8, summary.AvailableEntities); } [Theory] [InlineData("service")] [InlineData("SERVICE")] public void RenamedSystemServiceStillDoesNotBecomeFurniture(string entryType) { var registry = new HomeAssistantRegistries { Devices = [new() { Id = "service", Name = "系统服务", NameByUser = "我的灯", EntryType = entryType }], Entities = [new() { DeviceId = "service", EntityId = "sensor.service" }] }; Assert.Empty(Catalog().BuildDiscoveredDevices(registry, new Dictionary { ["sensor.service"] = new() { EntityId = "sensor.service", State = "on" } })); } [Theory] [InlineData("Sun", null)] [InlineData("Backup", "")] public void PhysicalDevicesAreNotHiddenJustBecauseTheyShareServiceNames(string name, string? entryType) { var registry = new HomeAssistantRegistries { Devices = [new() { Id = "physical", Name = name, EntryType = entryType, Manufacturer = "Other brand" }], Entities = [new() { DeviceId = "physical", EntityId = "sensor.physical", Platform = "other_integration" }] }; var device = Assert.Single(Catalog().BuildDiscoveredDevices(registry, new Dictionary { ["sensor.physical"] = new() { EntityId = "sensor.physical", State = "20" } })); Assert.Equal(name, device.Name); Assert.True(device.Online); } [Fact] public void ValidServiceOnlyRegistryDoesNotCreateFallbackFurniture() { var options = Options.Create(new HomeAssistantOptions { Entities = new() { MattressLeftHeatingLevel = "number.heating" } }); var runner = new DeviceActionRunner(new FakeHaGateway(), TimeProvider.System, new()); var catalog = new HomeAssistantDeviceCatalog(options, new DeviceModuleRegistry([new MattressModule(runner, options)])); var registry = new HomeAssistantRegistries { Devices = [new() { Id = "backup", Name = "Backup", EntryType = "service" }], Entities = [new() { DeviceId = "backup", EntityId = "sensor.backup", Platform = "backup" }] }; var states = new Dictionary { ["sensor.backup"] = new() { EntityId = "sensor.backup", State = "idle" }, ["number.heating"] = new() { EntityId = "number.heating", State = "0" } }; Assert.Empty(catalog.BuildDiscoveredDevices(registry, states)); Assert.Equal("mattress", Assert.Single(catalog.BuildDiscoveredDevices(null, states)).ModuleKey); } }