packages feed

sensei-0.8.0: test/ConfigSpec.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}

module ConfigSpec (spec) where

import Helper
import Data.Aeson
import Data.Yaml.TH
import Data.ByteString.Lazy qualified as LB

import Config

spec :: Spec
spec = do
  describe "readConfigFilesFrom" $ do
    it "reads config values from ./sensei.yaml" $ do
      withTempDirectory $ \ dir -> do
        let
          global = dir </> "global.yaml"
          local = dir </> "local.yaml"
        LB.writeFile local $ encode [yamlQQ|
          before-reload: local-before-reload
          on-success: local-on-success
        |]
        readConfigFilesFrom global local `shouldReturn` Right mempty {
          beforeReload = Just "local-before-reload"
        , onSuccess = Just "local-on-success"
        }

    it "reads config values from ~/.config/sensei/sensei.yaml" $ do
      withTempDirectory $ \ dir -> do
        let
          global = dir </> "global.yaml"
          local = dir </> "local.yaml"
        LB.writeFile global $ encode [yamlQQ|
          on-failure: global-on-failure
          on-success: global-on-success
        |]
        readConfigFilesFrom global local `shouldReturn` Right mempty {
          onFailure = Just "global-on-failure"
        , onSuccess = Just "global-on-success"
        }

    context "with both ~/.config/sensei/sensei.yaml and ./sensei.yaml" $ do
      it "gives fields from ./sensei.yaml precedence" $ do
        withTempDirectory $ \ dir -> do
          let
            global = dir </> "global.yaml"
            local = dir </> "local.yaml"
          LB.writeFile global $ encode [yamlQQ|
            on-failure: global-on-failure
            on-success: global-on-success
          |]
          LB.writeFile local $ encode [yamlQQ|
            before-reload: local-before-reload
            on-success: local-on-success
          |]
          readConfigFilesFrom global local `shouldReturn` Right mempty {
            beforeReload = Just "local-before-reload"
          , onFailure = Just "global-on-failure"
          , onSuccess = Just "local-on-success"
          }

    context "with unknown fields" $ do
      it "returns an error" $ do
        withTempDirectory $ \ dir -> do
          let
            global = dir </> "global.yaml"
            local = dir </> "local.yaml"
          LB.writeFile local $ encode [yamlQQ|
            some-field: some-value
          |]
          readConfigFilesFrom global local `shouldReturn` Left "Aeson exception:\nError in $: parsing Config.ConfigFile(ConfigFile) failed, unknown fields: [\"some-field\"]"

  describe "ConfigFile" $ do
    it "deserializes from yaml" $ do
      fromJSON [yamlQQ|
        after-reload: foo bar baz
        before-reload: blah
        on-success: snafu
        on-failure: failure
      |] `shouldBe` Success ConfigFile {
        afterReload = Just "foo bar baz"
      , beforeReload = Just "blah"
      , onSuccess = Just "snafu"
      , onFailure = Just "failure"
      }

    it "supports null" $ do
      fromJSON [yamlQQ|
        after-reload: null
        before-reload: blah
        on-success: finally
        on-failure: failure
      |] `shouldBe` Success ConfigFile {
        afterReload = Nothing
      , beforeReload = Just "blah"
      , onSuccess = Just "finally"
      , onFailure = Just "failure"
      }

    it "supports missing fields" $ do
      fromJSON [yamlQQ|
        after-reload: blah
      |] `shouldBe` Success ConfigFile {
        afterReload = Just "blah"
      , beforeReload = Nothing
      , onSuccess = Nothing
      , onFailure = Nothing
      }

    it "accepts an emty config" $ do
      fromJSON @ConfigFile [yamlQQ|
      |] `shouldBe` Success mempty