hsass 0.3.0 → 0.4.0
raw patch · 9 files changed
+422/−3 lines, 9 filesdep ~hlibsassPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hlibsass
API changes (from Hackage documentation)
- Text.Sass.Compilation: instance Eq SassError
- Text.Sass.Compilation: instance SassResult ByteString
- Text.Sass.Compilation: instance SassResult String
- Text.Sass.Compilation: instance SassResult a => SassResult (SassExtendedResult a)
- Text.Sass.Compilation: instance Show (SassExtendedResult a)
- Text.Sass.Compilation: instance Show SassError
- Text.Sass.Functions: funcComputation :: SassFunction -> SassFunctionType
- Text.Sass.Functions: funcSignature :: SassFunction -> String
- Text.Sass.Functions: importBase :: SassImport -> Maybe FilePath
- Text.Sass.Functions: importPath :: SassImport -> Maybe FilePath
- Text.Sass.Functions: importSource :: SassImport -> Maybe String
- Text.Sass.Functions: importSourceMap :: SassImport -> Maybe String
- Text.Sass.Functions: importerFunction :: SassImporter -> SassImporterType
- Text.Sass.Functions: importerPriority :: SassImporter -> Double
- Text.Sass.Options: instance Default SassOptions
- Text.Sass.Options: sassFunctions :: SassOptions -> Maybe [SassFunction]
- Text.Sass.Options: sassHeaders :: SassOptions -> Maybe [SassImporter]
- Text.Sass.Options: sassImporters :: SassOptions -> Maybe [SassImporter]
- Text.Sass.Options: sassIncludePaths :: SassOptions -> Maybe [FilePath]
- Text.Sass.Options: sassIndent :: SassOptions -> String
- Text.Sass.Options: sassInputPath :: SassOptions -> Maybe FilePath
- Text.Sass.Options: sassIsIndentedSyntax :: SassOptions -> Bool
- Text.Sass.Options: sassLinefeed :: SassOptions -> String
- Text.Sass.Options: sassOmitSourceMapUrl :: SassOptions -> Bool
- Text.Sass.Options: sassOutputPath :: SassOptions -> Maybe FilePath
- Text.Sass.Options: sassOutputStyle :: SassOptions -> SassOutputStyle
- Text.Sass.Options: sassPluginPaths :: SassOptions -> Maybe [FilePath]
- Text.Sass.Options: sassPrecision :: SassOptions -> Int
- Text.Sass.Options: sassSourceComments :: SassOptions -> Bool
- Text.Sass.Options: sassSourceMapContents :: SassOptions -> Bool
- Text.Sass.Options: sassSourceMapEmbed :: SassOptions -> Bool
- Text.Sass.Options: sassSourceMapFile :: SassOptions -> Maybe FilePath
- Text.Sass.Options: sassSourceMapRoot :: SassOptions -> Maybe String
- Text.Sass.Values: instance Eq SassValue
- Text.Sass.Values: sassColorA :: SassValue -> Double
- Text.Sass.Values: sassColorB :: SassValue -> Double
- Text.Sass.Values: sassColorG :: SassValue -> Double
- Text.Sass.Values: sassColorR :: SassValue -> Double
+ Text.Sass.Compilation: instance GHC.Classes.Eq Text.Sass.Compilation.SassError
+ Text.Sass.Compilation: instance GHC.Show.Show (Text.Sass.Compilation.SassExtendedResult a)
+ Text.Sass.Compilation: instance GHC.Show.Show Text.Sass.Compilation.SassError
+ Text.Sass.Compilation: instance Text.Sass.Compilation.SassResult Data.ByteString.Internal.ByteString
+ Text.Sass.Compilation: instance Text.Sass.Compilation.SassResult GHC.Base.String
+ Text.Sass.Compilation: instance Text.Sass.Compilation.SassResult a => Text.Sass.Compilation.SassResult (Text.Sass.Compilation.SassExtendedResult a)
+ Text.Sass.Functions: [funcComputation] :: SassFunction -> SassFunctionType
+ Text.Sass.Functions: [funcSignature] :: SassFunction -> String
+ Text.Sass.Functions: [importBase] :: SassImport -> Maybe FilePath
+ Text.Sass.Functions: [importPath] :: SassImport -> Maybe FilePath
+ Text.Sass.Functions: [importSourceMap] :: SassImport -> Maybe String
+ Text.Sass.Functions: [importSource] :: SassImport -> Maybe String
+ Text.Sass.Functions: [importerFunction] :: SassImporter -> SassImporterType
+ Text.Sass.Functions: [importerPriority] :: SassImporter -> Double
+ Text.Sass.Options: [sassFunctions] :: SassOptions -> Maybe [SassFunction]
+ Text.Sass.Options: [sassHeaders] :: SassOptions -> Maybe [SassImporter]
+ Text.Sass.Options: [sassImporters] :: SassOptions -> Maybe [SassImporter]
+ Text.Sass.Options: [sassIncludePaths] :: SassOptions -> Maybe [FilePath]
+ Text.Sass.Options: [sassIndent] :: SassOptions -> String
+ Text.Sass.Options: [sassInputPath] :: SassOptions -> Maybe FilePath
+ Text.Sass.Options: [sassIsIndentedSyntax] :: SassOptions -> Bool
+ Text.Sass.Options: [sassLinefeed] :: SassOptions -> String
+ Text.Sass.Options: [sassOmitSourceMapUrl] :: SassOptions -> Bool
+ Text.Sass.Options: [sassOutputPath] :: SassOptions -> Maybe FilePath
+ Text.Sass.Options: [sassOutputStyle] :: SassOptions -> SassOutputStyle
+ Text.Sass.Options: [sassPluginPaths] :: SassOptions -> Maybe [FilePath]
+ Text.Sass.Options: [sassPrecision] :: SassOptions -> Int
+ Text.Sass.Options: [sassSourceComments] :: SassOptions -> Bool
+ Text.Sass.Options: [sassSourceMapContents] :: SassOptions -> Bool
+ Text.Sass.Options: [sassSourceMapEmbed] :: SassOptions -> Bool
+ Text.Sass.Options: [sassSourceMapFile] :: SassOptions -> Maybe FilePath
+ Text.Sass.Options: [sassSourceMapRoot] :: SassOptions -> Maybe String
+ Text.Sass.Options: instance Data.Default.Class.Default Text.Sass.Options.SassOptions
+ Text.Sass.Values: [sassColorA] :: SassValue -> Double
+ Text.Sass.Values: [sassColorB] :: SassValue -> Double
+ Text.Sass.Values: [sassColorG] :: SassValue -> Double
+ Text.Sass.Values: [sassColorR] :: SassValue -> Double
+ Text.Sass.Values: instance GHC.Classes.Eq Text.Sass.Values.SassValue
+ Text.Sass.Values: instance GHC.Show.Show Text.Sass.Values.SassValue
+ Text.Sass.Values.Utils: SassAdd :: SassOp
+ Text.Sass.Values.Utils: SassAnd :: SassOp
+ Text.Sass.Values.Utils: SassDiv :: SassOp
+ Text.Sass.Values.Utils: SassEq :: SassOp
+ Text.Sass.Values.Utils: SassGt :: SassOp
+ Text.Sass.Values.Utils: SassGte :: SassOp
+ Text.Sass.Values.Utils: SassLt :: SassOp
+ Text.Sass.Values.Utils: SassLte :: SassOp
+ Text.Sass.Values.Utils: SassMod :: SassOp
+ Text.Sass.Values.Utils: SassMul :: SassOp
+ Text.Sass.Values.Utils: SassNeq :: SassOp
+ Text.Sass.Values.Utils: SassNumOps :: SassOp
+ Text.Sass.Values.Utils: SassOr :: SassOp
+ Text.Sass.Values.Utils: SassSub :: SassOp
+ Text.Sass.Values.Utils: combineSassValues :: SassOp -> SassValue -> SassValue -> SassValue
+ Text.Sass.Values.Utils: data SassOp :: *
- Text.Sass.Functions: type SassFunctionType = SassValue -> IO SassValue
+ Text.Sass.Functions: type SassFunctionType = SassValue Arguments of the function ('SassList'). -> IO SassValue Result of the computation.
- Text.Sass.Functions: type SassImporterType = String -> IO [SassImport]
+ Text.Sass.Functions: type SassImporterType = String Path to the import that needs to be loaded or file that is being processed when used as a header. -> IO [SassImport] Imports.
Files
- CHANGELOG.md +9/−0
- Text/Sass/Values.hs +1/−1
- Text/Sass/Values/Utils.hs +31/−0
- hsass.cabal +9/−2
- test/Text/Sass/CompilationSpec.hs +122/−0
- test/Text/Sass/FunctionsSpec.hs +65/−0
- test/Text/Sass/TestingUtils.hs +8/−0
- test/Text/Sass/TutorialSpec.hs +82/−0
- test/Text/Sass/ValuesSpec.hs +95/−0
CHANGELOG.md view
@@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.4.0] - 2015-12-19+### Added+- Support for combining `SassValues` (new in hlibsass 0.1.5)++### Changed+- Requires hlibsass version 0.1.5+- `SassValue` derives `Show`+ ## [0.3.0] - 2015-07-10 ### Added - Support for a `ByteString` result (thanks to [Andy@@ -33,3 +41,4 @@ [0.2.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.1.0...v0.2.0 [0.3.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.2.0...v0.3.0+[0.4.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.3.0...v0.4.0
Text/Sass/Values.hs view
@@ -28,4 +28,4 @@ | SassNull -- ^ Null value. | SassWarning String -- ^ Warning with message. | SassError String -- ^ Error with message.- deriving (Eq)+ deriving (Eq, Show)
+ Text/Sass/Values/Utils.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE BangPatterns #-}+-- | Provides utility functions for working with 'SassValues'+module Text.Sass.Values.Utils+ (+ combineSassValues+ , Lib.SassOp (..)+ ) where++import qualified Bindings.Libsass as Lib++import System.IO.Unsafe++import Text.Sass.Values+import Text.Sass.Values.Internal++-- | Combines two 'SassValue's using specified operator.+-- |+-- | Uses 'Lib.sass_value_op'.+combineSassValues :: Lib.SassOp -- ^ Operator.+ -> SassValue -- ^ First value.+ -> SassValue -- ^ Second value.+ -> SassValue -- ^ Resulting value.+combineSassValues op val1 val2 = unsafePerformIO $ do+ native1 <- toNativeValue val1+ native2 <- toNativeValue val2+ combined <- Lib.sass_value_op (fromIntegral $ fromEnum op) native1 native2+ !result <- fromNativeValue combined+ deleteNativeValue native1+ deleteNativeValue native2+ deleteNativeValue combined+ return result
hsass.cabal view
@@ -1,5 +1,5 @@ name: hsass-version: 0.3.0+version: 0.4.0 license: MIT license-file: LICENSE author: Jakub Fijałkowski <fiolek94@gmail.com>@@ -44,10 +44,11 @@ , Text.Sass.Functions.Internal , Text.Sass.Options.Internal , Text.Sass.Values.Internal+ , Text.Sass.Values.Utils , Text.Sass.Utils build-depends: base >= 4.7 && < 5- , hlibsass >= 0.1.1+ , hlibsass >= 0.1.5 , bytestring >= 0.10.0 , data-default-class , filepath >= 1.0@@ -61,6 +62,12 @@ test-suite test hs-source-dirs: test main-is: Spec.hs+ other-modules:+ Text.Sass.CompilationSpec+ , Text.Sass.FunctionsSpec+ , Text.Sass.TestingUtils+ , Text.Sass.TutorialSpec+ , Text.Sass.ValuesSpec type: exitcode-stdio-1.0 ghc-options: -Wall build-depends:
+ test/Text/Sass/CompilationSpec.hs view
@@ -0,0 +1,122 @@+module Text.Sass.CompilationSpec where++import System.IO+import System.IO.Temp+import Test.Hspec+import Text.Sass++import Data.ByteString.Char8 (pack)+import Data.Either (isLeft, isRight)+import Data.Maybe (isJust)+import Text.Sass.TestingUtils++main :: IO ()+main = hspec spec++importerFunc :: String -> IO [SassImport]+importerFunc _ = return [makeSourceImport "a { margin: 1px; }"]++importers :: [SassImporter]+importers = [SassImporter 1 importerFunc]++extendedResultSpec, compilationSpec, errorReportingSpec, spec :: Spec+spec = do+ describe "Compilation" compilationSpec+ describe "Extended compilation" extendedResultSpec+ describe "Error reporting" errorReportingSpec++compilationSpec = do+ it "should compile simple source" $+ compileString "foo { margin: 21px * 2; }" def `shouldReturn`+ Right "foo {\n margin: 42px; }\n"++ it "should compile simple source as a bytestring" $+ compileString "foo { margin: 21px * 2; }" def `shouldReturn`+ Right (pack "foo {\n margin: 42px; }\n")++ it "should respect options" $ do+ let opts = def { sassOutputStyle = SassStyleCompressed }+ compileString "foo { margin: 21px * 2; }" opts `shouldReturn`+ Right "foo{margin:42px}\n"++ it "should compile file" $+ withSystemTempFile "styles.sass" $ \p h -> do+ hPutStr h "foo { margin: 21px * 2; }"+ hClose h+ compileFile p def `shouldReturn` Right "foo {\n margin: 42px; }\n"++ it "compile file should respect options" $ do+ let opts = def { sassOutputStyle = SassStyleCompressed }+ withSystemTempFile "styles.sass" $ \p h -> do+ hPutStr h "foo { margin: 21px * 2; }"+ hClose h+ compileFile p opts `shouldReturn` Right "foo{margin:42px}\n"++extendedResultSpec = do+ it "should compile simple source" $ do+ res <- compileString "foo { margin: 21px * 2; }" def+ res `shouldSatisfy` isRight+ let Right res' = res+ resultString res' `shouldBe` "foo {\n margin: 42px; }\n"++ it "should compile simple source as a bytestring" $ do+ res <- compileString "foo { margin: 21px * 2; }" def+ res `shouldSatisfy` isRight+ let Right res' = res+ resultString res' `shouldBe` (pack "foo {\n margin: 42px; }\n")++ it "should report correct includes when available" $ do+ let opts = def { sassImporters = Just importers }+ Right res <- compileString "@import '_abc';" opts :: ExtendedResult+ resultIncludes res `shouldReturn` [ "_abc" ]++ it "should report no includes when unavailable" $ do+ Right res <- compileString "foo { margin: 1px; }" def :: ExtendedResult+ resultIncludes res `shouldReturn` [ ]++ it "should retrieve source map if available" $ do+ let opts = def { sassSourceMapFile = Just "abc.css" }+ Right res <- compileString "foo { margin: 1px; }" opts :: ExtendedResult+ m <- resultSourcemap res+ m `shouldSatisfy` isJust+ let Just m' = m+ m' `shouldSatisfy` (not . null)++ it "should return Nothing is source map if not available" $ do+ Right res <- compileString "foo { margin: 1px; }" def :: ExtendedResult+ resultSourcemap res `shouldReturn` Nothing++errorReportingSpec = do+ it "string compilation should report error on invalid code" $+ (compileString "inv mark" def :: StringResult)+ `returnShouldSatisfy` isLeft++ it "file compilation should report error on invalid code" $+ withSystemTempFile "styles.sass" $ \p h -> do+ hPutStr h "!@# !@## ## #"+ hClose h+ (compileFile p def :: StringResult) `returnShouldSatisfy` isLeft++ it "should contain line" $ do+ (Left r) <- compileString "invalid mark" def :: StringResult+ errorLine r `shouldReturn` 1++ it "should contain column" $ do+ (Left r) <- compileString "body { !! }" def :: StringResult+ errorColumn r `shouldReturn` 7++ it "should contain description" $ do+ (Left r) <- compileString "body { !! }" def :: StringResult+ errorText r `returnShouldSatisfy` (not . null)++ it "should contain message" $ do+ (Left r) <- compileString "body { !! }" def :: StringResult+ errorMessage r `returnShouldSatisfy` (not . null)++ it "should contain Json description" $ do+ (Left r) <- compileString "body { !! }" def :: StringResult+ errorJson r `returnShouldSatisfy` (not . null)++ it "should contain file path" $ do+ (Left r) <- compileString "body { !! }" def :: StringResult+ errorFile r `returnShouldSatisfy` (not . null)
+ test/Text/Sass/FunctionsSpec.hs view
@@ -0,0 +1,65 @@+module Text.Sass.FunctionsSpec where++import Test.Hspec+import Text.Sass++fooFunction :: SassValue -> IO SassValue+fooFunction _ = return $ SassNumber 1 "px"++barFunction :: SassValue -> IO SassValue+barFunction (SassList [SassString "a"] _) = return $ SassNumber 1 "px"+barFunction _ = return $ SassError "invalid arguments"++functions :: [SassFunction]+functions =+ [ SassFunction "foo()" fooFunction+ , SassFunction "bar($n)" barFunction+ ]++inclContent :: String+inclContent = "a {\n margin: 1px; }\n"++altInclContent :: String+altInclContent = "b {\n margin: 5px; }\n"++headerFunction :: String -> IO [SassImport]+headerFunction _ = return [makeSourceImport inclContent]++headers :: [SassImporter]+headers = [SassImporter 1 headerFunction]++importFunction :: String -> IO [SassImport]+importFunction "_imp" = return [makeSourceImport inclContent]+importFunction _ = return [makeSourceImport altInclContent]++importers :: [SassImporter]+importers = [SassImporter 1 importFunction]++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ it "should call simple function" $ do+ let opts = def { sassFunctions = Just functions }+ compileString "a { margin: foo(); }" opts `shouldReturn`+ Right "a {\n margin: 1px; }\n"++ it "should correctly pass arguments to function" $ do+ let opts = def { sassFunctions = Just functions }+ compileString "a { margin: bar('a'); }" opts `shouldReturn`+ Right "a {\n margin: 1px; }\n"++ it "should correctly inject header" $ do+ let opts = def { sassHeaders = Just headers }+ compileString "a { margin : 1px; }" opts `shouldReturn`+ Right (inclContent ++ "\na {\n margin: 1px; }\n")++ it "should call importers" $ do+ let opts = def { sassImporters = Just importers }+ compileString "@import '_imp';" opts `shouldReturn` Right inclContent++ it "should pass import name to importers" $ do+ let opts = def { sassImporters = Just importers }+ compileString "@import 'other';" opts `shouldReturn` Right altInclContent+
+ test/Text/Sass/TestingUtils.hs view
@@ -0,0 +1,8 @@+module Text.Sass.TestingUtils where++import Test.Hspec++-- | @a `returnShouldSatisfy` p@ asserts that the action @a@ returns value that+-- satisfies predicate @p@.+returnShouldSatisfy :: (Show a, Eq a) => IO a -> (a -> Bool) -> Expectation+v `returnShouldSatisfy` p = v >>= (`shouldSatisfy` p)
+ test/Text/Sass/TutorialSpec.hs view
@@ -0,0 +1,82 @@+module Text.Sass.TutorialSpec where++import Control.Concurrent.MVar+import Test.Hspec+import Text.Sass++max3 :: SassValue -> IO SassValue+max3 (SassList (SassNumber a _:SassNumber b _:SassNumber c _:_) _) =+ return $ SassNumber (max a $ max b c) "px"+max3 _ = return $ SassError "invalid arguments"++max3sig :: SassFunction+max3sig = SassFunction "max3($a, $b, $c)" max3++warn :: MVar String -> SassValue -> IO SassValue+warn m (SassList (SassString s:_) _) = do+ putMVar m s+ return $ SassString "warn!"+warn _ _ = return $ SassString "invalid arguments"++warnSig :: MVar String -> SassFunction+warnSig = SassFunction "@warn" . warn++header :: String -> IO [SassImport]+header src = return [makeSourceImport $ "$file: " ++ src ++ ";"]++headerSig :: SassImporter+headerSig = SassImporter 1 header++importer1 :: String -> IO [SassImport]+importer1 src = return [makeSourceImport $ "$file: " ++ src ++ "1;"]++importer2 :: String -> IO [SassImport]+importer2 src = return [makeSourceImport $ "$file: " ++ src ++ "2;"]++importerSigs :: [SassImporter]+importerSigs = [SassImporter 0.5 importer1, SassImporter 1 importer2]++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "max3" $ do+ it "should return max value" $ do+ let vals = SassList [SassNumber 1 "", SassNumber 2 "",+ SassNumber 3 ""] SassSeparatorSpace+ SassNumber v _ <- max3 vals+ v `shouldBe` 3++ it "should return error on invalid aruments" $ do+ let vals = SassList [SassString "", SassString "",+ SassNumber 3 ""] SassSeparatorSpace+ SassError e <- max3 vals+ e `shouldBe` "invalid arguments"++ it "should be usable by compile" $ do+ let opts = def { sassFunctions = Just [max3sig] }+ compileString "foo { margin: max3(1px, 2px, 3px); }" opts+ `shouldReturn` Right "foo {\n margin: 3px; }\n"++ describe "warn" $+ it "should call warn on @warn statement" $ do+ msg <- newEmptyMVar+ let opts = def { sassFunctions = Just [warnSig msg] }+ _ <- compileString "@warn \"message\";" opts :: StringResult+ tryTakeMVar msg `shouldReturn` Just "message"++ describe "Headers" $+ it "should inject header into file" $ do+ let opts = def {+ sassHeaders = Just [headerSig]+ , sassInputPath = Just "path"+ }+ compileString "foo { prop: $file; }" opts `shouldReturn`+ Right "foo {\n prop: path; }\n"++ describe "Importers" $+ it "should inject import with higher priority" $ do+ let opts = def { sassImporters = Just importerSigs }+ compileString "@import \"file\";\nfoo { prop: $file; }" opts+ `shouldReturn` Right "foo {\n prop: file2; }\n"
+ test/Text/Sass/ValuesSpec.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE StandaloneDeriving #-}+module Text.Sass.ValuesSpec where++import Test.Hspec+import Text.Sass+import Text.Sass.Values.Utils++optsWithVal :: SassValue -> SassOptions+optsWithVal v = def {+ sassFunctions = Just [SassFunction "foo()" (\_ -> return v)]+}++testSerialize :: SassValue -> String -> Expectation+testSerialize v e =+ let opts = optsWithVal v+ in compileString "foo { prop: foo(); }" opts `shouldReturn`+ Right ("foo {\n prop: " ++ e ++ "; }\n")++fooFunction :: SassValue -> SassValue -> IO SassValue+fooFunction e (SassList [a] _) = return $ if e == a+ then a+ else SassNull+fooFunction _ _ = error "fooFunction: invalid arguments"++optsWithArg :: SassValue -> SassOptions+optsWithArg a = def {+ sassFunctions = Just [SassFunction "foo($a)" (fooFunction a)]+}++testDeserialize :: SassValue -> String -> Expectation+testDeserialize a e =+ let opts = optsWithArg a+ in compileString ("foo { prop: foo(" ++ e ++ "); }") opts `shouldReturn`+ Right ("foo {\n prop: " ++ e ++ "; }\n")++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ it "should serialize boolean true" $+ testSerialize (SassBool True) "true"++ it "should serialize boolean false" $+ testSerialize (SassBool False) "false"++ it "should serialize number" $+ testSerialize (SassNumber 1 "px") "1px"++ it "should serialize color" $+ testSerialize (SassColor 1 2 3 0.5) "rgba(1, 2, 3, 0.5)"++ it "should serialize string" $+ testSerialize (SassString "abcd") "abcd"++ it "should serialize list" $+ testSerialize+ (SassList [SassNumber 1 "px", SassNumber 2 "px"]+ SassSeparatorComma)+ "1px, 2px"++ it "should serialize map" $ do+ let map = (SassMap [ (SassString "a", SassString "b")+ , (SassNumber 1 "", SassBool True)])+ let opts = optsWithVal map+ result <- compileString "@each $key, $val in foo() { #{$key} { val: #{$val} } }" opts+ result `shouldBe` Right "a {\n val: b; }\n\n1 {\n val: true; }\n"++ it "should deserialize boolean true" $+ testDeserialize (SassBool True) "true"++ it "should deserialize boolean false" $+ testDeserialize (SassBool False) "false"++ it "should deserialize number" $+ testDeserialize (SassNumber 1 "px") "1px"++ it "should deserialize color" $+ testDeserialize (SassColor 1 2 3 0.5) "rgba(1, 2, 3, 0.5)"++ it "should deserialize string" $+ testDeserialize (SassString "abcd") "abcd"++ it "should deserialize list" $+ testDeserialize+ (SassList [SassNumber 1 "px", SassNumber 2 "px"] SassSeparatorSpace)+ "1px 2px"++ it "should deserialize map" $+ pendingWith "Libsass does not allow maps in CSS any more"++ it "should correctly combine two SassValues" $ do+ let val1 = SassNumber 1.0 ""+ val2 = SassNumber 2.0 ""+ combineSassValues SassAdd val1 val2 `shouldBe` SassNumber 3.0 ""