{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Miso.Test
(
describe
, it
, expect
, beforeEach
, afterEach
, shouldBe
, shouldSatisfy
, shouldNotBe
, runTests
, choose
, Test
, TestState
) where
import Control.Exception (IOException)
import Control.Monad.Except (catchError)
import Text.Printf
import Control.Monad.State
import Control.Monad
import System.Exit
import Miso
import Miso.Lens
describe
:: MisoString
-> Test ()
-> Test ()
describe :: Text -> Test () -> Test ()
describe Text
name Test ()
tests = do
Lens TestState Text
currentTestGroup Lens TestState Text -> Text -> Test ()
forall record (m :: * -> *) field.
MonadState record m =>
Lens record field -> field -> m ()
.= Text
name
Test ()
tests
it
:: MisoString
-> Test ()
-> Test ()
it :: Text -> Test () -> Test ()
it Text
name Test ()
action = do
preamble <- Lens TestState (IO ()) -> StateT TestState IO (IO ())
forall record (m :: * -> *) field.
MonadState record m =>
Lens record field -> m field
use Lens TestState (IO ())
beforeAction
liftIO preamble
total += 1
currentTestName .= name
Clocked {..} <- clock action
currentTestTime .= time
totalDuration += time
successful <- use currentTestResult
errorMessage <- use currentErrorMessage
if successful
then passed += 1
else failed += 1
testGroup <- use currentTestGroup
caughtEx <- use caughtException
when (successful || caughtEx) $ do
liftIO $ prettyTest CurrentTest
{ duration = time
, ..
}
conclusion <- use afterAction
liftIO conclusion
currentTestResult .= True
currentErrorMessage .= mempty
caughtException .= False
data CurrentTest
= CurrentTest
{ CurrentTest -> Text
testGroup :: MisoString
, CurrentTest -> Text
name :: MisoString
, CurrentTest -> Bool
successful :: Bool
, CurrentTest -> Text
errorMessage :: MisoString
, CurrentTest -> Double
duration :: Double
} deriving (Int -> CurrentTest -> ShowS
[CurrentTest] -> ShowS
CurrentTest -> [Char]
(Int -> CurrentTest -> ShowS)
-> (CurrentTest -> [Char])
-> ([CurrentTest] -> ShowS)
-> Show CurrentTest
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CurrentTest -> ShowS
showsPrec :: Int -> CurrentTest -> ShowS
$cshow :: CurrentTest -> [Char]
show :: CurrentTest -> [Char]
$cshowList :: [CurrentTest] -> ShowS
showList :: [CurrentTest] -> ShowS
Show, CurrentTest -> CurrentTest -> Bool
(CurrentTest -> CurrentTest -> Bool)
-> (CurrentTest -> CurrentTest -> Bool) -> Eq CurrentTest
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CurrentTest -> CurrentTest -> Bool
== :: CurrentTest -> CurrentTest -> Bool
$c/= :: CurrentTest -> CurrentTest -> Bool
/= :: CurrentTest -> CurrentTest -> Bool
Eq)
type Test a = StateT TestState IO a
data TestState
= TestState
{ TestState -> Text
_currentTestGroup :: MisoString
, TestState -> Text
_currentErrorMessage :: MisoString
, TestState -> Text
_currentTestName :: MisoString
, TestState -> Double
_currentTestTime :: Double
, TestState -> Int
_expects :: Int
, TestState -> Int
_failed :: Int
, TestState -> Int
_passed :: Int
, TestState -> Int
_total :: Int
, TestState -> Double
_totalDuration :: Double
, TestState -> Bool
_currentTestResult :: Bool
, TestState -> IO ()
_beforeAction :: IO ()
, TestState -> IO ()
_afterAction :: IO ()
, TestState -> Bool
_caughtException :: Bool
}
emptyTestState :: TestState
emptyTestState :: TestState
emptyTestState = Text
-> Text
-> Text
-> Double
-> Int
-> Int
-> Int
-> Int
-> Double
-> Bool
-> IO ()
-> IO ()
-> Bool
-> TestState
TestState Text
forall a. Monoid a => a
mempty Text
forall a. Monoid a => a
mempty Text
forall a. Monoid a => a
mempty Double
0 Int
0 Int
0 Int
0 Int
0 Double
0 Bool
True (() -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) (() -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) Bool
False
beforeAction :: Lens TestState (IO ())
beforeAction :: Lens TestState (IO ())
beforeAction = (TestState -> IO ())
-> (TestState -> IO () -> TestState) -> Lens TestState (IO ())
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> IO ()
_beforeAction ((TestState -> IO () -> TestState) -> Lens TestState (IO ()))
-> (TestState -> IO () -> TestState) -> Lens TestState (IO ())
forall a b. (a -> b) -> a -> b
$ \TestState
r IO ()
x -> TestState
r { _beforeAction = x }
afterAction :: Lens TestState (IO ())
afterAction :: Lens TestState (IO ())
afterAction = (TestState -> IO ())
-> (TestState -> IO () -> TestState) -> Lens TestState (IO ())
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> IO ()
_afterAction ((TestState -> IO () -> TestState) -> Lens TestState (IO ()))
-> (TestState -> IO () -> TestState) -> Lens TestState (IO ())
forall a b. (a -> b) -> a -> b
$ \TestState
r IO ()
x -> TestState
r { _afterAction = x }
expects :: Lens TestState Int
expects :: Lens TestState Int
expects = (TestState -> Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Int
_expects ((TestState -> Int -> TestState) -> Lens TestState Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall a b. (a -> b) -> a -> b
$ \TestState
r Int
x -> TestState
r { _expects = x }
caughtException :: Lens TestState Bool
caughtException :: Lens TestState Bool
caughtException = (TestState -> Bool)
-> (TestState -> Bool -> TestState) -> Lens TestState Bool
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Bool
_caughtException ((TestState -> Bool -> TestState) -> Lens TestState Bool)
-> (TestState -> Bool -> TestState) -> Lens TestState Bool
forall a b. (a -> b) -> a -> b
$ \TestState
r Bool
x -> TestState
r { _caughtException = x }
totalDuration :: Lens TestState Double
totalDuration :: Lens TestState Double
totalDuration = (TestState -> Double)
-> (TestState -> Double -> TestState) -> Lens TestState Double
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Double
_totalDuration ((TestState -> Double -> TestState) -> Lens TestState Double)
-> (TestState -> Double -> TestState) -> Lens TestState Double
forall a b. (a -> b) -> a -> b
$ \TestState
r Double
x -> TestState
r { _totalDuration = x }
passed :: Lens TestState Int
passed :: Lens TestState Int
passed = (TestState -> Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Int
_passed ((TestState -> Int -> TestState) -> Lens TestState Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall a b. (a -> b) -> a -> b
$ \TestState
r Int
x -> TestState
r { _passed = x }
failed :: Lens TestState Int
failed :: Lens TestState Int
failed = (TestState -> Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Int
_failed ((TestState -> Int -> TestState) -> Lens TestState Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall a b. (a -> b) -> a -> b
$ \TestState
r Int
x -> TestState
r { _failed = x }
total :: Lens TestState Int
total :: Lens TestState Int
total = (TestState -> Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Int
_total ((TestState -> Int -> TestState) -> Lens TestState Int)
-> (TestState -> Int -> TestState) -> Lens TestState Int
forall a b. (a -> b) -> a -> b
$ \TestState
r Int
x -> TestState
r { _total = x }
currentTestResult :: Lens TestState Bool
currentTestResult :: Lens TestState Bool
currentTestResult = (TestState -> Bool)
-> (TestState -> Bool -> TestState) -> Lens TestState Bool
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Bool
_currentTestResult ((TestState -> Bool -> TestState) -> Lens TestState Bool)
-> (TestState -> Bool -> TestState) -> Lens TestState Bool
forall a b. (a -> b) -> a -> b
$ \TestState
r Bool
x -> TestState
r { _currentTestResult = x }
currentTestName :: Lens TestState MisoString
currentTestName :: Lens TestState Text
currentTestName = (TestState -> Text)
-> (TestState -> Text -> TestState) -> Lens TestState Text
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Text
_currentTestName ((TestState -> Text -> TestState) -> Lens TestState Text)
-> (TestState -> Text -> TestState) -> Lens TestState Text
forall a b. (a -> b) -> a -> b
$ \TestState
r Text
x -> TestState
r { _currentTestName = x }
currentErrorMessage :: Lens TestState MisoString
currentErrorMessage :: Lens TestState Text
currentErrorMessage = (TestState -> Text)
-> (TestState -> Text -> TestState) -> Lens TestState Text
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Text
_currentErrorMessage ((TestState -> Text -> TestState) -> Lens TestState Text)
-> (TestState -> Text -> TestState) -> Lens TestState Text
forall a b. (a -> b) -> a -> b
$ \TestState
r Text
x -> TestState
r { _currentErrorMessage = x }
currentTestGroup :: Lens TestState MisoString
currentTestGroup :: Lens TestState Text
currentTestGroup = (TestState -> Text)
-> (TestState -> Text -> TestState) -> Lens TestState Text
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Text
_currentTestGroup ((TestState -> Text -> TestState) -> Lens TestState Text)
-> (TestState -> Text -> TestState) -> Lens TestState Text
forall a b. (a -> b) -> a -> b
$ \TestState
r Text
x -> TestState
r { _currentTestGroup = x }
currentTestTime :: Lens TestState Double
currentTestTime :: Lens TestState Double
currentTestTime = (TestState -> Double)
-> (TestState -> Double -> TestState) -> Lens TestState Double
forall record field.
(record -> field)
-> (record -> field -> record) -> Lens record field
lens TestState -> Double
_currentTestTime ((TestState -> Double -> TestState) -> Lens TestState Double)
-> (TestState -> Double -> TestState) -> Lens TestState Double
forall a b. (a -> b) -> a -> b
$ \TestState
r Double
x -> TestState
r { _currentTestTime = x }
expect
:: (Eq a, Show a)
=> (a -> a -> Bool)
-> a
-> a
-> Test ()
expect :: forall a. (Eq a, Show a) => (a -> a -> Bool) -> a -> a -> Test ()
expect a -> a -> Bool
f a
x a
y = do
let succeeded :: Bool
succeeded = a -> a -> Bool
f a
x a
y
name <- Lens TestState Text -> StateT TestState IO Text
forall record (m :: * -> *) field.
MonadState record m =>
Lens record field -> m field
use Lens TestState Text
currentTestName
start <- use currentTestTime
groupName <- use currentTestGroup
expects += 1
currentTestResult %= (&& succeeded)
unless succeeded $ liftIO $ do
stop <- now
prettyTest (CurrentTest groupName name succeeded expectationMessage (stop - start))
where
expectationMessage :: Text
expectationMessage = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Expecting: "
, Text
yellow
, [Char] -> Text
forall str. ToMisoString str => str -> Text
ms (a -> [Char]
forall a. Show a => a -> [Char]
show a
y)
, Text
"\n"
, Text
reset
, Text
" "
, Text
cyan Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"↳ " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
reset Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"Received: "
, Text
red
, [Char] -> Text
forall str. ToMisoString str => str -> Text
ms (a -> [Char]
forall a. Show a => a -> [Char]
show a
x)
, Text
" \n"
, Text
reset
]
shouldSatisfy
:: (Eq a, Show a)
=> a
-> (a -> Bool)
-> Test ()
shouldSatisfy :: forall a. (Eq a, Show a) => a -> (a -> Bool) -> Test ()
shouldSatisfy a
x a -> Bool
f = do
let succeeded :: Bool
succeeded = a -> Bool
f a
x
name <- Lens TestState Text -> StateT TestState IO Text
forall record (m :: * -> *) field.
MonadState record m =>
Lens record field -> m field
use Lens TestState Text
currentTestName
start <- use currentTestTime
groupName <- use currentTestGroup
expects += 1
currentTestResult %= (&& succeeded)
unless succeeded $ liftIO $ do
stop <- now
prettyTest (CurrentTest groupName name succeeded expectationMessage (stop - start))
where
expectationMessage :: Text
expectationMessage = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"Expecting: "
, Text
yellow
, [Char] -> Text
forall str. ToMisoString str => str -> Text
ms (a -> [Char]
forall a. Show a => a -> [Char]
show a
x)
, Text
" to satisfy predicate"
, Text
"\n"
, Text
reset
, Text
" "
, Text
cyan Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"↳ " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
reset Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"Received: "
, Text
red
, [Char] -> Text
forall str. ToMisoString str => str -> Text
ms (a -> [Char]
forall a. Show a => a -> [Char]
show a
x)
, Text
" \n"
, Text
reset
]
shouldNotBe
:: (Show a, Eq a)
=> a
-> a
-> Test ()
shouldNotBe :: forall a. (Show a, Eq a) => a -> a -> Test ()
shouldNotBe = (a -> a -> Bool) -> a -> a -> Test ()
forall a. (Eq a, Show a) => (a -> a -> Bool) -> a -> a -> Test ()
expect a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(/=)
shouldBe
:: (Show a, Eq a)
=> a
-> a
-> Test ()
shouldBe :: forall a. (Show a, Eq a) => a -> a -> Test ()
shouldBe = (a -> a -> Bool) -> a -> a -> Test ()
forall a. (Eq a, Show a) => (a -> a -> Bool) -> a -> a -> Test ()
expect a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)
beforeEach
:: IO ()
-> Test ()
-> Test ()
beforeEach :: IO () -> Test () -> Test ()
beforeEach IO ()
action Test ()
x = do
Lens TestState (IO ())
beforeAction Lens TestState (IO ()) -> (IO () -> IO ()) -> Test ()
forall record (m :: * -> *) field.
MonadState record m =>
Lens record field -> (field -> field) -> m ()
%= \IO ()
f -> IO ()
f IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
action
Test ()
x
afterEach
:: IO ()
-> Test ()
-> Test ()
afterEach :: IO () -> Test () -> Test ()
afterEach IO ()
action Test ()
x = do
Lens TestState (IO ())
afterAction Lens TestState (IO ()) -> (IO () -> IO ()) -> Test ()
forall record (m :: * -> *) field.
MonadState record m =>
Lens record field -> (field -> field) -> m ()
%= \IO ()
f -> IO ()
f IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
action
Test ()
x
data Clocked a
= Clocked
{ forall a. Clocked a -> Double
time :: Double
, forall a. Clocked a -> Either [Char] a
result :: Either String a
} deriving (Int -> Clocked a -> ShowS
[Clocked a] -> ShowS
Clocked a -> [Char]
(Int -> Clocked a -> ShowS)
-> (Clocked a -> [Char])
-> ([Clocked a] -> ShowS)
-> Show (Clocked a)
forall a. Show a => Int -> Clocked a -> ShowS
forall a. Show a => [Clocked a] -> ShowS
forall a. Show a => Clocked a -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Clocked a -> ShowS
showsPrec :: Int -> Clocked a -> ShowS
$cshow :: forall a. Show a => Clocked a -> [Char]
show :: Clocked a -> [Char]
$cshowList :: forall a. Show a => [Clocked a] -> ShowS
showList :: [Clocked a] -> ShowS
Show, Clocked a -> Clocked a -> Bool
(Clocked a -> Clocked a -> Bool)
-> (Clocked a -> Clocked a -> Bool) -> Eq (Clocked a)
forall a. Eq a => Clocked a -> Clocked a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Clocked a -> Clocked a -> Bool
== :: Clocked a -> Clocked a -> Bool
$c/= :: forall a. Eq a => Clocked a -> Clocked a -> Bool
/= :: Clocked a -> Clocked a -> Bool
Eq)
clock :: Test a -> Test (Clocked a)
clock :: forall a. Test a -> Test (Clocked a)
clock Test a
action = do
start <- IO Double -> StateT TestState IO Double
forall a. IO a -> StateT TestState IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO Double
now
currentTestTime .= start
result <- (Right <$> action) `catchError` errorHandler start
stop <- liftIO now
let time = Double
stop Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
start
currentTestTime .= time
pure Clocked {..}
where
errorHandler :: Double -> IOException -> m (Either [Char] b)
errorHandler Double
start (IOException
e :: IOException) = do
stop <- IO Double -> m Double
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO Double
now
currentErrorMessage .= ms e
caughtException .= True
currentTestResult %= (&& False)
currentTestTime .= stop - start
pure $ Left (show e)
runTests
:: Test a
-> IO ()
runTests :: forall a. Test a -> IO ()
runTests Test a
ts = do
#ifdef JSDOM
_ <- global # ("initJSDOM" :: String) $ ()
#endif
summary <- Test a -> TestState -> IO TestState
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m s
execStateT Test a
ts TestState
emptyTestState
printSummary summary
when (summary ^. failed > 0) $ do
consoleLog "ERROR"
liftIO exitFailure
consoleLog "SUCCESS"
liftIO exitSuccess
formatMillis :: Double -> MisoString
formatMillis :: Double -> Text
formatMillis Double
duration = [Char] -> Text
forall str. ToMisoString str => str -> Text
ms ([Char] -> Double -> [Char]
forall r. PrintfType r => [Char] -> r
printf [Char]
"%.3f ms" Double
duration :: String)
prettyTest :: CurrentTest -> IO ()
prettyTest :: CurrentTest -> IO ()
prettyTest CurrentTest {Bool
Double
Text
duration :: CurrentTest -> Double
testGroup :: CurrentTest -> Text
name :: CurrentTest -> Text
successful :: CurrentTest -> Bool
errorMessage :: CurrentTest -> Text
testGroup :: Text
name :: Text
successful :: Bool
errorMessage :: Text
duration :: Double
..} = IO JSVal -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO JSVal -> IO ()) -> IO JSVal -> IO ()
forall a b. (a -> b) -> a -> b
$
if Bool
successful
then
Text -> IO JSVal
jsg (Text
"console" :: MisoString) IO JSVal -> Text -> [Text] -> IO JSVal
forall object args.
(ToObject object, ToArgs args) =>
object -> Text -> args -> IO JSVal
# (Text
"log" :: MisoString) ([Text] -> IO JSVal) -> [Text] -> IO JSVal
forall a b. (a -> b) -> a -> b
$
[ Text
green
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"✓"
, Text
reset Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall str. ToMisoString str => str -> Text
ms Text
testGroup
, Text
">"
, Text
white
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall str. ToMisoString str => str -> Text
ms Text
name
, Text
gray
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"["
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Double -> Text
formatMillis Double
duration
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]"
]
else
Text -> IO JSVal
jsg (Text
"console" :: MisoString) IO JSVal -> Text -> [Text] -> IO JSVal
forall object args.
(ToObject object, ToArgs args) =>
object -> Text -> args -> IO JSVal
# (Text
"log" :: MisoString) ([Text] -> IO JSVal) -> [Text] -> IO JSVal
forall a b. (a -> b) -> a -> b
$
[ Text
red Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"✗"
, Text
reset Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
testGroup
, Text
">"
, Text
white
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
gray
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ["
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Double -> Text
formatMillis Double
duration
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]"
, Text
cyan
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n ↳ "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
reset
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
errorMessage
]
printSummary :: TestState -> IO ()
printSummary :: TestState -> IO ()
printSummary TestState {Bool
Double
Int
IO ()
Text
_currentTestGroup :: TestState -> Text
_currentErrorMessage :: TestState -> Text
_currentTestName :: TestState -> Text
_currentTestTime :: TestState -> Double
_expects :: TestState -> Int
_failed :: TestState -> Int
_passed :: TestState -> Int
_total :: TestState -> Int
_totalDuration :: TestState -> Double
_currentTestResult :: TestState -> Bool
_beforeAction :: TestState -> IO ()
_afterAction :: TestState -> IO ()
_caughtException :: TestState -> Bool
_currentTestGroup :: Text
_currentErrorMessage :: Text
_currentTestName :: Text
_currentTestTime :: Double
_expects :: Int
_failed :: Int
_passed :: Int
_total :: Int
_totalDuration :: Double
_currentTestResult :: Bool
_beforeAction :: IO ()
_afterAction :: IO ()
_caughtException :: Bool
..} = IO JSVal -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO JSVal -> IO ()) -> IO JSVal -> IO ()
forall a b. (a -> b) -> a -> b
$
Text -> IO JSVal
jsg (Text
"console" :: MisoString) IO JSVal -> Text -> [Text] -> IO JSVal
forall object args.
(ToObject object, ToArgs args) =>
object -> Text -> args -> IO JSVal
# (Text
"log" :: MisoString) ([Text] -> IO JSVal) -> [Text] -> IO JSVal
forall a b. (a -> b) -> a -> b
$
[ Text
"\n "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
green
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall str. ToMisoString str => str -> Text
ms Int
_passed
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" passed"
, Text
"\n "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
red
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall str. ToMisoString str => str -> Text
ms Int
_failed
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" failed"
, Text
"\n "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
reset
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"Ran "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall str. ToMisoString str => str -> Text
ms Int
_total
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" tests"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
gray
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ["
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Double -> Text
formatMillis Double
_totalDuration
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]"
, Text
"\n "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
reset
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall str. ToMisoString str => str -> Text
ms Int
_expects
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" expect() calls"
]
green, cyan, yellow, red, reset, white, gray :: MisoString
green :: Text
green = Text
"\x1b[32m"
gray :: Text
gray = Text
"\x1b[90m"
red :: Text
red = Text
"\x1b[31m"
reset :: Text
reset = Text
"\x1b[0m"
yellow :: Text
yellow = Text
"\x1b[33m"
cyan :: Text
cyan = Text
"\x1b[36m"
white :: Text
white = Text
"\x1b[37m"
choose
:: Int
-> Int
-> IO Int
choose :: Int -> Int -> IO Int
choose Int
x Int
y = JSVal -> IO Int
forall a. FromJSVal a => JSVal -> IO a
fromJSValUnchecked (JSVal -> IO Int) -> IO JSVal -> IO Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< do
JSVal
global JSVal -> Text -> (Int, Int) -> IO JSVal
forall object args.
(ToObject object, ToArgs args) =>
object -> Text -> args -> IO JSVal
# Text
"getRandomNumber" ((Int, Int) -> IO JSVal) -> (Int, Int) -> IO JSVal
forall a b. (a -> b) -> a -> b
$ (Int
x,Int
y)