seihou-core-0.12.0.0: test/Seihou/Composition/RecipeSpec.hs
module Seihou.Composition.RecipeSpec (tests) where
import Data.Map.Strict qualified as Map
import Data.Text (Text)
import Seihou.Composition.Recipe (expandRecipe)
import Seihou.Core.Recipe (validateRecipe)
import Seihou.Core.Types
import Test.Hspec
import Test.Tasty
import Test.Tasty.Hspec (testSpec)
tests :: IO TestTree
tests = testSpec "Seihou.Composition.Recipe" spec
expectExpanded :: Recipe -> (ModuleName, [ModuleName], Map.Map VarName Text, [VarDecl], [Prompt], [Dependency])
expectExpanded recipe =
case expandRecipe recipe of
Right expanded -> expanded
Left errs -> error ("expected recipe expansion, got errors: " <> show errs)
spec :: Spec
spec = do
describe "expandRecipe" $ do
it "returns correct primary and additional module names" $ do
let recipe =
Recipe
{ name = "combo",
version = Just "1.0.0",
description = Nothing,
modules =
[ simpleDep "mod-a",
Dependency "mod-b" mempty (Just "https://example.com/registry"),
simpleDep "mod-c"
],
vars = [],
prompts = []
}
(primary, additional, _, _, _, requirements) = expectExpanded recipe
primary `shouldBe` ModuleName "mod-a"
additional `shouldBe` [ModuleName "mod-b", ModuleName "mod-c"]
requirements `shouldBe` [simpleDep "mod-a", Dependency "mod-b" mempty (Just "https://example.com/registry"), simpleDep "mod-c"]
it "collects variable overrides from module entries" $ do
let recipe =
Recipe
{ name = "pinned",
version = Nothing,
description = Nothing,
modules =
[ Dependency (ModuleName "base") (Map.singleton "project.name" "my-app") Nothing,
Dependency (ModuleName "nix") (Map.singleton "nix.system" "aarch64-darwin") Nothing
],
vars = [],
prompts = []
}
(_, _, overrides, _, _, _) = expectExpanded recipe
Map.lookup (VarName "project.name") overrides `shouldBe` Just "my-app"
Map.lookup (VarName "nix.system") overrides `shouldBe` Just "aarch64-darwin"
it "passes through recipe-level vars and prompts" $ do
let recipeVar =
VarDecl
{ name = "project.name",
type_ = VTText,
default_ = Nothing,
description = Just "Project name",
required = True,
validation = Nothing
}
recipePrompt =
Prompt
{ var = "project.name",
text = "Enter name:",
condition = Nothing,
choices = Nothing
}
recipe =
Recipe
{ name = "prompted",
version = Nothing,
description = Nothing,
modules = [simpleDep "base"],
vars = [recipeVar],
prompts = [recipePrompt]
}
(_, _, _, vars, prompts, _) = expectExpanded recipe
vars `shouldBe` [recipeVar]
prompts `shouldBe` [recipePrompt]
it "handles a single-module recipe (alias)" $ do
let recipe =
Recipe
{ name = "alias",
version = Nothing,
description = Nothing,
modules = [simpleDep "the-module"],
vars = [],
prompts = []
}
(primary, additional, overrides, _, _, _) = expectExpanded recipe
primary `shouldBe` ModuleName "the-module"
additional `shouldBe` []
Map.null overrides `shouldBe` True
it "returns validation errors for an empty recipe" $ do
let recipe =
Recipe
{ name = "empty",
version = Nothing,
description = Nothing,
modules = [],
vars = [],
prompts = []
}
expandRecipe recipe `shouldBe` Left ["modules: recipe must list at least one module"]
it "shares rejection of malformed prompt targets and conditions with descriptor validation" $ do
let recipe =
Recipe
"bad-prompts"
Nothing
Nothing
[simpleDep "unavailable"]
[]
[Prompt "missing-target" "Question" (Just (ExprNot (ExprIsSet "missing-condition"))) Nothing]
case validateRecipe recipe of
Left errors -> do
length errors `shouldBe` 2
expandRecipe recipe `shouldBe` Left errors
Right _ -> expectationFailure "Expected malformed prompt references to fail"