52 lines
2.3 KiB
Haskell
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"
|