From 704684b282e41e8aaaf34209a58b0fdf5c474a7d Mon Sep 17 00:00:00 2001 From: Eugene Niemand Date: Tue, 12 Jan 2021 10:26:32 +0000 Subject: [PATCH 1/2] Added State() Functionality to RxAppMock --- src/Fakes/NetDaemon.Fakes/RxAppMock.cs | 9 +++++++++ .../FakesTests/FakeMockableApp.cs | 8 ++++++++ .../FakesTests/RxMockTests.cs | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/Fakes/NetDaemon.Fakes/RxAppMock.cs b/src/Fakes/NetDaemon.Fakes/RxAppMock.cs index 433c61e4b..e2579bd5a 100644 --- a/src/Fakes/NetDaemon.Fakes/RxAppMock.cs +++ b/src/Fakes/NetDaemon.Fakes/RxAppMock.cs @@ -51,6 +51,8 @@ public RxAppMock() return m.Object; }); + Setup(n => n.State(It.IsAny())).Returns(entityId => MockState.First(state => state.EntityId == entityId)); + Setup(n => n.Entities(It.IsAny())).Returns(entityIds => { var m = new Mock(); @@ -118,6 +120,12 @@ public void TriggerEvent(string haEvent, string? domain, dynamic? data) /// New state public void TriggerStateChange(EntityState oldState, EntityState newState) { + var state = MockState.FirstOrDefault(entity => entity.EntityId == newState.EntityId); + var index = MockState.IndexOf(state!); + + if (index != -1) + MockState[index] = newState; + // Call the observable with no blocking foreach (var observer in ((StateChangeObservable)StateChangesObservable).Observers) { @@ -131,6 +139,7 @@ public void TriggerStateChange(EntityState oldState, EntityState newState) throw; } } + } /// diff --git a/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs b/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs index 9b361a7e5..e3ae979da 100644 --- a/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs +++ b/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs @@ -64,6 +64,14 @@ public void Initialize() _app.SetState("sensor.any_sensor", 20, new { battery_level = 70 }); _app.SetState("sensor.any_sensor2", 20, new { battery_level = 70 }); + + _app.Entity("binary_sensor.test_state_entity") + .StateChanges + .Subscribe(_ => { + if (_app.State("sensor.some_other_entity")?.State == "on") + _app.Entity("light.state_light").TurnOn(); + }); } + } } diff --git a/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs b/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs index e753dcd88..61c80c437 100644 --- a/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs +++ b/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs @@ -92,6 +92,25 @@ public void TestFakeMockableBinarySensorAppEntities() VerifyEntityTurnOn("light.kitchen"); } + [Fact] + public void TestFakeMockableGetStateForEntity() + { + // ARRANGE + FakeMockableAppImplementation app = new(Object); + // Have to add the entity before initialize to support lambda selections + MockState.Add(new() { EntityId = "sensor.some_other_entity" }); + MockState.Add(new() { EntityId = "binary_sensor.test_state_entity" }); + + app.Initialize(); + + // ACT + TriggerStateChange("sensor.some_other_entity", "off", "on"); + TriggerStateChange("binary_sensor.test_state_entity", "off", "on"); + + // ASSERT + VerifyEntityTurnOn("light.state_light"); + } + [Fact] public void TestFakeMockableBinarySensorAppEntitiesFalse() { From 36351b9c4d08f3e49e36f662d9a864180183602c Mon Sep 17 00:00:00 2001 From: Eugene Niemand Date: Wed, 27 Jan 2021 13:02:52 +0000 Subject: [PATCH 2/2] Added Mock for RunIn --- src/Fakes/NetDaemon.Fakes/NetDaemon.Fakes.csproj | 1 + src/Fakes/NetDaemon.Fakes/RxAppMock.cs | 15 ++++++++++++++- .../FakesTests/FakeMockableApp.cs | 2 ++ .../FakesTests/RxMockTests.cs | 14 ++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Fakes/NetDaemon.Fakes/NetDaemon.Fakes.csproj b/src/Fakes/NetDaemon.Fakes/NetDaemon.Fakes.csproj index 48ae107c0..7d6a192e1 100644 --- a/src/Fakes/NetDaemon.Fakes/NetDaemon.Fakes.csproj +++ b/src/Fakes/NetDaemon.Fakes/NetDaemon.Fakes.csproj @@ -28,6 +28,7 @@ + diff --git a/src/Fakes/NetDaemon.Fakes/RxAppMock.cs b/src/Fakes/NetDaemon.Fakes/RxAppMock.cs index e2579bd5a..b88323e19 100644 --- a/src/Fakes/NetDaemon.Fakes/RxAppMock.cs +++ b/src/Fakes/NetDaemon.Fakes/RxAppMock.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; +using Microsoft.Reactive.Testing; namespace NetDaemon.Daemon.Fakes { @@ -27,10 +28,15 @@ public class RxAppMock : Mock public ObservableBase<(EntityState Old, EntityState New)> StateChangesObservable { get; } /// - /// Observalbe fake events + /// Observable fake events /// public ObservableBase EventChangesObservable { get; } + /// + /// This is a Scheduler to support time travel for Observable Timer and Interval + /// + public TestScheduler TestScheduler { get; } = new(); + /// /// Default constructor /// @@ -69,6 +75,13 @@ public RxAppMock() m.Setup(n => n.StateChanges).Returns(StateChangesObservable.Where(f => y.Contains(f.New.EntityId) && f.New?.State != f.Old?.State)); m.Setup(n => n.StateAllChanges).Returns(StateChangesObservable.Where(f => y.Contains(f.New.EntityId))); return m.Object; }); + + Setup(s => s.RunIn(It.IsAny(), It.IsAny())) + .Callback((span, action) => + { + Observable.Timer(span, TestScheduler) + .Subscribe(_ => action()); + }); } /// diff --git a/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs b/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs index e3ae979da..95d4f66c0 100644 --- a/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs +++ b/tests/NetDaemon.Daemon.Tests/FakesTests/FakeMockableApp.cs @@ -71,6 +71,8 @@ public void Initialize() if (_app.State("sensor.some_other_entity")?.State == "on") _app.Entity("light.state_light").TurnOn(); }); + + _app.RunIn(TimeSpan.FromMilliseconds(100), () => _app.Entity("binary_sensor.fake_run_in_happened").TurnOn()); } } diff --git a/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs b/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs index 61c80c437..04c5f1cbe 100644 --- a/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs +++ b/tests/NetDaemon.Daemon.Tests/FakesTests/RxMockTests.cs @@ -128,6 +128,20 @@ public void TestFakeMockableBinarySensorAppEntitiesFalse() VerifyEntityTurnOn("light.kitchen", times: Times.Never()); } + [Fact] + public void TestFakeRunIn() + { + // ARRANGE + FakeMockableAppImplementation app = new(Object); + app.Initialize(); + + // ACT + TestScheduler.AdvanceBy(TimeSpan.FromMilliseconds(100).Ticks); + + // ASSERT + VerifyEntityTurnOn("binary_sensor.fake_run_in_happened", times: Times.Once()); + } + [Fact] public void TestFakeEventTurnsOnLight() {