packages feed

css-selectors-0.4.0.0: test/Spec.hs

{-# LANGUAGE TypeApplications #-}

import Css3.Selector
import Css3.Selector.Utils(encodeString, readCssString)

import Data.Binary(Binary, encode, decode)
import Data.Function(on)
import Data.Hashable(Hashable(hashWithSalt))
import Data.Text(pack, unpack)

import Test.Framework (defaultMain, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck

main :: IO ()
main = defaultMain tests

tests = [
    testGroup "Encode-decode strings" [
        testProperty "Encode-decode identity 1" (encodeDecode '"'),
        testProperty "Encode-decode identity 2" (encodeDecode '\''),
        testProperty "Encode-decode identifier" encodeDecodeId
    ],
    testGroup "Arbitrary css parsing" [
        testProperty "Encode-decode css identity" encodeDecodeCss,
        testProperty "Encode-decode css identity: selector group" (encodeDecodeCss' @SelectorGroup),
        testProperty "Encode-decode css identity: selector" (encodeDecodeCss' @Selector),
        testProperty "Encode-decode css identity: selector sequence" (encodeDecodeCss' @SelectorSequence),
        testProperty "Encode-decode css identity: selector filter" (encodeDecodeCss' @SelectorFilter),
        testProperty "Encode-decode css identity: namespace" (encodeDecodeCss' @Namespace),
        testProperty "Encode-decode css identity: element name" (encodeDecodeCss' @ElementName),
        testProperty "Encode-decode css identity: type selector" (encodeDecodeCss' @TypeSelector),
        testProperty "Encode-decode css identity: attribute" (encodeDecodeCss' @Attrib),
        testProperty "Encode-decode css identity: attribute name" (encodeDecodeCss' @AttributeName),
        testProperty "Encode-decode css identity: class" (encodeDecodeCss' @Class),
        testProperty "Encode-decode css identity: hash" (encodeDecodeCss' @Hash)
    ],
    testGroup "SelectorSequences" [
        testProperty "Adding and removing filters" addRemFilters
    ],
    testGroup "Normalization" [
        testProperty "Normalized variant has the same specificity" normSpec,
        testProperty "Normalization is idempotent" normIdem
    ],
    testGroup "Build an expression or pattern" [
        testProperty "Check build of pattern 1" buildPattern1,
        testProperty "Check build of pattern 2" buildPattern2
    ],
    testGroup "Convert to binary and back" [
        testProperty "Binary identity: selector group" (binaryEquivalent @SelectorGroup),
        testProperty "Binary identity: selector" (binaryEquivalent @Selector),
        testProperty "Binary identity: selector sequence" (binaryEquivalent @SelectorSequence),
        testProperty "Binary identity: selector filter" (binaryEquivalent @SelectorFilter),
        testProperty "Binary identity: namespace" (binaryEquivalent @Namespace),
        testProperty "Binary identity: element name" (binaryEquivalent @ElementName),
        testProperty "Binary identity: type selector" (binaryEquivalent @TypeSelector),
        testProperty "Binary identity: attribute" (binaryEquivalent @Attrib),
        testProperty "Binary identity: attribute name" (binaryEquivalent @AttributeName),
        testProperty "Binary identity: class" (binaryEquivalent @Class),
        testProperty "Binary identity: hash" (binaryEquivalent @Hash)
    ],
    testGroup "Check binary equality" [
        testProperty "Binary uniqness: selector group" (uniqnessEncoding @SelectorGroup),
        testProperty "Binary uniqness: selector" (uniqnessEncoding @Selector),
        testProperty "Binary uniqness: selector sequence" (uniqnessEncoding @SelectorSequence),
        testProperty "Binary uniqness: selector filter" (uniqnessEncoding @SelectorFilter),
        testProperty "Binary uniqness: namespace" (uniqnessEncoding @Namespace),
        testProperty "Binary uniqness: element name" (uniqnessEncoding @ElementName),
        testProperty "Binary uniqness: type selector" (uniqnessEncoding @TypeSelector),
        testProperty "Binary uniqness: attribute" (uniqnessEncoding @Attrib),
        testProperty "Binary uniqness: attribute name" (uniqnessEncoding @AttributeName),
        testProperty "Binary uniqness: class" (uniqnessEncoding @Class),
        testProperty "Binary uniqness: hash" (uniqnessEncoding @Hash)
    ],
    testGroup "Check hash constraint for the Hashable instances" [
        testProperty "Different hash implies different items: selector group" (hashingDifferent @SelectorGroup),
        testProperty "Different hash implies different items: selector" (hashingDifferent @Selector),
        testProperty "Different hash implies different items: selector sequence" (hashingDifferent @SelectorSequence),
        testProperty "Different hash implies different items: selector filter" (hashingDifferent @SelectorFilter),
        testProperty "Different hash implies different items: namespace" (hashingDifferent @Namespace),
        testProperty "Different hash implies different items: element name" (hashingDifferent @ElementName),
        testProperty "Different hash implies different items: type selector" (hashingDifferent @TypeSelector),
        testProperty "Different hash implies different items: attribute" (hashingDifferent @Attrib),
        testProperty "Different hash implies different items: attribute name" (hashingDifferent @AttributeName),
        testProperty "Different hash implies different items: class" (hashingDifferent @Class),
        testProperty "Different hash implies different items: hash" (hashingDifferent @Hash)
    ]
  ]

encodeDecode :: Char -> String -> Bool
encodeDecode c b = readCssString (encodeString c b) == b

encodeDecodeId :: String -> Bool
encodeDecodeId b = readIdentifier (unpack (encodeIdentifier (pack b))) == b

encodeDecodeCss :: SelectorGroup -> Bool
encodeDecodeCss sg = sg == (parseCss . unpack . toCssSelector) sg

binaryEquivalent :: (Binary a, Eq a, ToCssSelector a) => a -> Bool
binaryEquivalent x = decode (encode x) == x

hashingDifferent :: (Hashable a, Eq a) => Int -> a -> a -> Bool
hashingDifferent slt xa xb = (hashWithSalt slt xa == hashWithSalt slt xb) || (xa /= xb)

uniqnessEncoding :: (Binary a, Eq a, ToCssSelector a) => a -> a -> Bool
uniqnessEncoding ca cb = (encode ca == encode cb) == (ca == cb)

encodeDecodeCss' :: ToCssSelector a => a -> Bool
encodeDecodeCss' sg = (parseCss . unpack . toCssSelector . toSelectorGroup) sg == toSelectorGroup sg

buildPattern1 :: SelectorGroup -> Bool
buildPattern1 x = toPattern x == toPattern x -- we use equality checks to force evaluation

buildPattern2 :: SelectorGroup -> SelectorGroup -> Bool
buildPattern2 x y = (x == y) == (toPattern x == toPattern y)

addRemFilters :: TypeSelector -> [SelectorFilter] -> Bool
addRemFilters x fs = filters (addFilters (SimpleSelector x) fs) == fs

normSpec :: SelectorGroup -> Bool
normSpec x = specificity' x == specificity' nx
    where nx = normalize x

normIdem :: SelectorGroup -> Bool
normIdem x = normalize nx == nx
    where nx = normalize x