Skip to content

Commit 65ae741

Browse files
committed
Add a single snap handler test
1 parent 69528f4 commit 65ae741

7 files changed

+75
-14
lines changed

TODO

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
-- OTHER IDEAS (EITHER R1 OR AFTER) --
1818

1919
* Setup Snap Handler tests
20+
** Done for one test, need more tests
2021

2122
* Multiple colors of cells based on user?
2223

polygod.cabal

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ Executable polygod
3838
time >= 1.1.4 && < 2,
3939
containers,
4040
MonadCatchIO-transformers,
41-
filepath >= 1.1 && <1.2
41+
filepath >= 1.1 && < 1.2,
42+
iteratee >= 0.3.5 && < 0.4
4243

4344
extensions: BangPatterns, OverloadedStrings
4445

src/WebApp.hs

+13-8
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,23 @@ worldWidth, worldHeight :: Dimension
2121

2222
main :: IO ()
2323
main = do
24-
timeline <- newTimeline (worldWidth, worldHeight) worldView
24+
timeline <- newAppTimeline
2525
users <- newUserSet
2626

2727
gliderGunPattern <- loadPattern "gospersGliderGun.txt"
2828
interfere (drawPatternAt (0, 0) gliderGunPattern) timeline
29-
quickServer $
30-
ifTop (rootHandler timeline) <|>
31-
noCache (route [ ("world/current.json", worldHandler users timeline)
32-
, ("world/next.json", nextWorldHandler users timeline)
33-
, ("world", updateWorldHandler timeline)
34-
]) <|>
35-
fileServe "public"
29+
quickServer $ site timeline users
30+
31+
newAppTimeline :: IO (Timeline SharedTimelineView)
32+
newAppTimeline = newTimeline (worldWidth, worldHeight) worldView
33+
34+
site :: Timeline SharedTimelineView -> UserSet -> Snap ()
35+
site timeline users = ifTop (rootHandler timeline) <|>
36+
noCache (route [ ("world/current.json", worldHandler users timeline)
37+
, ("world/next.json", nextWorldHandler users timeline)
38+
, ("world", updateWorldHandler timeline)
39+
]) <|>
40+
fileServe "public"
3641

3742
noCache :: Snap () -> Snap ()
3843
noCache handler = do

src/WorldHandlers.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Life.JSON
1414
import Timeline
1515
import Util
1616
import ConcurrentUsers
17+
import WorldView
1718

1819
updateWorldHandler :: Timeline a -> Snap ()
1920
updateWorldHandler timeline = do
@@ -32,13 +33,13 @@ generateNewUserToken userSet = do
3233
newUser <- liftIO (trackNewUser userSet)
3334
maybe (error500 "Failed to generate UUID" >> undefined) return newUser
3435

35-
worldHandler :: UserSet -> Timeline (UserToken -> UserSet -> Snap ()) -> Snap ()
36+
worldHandler :: UserSet -> Timeline SharedTimelineView -> Snap ()
3637
worldHandler userSet timeline = do
3738
user <- generateNewUserToken userSet
3839
(_, _, renderWorldJson) <- liftIO (now timeline)
3940
renderWorldJson user userSet
4041

41-
nextWorldHandler :: UserSet -> Timeline (UserToken -> UserSet -> Snap ()) -> Snap ()
42+
nextWorldHandler :: UserSet -> Timeline SharedTimelineView -> Snap ()
4243
nextWorldHandler userSet timeline = do
4344
userTokenParam <- getParam "u"
4445
user <- maybe (generateNewUserToken userSet)

src/WorldView.hs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module WorldView
2-
(worldView)
2+
( worldView
3+
, SharedTimelineView
4+
)
35
where
46

57
import Control.Monad.Trans (liftIO)
@@ -13,7 +15,9 @@ import Life
1315
import Life.JSON
1416
import Timeline
1517

16-
worldView :: World -> Tick -> UserToken -> UserSet -> Snap ()
18+
type SharedTimelineView = UserToken -> UserSet -> Snap ()
19+
20+
worldView :: World -> Tick -> SharedTimelineView
1721
worldView world tick userToken userSet = do
1822
count <- liftIO (userCount userSet)
1923
jsonTemplate $ worldViewJson world tick userToken count

test/Tests.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import Test.Framework (defaultMain)
55
import qualified LifeTests as LifeTests
66
import qualified Life.JSONTests as JSONTests
77
import qualified TimelineTests as TimelineTests
8+
import qualified WebAppTests as WebAppTests
89
import qualified ConcurrentUsersTests as ConcurrentUsersTests
910

1011
main :: IO ()
11-
main = defaultMain [ TimelineTests.tests, ConcurrentUsersTests.tests, LifeTests.tests, JSONTests.tests ]
12+
main = defaultMain [ TimelineTests.tests, ConcurrentUsersTests.tests, WebAppTests.tests, LifeTests.tests, JSONTests.tests ]
1213

1314

test/WebAppTests.hs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module WebAppTests where
2+
3+
import TestHelper
4+
5+
import qualified Data.Map as Map
6+
import qualified Data.ByteString as Strict
7+
import Data.IORef
8+
9+
import Text.JSONb
10+
import Snap.Iteratee
11+
import Snap.Types
12+
import Snap.Internal.Http.Types
13+
14+
import ConcurrentUsers
15+
import WebApp
16+
17+
tests :: Test
18+
tests = testGroup "WebApp" [
19+
"renders valid json" `testCase` do
20+
timeline <- newAppTimeline
21+
users <- newUserSet
22+
bodyRef <- newIORef (SomeEnumerator $ enumBS "")
23+
let request = Request { rqServerName = "localhost",
24+
rqServerPort = 0,
25+
rqRemoteAddr = "127.0.0.1",
26+
rqRemotePort = 0,
27+
rqLocalAddr = "127.0.0.1",
28+
rqLocalPort = 0,
29+
rqLocalHostname = "localhost",
30+
rqIsSecure = False,
31+
rqHeaders = Map.empty,
32+
rqBody = bodyRef,
33+
rqContentLength = Nothing,
34+
rqMethod = GET,
35+
rqVersion = (1, 1),
36+
rqCookies = [],
37+
rqSnapletPath = "",
38+
rqPathInfo = "world/next.json",
39+
rqContextPath = "/",
40+
rqURI = "/world/next.json",
41+
rqQueryString = "tick=1",
42+
rqParams = Map.singleton "tick" ["1"]
43+
}
44+
(_, testResponse) <- run (runSnap (site timeline users) (const $ return ()) request)
45+
bodyIteratee <- (rspBodyToEnum $ rspBody testResponse) stream2list
46+
!body <- run bodyIteratee
47+
assertBool "Expected response to be parseable json" (either (const False) (const True) $ decode (Strict.pack body))
48+
]

0 commit comments

Comments
 (0)