-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
907fc0c
commit 94b4b11
Showing
2 changed files
with
101 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
(local is (require :lib.testing.assert)) | ||
(local statemachine (require :lib.new-statemachine)) | ||
(local atom (require :lib.atom)) | ||
|
||
(fn make-fsm | ||
[] | ||
(statemachine.new | ||
;; States that the machine can be in mapped to their actions and transitions | ||
{:state {:current-state :closed | ||
:context {:i 0 | ||
:event nil}} | ||
|
||
:states {:closed {:toggle (fn closed->opened | ||
[state action extra] | ||
{:state {:current-state :opened | ||
:context {:i (+ state.context.i 1)}} | ||
:effect :opening})} | ||
:opened {:toggle (fn opened->closed | ||
[state action extra] | ||
{:state {:current-state :closed | ||
:context {:i (+ state.context.i 1)}} | ||
:effect :closing})}}})) | ||
|
||
(describe | ||
"State Machine" | ||
(fn [] | ||
|
||
(it "Should create a new fsm in the closed state" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(is.eq? (. (atom.deref fsm.state) :current-state) :closed "Initial state was not closed")))) | ||
|
||
(it "Should include some methods" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(is.eq? (type fsm.get-state) :function "No get-state method") | ||
(is.eq? (type fsm.signal) :function "No get-state method") | ||
(is.eq? (type fsm.subscribe) :function "No get-state method")))) | ||
|
||
(it "Should transition to opened on toggle action" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(is.eq? (fsm.signal :toggle) true "Dispatch did not return true for handled event") | ||
(is.eq? (. (atom.deref fsm.state) :current-state) :opened "State did not transition to opened")))) | ||
|
||
(it "Should transition from closed -> opened -> closed" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(fsm.signal :toggle) | ||
(fsm.signal :toggle) | ||
(is.eq? (. (atom.deref fsm.state) :current-state) :closed "State did not transition back to closed") | ||
(is.eq? (. (atom.deref fsm.state) :context :i) 2 "context.i should be 2 from 2 transitions")))) | ||
|
||
(it "Should not explode when dispatching an unhandled event" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(is.eq? (fsm.signal :fail nil) false "The FSM exploded from dispatching a :fail event")))) | ||
|
||
(it "Subscribers should be called on events" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(let [i (atom.new 0)] | ||
(fsm.subscribe (fn [] (atom.swap! i (fn [v] (+ v 1))))) | ||
(fsm.signal :toggle) | ||
(is.eq? (atom.deref i) 1 "The subscriber was not called"))))) | ||
|
||
(it "Subscribers should be provided old and new context, action, effect, and extra" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(let [_old (atom.new nil) | ||
_new (atom.new nil) | ||
_action (atom.new nil) | ||
_effect (atom.new nil) | ||
_extra (atom.new nil)] | ||
(fsm.subscribe (fn [{: prev-state : next-state : action : effect : extra}] | ||
(atom.swap! _old (fn [_ nv] nv) prev-state) | ||
(atom.swap! _new (fn [_ nv] nv) next-state) | ||
(atom.swap! _action (fn [_ nv] nv) action) | ||
(atom.swap! _effect (fn [_ nv] nv) effect) | ||
(atom.swap! _extra (fn [_ nv] nv) extra))) | ||
(fsm.signal :toggle :extra) | ||
(is.not-eq? (. (atom.deref _old) :context :i) | ||
(. (atom.deref _new) :context :i) "Subscriber did not get old and new state") | ||
(is.eq? (atom.deref _action) :toggle "Subscriber did not get correct action") | ||
(is.eq? (atom.deref _effect) :opening "Subscriber did not get correct effect") | ||
(is.eq? (atom.deref _extra) :extra "Subscriber did not get correct extra"))))) | ||
|
||
;; (print (hs.inspect fsm)) ;; DELETEME | ||
(it "Subscribers should be able to unsubscribe" | ||
(fn [] | ||
(let [fsm (make-fsm)] | ||
(let [i (atom.new 0) | ||
unsub (fsm.subscribe (fn [] (atom.swap! i (fn [v] (+ v 1)))))] | ||
(fsm.signal :toggle) | ||
(unsub) | ||
(fsm.signal :toggle) | ||
(is.eq? (atom.deref i) 1 "The subscriber was called after unsubscribing"))))))) |