Phase 4: Recipe references + all 4 example file validation
- Fix pRecipeRef to include ./ prefix in stored path - Add recipe reference test - Add parse-validation tests for all 4 example .cook files (EasyPancakes, FriedRice, CoffeeSouffle, OlivierSalad) - All 24 tests passing, all examples parse without error
This commit is contained in:
+2
-1
@@ -131,11 +131,12 @@ pLineBreak = do
|
|||||||
pRecipeRef :: Parser StepItem
|
pRecipeRef :: Parser StepItem
|
||||||
pRecipeRef = do
|
pRecipeRef = do
|
||||||
_ <- P.char '@'
|
_ <- P.char '@'
|
||||||
|
-- Consume @ and store ./ as part of the path
|
||||||
_ <- P.char '.'
|
_ <- P.char '.'
|
||||||
_ <- P.char '/'
|
_ <- P.char '/'
|
||||||
path <- P.many (P.noneOf "{(\n\\")
|
path <- P.many (P.noneOf "{(\n\\")
|
||||||
mqty <- P.optionMaybe (P.between (P.char '{') (P.char '}') pQuantityBody)
|
mqty <- P.optionMaybe (P.between (P.char '{') (P.char '}') pQuantityBody)
|
||||||
return (StepRecipeRef (RecipeRef path (join mqty)))
|
return (StepRecipeRef (RecipeRef ("./" <> path) (join mqty)))
|
||||||
|
|
||||||
-- | Ingredient: @name{quantity%unit}(preparation)
|
-- | Ingredient: @name{quantity%unit}(preparation)
|
||||||
pIngredient :: Parser StepItem
|
pIngredient :: Parser StepItem
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ module Roux.ParserSpec (spec) where
|
|||||||
|
|
||||||
import Data.List.NonEmpty (NonEmpty ((:|)))
|
import Data.List.NonEmpty (NonEmpty ((:|)))
|
||||||
import qualified Data.List.NonEmpty as NE
|
import qualified Data.List.NonEmpty as NE
|
||||||
|
import qualified Data.Text.IO as TIO
|
||||||
import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe)
|
import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe)
|
||||||
|
|
||||||
import Roux.Parser (parseCookFile)
|
import Roux.Parser (parseCookFile)
|
||||||
@@ -369,3 +370,44 @@ spec = do
|
|||||||
_ ->
|
_ ->
|
||||||
expectationFailure
|
expectationFailure
|
||||||
("expected SecStep as third body item, got body=" <> show body)
|
("expected SecStep as third body item, got body=" <> show body)
|
||||||
|
|
||||||
|
describe "Recipe references" $ do
|
||||||
|
it "parses a recipe reference" $ do
|
||||||
|
let input = "Pour over with @./sauces/Hollandaise{150%g}."
|
||||||
|
case parseCookFile input of
|
||||||
|
Left err -> expectationFailure ("parse failed: " <> err)
|
||||||
|
Right recipe -> do
|
||||||
|
let items = stepItems recipe
|
||||||
|
let expected =
|
||||||
|
[ StepText "Pour over with "
|
||||||
|
, StepRecipeRef (RecipeRef "./sauces/Hollandaise" (Just (Quantity 150 (Just "g") False)))
|
||||||
|
, StepText "."
|
||||||
|
]
|
||||||
|
items `shouldBe` expected
|
||||||
|
|
||||||
|
describe "Full recipe files" $ do
|
||||||
|
let readExample name = do
|
||||||
|
content <- TIO.readFile ("cooklang-examples/" <> name <> ".cook")
|
||||||
|
case parseCookFile content of
|
||||||
|
Left err -> expectationFailure (name <> ": " <> err)
|
||||||
|
Right _ -> pure ()
|
||||||
|
|
||||||
|
it "EasyPancakes parses without error" $ do
|
||||||
|
readExample "EasyPancakes"
|
||||||
|
|
||||||
|
it "FriedRice parses without error" $ do
|
||||||
|
readExample "FriedRice"
|
||||||
|
|
||||||
|
it "CoffeeSouffle parses without error" $ do
|
||||||
|
readExample "CoffeeSouffle"
|
||||||
|
|
||||||
|
it "OlivierSalad parses without error" $ do
|
||||||
|
readExample "OlivierSalad"
|
||||||
|
|
||||||
|
-- | Extract step items from the first step of an unnamed section.
|
||||||
|
stepItems :: Recipe -> [StepItem]
|
||||||
|
stepItems r =
|
||||||
|
let s = NE.head (recipeSections r)
|
||||||
|
in case NE.head (sectionBody s) of
|
||||||
|
SecStep step -> unStep step
|
||||||
|
_ -> []
|
||||||
|
|||||||
Reference in New Issue
Block a user