packages feed

method-0.4.0.0: test/Test/Method/LabelSpec.hs

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

--{-# OPTIONS_GHC -ddump-splices -ddump-simpl -ddump-to-file #-}

module Test.Method.LabelSpec where

import Data.Typeable (typeRep)
import RIO
  ( Display (textDisplay),
    Proxy (Proxy),
    RIO,
    Text,
    Typeable,
    displayShow,
    runRIO,
  )
import Test.Hspec (Spec, describe, it, shouldBe, shouldReturn)
import Test.Method.Label
  ( Label (toInterface),
    deriveLabel,
    type (:|:) (L, R),
  )

data API env = API
  { _foo :: RIO env Int,
    _bar :: Text -> RIO env Text,
    _baz :: forall a. Typeable a => (Int, Bool) -> RIO env [a]
  }

deriveLabel ''API

data FizzBuzz env = FizzBuzz
  { _fizz :: RIO env Text,
    _buzz :: RIO env Text,
    _others :: forall a. (Show a, Typeable a) => a -> RIO env Text
  }

deriveLabel ''FizzBuzz

spec :: Spec
spec = do
  describe "deriveLabel ''API" $ do
    describe "APILabel" $ do
      it "Foo is defined" $ do
        typeRep (Foo @()) `shouldBe` typeRep (Proxy :: Proxy (RIO () Int))
      it "Bar is defined" $ do
        typeRep (Bar @()) `shouldBe` typeRep (Proxy :: Proxy (Text -> RIO () Text))
    describe "toRecord" $ do
      let api = toInterface mock
      it "_foo api returns 0" $ do
        runRIO () (_foo api) `shouldReturn` 0
      it "_bar api \"hello\" returns \"hello hoge\"" $ do
        runRIO () (_bar api "hello") `shouldReturn` "hello hoge"
  describe "(:|:)" $ do
    let (api, fizzbuzz) = toInterface mock2
    it "_foo api returns 1" $ do
      runRIO () (_foo api) `shouldReturn` 1
    it "_fizz fizzbuzz returns \"Fizz\"" $ do
      runRIO () (_fizz fizzbuzz) `shouldReturn` "Fizz"
    it "_others fizzbuzz 10 returns \"<<10 :: Int>>\"" $ do
      runRIO () (_others fizzbuzz (10 :: Int)) `shouldReturn` "<<10 :: Int>>"

mock :: APILabel env m -> m
mock Foo = pure 0
mock Bar = \x -> pure (x <> " hoge")
mock Baz = undefined

mock2 :: (:|:) (APILabel env) (FizzBuzzLabel env) m -> m
mock2 (L Foo) = pure 1
mock2 (L Bar) = \x -> pure (x <> " bar")
mock2 (L Baz) = undefined
mock2 (R Fizz) = pure "Fizz"
mock2 (R Buzz) = pure "Buzz"
mock2 (R Others) = pure . textDisplay . displayShow