Improve types for remote button presses in tests

This commit is contained in:
Sven van Heugten 2026-03-15 11:33:26 +01:00
parent 3913522cc3
commit 1dc1faa16a
4 changed files with 25 additions and 27 deletions

View file

@ -6,11 +6,12 @@ open NightLight.Core.Models
open FsToolkit.ErrorHandling open FsToolkit.ErrorHandling
open FSharp.Data open FSharp.Data
type RemoteInteraction = type BedroomControllingRemoteInteraction =
| RemotePressedOnButton | RemotePressedOnButton
| RemotePressedOffButton | RemotePressedOffButton
| RemotePressedLeftButton | RemotePressedLeftButton
| RemotePressedRightButton
type LivingRoomControllingRemoteAction = | RemotePressedRightButton
type HumanInteraction = type HumanInteraction =
| LightPoweredOn of Light | LightPoweredOn of Light
@ -18,7 +19,8 @@ type HumanInteraction =
type Interaction = type Interaction =
| HumanInteraction of HumanInteraction | HumanInteraction of HumanInteraction
| RemoteInteraction of RemoteInteraction | BedroomControllingRemoteInteraction of BedroomControllingRemoteInteraction
| LivingRoomControllingRemoteInteraction of LivingRoomControllingRemoteAction
| TimeChanged of DateTime | TimeChanged of DateTime
type Color = type Color =
@ -123,22 +125,22 @@ type FakeHome() =
|> ReceivedZigbeeEvent |> ReceivedZigbeeEvent
|> onEventPublished.Trigger |> onEventPublished.Trigger
| HumanInteraction(LightPoweredOff light) -> friendlyNameToFakeLight[(lightProps light).FriendlyName].PowerOff() | HumanInteraction(LightPoweredOff light) -> friendlyNameToFakeLight[(lightProps light).FriendlyName].PowerOff()
| RemoteInteraction RemotePressedOnButton -> | BedroomControllingRemoteInteraction RemotePressedOnButton ->
{ Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}" { Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}"
Payload = @"{ ""action"": ""on"" }" } Payload = @"{ ""action"": ""on"" }" }
|> ReceivedZigbeeEvent |> ReceivedZigbeeEvent
|> onEventPublished.Trigger |> onEventPublished.Trigger
| RemoteInteraction RemotePressedOffButton -> | BedroomControllingRemoteInteraction RemotePressedOffButton ->
{ Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}" { Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}"
Payload = @"{ ""action"": ""off"" }" } Payload = @"{ ""action"": ""off"" }" }
|> ReceivedZigbeeEvent |> ReceivedZigbeeEvent
|> onEventPublished.Trigger |> onEventPublished.Trigger
| RemoteInteraction RemotePressedLeftButton -> | BedroomControllingRemoteInteraction RemotePressedLeftButton ->
{ Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}" { Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}"
Payload = @"{ ""action"": ""arrow_left_click"" }" } Payload = @"{ ""action"": ""arrow_left_click"" }" }
|> ReceivedZigbeeEvent |> ReceivedZigbeeEvent
|> onEventPublished.Trigger |> onEventPublished.Trigger
| RemoteInteraction RemotePressedRightButton -> | LivingRoomControllingRemoteInteraction RemotePressedRightButton ->
{ Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}" { Topic = $"zigbee2mqtt/{remoteControlFriendlyName.Get}"
Payload = @"{ ""action"": ""arrow_right_click"" }" } Payload = @"{ ""action"": ""arrow_right_click"" }" }
|> ReceivedZigbeeEvent |> ReceivedZigbeeEvent

View file

@ -36,12 +36,11 @@ let private genHumanInteraction =
|> Gen.map Interaction.HumanInteraction |> Gen.map Interaction.HumanInteraction
let private genRemoteInteraction = let private genRemoteInteraction =
Gen.elements Gen.oneof
[ RemotePressedOnButton [ Gen.elements [ RemotePressedOnButton; RemotePressedOffButton; RemotePressedLeftButton ]
RemotePressedOffButton |> Gen.map BedroomControllingRemoteInteraction
RemotePressedLeftButton
RemotePressedRightButton ] Gen.constant (LivingRoomControllingRemoteInteraction RemotePressedRightButton) ]
|> Gen.map RemoteInteraction
let private genInteraction = let private genInteraction =
Gen.frequency [ 4, genTimeChanged; 1, genHumanInteraction; 1, genRemoteInteraction ] Gen.frequency [ 4, genTimeChanged; 1, genHumanInteraction; 1, genRemoteInteraction ]

View file

