packages feed

suckless-conf-0.1.2.9: test/Data/Config/Suckless/KeyValueSpec.hs

{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Data.Config.Suckless.KeyValueSpec (spec) where

import Data.Function
import Control.Monad.IO.Class
import Control.Monad.Reader
import Data.Config.Suckless.KeyValue
import Data.Config.Suckless.Parse
import Data.Config.Suckless.Syntax
import Data.Functor
import Data.Scientific
import Data.Text.IO qualified as Text
import Data.Set (Set)
import qualified Data.Set as Set
import Prettyprinter
import Data.Aeson
import Text.InterpolatedString.Perl6 (qc,q)
import Test.Hspec


data FirstKey

data SecondKey

data ThirdKey

data Int1
data Int2
data Int3
data Int4
data Int5
data Int6

data Sci1
data Sci2
data Sci3
data Sci4
data Sci5

data O1
data O2

instance HasCfgKey FirstKey (Maybe String) where
  key = "foo"

instance HasCfgKey SecondKey (Set String) where
  key = "bar"

instance HasCfgKey ThirdKey (Maybe String) where
  key = "baz"

instance HasCfgKey Int1 b where
  key = "int1"

instance HasCfgKey Int2 b where
  key = "int2"

instance HasCfgKey Int3 b where
  key = "int3"

instance HasCfgKey Int4 b  where
  key = "int4"

instance HasCfgKey Int5 b where
  key = "int5"

instance HasCfgKey Int6 b where
  key = "int6"

instance HasCfgKey Sci1 b where
  key = "sci1"

instance HasCfgKey Sci2 b where
  key = "sci2"

instance HasCfgKey Sci3 b where
  key = "sci3"

instance HasCfgKey Sci4 b where
  key = "sci4"

instance HasCfgKey Sci5 b where
  key = "sci5"

instance HasCfgKey O1 b where
  key = "some-object"

instance HasCfgKey O2 b where
  key = "another-object"

instance HasConf IO where
  getConf = liftIO readConfig

readConfig :: IO [Syntax C]
readConfig = do
  let configFilePath = "t/key-value-test-config"
  f <- Text.readFile configFilePath <&> parseTop <&> either mempty id
  print $ pretty f
  pure f

spec :: Spec
spec = do
  describe "config parsing" $ do

    it "reads string" $ do
      firstValue <- cfgValue @FirstKey @(Maybe String)
      firstValue `shouldBe` Just "a"

    it "reads a set of strings" $ do
      secondValue <- cfgValue @SecondKey @(Set String)
      secondValue `shouldBe` Set.fromList ["a", "b"]

    it "reads nothing" $ do
      thridValue <- cfgValue @ThirdKey @(Maybe String)
      thridValue `shouldBe` Nothing

    it "reads ints" $ do
      x1 <- cfgValue @Int1 @(Maybe Integer)
      x1 `shouldBe` Just 122

      x2 <- cfgValue @Int2
      x2 `shouldBe` Just (0 :: Integer)

      x3 <- cfgValue @Int3
      x3 `shouldBe` Just (-22 :: Integer)

      x4 <- cfgValue @Int4 @(Maybe Integer)
      x4 `shouldBe` Just 0xFAFA

      x5 <- cfgValue @Int5 @(Maybe Integer)
      x5 `shouldBe` Just 255

      x6 <- cfgValue @Int6 @(Maybe Integer)
      x6 `shouldBe` Just (-0xFAFA)

    it "reads scientifics" $ do
      x1 <- cfgValue @Sci1 @(Maybe Scientific)
      x1 `shouldBe` Just 1e9

      x2 <- cfgValue @Sci2 @(Maybe Scientific)
      x2 `shouldBe` Just 0.003

      -- x3 <- cfgValue @Sci3 @(Maybe Scientific)
      -- x3 `shouldBe` Just (-0.001)

      x4 <- cfgValue @Sci4 @(Maybe Scientific)
      x4 `shouldBe` Just (-2e11)

      x5 <- cfgValue @Sci5 @(Maybe Scientific)
      x5 `shouldBe` Just (-2e-3)

    it "reads objects" $ do
      o1 <- cfgValue @O1 @(Maybe Value)
      let wtf1 = [q|{ "key" : 42 }|]
      o1 `shouldBe` decode wtf1
      let wtf2 = [q|
        {   "key1" : 42
          , "key2" : false
          , "key3" : [ 1, 2, 3, 4]
        }
      |]
      o2 <- cfgValue @O2 @(Maybe Value)
      o2 `shouldBe` decode wtf2


    it "works in Reader" $ do

      let cfg = [qc|
int1 123

|]
      let conf = parseTop cfg & either mempty id

      let v = runReader (cfgValue @Int1 @(Maybe Int)) conf

      v `shouldBe` Just 123