From 15bf8db9f468f9e3eb30865d4e40c81102ae1ecf Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Sun, 4 Jan 2026 20:17:35 +0100 Subject: [PATCH] Make FakeHome independent of NightLightStateMachine --- NightLight.Core.Tests/FakeHome.fs | 30 ++++++++---------------- NightLight.Core.Tests/NightLightTests.fs | 26 +++++++++++++++----- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/NightLight.Core.Tests/FakeHome.fs b/NightLight.Core.Tests/FakeHome.fs index bf7aa6c..6413cbd 100644 --- a/NightLight.Core.Tests/FakeHome.fs +++ b/NightLight.Core.Tests/FakeHome.fs @@ -3,7 +3,6 @@ namespace NightLight.Core.Tests open System open System.Text.RegularExpressions open NightLight.Core.Models -open NightLight.Core.Core open FsToolkit.ErrorHandling open FSharp.Data @@ -44,19 +43,19 @@ type FakeLight(light: Light) = color <- newColor type FakeHome() = - let mutable nightLightStateMachine = NightLightStateMachine() - - let assertIsOkAndGet result = - match result with - | Ok value -> value - | Error error -> failwith $"Expected Ok, got Error {error}" - let friendlyNameToFakeLight = lights |> Seq.map (fun light -> light.FriendlyName, FakeLight light) |> Map.ofSeq - let processCommand command = + let onEventPublished = new Event() + + member _.LightStates = friendlyNameToFakeLight.Values |> Seq.map _.LightWithState + + [] + member _.OnEventPublished = onEventPublished.Publish + + member _.ProcessCommand(command: Message) = option { let! friendlyName = let m = Regex.Match(command.Topic, "^zigbee2mqtt/(.+)/set$") @@ -86,15 +85,6 @@ type FakeHome() = } |> ignore - let sendEvent event = - let newState, commands = - event |> nightLightStateMachine.OnEventReceived |> assertIsOkAndGet - - commands |> Seq.iter processCommand - nightLightStateMachine <- newState - - member _.LightStates = friendlyNameToFakeLight.Values |> Seq.map _.LightWithState - member _.Interact(interaction: Interaction) = match interaction with | HumanInteraction(LightTurnedOn light) -> @@ -107,9 +97,9 @@ type FakeHome() = ""data"": {{ ""friendly_name"": ""{light.FriendlyName}"" }} }}" } |> ReceivedZigbeeEvent - |> sendEvent + |> onEventPublished.Trigger | HumanInteraction(LightTurnedOff light) -> friendlyNameToFakeLight[light.FriendlyName].TurnOff() - | TimeChanged newTime -> newTime |> Event.TimeChanged |> sendEvent + | TimeChanged newTime -> newTime |> Event.TimeChanged |> onEventPublished.Trigger type FakeHome with member this.Interact(interactions: Interaction seq) = interactions |> Seq.iter this.Interact diff --git a/NightLight.Core.Tests/NightLightTests.fs b/NightLight.Core.Tests/NightLightTests.fs index 612ad49..cc8edfc 100644 --- a/NightLight.Core.Tests/NightLightTests.fs +++ b/NightLight.Core.Tests/NightLightTests.fs @@ -1,6 +1,7 @@ namespace NightLight.Core.Tests open System +open NightLight.Core.Core open FsCheck.Xunit open FsCheck.FSharp @@ -26,24 +27,37 @@ module InteractionsHelpers = [ |])>] type NightLightTests() = + let createFakeHomeWithNightLightAndInteract (interactions: Interaction list) = + let mutable nightLightStateMachine = NightLightStateMachine() + + let fakeHome = FakeHome() + + fakeHome.OnEventPublished.Add(fun event -> + match event |> nightLightStateMachine.OnEventReceived with + | Ok(newState, commands) -> + commands |> Seq.iter fakeHome.ProcessCommand + nightLightStateMachine <- newState + | Error error -> failwith $"Unexpected error {error}") + + fakeHome.Interact interactions + + fakeHome + [] let ``Brightness should always be under 255`` (interactions: Interaction list) = - let fakeHome = FakeHome() - fakeHome.Interact interactions + let fakeHome = createFakeHomeWithNightLightAndInteract interactions fakeHome.ForAllLightsThatAreOn(fun (_, brightness, _) -> brightness < 255uy) [] let ``Lights should be red during the night`` (interactions: Interaction list) = - let fakeHome = FakeHome() - fakeHome.Interact interactions + let fakeHome = createFakeHomeWithNightLightAndInteract interactions InteractionsHelpers.isNightAfter interactions ==> fakeHome.ForAllLightsThatAreOn(fun (_, _, color) -> color = Red) [] let ``Lights should be white or yellow during the day`` (interactions: Interaction list) = - let fakeHome = FakeHome() - fakeHome.Interact interactions + let fakeHome = createFakeHomeWithNightLightAndInteract interactions InteractionsHelpers.isDayAfter interactions ==> fakeHome.ForAllLightsThatAreOn(fun (_, _, color) -> color = White || color = Yellow)