Skip to content

Commit

Permalink
added TestRunner component, integrated into sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
MitchStevens committed Sep 24, 2024
1 parent 82a62e5 commit 63827a6
Show file tree
Hide file tree
Showing 17 changed files with 313 additions and 113 deletions.
46 changes: 46 additions & 0 deletions docs/test_runner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

```mermaid
flowchart TD
not_started((Not Started))
check_for_port_mismatch
check_for_failed_restriction
convert_to_evaluable
ready_for_testing
level_complete((Level Complete))
not_started --- check_for_port_mismatch
test_n_succeeded --- check_for_port_mismatch
check_for_port_mismatch --- check_for_failed_restriction
check_for_failed_restriction --- convert_to_evaluable
convert_to_evaluable --- ready_for_testing
ready_for_testing --- run_tests
subgraph test_runner
run_tests
all_tests_succeeded
test_n_failed
test_n_succeeded
run_test_n
run_tests --- test_n_failed
run_tests --- all_tests_succeeded
test_n_failed --- run_test_n
run_test_n --- test_n_failed
run_test_n --- test_n_succeeded
end
all_tests_succeeded --- level_complete
```
6 changes: 3 additions & 3 deletions src/Component/DataAttribute.purs
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ completionStatus = dataAttribute (AttrName "data-completion-status") attrPrint a
where
attrPrint = case _ of
NotStarted -> "not-started"
PortMismatch _ -> "port-mismatch"
FailedRestriction _ -> "failed-restriction"
NotEvaluable _ -> "not-evaluable"
PortMismatch _ -> "port-mismatch"
ReadyForTesting -> "ready-for-testing"
RunningTestCase _ -> "running-test"
TestCaseOutcome _ -> "testCaseOutcome"
--RunningTestCase _ -> "running-test"
--TestCaseOutcome _ -> "testCaseOutcome"
Completed -> "completed"
attrParse = fail "no parser for completion status!"

Expand Down
10 changes: 9 additions & 1 deletion src/Component/Marginalium.purs
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
module Component.Marginalium where
module Component.Marginalium
( Action(..)
, Input
, Output(..)
, Query
, State
, component
)
where

import Prelude

Expand Down
20 changes: 6 additions & 14 deletions src/Component/Sidebar/Render.purs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import Component.DataAttribute as DA
import Component.Piece as Piece
import Component.Rendering.BoardPortDiagram (renderBoardPortDiagram)
import Component.Rendering.Piece (renderPiece)
import Component.TestRunner as TestRunner
import Data.Array as A
import Data.Array.NonEmpty.Internal (NonEmptyArray(..))
import Data.Either (Either(..))
import Data.Filterable (eitherBool)
import Data.List (List(..), (:))
Expand All @@ -31,7 +33,7 @@ import Halogen.HTML.Events as HE
import Halogen.HTML.Extras (mapActionOverHTML)
import Halogen.HTML.Properties as HP

render :: forall m s. State -> ComponentHTML Action s m
render :: forall m. State -> ComponentHTML Action Slots m
render state =
HH.div
[ HP.id "sidebar-component" ]
Expand Down Expand Up @@ -78,7 +80,7 @@ render state =
[ HH.h3_ [ HH.text "Available pieces:"]
, HH.span [ HP.class_ (ClassName "pieces") ] $
renderAvailablePiece <$>
A.nub state.problem.availablePieces
A.nub (A.fromFoldable state.problem.availablePieces)
]
]

Expand Down Expand Up @@ -119,18 +121,8 @@ render state =
]
ReadyForTesting ->
[ HH.text "Ready for testing: "
, HH.button
[ HP.class_ (ClassName "ready-for-testing")
, HE.onClick (ButtonClicked RunTests) ]
[ HH.text "Run Tests"]
]
RunningTestCase { testIndex, numTests } ->
[ HH.b_ [ HH.text "Running tests..." ]
, HH.br_
, HH.text $ "Running "<> show (testIndex+1) <>"/"<> show numTests
, HH.slot_ TestRunner.slot unit TestRunner.component { ports: state.boardPorts, base: state.base, inputs: NonEmptyArray state.problem.testCases, model: state.problem.goal }
]
TestCaseOutcome failedTestCase -> []
--[ renderTestError failedTestCase ]
Completed ->
[ HH.text "Level Complete!"
, HH.button
Expand Down Expand Up @@ -223,7 +215,7 @@ render state =
]
]
where
signalRepresentationOption :: Base -> String -> ComponentHTML Action s m
signalRepresentationOption :: Base -> String -> ComponentHTML Action Slots m
signalRepresentationOption base text =
HH.span
[ HE.onClick (ButtonClicked (Base base)) ]
Expand Down
47 changes: 0 additions & 47 deletions src/Component/Sidebar/TestCaseTable.purs

This file was deleted.

9 changes: 9 additions & 0 deletions src/Component/Sidebar/Types.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ module Component.Sidebar.Types where

import Prelude

