nirum-0.1.0: test/Nirum/Constructs/IdentifierSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Nirum.Constructs.IdentifierSpec where
import Control.Exception (evaluate)
import Control.Monad (forM_)
import Data.Maybe (fromJust)
import Data.Text (Text)
import Test.Hspec.Meta
import Nirum.Constructs.Identifier ( Identifier
, fromText
, normalize
, toCamelCaseText
, toCode
, toLispCaseText
, toNormalizedString
, toNormalizedText
, toPascalCaseText
, toSnakeCaseText
, toString
, toText
, tokens
)
fromText' :: Text -> Identifier
fromText' = fromJust . fromText
getIdentifier :: Text -> Text
getIdentifier = toText . fromText'
getCode :: Text -> Text
getCode = toCode . fromText'
getNormalizedIdentifier :: Text -> Text
getNormalizedIdentifier = toText . normalize . fromText'
spec :: Spec
spec = do
describe "fromText" $ do
it "returns Nothing if identifier text is invalid" $ do
fromText "" `shouldBe` Nothing
fromText "-" `shouldBe` Nothing
fromText "1dentifier-cannot-start-with-digits" `shouldBe` Nothing
fromText "-identifier-cannot-start-with-hyphen" `shouldBe` Nothing
fromText "_identifier_cannot_start_with_underscore"
`shouldBe` Nothing
fromText "identifier-cannot-end-with-hyphen-" `shouldBe` Nothing
fromText "identifier_cannot_end_with_underscore_"
`shouldBe` Nothing
fromText "identifier-cannot-have-two--or---more---continued-hyphens"
`shouldBe` Nothing
fromText "identifier_cannot_have_two__or_more_continued_underscores"
`shouldBe` Nothing
fromText "무효한-식별자" `shouldBe` Nothing
fromText "invalid-식별자" `shouldBe` Nothing
fromText "identifier cannot contain whitepsaces" `shouldBe` Nothing
it "returns Just Identifier if nothing goes wrong" $ do
toText "datetime" `shouldBe` "datetime"
toText "person-name" `shouldBe` "person-name"
describe "tokens" $ do
it "returns tokens behind" $ do
tokens (fromText' "name") `shouldBe` ["name"]
tokens (fromText' "a-name") `shouldBe` ["a", "name"]
it "returns normalized tokens" $ do
tokens (fromText' "Name") `shouldBe` ["name"]
tokens (fromText' "A-Name") `shouldBe` ["a", "name"]
describe "normalize" $
it "returns normalized Identifier" $ do
getNormalizedIdentifier "name" `shouldBe` "name"
getNormalizedIdentifier "Name" `shouldBe` "name"
getNormalizedIdentifier "normalize_test" `shouldBe` "normalize-test"
describe "Identifier == Identifier" $ do
it "returns True if words are all the same" $ do
fromText "name" `shouldBe` fromText "name"
fromText "valid-name" `shouldBe` fromText "valid-name"
it "returns False if any word does not match" $ do
fromText "name" `shouldNotBe` fromText "nam"
fromText "a-name" `shouldNotBe` fromText "an-ame"
it "is case-insensitive" $ do
fromText "name" `shouldBe` fromText "Name"
fromText "Valid-Name" `shouldBe` fromText "valid-name"
fromText "valid_name" `shouldBe` fromText "valid-name"
describe "compare Identifier Identifier" $ do
it "returns Ordering in lexicographical order" $ do
compare ("aaaab" :: Identifier) "aaaac" `shouldBe` LT
compare ("aaaab" :: Identifier) "aaaaa" `shouldBe` GT
it "is case-insensitive" $ do
compare ("AAAAB" :: Identifier) "aaaac" `shouldBe` LT
compare ("aaaab" :: Identifier) "AAAAC" `shouldBe` LT
compare ("AAAAB" :: Identifier) "aaaaa" `shouldBe` GT
compare ("aaaab" :: Identifier) "AAAAA" `shouldBe` GT
describe "toCode Identifier" $ do
it "returns its code representation" $ do
getCode "name" `shouldBe` "name"
getCode "person-name" `shouldBe` "person-name"
it "quotes identifier if the identifier is a reserved keyword" $
getCode "enum" `shouldBe` "`enum`"
describe "fromString" $ do
it "overrides strings if it's a valid identifier" $ do
"name" `shouldBe` fromText' "name"
"valid-name" `shouldBe` fromText' "valid-name"
it "errors if it's a invalid identifier" $
evaluate ("-" :: Identifier) `shouldThrow`
errorCall "invalid identifier: -"
describe "toString" $
it "behaves same as toText except its return type is [Char]" $
toString (fromText' "asdf") `shouldBe` ("asdf" :: String)
describe "toNormalizedText Identifier" $ do
let normalizers = [ toNormalizedText
, toLispCaseText
] :: [Identifier -> Text]
forM_ normalizers $ \normalizer -> do
it "returns lowercased identifier text" $ do
normalizer "IDENTIFIER" `shouldBe` "identifier"
normalizer "Identifier" `shouldBe` "identifier"
it "replaces underscores with hyphens" $ do
normalizer "valid_identifier" `shouldBe` "valid-identifier"
normalizer "Valid_Identifier" `shouldBe` "valid-identifier"
describe "toNormalizedString Identifier" $ do
it "returns lowercased identifier string" $ do
toNormalizedString "IDENTIFIER" `shouldBe` "identifier"
toNormalizedString "Identifier" `shouldBe` "identifier"
it "replaces underscores with hyphens" $ do
toNormalizedString "valid_identifier" `shouldBe` "valid-identifier"
toNormalizedString "Valid_Identifier" `shouldBe` "valid-identifier"
describe "toPascalCaseText Identifier" $
it "returns PascalCase-ed identifier string" $ do
toPascalCaseText (fromText' "pascal-case") `shouldBe` "PascalCase"
toPascalCaseText (fromText' "PASCAL-CASE") `shouldBe` "PascalCase"
toPascalCaseText (fromText' "pascal_case") `shouldBe` "PascalCase"
toPascalCaseText (fromText' "PASCAL_CASE") `shouldBe` "PascalCase"
describe "toCamelCaseText Identifier" $
it "returns camelCase-ed identifier string" $ do
toCamelCaseText (fromText' "camel-case") `shouldBe` "camelCase"
toCamelCaseText (fromText' "CAMEL-CASE") `shouldBe` "camelCase"
toCamelCaseText (fromText' "camel_case") `shouldBe` "camelCase"
toCamelCaseText (fromText' "CAMEL_CASE") `shouldBe` "camelCase"
describe "toSnakeCaseText Identifier" $
it "returns snake_case-ed identifier string" $ do
toSnakeCaseText (fromText' "snake-case") `shouldBe` "snake_case"
toSnakeCaseText (fromText' "SNAKE-CASE") `shouldBe` "snake_case"
toSnakeCaseText (fromText' "snake_case") `shouldBe` "snake_case"
toSnakeCaseText (fromText' "SNAKE_CASE") `shouldBe` "snake_case"