packages feed

app-settings-0.2.0.3: tests/Tests.hs

{-# LANGUAGE ScopedTypeVariables #-}

import Data.AppSettings
import Data.AppSettingsInternal

import Test.Hspec
import Test.HUnit (assertBool)

import System.Directory (removeFile, copyFile, doesFileExist)
import Control.Exception (try, SomeException)

textSizeFromWidth :: Setting Double
textSizeFromWidth = Setting "textSizeFromWidth" 0.04

textFill :: Setting (Double,Double,Double,Double)
textFill = Setting "textFill" (1, 1, 0, 1)

textSizeFromHeight :: Setting Double
textSizeFromHeight = Setting "textSizeFromHeight" 12.4

testInlineList :: Setting [String]
testInlineList = Setting "testInlineList" ["inline1", "inline2", "inline3"]

testList :: Setting [String]
testList = ListSetting "testList" ["list1", "list2", "list3"]

defaultConfig :: DefaultConfig
defaultConfig = getDefaultConfig $ do
	setting textSizeFromWidth
	setting textSizeFromHeight
	setting textFill
	setting testInlineList
	setting testList

main :: IO ()
main = hspec $ do
	describe "unit tests" testIsKeyForListSetting
	describe "load config" $ do
		testEmptyFileDefaults
		testPartialFileDefaults
		testPartialFileDefaults2
		testFileWithComments
		testInvalidFile
		testInvalidValue
		testNonExistingFile
	describe "save config" $ do
		testSaveUserSetAndDefaults
		createBakBeforeSaving
	describe "set setting" testSetListSetting

testEmptyFileDefaults :: Spec
testEmptyFileDefaults = it "parses correctly an empty file with defaults" $ do
	readResult <- try $ readSettings (Path "tests/empty.config")
	case readResult of
		Right (_, GetSetting getSetting) -> do
			getSetting textSizeFromWidth `shouldBe` 0.04
			getSetting textSizeFromHeight `shouldBe` 12.4
			getSetting textFill `shouldBe` (1,1,0,1)
			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
			getSetting testList `shouldBe` ["list1", "list2", "list3"]
		Left (x :: SomeException) -> assertBool (show x) False

testPartialFileDefaults :: Spec
testPartialFileDefaults = it "parses correctly a partial file with defaults" $ do
	readResult <- try $ readSettings (Path "tests/partial.config")
	case readResult of
		Right (_, GetSetting getSetting) -> do
			getSetting textSizeFromWidth `shouldBe` 1.02
			getSetting textSizeFromHeight `shouldBe` 12.4
			getSetting textFill `shouldBe` (1,2,3,4)
			getSetting testInlineList `shouldBe` ["un", "deux"]
			getSetting testList `shouldBe` ["one", "two"]
		Left (x :: SomeException) -> assertBool (show x) False

testPartialFileDefaults2 :: Spec
testPartialFileDefaults2 = it "parses correctly a partial2 file with defaults" $ do
	readResult <- try $ readSettings (Path "tests/partial2.config")
	case readResult of
		Right (_, GetSetting getSetting) -> do
			getSetting textSizeFromWidth `shouldBe` 1.02
			getSetting textSizeFromHeight `shouldBe` 12.4
			getSetting textFill `shouldBe` (1,2,3,4)
			getSetting testInlineList `shouldBe` ["un", "deux"]
			getSetting testList `shouldBe` []
		Left (x :: SomeException) -> assertBool (show x) False

testFileWithComments :: Spec
testFileWithComments = it "parses correctly a partial file with comments" $ do
	readResult <- try $ readSettings (Path "tests/test-save.txt")
	case readResult of
		Right (_, GetSetting getSetting) -> do
			getSetting textSizeFromWidth `shouldBe` 1.02
			getSetting textSizeFromHeight `shouldBe` 12.4
			getSetting textFill `shouldBe` (1,2,3,4)
			getSetting testInlineList `shouldBe` ["un", "deux"]
			getSetting testList `shouldBe` ["one", "two"]
		Left (x :: SomeException) -> assertBool (show x) False

testInvalidValue :: Spec
testInvalidValue = it "parses correctly a file with invalid values" $ do
	readResult <- try $ readSettings (Path "tests/brokenvalue.config")
	case readResult of
		Right (_, GetSetting getSetting) -> do
			-- give the default for the invalid value
			getSetting textSizeFromWidth `shouldBe` 0.04
			getSetting textSizeFromHeight `shouldBe` 12.4
			getSetting textFill `shouldBe` (1,2,3,4)
			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
			getSetting testList `shouldBe` ["list1", "list2", "list3"]
		Left (x :: SomeException) -> assertBool (show x) False

testNonExistingFile :: Spec
testNonExistingFile = it "returns empty config for a non-existing file" $ do
	readResult <- try $ readSettings (Path "tests/dontexist.conf")
	case readResult of
		Right (_, GetSetting getSetting) -> do
			getSetting textSizeFromWidth `shouldBe` 0.04
			getSetting textSizeFromHeight `shouldBe` 12.4
			getSetting textFill `shouldBe` (1,1,0,1)
			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
			getSetting testList `shouldBe` ["list1", "list2", "list3"]
		Left (x :: SomeException) -> assertBool (show x) False

testInvalidFile :: Spec
testInvalidFile = it "reports errors properly for invalid files" $ do
	readResult <- try $ readSettings (Path "tests/broken.config")
	case readResult of
		Left (_ :: SomeException) -> assertBool "ok" True
		Right _ -> assertBool "did not get an error!" False

testSaveUserSetAndDefaults :: Spec
testSaveUserSetAndDefaults = it "saves a file with user-set and default settings" $ do
	readResult <- try $ readSettings (Path "tests/partial.config") 
	case readResult of 
		Right (conf, _) -> do
			saveSettings defaultConfig (Path "test.txt") conf
			actual <- readFile "test.txt"
			reference <- readFile "tests/test-save.txt"
			actual `shouldBe` reference
			removeFile "test.txt"
		Left (x :: SomeException) -> assertBool (show x) False

createBakBeforeSaving :: Spec
createBakBeforeSaving = it "creates a backup of the config file before overwriting it" $ do
	readResult <- try $ readSettings (Path "tests/partial.config") 
	case readResult of 
		Right (conf, _) -> do
			copyFile "tests/partial.config" "p.config"
			saveSettings defaultConfig (Path "p.config") conf
			doesFileExist "p.config.bak" >>= flip shouldBe True
			doesFileExist "p.config" >>= flip shouldBe True
			removeFile "p.config"
			removeFile "p.config.bak"
		Left (x :: SomeException) -> assertBool (show x) False

testSetListSetting :: Spec
testSetListSetting = it "overwrites correctly a list setting" $ do
	readResult <- try $ readSettings (Path "tests/empty.config")
	case readResult of
		Right (conf, GetSetting getSetting) -> do
			getSetting testList `shouldBe` ["list1", "list2", "list3"]
			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
			let conf0 = setSetting conf testList ["un"]
			let conf1 = setSetting conf0 testInlineList ["one"]
			getSetting' conf1 testList `shouldBe` ["un"]
			getSetting' conf1 testInlineList `shouldBe` ["one"]
			let conf2 = setSetting conf1 testList []
			let conf3 = setSetting conf2 testInlineList []
			getSetting' conf3 testList `shouldBe` []
			getSetting' conf3 testInlineList `shouldBe` []
		Left (x :: SomeException) -> assertBool (show x) False

testIsKeyForListSetting :: Spec
testIsKeyForListSetting = it "checks correctly whether a key is attached to a list setting" $ do
	isKeyForListSetting "listTest" "listTest_1" `shouldBe` True
	isKeyForListSetting "listTest" "listTest_13" `shouldBe` True
	isKeyForListSetting "listTest" "listTest_unrelated" `shouldBe` False
	isKeyForListSetting "listTest" "listTest_1notanumber" `shouldBe` False
	isKeyForListSetting "listTest" "listTestX_1" `shouldBe` False