1module PlainTextResponse.Spec where
4import Data.String as String
6import Effect.Aff (Aff, bracket)
7import Effect.Aff.Class (liftAff)
8import Effect.Class (liftEffect)
10import Effect.Exception as Exn
11import Effect.Ref as Ref
12import Foreign (unsafeToForeign)
13import Test.Spec (Spec, around, describe, it)
14import Test.Spec.Assertions (shouldEqual)
15import Yoga.Fastify.Fastify as F
16import Yoga.Fastify.Fastify (Port(..), Host(..), RouteURL(..), StatusCode(..))
17import Yoga.Fastify.Om (createOmFastify, getOm, postOm)
18import Yoga.Fetch.Om (GET, POST, Route, type (/), JSON, PlainText, Streaming, client)
19import Yoga.Fetch.Om.Simple as Simple
20import Yoga.Om (Om, runOm)
21import Yoga.Om.Strom (Strom)
22import Yoga.Om.Strom as Strom
24type Payload = { value :: Int }
25type Result = { doubled :: Int }
30 ("plain-text-test" / "double")
31 { body :: JSON Payload }
32 ( ok :: { body :: Result }
33 , badRequest :: { body :: PlainText }
35 , health :: Route GET ("plain-text-test" / "health") {} (ok :: { body :: PlainText })
36 , stream :: Route GET ("plain-text-test" / "stream") {} (ok :: { body :: Streaming String })
41 . { double :: Payload -> Om (Record ctx) (badRequest :: String | err) Result
42 , health :: Om (Record ctx) err String
43 , stream :: Om (Record ctx) err (Strom {} () String)
45api = client @TestAPI "http://localhost:44933"
48spec = around withServer $ describe "String body on error responses" do
49 it "200 OK decodes the JSON response body" \_ -> do
51 { exception: \_ -> pure { doubled: -1 }
52 , badRequest: \_ -> pure { doubled: -1 }
54 (api.double { value: 21 })
55 liftAff $ result `shouldEqual` { doubled: 42 }
57 it "400 badRequest delivers the raw text body as a String" \serverMode -> do
58 liftEffect $ Ref.write "badRequest" serverMode
59 captured <- liftEffect $ Ref.new ""
61 { exception: \_ -> pure unit
62 , badRequest: \b -> liftEffect $ Ref.write b captured
64 (void $ api.double { value: 0 })
65 body <- liftEffect $ Ref.read captured
66 liftAff $ body `shouldEqual` "invalid value"
68 it "Simple.get returns plain text for String responses" \_ -> do
70 { exception: \e -> pure $ "exception: " <> Exn.message e
71 , fetchError: \e -> pure $ "fetch error: " <> e.body
73 (Simple.get @String "http://localhost:44933/plain-text-test/health" {})
74 liftAff $ result `shouldEqual` "healthy"
76 it "derived PlainText responses decode to String" \_ -> do
78 { exception: \e -> pure $ "exception: " <> Exn.message e }
80 liftAff $ result `shouldEqual` "healthy"
82 it "derived Streaming responses decode to a usable Strom" \_ -> do
84 { exception: \e -> pure [ "exception: " <> Exn.message e ] }
87 Strom.runCollect stream
88 liftAff $ String.joinWith "" chunks `shouldEqual` "stream €"
90withServer :: forall a. (Ref String -> Aff a) -> Aff a
91withServer test = bracket acquire release (\{ serverMode } -> test serverMode)
94 serverMode <- liftEffect $ Ref.new "ok"
95 fastify <- liftEffect do
97 omApp <- createOmFastify {} f
98 postOm (RouteURL "/plain-text-test/double") (handler serverMode) omApp
99 getOm (RouteURL "/plain-text-test/health") (plainTextHandler "healthy") omApp
100 getOm (RouteURL "/plain-text-test/stream") (plainTextHandler "stream €") omApp
102 void $ F.listen { port: Port 44933, host: Host "0.0.0.0" } fastify
103 pure { fastify, serverMode }
105 release { fastify } = F.close fastify
107 plainTextHandler text reply = do
108 void $ F.status (StatusCode 200) reply # liftEffect
109 void $ F.header "content-type" "text/plain" reply # liftEffect
110 F.send (unsafeToForeign text) reply # liftAff
112 handler serverMode reply = do
113 mode <- liftEffect $ Ref.read serverMode
116 void $ F.status (StatusCode 400) reply # liftEffect
117 void $ F.header "content-type" "text/plain" reply # liftEffect
118 F.send (unsafeToForeign "invalid value") reply # liftAff
120 void $ F.status (StatusCode 200) reply # liftEffect
121 void $ F.header "content-type" "application/json" reply # liftEffect
122 F.sendJson (unsafeToForeign { doubled: 42 }) reply # liftAff
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list