packages feed

json-api-lib-0.1.0.0: test/Network/JSONApi/DocumentSpec.hs

module Network.JSONApi.DocumentSpec where

import Control.Lens ((^?))

import           Data.Aeson (ToJSON)
import qualified Data.Aeson as AE
import qualified Data.Aeson.Lens as Lens
import           Data.ByteString.Lazy.Char8 (ByteString)
import           Data.Either (isRight)
import           Data.Maybe

import           Network.JSONApi

import           TestHelpers
import           Test.Hspec

main :: IO ()
main = hspec spec

spec :: Spec
spec =
  describe "JSON serialization" $ do
    it "JSON encodes/decodes a singleton resource" $ do
      -- TODO: test the main resource actually is a singleton
      let jsonApiObj = mkDocument [testObject] Nothing Nothing
          encodedJson = encodeDocumentObject jsonApiObj
          decodedJson = decodeDocumentObject encodedJson

      isRight decodedJson `shouldBe` True

    it "JSON encodes/decodes a list of resources" $ do
      -- TODO: test the main resource actually is a list
      let jsonApiObj = mkDocument [testObject, testObject2] Nothing Nothing
          encodedJson = encodeDocumentObject jsonApiObj
          decodedJson = decodeDocumentObject encodedJson

      isRight decodedJson `shouldBe` True

    it "contains the allowable top-level keys" $ do
      let jsonApiObj = mkDocument [testObject] Nothing Nothing
          encodedJson = encodeDocumentObject jsonApiObj
          dataObject = encodedJson ^? Lens.key "data"
          linksObject = encodedJson ^? Lens.key "links"
          metaObject = encodedJson ^? Lens.key "meta"
          includedObject = encodedJson ^? Lens.key "included"

      isJust dataObject `shouldBe` True
      isJust linksObject `shouldBe` True
      isJust metaObject `shouldBe` True
      isJust includedObject `shouldBe` True

    it "allows an optional top-level links object" $ do
      let jsonApiObj = mkDocument [testObject] (Just linksObj) Nothing
          encodedJson = encodeDocumentObject jsonApiObj
          decodedJson = decodeDocumentObject encodedJson

      isRight decodedJson `shouldBe` True

    it "allows an optional top-level meta object" $ do
      let jsonApiObj = mkDocument [testObject] Nothing (Just testMetaObj)
          encodedJson = encodeDocumentObject jsonApiObj
          decodedJson = decodeDocumentObject encodedJson

      isRight decodedJson `shouldBe` True

    it "allows a heterogeneous list of related resources" $ do
      let includedResources = mkIncludedResource testObject
          jsonApiObj = mkCompoundDocument [testObject] Nothing Nothing includedResources
          encodedJson = encodeDocumentObject jsonApiObj
          decodedJson = decodeDocumentObject encodedJson

      isRight decodedJson `shouldBe` True

decodeDocumentObject :: ByteString -> Either String (Document TestResource)
decodeDocumentObject = AE.eitherDecode

encodeDocumentObject :: (ToJSON a) => Document a -> ByteString
encodeDocumentObject = prettyEncode