{-# LANGUAGE RecursiveDo #-}
module Reflex.Data.ListSpec
( spec
)
where
import Relude
import Test.Hspec
import Test.Hspec.Contrib.HUnit ( fromHUnitTest )
import Test.HUnit
import qualified Data.List as L
( last
, tail
)
import Reflex
import Reflex.Data.List
import Reflex.Test.Host
pushAdd_network
:: forall t m
. (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
=> (Event t Int -> PerformEventT t m (Event t [Int]))
pushAdd_network ev = mdo
let
-- element in the list is a dynamic int that adds to itself each new element added to the list
-- this includes the element itself!
pushAddEvent :: Int -> PushM t (Int, Dynamic t Int)
pushAddEvent n = do
-- this causes an RTE, maybe a bug?
--addedEvExcludeSelf <- tailE addedEv
addedEvExcludeSelf <- return addedEv
let foldfn :: (Int, Dynamic t Int) -> Int -> PushM t (Maybe Int)
foldfn (_, justAdded) old = do
addme <- sample . current $ justAdded
return $ Just (old + addme)
dyn <- foldDynMaybeM foldfn n addedEvExcludeSelf
return (0, dyn)
mdl = defaultDynamicListConfig
{ _dynamicListConfig_add = pushAlways pushAddEvent ev
, _dynamicListConfig_remove = never
}
addedEv = _dynamicList_added dl
dl <- holdDynamicList [] mdl
return . updated . join . fmap sequence $ _dynamicList_contents dl
-- use list as a queue of fixed size
pushAdd_test :: Test
pushAdd_test = TestLabel "pushAdd" $ TestCase $ do
let bs = [1, 1, 1, 1, 1] :: [Int]
run = runAppSimple pushAdd_network bs
v <- liftIO run
--print v
let expected = [2, 3, 4, 5, 6]
L.last v @?= [Just expected]
push_enqueue_pop_dequeue_network
:: forall t m
. (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
=> (Event t Int -> PerformEventT t m (Event t [Int]))
push_enqueue_pop_dequeue_network ev = do
let
mdl = defaultDynamicListConfig
{ _dynamicListConfig_push = fmapMaybe
(\x -> if x `mod` 4 == 0 then Just x else Nothing)
ev
, _dynamicListConfig_enqueue = fmapMaybe
(\x -> if x `mod` 4 == 1 then Just x else Nothing)
ev
, _dynamicListConfig_pop = fmapMaybe
(\x -> if x `mod` 4 == 2 then Just () else Nothing)
ev
, _dynamicListConfig_dequeue = fmapMaybe
(\x -> if x `mod` 4 == 3 then Just () else Nothing)
ev
}
dl <- holdDynamicList [] mdl
return $ updated (_dynamicList_contents dl)
-- basic test case, add to list on each event tick
push_enqueue_pop_dequeue_test :: Test
push_enqueue_pop_dequeue_test =
TestLabel "push/enqueue/pop/dequeue" $ TestCase $ do
let bs = [0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 3] :: [Int]
run = runAppSimple push_enqueue_pop_dequeue_network bs
v <- liftIO run
let expected = Just [0, 0, 0, 1, 1]
L.last v @?= [expected]
add_network
:: forall t m
. (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
=> (Event t Int -> PerformEventT t m (Event t [Int]))
add_network ev = do
let mdl = defaultDynamicListConfig
{ _dynamicListConfig_add = (fmap (\x -> (0, x)) ev)
}
dl <- holdDynamicList [] mdl
return $ updated (_dynamicList_contents dl)
-- basic test case, add to list on each event tick
add_test :: Test
add_test = TestLabel "add" $ TestCase $ do
let bs = [1 .. 10] :: [Int]
run = runAppSimple add_network bs
v <- liftIO run
let expected = fmap Just . L.tail . scanl (\acc x -> x : acc) [] $ bs
join v @?= expected
spec :: Spec
spec = do
describe "List" $ do
fromHUnitTest add_test
fromHUnitTest push_enqueue_pop_dequeue_test
fromHUnitTest pushAdd_test