packages feed

graphql-0.7.0.0: tests/Language/GraphQL/AST/EncoderSpec.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module Language.GraphQL.AST.EncoderSpec
    ( spec
    ) where

import Language.GraphQL.AST
import Language.GraphQL.AST.Encoder
import Test.Hspec (Spec, context, describe, it, shouldBe, shouldStartWith, shouldEndWith, shouldNotContain)
import Test.QuickCheck (choose, oneof, forAll)
import Text.RawString.QQ (r)
import Data.Text.Lazy (cons, toStrict, unpack)

spec :: Spec
spec = do
    describe "value" $ do
        context "null value" $ do
            let testNull formatter = value formatter Null `shouldBe` "null"
            it "minified" $ testNull minified
            it "pretty" $ testNull pretty

        context "minified" $ do
            it "escapes \\" $
                value minified (String "\\") `shouldBe` "\"\\\\\""
            it "escapes double quotes" $
                value minified (String "\"") `shouldBe` "\"\\\"\""
            it "escapes \\f" $
                value minified (String "\f") `shouldBe` "\"\\f\""
            it "escapes \\n" $
                value minified (String "\n") `shouldBe` "\"\\n\""
            it "escapes \\r" $
                value minified (String "\r") `shouldBe` "\"\\r\""
            it "escapes \\t" $
                value minified (String "\t") `shouldBe` "\"\\t\""
            it "escapes backspace" $
                value minified (String "a\bc") `shouldBe` "\"a\\bc\""
            context "escapes Unicode for chars less than 0010" $ do
                it "Null" $ value minified (String "\x0000") `shouldBe` "\"\\u0000\""
                it "bell" $ value minified (String "\x0007") `shouldBe` "\"\\u0007\""
            context "escapes Unicode for char less than 0020" $ do
                it "DLE" $ value minified (String "\x0010") `shouldBe` "\"\\u0010\""
                it "EM" $ value minified (String "\x0019") `shouldBe` "\"\\u0019\""
            context "encodes without escape" $ do
                it "space" $ value minified (String "\x0020") `shouldBe` "\" \""
                it "~" $ value minified (String "\x007E") `shouldBe` "\"~\""

        context "pretty" $ do
            it "uses strings for short string values" $
                value pretty (String "Short text") `shouldBe` "\"Short text\""
            it "uses block strings for text with new lines, with newline symbol" $
                value pretty (String "Line 1\nLine 2")
                    `shouldBe` [r|"""
  Line 1
  Line 2
"""|]
            it "uses block strings for text with new lines, with CR symbol" $
                value pretty (String "Line 1\rLine 2")
                    `shouldBe` [r|"""
  Line 1
  Line 2
"""|]
            it "uses block strings for text with new lines, with CR symbol followed by newline" $
                value pretty (String "Line 1\r\nLine 2")
                    `shouldBe` [r|"""
  Line 1
  Line 2
"""|]
            it "encodes as one line string if has escaped symbols" $ do
                let
                  genNotAllowedSymbol = oneof
                    [ choose ('\x0000', '\x0008')
                    , choose ('\x000B', '\x000C')
                    , choose ('\x000E', '\x001F')
                    , pure '\x007F'
                    ]

                forAll genNotAllowedSymbol $ \x -> do
                    let
                      rawValue = "Short \n" <> cons x "text"
                      encoded = value pretty (String $ toStrict rawValue)
                    shouldStartWith (unpack encoded) "\""
                    shouldEndWith (unpack encoded) "\""
                    shouldNotContain (unpack encoded) "\"\"\""

            it "Hello world" $ value pretty (String "Hello,\n  World!\n\nYours,\n  GraphQL.")
              `shouldBe` [r|"""
  Hello,
    World!

  Yours,
    GraphQL.
"""|]

            it "has only newlines" $ value pretty (String "\n") `shouldBe` [r|"""


"""|]
            it "has newlines and one symbol at the begining" $
              value pretty (String "a\n\n") `shouldBe` [r|"""
  a


"""|]
            it "has newlines and one symbol at the end" $
              value pretty (String "\n\na") `shouldBe` [r|"""


  a
"""|]
            it "has newlines and one symbol in the middle" $
              value pretty (String "\na\n") `shouldBe` [r|"""

  a

"""|]
            it "skip trailing whitespaces" $ value pretty (String "  Short\ntext    ")
              `shouldBe` [r|"""
  Short
  text
"""|]

    describe "definition" $
        it "indents block strings in arguments" $
            let arguments = [Argument "message" (String "line1\nline2")]
                field = Field Nothing "field" arguments [] []
                operation = DefinitionOperation $ SelectionSet $ pure field
             in definition pretty operation `shouldBe` [r|{
  field(message: """
    line1
    line2
  """)
}
|]