{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Network.Lastfm.ResponseSpec (spec) where
import Control.Exception (ArithException(..), throwIO, try)
import Control.Exception.Lens
import Control.Lens
import Data.Aeson (Value)
import Data.ByteString.Lazy (ByteString)
import Data.Aeson.Lens
import Test.Hspec.Lens
import Text.Xml.Lens
import Network.HTTP.Client (HttpException(..))
import Network.Lastfm.Response
instance Eq HttpException where
  _ == _ = True
spec :: Spec
spec = do
  describe "md5" $ do
    it "calculates the right hash for an empty string" $
      md5 "" `shouldBe` "d41d8cd98f00b204e9800998ecf8427e"
    it "calculates the right hash for an ascii string" $
      md5 "Enduser" `shouldBe` "28ced1fafec20ae302a04e9f27f4800f"
    it "calculates the right hash for a unicode string" $
      md5 "ДМИТРИЙ МАЛИКОВ" `shouldBe` "e02e5affef1004a02d9762619dc2a585"
  describe "try for LastfmError" $ do
    let tryLastfmError :: IO a -> IO (Either LastfmError a)
        tryLastfmError = try
    it "catches 'HttpException'" $ do
      val <- tryLastfmError (throwIO ResponseTimeout) :: IO (Either LastfmError ())
      val `shouldHave` _Left._LastfmHttpError.only ResponseTimeout
    it "does not catch other exceptions" $
      tryLastfmError (throwIO DivideByZero) `shouldThrow` _DivideByZero
  describe "parse" $ do
    context "JSON" $ do
      let parseJSON :: ByteString -> Either LastfmError Value
          parseJSON = parse
      it "handles good input" $
        let
          good = "{ \"a\": { \"b\": 4 } }"
        in
          parseJSON good `shouldHave` _Right.key "a".key "b"._Integer.only 4
      it "handles malformed input" $
        let
          malformed = "not a json"
        in
          parseJSON malformed `shouldHave` _Left._LastfmBadResponse.only malformed
      it "handles input with encoded errors" $
        let
          encodedError = "{ \"error\": 5, \"message\": \"foo\" }"
        in
          parseJSON encodedError `shouldHave` _Left._LastfmEncodedError.only (5, "foo")
    context "XML" $ do
      let parseXML :: ByteString -> Either LastfmError Document
          parseXML = parse
      it "handles good input" $
        let
          good = "baz"
        in
          parseXML good `shouldHave` _Right.root.node "foo".node "bar".text.only "baz"
      it "handles malformed input" $
        let
          malformed = "not a xml"
        in
          parseXML malformed `shouldHave` _Left._LastfmBadResponse.only malformed
      it "handles input with encoded errors" $
        let
          encodedError = "foo"
        in
          parseXML encodedError `shouldHave` _Left._LastfmEncodedError.only (5, "foo")