Skip to content

Commit 28076d4

Browse files
committed
Add spec for serverLayout
1 parent 043ede7 commit 28076d4

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

servant-server/test/Servant/Server/RouterSpec.hs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ spec :: Spec
2929
spec = describe "Servant.Server.Internal.Router" $ do
3030
routerSpec
3131
distributivitySpec
32+
serverLayoutSpec
3233

3334
routerSpec :: Spec
3435
routerSpec = do
@@ -103,12 +104,30 @@ distributivitySpec =
103104
it "properly handles mixing static paths at different levels" $ do
104105
level `shouldHaveSameStructureAs` levelRef
105106

107+
serverLayoutSpec :: Spec
108+
serverLayoutSpec =
109+
describe "serverLayout" $ do
110+
it "correctly represents the example API" $ do
111+
exampleLayout `shouldHaveLayout` expectedExampleLayout
112+
it "aggregates capture hints when different" $ do
113+
dynamic `shouldHaveLayout` expectedDynamicLayout
114+
it "nubs capture hints when equal" $ do
115+
dynamicSameType `shouldHaveLayout` expectedDynamicSameTypeLayout
116+
it "properly displays CaptureAll hints" $ do
117+
captureAllLayout `shouldHaveLayout` expectedCaptureAllLayout
118+
106119
shouldHaveSameStructureAs ::
107120
(HasServer api1 '[], HasServer api2 '[]) => Proxy api1 -> Proxy api2 -> Expectation
108121
shouldHaveSameStructureAs p1 p2 =
109122
unless (sameStructure (makeTrivialRouter p1) (makeTrivialRouter p2)) $
110123
expectationFailure ("expected:\n" ++ unpack (layout p2) ++ "\nbut got:\n" ++ unpack (layout p1))
111124

125+
shouldHaveLayout ::
126+
(HasServer api '[]) => Proxy api -> Text -> Expectation
127+
shouldHaveLayout p l =
128+
unless (routerLayout (makeTrivialRouter p) == l) $
129+
expectationFailure ("expected:\n" ++ unpack l ++ "\nbut got:\n" ++ unpack (layout p))
130+
112131
makeTrivialRouter :: (HasServer layout '[]) => Proxy layout -> Router ()
113132
makeTrivialRouter p =
114133
route p EmptyContext (emptyDelayed (FailFatal err501))
@@ -344,3 +363,90 @@ level = Proxy
344363

345364
levelRef :: Proxy LevelRef
346365
levelRef = Proxy
366+
367+
-- The example API for the 'layout' function.
368+
-- Should get factorized by the 'choice' smart constructor.
369+
type ExampleLayout =
370+
"a" :> "d" :> Get '[JSON] NoContent
371+
:<|> "b" :> Capture "x" Int :> Get '[JSON] Bool
372+
:<|> "c" :> Put '[JSON] Bool
373+
:<|> "a" :> "e" :> Get '[JSON] Int
374+
:<|> "b" :> Capture "x" Int :> Put '[JSON] Bool
375+
:<|> Raw
376+
377+
exampleLayout :: Proxy ExampleLayout
378+
exampleLayout = Proxy
379+
380+
-- The expected representation of the example API layout
381+
--
382+
expectedExampleLayout :: Text
383+
expectedExampleLayout =
384+
"/\n\
385+
\├─ a/\n\
386+
\│ ├─ d/\n\
387+
\│ │ └─•\n\
388+
\│ └─ e/\n\
389+
\│ └─•\n\
390+
\├─ b/\n\
391+
\│ └─ <x::Int>/\n\
392+
\│ ├─•\n\
393+
\│ ┆\n\
394+
\│ └─•\n\
395+
\├─ c/\n\
396+
\│ └─•\n\
397+
\┆\n\
398+
\└─ <raw>\n"
399+
400+
-- The expected representation of the Dynamic API layout.
401+
--
402+
expectedDynamicLayout :: Text
403+
expectedDynamicLayout =
404+
"/\n\
405+
\└─ a/\n\
406+
\ └─ <foo::Int|bar::Bool|baz::Char>/\n\
407+
\ ├─ b/\n\
408+
\ │ └─•\n\
409+
\ ├─ c/\n\
410+
\ │ └─•\n\
411+
\ └─ d/\n\
412+
\ └─•\n"
413+
414+
-- The same Dynamic API as above, except that the captured
415+
-- values have the same hints
416+
type DynamicSameType =
417+
"a" :> Capture "foo" Int :> "b" :> End
418+
:<|> "a" :> Capture "foo" Int :> "c" :> End
419+
:<|> "a" :> Capture "foo" Int :> "d" :> End
420+
421+
dynamicSameType :: Proxy DynamicSameType
422+
dynamicSameType = Proxy
423+
424+
-- The expected representation of the DynamicSameType API layout.
425+
--
426+
expectedDynamicSameTypeLayout :: Text
427+
expectedDynamicSameTypeLayout =
428+
"/\n\
429+
\└─ a/\n\
430+
\ └─ <foo::Int>/\n\
431+
\ ├─ b/\n\
432+
\ │ └─•\n\
433+
\ ├─ c/\n\
434+
\ │ └─•\n\
435+
\ └─ d/\n\
436+
\ └─•\n"
437+
438+
-- An API with a CaptureAll part
439+
440+
type CaptureAllLayout = "a" :> CaptureAll "foos" Int :> End
441+
442+
captureAllLayout :: Proxy CaptureAllLayout
443+
captureAllLayout = Proxy
444+
445+
-- The expected representation of the CaptureAllLayout API.
446+
--
447+
expectedCaptureAllLayout :: Text
448+
expectedCaptureAllLayout =
449+
"/\n\
450+
\└─ a/\n\
451+
\ └─ <foos::[Int]>/\n\
452+
\ └─•\n"

0 commit comments

Comments
 (0)