packages feed

dojang-0.2.0: test/Dojang/Commands/DisambiguationSpec.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}

module Dojang.Commands.DisambiguationSpec (spec) where

import Prelude hiding (readFile, writeFile)

import Control.Exception (bracket_)
import System.Environment (lookupEnv, setEnv, unsetEnv)
import System.OsPath (encodeFS)
import Test.Hspec (Spec, describe, it, runIO, sequential)
import Test.Hspec.Expectations.Pretty (shouldBe)

import Dojang.Commands.Disambiguation
  ( AutoSelectMode (..)
  , getAutoSelectMode
  )
import Dojang.MonadFileSystem qualified (FileType (..))
import Dojang.Types.Context (CandidateRoute (..))
import Dojang.Types.Repository (RouteResult (..))


-- | Helper to run a test with a specific environment variable setting.
withEnvVar :: String -> Maybe String -> IO a -> IO a
withEnvVar name value action = do
  oldValue <- lookupEnv name
  bracket_
    (setOrUnset value)
    (setOrUnset oldValue)
    action
 where
  setOrUnset :: Maybe String -> IO ()
  setOrUnset (Just v) = setEnv name v
  setOrUnset Nothing = unsetEnv name


spec :: Spec
spec = do
  foo <- runIO $ encodeFS "foo"
  dst <- runIO $ encodeFS "dst"

  -- These tests must run sequentially because they modify global env vars.
  sequential $ describe "getAutoSelectMode" $ do
    it "returns Interactive when DOJANG_AUTO_SELECT is unset" $ do
      withEnvVar "DOJANG_AUTO_SELECT" Nothing $ do
        mode <- getAutoSelectMode
        mode `shouldBe` Interactive

    it "returns AutoSelectFirst when DOJANG_AUTO_SELECT is 'first'" $ do
      withEnvVar "DOJANG_AUTO_SELECT" (Just "first") $ do
        mode <- getAutoSelectMode
        mode `shouldBe` AutoSelectFirst

    it "returns ErrorOnAmbiguity when DOJANG_AUTO_SELECT is 'error'" $ do
      withEnvVar "DOJANG_AUTO_SELECT" (Just "error") $ do
        mode <- getAutoSelectMode
        mode `shouldBe` ErrorOnAmbiguity

    it "returns Interactive for unknown values" $ do
      withEnvVar "DOJANG_AUTO_SELECT" (Just "unknown") $ do
        mode <- getAutoSelectMode
        mode `shouldBe` Interactive

  describe "CandidateRoute" $ do
    it "has expected fields" $ do
      let route =
            RouteResult
              { sourcePath = foo
              , routeName = foo
              , destinationPath = dst
              , fileType = Dojang.MonadFileSystem.Directory
              }
      let candidate = CandidateRoute route 1 foo True
      candidate.specificity `shouldBe` 1
      candidate.sourceFilePath `shouldBe` foo
      candidate.sourceExists `shouldBe` True
      candidate.route.routeName `shouldBe` foo