@ -36,17 +36,13 @@ let doesLightHavePowerAfterInteractions light interactions =
|> Seq.tryLast |> Seq.tryLast
|> Option.defaultValue false |> Option.defaultValue false
let tryGetLastBedroomRemoteInteraction interactions = let tryGetLastBedroomControllingRemoteInteraction interactions =
interactions interactions
|> Seq.indexed |> Seq.indexed
|> Seq.choose (fun (index, interaction) -> |> Seq.choose (fun (index, interaction) ->
match interaction with match interaction with
| Interaction.RemoteInteraction remoteInteraction -> | Interaction.BedroomControllingRemoteInteraction bedroomRemoteInteraction ->
match remoteInteraction with Some(index, bedroomRemoteInteraction)
| RemotePressedOnButton
| RemotePressedOffButton
| RemotePressedLeftButton -> Some(index, remoteInteraction)
| RemotePressedRightButton -> None
| _ -> None) | _ -> None)
|> Seq.tryLast |> Seq.tryLast

View file

@ -47,7 +47,7 @@ type NightLightTests() =
let time = getTimeAfterInteractions interactions |> _.TimeOfDay let time = getTimeAfterInteractions interactions |> _.TimeOfDay
let alarm = let alarm =
hasNewDayStartedSince interactions (tryGetLastBedroomRemoteInteraction interactions) hasNewDayStartedSince interactions (tryGetLastBedroomControllingRemoteInteraction interactions)
&& startOfDay <= time && startOfDay <= time
&& time <= endOfAlarm && time <= endOfAlarm
@ -90,15 +90,16 @@ type NightLightTests() =
|> Seq.filter (fun (light, _) -> doesLightHavePowerAfterInteractions light interactions) |> Seq.filter (fun (light, _) -> doesLightHavePowerAfterInteractions light interactions)
|> Seq.toList |> Seq.toList
let lastBedroomRemoteInteraction = tryGetLastBedroomRemoteInteraction interactions let lastBedroomControllingRemoteInteraction =
tryGetLastBedroomControllingRemoteInteraction interactions
let newDayStartedSinceBedroomRemote = let newDayStartedSinceBedroomRemote =
hasNewDayStartedSince interactions lastBedroomRemoteInteraction hasNewDayStartedSince interactions lastBedroomControllingRemoteInteraction
let hasPressedRight = let hasPressedRight =
interactions interactions
|> Seq.exists (function |> Seq.exists (function
| Interaction.RemoteInteraction RemotePressedRightButton -> true | Interaction.LivingRoomControllingRemoteInteraction RemotePressedRightButton -> true
| _ -> false) | _ -> false)
let isExpectedOn light = let isExpectedOn light =
@ -108,11 +109,10 @@ type NightLightTests() =
if newDayStartedSinceBedroomRemote then if newDayStartedSinceBedroomRemote then
true true
else else
match lastBedroomRemoteInteraction with match lastBedroomControllingRemoteInteraction with
| Some(_, RemotePressedOffButton) -> false | Some(_, RemotePressedOffButton) -> false
| Some(_, RemotePressedLeftButton) -> light = LeftBedroomLamp | Some(_, RemotePressedLeftButton) -> light = LeftBedroomLamp
| Some(_, RemotePressedOnButton) -> true | Some(_, RemotePressedOnButton) -> true
| Some(_, RemotePressedRightButton) -> failwith "unexpected"
| None -> true | None -> true
| LivingRoomWallLamp | LivingRoomWallLamp
| LivingRoomFloorLamp -> not hasPressedRight | LivingRoomFloorLamp -> not hasPressedRight
@ -120,7 +120,8 @@ type NightLightTests() =
lightsWithPower lightsWithPower
|> Seq.forall (fun (light, state) -> state.IsOn = isExpectedOn light) |> Seq.forall (fun (light, state) -> state.IsOn = isExpectedOn light)
|> Prop.collect $"last bedroom remote interaction is {lastBedroomRemoteInteraction |> Option.map snd}" |> Prop.collect
$"last bedroom controlling remote interaction is {lastBedroomControllingRemoteInteraction |> Option.map snd}"
|> Prop.collect $"pressed right: {hasPressedRight}" |> Prop.collect $"pressed right: {hasPressedRight}"
|> Prop.collect $"{lightsWithPower.Length} light(s) with power" |> Prop.collect $"{lightsWithPower.Length} light(s) with power"
|> Prop.classify newDayStartedSinceBedroomRemote "new day since bedroom remote" |> Prop.classify newDayStartedSinceBedroomRemote "new day since bedroom remote"