packages feed

getopt-generics-0.8: test/System/Console/GetOpt/Generics/FieldStringSpec.hs

{-# LANGUAGE ViewPatterns #-}

module System.Console.GetOpt.Generics.FieldStringSpec where

import           Data.Char
import           Test.Hspec
import           Test.QuickCheck hiding (Success)

import           System.Console.GetOpt.Generics.FieldString

normalize :: String -> String
normalize = normalized . mkFieldString

isValidInputChar :: Char -> Bool
isValidInputChar c = c `elem` ['A' .. 'Z'] ++ ['a' .. 'z'] ++ ['0' .. '9'] ++ "-_"

isAllowedOutputChar :: Char -> Bool
isAllowedOutputChar c = c `elem` ['a' .. 'z'] ++ ['0' .. '9'] ++ "-"

upperCaseChar :: Gen Char
upperCaseChar = elements ['A' .. 'Z']

spec :: Spec
spec = do
  describe "normalized" $ do
    it "is idempotent" $ do
      property $ \ x -> do
        let once = normalize x
            twice = normalize once
        once `shouldBe` twice

    it "replaces underscores with dashes" $ do
      normalize "foo_bar" `shouldBe` "foo-bar"

    it "doesn't modify digits" $ do
      normalize "foo2bar" `shouldBe` "foo2bar"

    it "when there's one valid character it returns only dashes and lower case characters" $ do
      property $ \ x ->
        any isValidInputChar x ==>
        normalize x `shouldSatisfy`
          (\ s -> all isAllowedOutputChar s)

    it "when there are no valid characters it returns its input" $ do
      property $ forAll (listOf (arbitrary `suchThat` (not . isValidInputChar))) $ \ x ->
        normalize x `shouldBe` x

    it "replaces camelCase with dashes" $ do
      let isValidPrefixChar c = c `elem` ['A' .. 'Z'] ++ ['a' .. 'z']
      property $
        \ prefix suffix ->
        (any isValidPrefixChar prefix) ==>
        forAll upperCaseChar $ \ upper ->
        counterexample (prefix ++ [upper] ++ suffix) $
        normalize (prefix ++ [upper] ++ suffix)
          `shouldBe`
            normalize prefix ++ "-" ++ normalize (toLower upper : suffix)

  describe "matches" $ do
    it "matches normalized strings" $ do
      property $ \ s ->
        normalize s `matches` mkFieldString s

    it "matches unnormalized strings" $ do
      property $ \ s ->
        s `matches` mkFieldString s

  describe "renameUnnormalized" $ do
    it "allows to rename the unnormalized field names" $ do
      let f "camelCaseFoo" = Just "caseFoo"
          f _ = Nothing
      normalized (renameUnnormalized f (mkFieldString "camelCaseFoo")) `shouldBe`
        "case-foo"

    it "doesn't allow to rename normalized field names" $ do
      let f "camel-case-foo" = Just "case-foo"
          f _ = Nothing
      normalized (renameUnnormalized f (mkFieldString "camelCaseFoo")) `shouldBe`
        "camel-case-foo"