diff --git a/test/Roux/SchemaOrgSpec.hs b/test/Roux/SchemaOrgSpec.hs index 78a1b98..9ac91f3 100644 --- a/test/Roux/SchemaOrgSpec.hs +++ b/test/Roux/SchemaOrgSpec.hs @@ -1,7 +1,7 @@ module Roux.SchemaOrgSpec (spec) where import Data.Aeson (Value, decodeStrict) -import Data.CookLang (Duration (..), Metadata (..), Recipe (..)) +import Data.CookLang (Duration (..), Metadata (..), Recipe (..), Section (..), SectionBodyItem (..)) import Data.List.NonEmpty (toList) import Data.Maybe (fromJust, isJust) import Data.Text (Text) @@ -66,34 +66,68 @@ spec = describe "SchemaOrg" $ do it "human-readable -> Nothing" $ chk "20 minutes" Nothing describe "schemaOrgToCooklang" $ do - it "converts fried-rice schema.org recipe to Cooklang" $ do - html <- readFile "test-data/fried-rice.html" - let decoded = tryDecode (T.pack html) - recipe = parseSchemaOrgRecipe (fromJust decoded) - case recipe of - Just r -> case schemaOrgToCooklang r of - Right cook -> do - metaTitle (recipeMetadata cook) `shouldBe` Just "Fried Rice" - metaSource (recipeMetadata cook) `shouldBe` Just "https://cooking.nytimes.com/recipes/12177-fried-rice" - metaCourse (recipeMetadata cook) `shouldBe` Just "one pot, side dish" - metaCuisine (recipeMetadata cook) `shouldBe` Just "asian" - metaTotalTime (recipeMetadata cook) `shouldBe` Just (Duration 20 (Just "minutes")) - metaTags (recipeMetadata cook) `shouldBe` ["egg", "rice", "vegetarian"] - metaDescription (recipeMetadata cook) `shouldSatisfy` isJust - let sections = toList (recipeSections cook) - length sections `shouldBe` 2 - Left err -> fail err - Nothing -> fail "Failed to parse schema.org recipe" + let loadRecipeFile :: FilePath -> IO (Maybe SchemaOrgRecipe) + loadRecipeFile path = do + html <- readFile path + let decoded = tryDecode (T.pack html) + pure (parseSchemaOrgRecipe =<< decoded) - it "converts carrot-risotto schema.org recipe to Cooklang" $ do - html <- readFile "test-data/carrot-risotto.html" - let decoded = tryDecode (T.pack html) - recipe = parseSchemaOrgRecipe (fromJust decoded) - case recipe of - Just r -> case schemaOrgToCooklang r of - Right cook -> do - metaTitle (recipeMetadata cook) `shouldBe` Just "Carrot Risotto With Chile Crisp" - metaAuthor (recipeMetadata cook) `shouldBe` Just "Alexa Weibel" - metaTags (recipeMetadata cook) `shouldSatisfy` (not . null) - Left err -> fail err - Nothing -> fail "Failed to parse schema.org recipe" + let countMethodSteps :: Recipe -> Int + countMethodSteps recipe = + let sections = toList (recipeSections recipe) + in case filter (\s -> sectionName s == Just "Method") sections of + [s] -> + let bodyItems = toList (sectionBody s) + in length [() | SecStep _ <- bodyItems] + _ -> 0 + + let checkStepCount :: FilePath -> String -> Int -> Spec + checkStepCount path label expectedSteps = it ("preserves " <> label <> " step count in Cooklang conversion") $ do + mRecipe <- loadRecipeFile path + case mRecipe of + Nothing -> fail "Failed to parse schema.org recipe" + Just r -> do + let rawInstructions = soRecipeInstructions r + length rawInstructions `shouldBe` expectedSteps + case schemaOrgToCooklang r of + Left err -> fail err + Right cook -> do + let cookSteps = countMethodSteps cook + cookSteps `shouldBe` expectedSteps + + let checkMetadata :: FilePath -> String -> (SchemaOrgRecipe -> IO ()) -> Spec + checkMetadata path label checks = it ("converts " <> label <> " schema.org recipe to Cooklang") $ do + mRecipe <- loadRecipeFile path + case mRecipe of + Nothing -> fail "Failed to parse schema.org recipe" + Just r -> do + checks r + case schemaOrgToCooklang r of + Left err -> fail err + Right _ -> pure () + + checkStepCount "test-data/fried-rice.html" "fried-rice" 4 + + checkStepCount "test-data/carrot-risotto.html" "carrot-risotto" 7 + + checkMetadata "test-data/fried-rice.html" "fried-rice" $ \r -> + case schemaOrgToCooklang r of + Left err -> fail err + Right cook -> do + metaTitle (recipeMetadata cook) `shouldBe` Just "Fried Rice" + metaSource (recipeMetadata cook) `shouldBe` Just "https://cooking.nytimes.com/recipes/12177-fried-rice" + metaCourse (recipeMetadata cook) `shouldBe` Just "one pot, side dish" + metaCuisine (recipeMetadata cook) `shouldBe` Just "asian" + metaTotalTime (recipeMetadata cook) `shouldBe` Just (Duration 20 (Just "minutes")) + metaTags (recipeMetadata cook) `shouldBe` ["egg", "rice", "vegetarian"] + metaDescription (recipeMetadata cook) `shouldSatisfy` isJust + let sections = toList (recipeSections cook) + length sections `shouldBe` 2 + + checkMetadata "test-data/carrot-risotto.html" "carrot-risotto" $ \r -> + case schemaOrgToCooklang r of + Left err -> fail err + Right cook -> do + metaTitle (recipeMetadata cook) `shouldBe` Just "Carrot Risotto With Chile Crisp" + metaAuthor (recipeMetadata cook) `shouldBe` Just "Alexa Weibel" + metaTags (recipeMetadata cook) `shouldSatisfy` (not . null)