import Component.TestRunner as TestRunner
import Data.Map (Map)
import Game.Direction (CardinalDirection)
import Game.Level.Completion (CompletionStatus)
import Game.Level.Problem (Problem)
import Game.Piece (PieceId(..))
import Game.Port (Port(..))
import Game.Signal (Base, SignalRepresentation)
import Halogen (Slot)
import Type.Proxy (Proxy(..))
import Web.HTML.Event.DragEvent (DragEvent)
import Web.UIEvent.MouseEvent (MouseEvent)

Expand Down Expand Up @@ -60,3 +63,9 @@ data Action
data Output
= PieceDropped PieceId
| ButtonOutput Button

type Slots =
( testRunner :: Slot TestRunner.Query TestRunner.Output Unit )

slot =
{ testRunner: Proxy :: _ "testRunner" }
36 changes: 36 additions & 0 deletions src/Component/TestRunner.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Component.TestRunner
( component
, module Component.TestRunner.Types
) where

import Component.TestRunner.Render
import Component.TestRunner.Types
import Prelude

import Control.Monad.State.Class (modify_)
import Data.Array as A
import Data.FunctorWithIndex (mapWithIndex)
import Data.LimitQueue (LimitQueue)
import Data.LimitQueue as LQ
import Data.Map (Map)
import Data.Map as M
import Data.Maybe (Maybe(..), maybe)
import Data.Set as S
import Data.Traversable (for)
import Data.TraversableWithIndex (forWithIndex)
import Game.Capacity (Capacity(..))
import Game.Direction (CardinalDirection)
import Game.Level.Completion (TestCaseOutcome)
import Game.Port (Port(..), isInput, isOutput, portCapacity)
import Game.Signal (Base, Signal, SignalRepresentation(..), printSignal)
import Halogen (ComponentHTML, defaultEval, mkEval)
import Halogen as H
import Halogen.HTML (HTML)
import Halogen.HTML as HH
import Halogen.HTML.Properties as HP

component :: forall m. H.Component Query Input Output m
component = H.mkComponent { eval, initialState, render }
where
eval = mkEval (defaultEval)

85 changes: 85 additions & 0 deletions src/Component/TestRunner/Render.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module Component.TestRunner.Render where

import Component.TestRunner.Types
import Prelude

import Data.Array (replicate)
import Data.Array as A
import Data.Foldable (length)
import Data.FunctorWithIndex (mapWithIndex)
import Data.Map as M
import Data.Maybe (maybe)
import Data.Set as S
import Data.Zipper as Z
import Game.Capacity (Capacity(..))
import Game.Port (isInput, isOutput, portCapacity)
import Game.Signal (SignalRepresentation(..), printSignal)
import Halogen (ComponentHTML)
import Halogen.HTML as HH
import Halogen.HTML.Properties as HP

render :: forall s m. State -> ComponentHTML Action s m
render state = HH.table_ (renderHeaders <> renderRows)
where
inputDirs = M.keys $ M.filter isInput state.ports
outputDirs = M.keys $ M.filter isOutput state.ports

renderHeaders =
[ HH.tr_
[ HH.td_
[ HH.text "Index" ]
, HH.td
[ HP.colSpan (S.size inputDirs) ]
[ HH.text "Inputs" ]
, HH.td
[ HP.colSpan (S.size outputDirs) ]
[ HH.text "Expected" ]
, HH.td
[ HP.colSpan (S.size outputDirs) ]
[ HH.text "Reveived" ]
, HH.td_
[ HH.text "Status" ]
]
, HH.tr_
[ HH.td_ [ ] -- index
, HH.td_ [ HH.text "L"]
, HH.td_ [ HH.text "R"]
, HH.td_ [ HH.text "R"]
]
]

renderRows :: Array (ComponentHTML Action s m)
renderRows = flip mapWithIndex relevantTestCases \i testCase -> renderRow 99 testCase
where
relevantTestCases = A.slice start end (A.fromFoldable state.testCases)
n = min maxRows (length state.testCases)
start = max 0 (end - n)
end = max n (Z.currentIndex state.testCases)

renderRow :: Int -> TestCase -> ComponentHTML Action s m
renderRow testIndex testCase =
HH.tr_ $ join
[ [ HH.td_ [ HH.text (show testIndex) ] ]
, renderInputs
, renderExpected
, renderReceived
]
where
rep dir = SignalRepresentation state.base (maybe EightBit portCapacity (M.lookup dir state.ports))

renderSignals signals = A.fromFoldable $
flip mapWithIndex signals \dir signal ->
HH.td_
[ HH.text (printSignal (rep dir) signal) ]

renderInputs = renderSignals testCase.inputs
renderExpected = renderSignals testCase.expected
renderReceived = case testCase.status of
Pending -> replicate n (HH.td_ [])
Completed -> renderSignals testCase.expected
Failed -> maybe (replicate (M.size testCase.expected) (HH.td_ [HH.text "X"])) renderSignals testCase.received
where
n = M.size testCase.expected



Loading

0 comments on commit 63827a6

Please sign in to comment.