Files
roux/test/Roux/SchemaOrgSpec.hs
T

52 lines
2.3 KiB
Haskell

module Roux.SchemaOrgSpec (spec) where
import qualified Data.Aeson as A
import Data.Maybe (fromJust, isJust)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe, shouldSatisfy)
import Roux.SchemaOrg
-- | Extract the first schema.org Recipe JSON-LD from HTML.
tryDecode :: Text -> Maybe A.Value
tryDecode html =
case T.splitOn "<script type=\"application/ld+json" html of
(_before : rest : _) ->
-- Skip past the closing > of the opening script tag, which may have extra attributes
let afterOpenTag = T.drop 1 (T.dropWhile (/= '>') rest)
in case T.splitOn "</script>" afterOpenTag of
(jsonContent : _) -> A.decodeStrict (TE.encodeUtf8 (T.strip jsonContent))
_ -> Nothing
_ -> Nothing
spec :: Spec
spec = describe "SchemaOrg" $ do
describe "parseSchemaOrgRecipe" $ do
it "parses fried-rice.html embedded JSON-LD" $ do
html <- readFile "test-data/fried-rice.html"
let decoded = tryDecode (T.pack html)
decoded `shouldSatisfy` isJust
let recipe = parseSchemaOrgRecipe (fromJust decoded)
recipe `shouldSatisfy` isJust
case recipe of
Nothing -> expectationFailure "expected Just SchemaOrgRecipe, got Nothing"
Just r -> do
soName r `shouldBe` "Fried Rice"
soRecipeYield r `shouldBe` Just "4 to 6 servings"
soTotalTime r `shouldBe` Just "PT20M"
soRecipeCuisine r `shouldBe` Just "asian"
length (soRecipeIngredient r) `shouldBe` 14
length (soRecipeInstructions r) `shouldBe` 4
it "parses carrot-risotto.html embedded JSON-LD" $ do
html <- readFile "test-data/carrot-risotto.html"
let decoded = tryDecode (T.pack html)
decoded `shouldSatisfy` isJust
let recipe = parseSchemaOrgRecipe (fromJust decoded)
recipe `shouldSatisfy` isJust
case recipe of
Nothing -> expectationFailure "expected Just SchemaOrgRecipe, got Nothing"
Just r -> soName r `shouldBe` "Carrot Risotto With Chile Crisp"