aboutsummaryrefslogtreecommitdiff
path: root/specs/Specs/AppStateUpdateSpec.hs
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2024-12-20 18:22:19 +0530
committerAkshay Nair <phenax5@gmail.com>2024-12-20 19:16:51 +0530
commit4a13725300303940416bd6260af62ba478d30ec5 (patch)
treec2897e0d80d373c9335b69cbf9c155c6264065f0 /specs/Specs/AppStateUpdateSpec.hs
parent5dc3696f38433c79939bb182c4590a6ce04f4c63 (diff)
downloadchelleport-4a13725300303940416bd6260af62ba478d30ec5.tar.gz
chelleport-4a13725300303940416bd6260af62ba478d30ec5.zip
Add tests for state management
Diffstat (limited to 'specs/Specs/AppStateUpdateSpec.hs')
-rw-r--r--specs/Specs/AppStateUpdateSpec.hs113
1 files changed, 108 insertions, 5 deletions
diff --git a/specs/Specs/AppStateUpdateSpec.hs b/specs/Specs/AppStateUpdateSpec.hs
index 0b5cac0..169cd8b 100644
--- a/specs/Specs/AppStateUpdateSpec.hs
+++ b/specs/Specs/AppStateUpdateSpec.hs
@@ -1,20 +1,123 @@
module Specs.AppStateUpdateSpec where
-import Chelleport (update)
+import Chelleport (initialState, update)
import Chelleport.Types
import Mock
+import qualified SDL
import Test.Hspec
+test :: SpecWith ()
test = do
+ describe "#initialState" $ do
+ it "returns the initial state of the app" $ do
+ (initState, _) <- runWithMocks initialState
+ length (stateGrid initState) `shouldBe` 9
+ stateGrid initState `shouldSatisfy` all ((== 16) . length)
+ stateGrid initState `shouldSatisfy` all (all ((== 2) . length))
+ stateKeySequence initState `shouldBe` []
+ stateIsMatched initState `shouldBe` False
+ stateIsShiftPressed initState `shouldBe` False
+
describe "#update" $ do
+ let defaultState =
+ State
+ { stateKeySequence = [],
+ stateIsShiftPressed = False,
+ stateIsMatched = False,
+ stateGrid = [["ABC", "DEF"], ["DJK", "JKL"]]
+ }
+
+ context "with action HandleKeyInput" $ do
+ context "when there are no matches" $ do
+ let currentState = defaultState {stateKeySequence = "D"}
+
+ context "when input key sequence has matching values in grid" $ do
+ it "does not update" $ do
+ ((nextState, action), _) <- runWithMocks $ update currentState $ HandleKeyInput SDL.KeycodeZ
+ action `shouldBe` Nothing
+ nextState `shouldBe` currentState
+
+ context "when input key sequence does not have matching values in grid" $ do
+ it "adds key to key sequence" $ do
+ ((nextState, action), _) <- runWithMocks $ update currentState $ HandleKeyInput SDL.KeycodeE
+ action `shouldBe` Nothing
+ nextState `shouldBe` currentState {stateKeySequence = "DE"}
+
+ context "when there is a matches" $ do
+ let currentState = defaultState {stateKeySequence = "DE"}
+
+ context "when input key sequence does not have matching values in grid" $ do
+ it "adds key to key sequence and enables isMatched" $ do
+ ((nextState, _), _) <- runWithMocks $ update currentState $ HandleKeyInput SDL.KeycodeF
+ nextState `shouldBe` currentState {stateKeySequence = "DEF", stateIsMatched = True}
+
+ it "continues with MoveMousePosition action" $ do
+ ((_, action), _) <- runWithMocks $ update currentState $ HandleKeyInput SDL.KeycodeF
+ action `shouldBe` Just (MoveMousePosition (0, 1))
+
context "with action TriggerLeftClick" $ do
- let state = State {stateKeySequence = [], stateIsShiftPressed = False, stateIsMatched = False, stateGrid = []}
+ let currentState = defaultState
it "hides window and triggers left clicks" $ do
- (_, mock) <- runWithMocks $ update state TriggerLeftClick
+ (_, mock) <- runWithMocks $ update currentState TriggerLeftClick
calls mock `shouldContain` [CallHideWindow, CallPressMouseButton LeftClick]
it "continues with action ShutdownApp without updating state" $ do
- ((state, action), mock) <- runWithMocks $ update state TriggerLeftClick
+ ((nextState, action), _) <- runWithMocks $ update currentState TriggerLeftClick
+ -- handleMocks
+ -- [ CallPressMouseButton LeftClick `returns` (1, 2),
+ -- CallHideWindow `returns` ()
+ -- ]
action `shouldBe` Just ShutdownApp
- state `shouldBe` state
+ nextState `shouldBe` currentState
+
+ context "with action MoveMousePosition" $ do
+ let currentState = defaultState
+
+ -- TODO: Test with inline mocked values
+ it "moves mouse pointer to center of cell of given coordinates" $ do
+ (_, mock) <- runWithMocks $ update currentState $ MoveMousePosition (0, 0)
+ mock `shouldHaveCalled` CallMoveMousePosition 25 25
+
+ it "does not continue or update state" $ do
+ (result, _) <- runWithMocks $ update currentState $ MoveMousePosition (0, 0)
+ result `shouldBe` (currentState, Nothing)
+
+ context "with action ResetKeys" $ do
+ let currentState = defaultState
+
+ it "resets state without any action" $ do
+ ((nextState, action), _) <- runWithMocks $ update currentState ResetKeys
+ action `shouldBe` Nothing
+ nextState `shouldBe` currentState {stateKeySequence = [], stateIsMatched = False}
+
+ context "with action IncrementMouseCursor" $ do
+ let currentState = defaultState
+
+ -- TODO: Test with inline mocked values
+ it "hides window and triggers left clicks" $ do
+ (_, mock) <- runWithMocks $ update currentState $ IncrementMouseCursor (10, -20)
+ mock `shouldHaveCalled` CallMoveMousePosition 52 22
+
+ it "does not continue or update state" $ do
+ (result, _) <- runWithMocks $ update currentState $ IncrementMouseCursor (0, 0)
+ result `shouldBe` (currentState, Nothing)
+
+ context "with action ShutdownApp" $ do
+ let currentState = defaultState
+
+ it "hides window and triggers left clicks" $ do
+ (_, mock) <- runWithMocks $ update currentState ShutdownApp
+ mock `shouldHaveCalled` CallShutdownApp
+
+ it "does not continue or update state" $ do
+ (result, _) <- runWithMocks $ update currentState ShutdownApp
+ result `shouldBe` (currentState, Nothing)
+
+ context "with action UpdateShiftState" $ do
+ let currentState = defaultState
+
+ it "updates shift state without any action" $ do
+ ((nextState, action), _) <- runWithMocks $ update currentState $ UpdateShiftState True
+ action `shouldBe` Nothing
+ nextState `shouldBe` currentState {stateIsShiftPressed = True}