packages feed

linnet-0.1.0.0: test/ParamSpec.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications  #-}

module ParamSpec where

import           Control.Exception          (SomeException, fromException,
                                             toException)
import qualified Data.ByteString            as BS
import           Data.ByteString.Conversion (ToByteString, toByteString')
import           Data.Functor.Identity      (Identity)
import           Data.List.NonEmpty         (NonEmpty (..))
import qualified Data.Text                  as T
import           EntityEndpointLaws
import           Instances
import           Linnet
import           Linnet.Endpoints.Entity
import           Linnet.Errors
import           Linnet.Input
import           Test.Hspec
import           Util

withParam :: (ToByteString a) => BS.ByteString -> a -> Input
withParam key a = inputGet "/" [(key, Just $ toByteString' a)]

spec :: Spec
spec = do
  checkLaws "ByteString" $ entityEndpointLaws @BS.ByteString @(Either SomeException) (param "x") (withParam "x")
  checkLaws "Text" $ entityEndpointLaws @T.Text @(Either SomeException) (param "x") (withParam "x")
  checkLaws "Int" $ entityEndpointLaws @Int @(Either SomeException) (param "x") (withParam "x")
  checkLaws "Double" $ entityEndpointLaws @Double @(Either SomeException) (param "x") (withParam "x")
  checkLaws "Float" $ entityEndpointLaws @Float @(Either SomeException) (param "x") (withParam "x")
  it "throws an error if param is missing" $ do
    let e = param @BS.ByteString @IO "foo"
    result <- resultOutputEither (runEndpoint e (inputGet "/" []))
    result `shouldBe` (Left $ toException (MissingEntity (Param "foo")))
  it "throws an error if param is malformed" $ do
    let e = param @Int @IO "foo"
    result <- resultOutputEither (runEndpoint e (inputGet "/" [("foo", Just "bar")]))
    result `shouldBe` (Left $ toException (EntityNotParsed (Param "foo") (DecodeError "Failed reading: Invalid Int")))
  it "collect errors in params & paramsNel" $ do
    let ps = params @Int @IO "test"
    let psNel = paramsNel @Int @IO "test"
    let exception = LinnetErrors $ EntityNotParsed (Param "test") (DecodeError "Failed reading: Invalid Int") :| []
    let i = inputGet "/" [("test", Just "foo")]
    result <- resultOutputEither (runEndpoint ps i)
    result `shouldBe` (Left $ toException exception)
    result' <- resultOutputEither (runEndpoint psNel i)
    result' `shouldBe` (Left $ toException exception)
  it "returns nothing if param is not required" $ do
    let e = paramMaybe @BS.ByteString @IO "foo"
    result <- resultOutputEither (runEndpoint e (inputGet "/" []))
    result `shouldBe` (Right $ Just $ ok Nothing)