{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneDeriving #-} module Spec.Blogger (tests) where import Data.DateTime (fromGregorian) import qualified Data.Text as T import Hakyll.Convert.Blogger import Hakyll.Convert.Common (DistilledPost (..)) import Test.Tasty (TestTree, testGroup) import Test.Tasty.ExpectedFailure (expectFail) import Test.Tasty.HUnit import qualified Text.Atom.Feed as Atom deriving instance Eq DistilledPost deriving instance Show DistilledPost tests :: TestTree tests = testGroup "Blogger.distill" [ extractsPostUri, extractsPostBody, extractsPostTitle, canSkipComments, canExtractComments, enumeratesAllCommentAuthors, errorsOnNonHtmlPost, errorsOnNonHtmlComment, turnsIncorrectDatesIntoEpochStart, parsesDates, extractsPostTags ] extractsPostUri :: TestTree extractsPostUri = testGroup "extracts post's URI" [ testCase (T.unpack uri) (dpUri (distill False (createInput uri)) @?= uri) | uri <- [ "https://example.com/testing-post-uris", "http://www.example.com/~joe/posts.atom" ] ] where createInput uri = FullPost { fpPost = entry, fpComments = [], fpUri = uri } entry = Atom.nullEntry "https://example.com/entry" (Atom.TextString "Test post") "2003-12-13T18:30:02Z" extractsPostBody :: TestTree extractsPostBody = testGroup "extracts post's body" [ testCase (T.unpack body) (dpBody (distill False (createInput body)) @?= body) | body <- [ "

Today was a snowy day, and I decided to...

", "

My opinion on current affairs

So you see, I...

" ] ] where createInput body = FullPost { fpPost = createEntry body, fpComments = [], fpUri = "https://example.com" } createEntry body = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "Test post") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.HTMLContent body) } extractsPostTitle :: TestTree extractsPostTitle = testGroup "extracts post's title" [ testCase (T.unpack title) (dpTitle (distill False (createInput title)) @?= Just (title)) | title <- [ "First post", "You won't believe what happened to me today", "Trying out things…" ] ] where createInput title = FullPost { fpPost = createEntry title, fpComments = [], fpUri = "https://example.com/titles.atom" } createEntry title = Atom.nullEntry "https://example.com/entry" (Atom.TextString title) "2003-12-13T18:30:02Z" canSkipComments :: TestTree canSkipComments = testCase "does not extract comments if first argument is False" (dpBody (distill False input) @?= expected) where input = FullPost { fpPost = entry, fpComments = [comment], fpUri = "https://example.com/feed" } entry = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.HTMLContent "

Hello, world!

"), Atom.entryPublished = Just "2003-12-13T18:30:02Z" } comment = ( Atom.nullEntry "https://example.com/entry#comment1" (Atom.TextString "Nice") "2003-12-13T20:00:03Z" ) { Atom.entryContent = Just (Atom.HTMLContent "

Nice post.

") } expected = "

Hello, world!

" canExtractComments :: TestTree canExtractComments = testGroup "extracts comments if first argument is True" [ noDateNoAuthor, dateNoAuthor, noDateAuthor, dateAuthor ] where createInput comment = FullPost { fpPost = entry, fpComments = [comment], fpUri = "https://example.com/feed" } entry = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.HTMLContent "

Hello, world!

"), Atom.entryPublished = Just "2003-12-13T18:30:02Z" } noDateNoAuthor = testCase "comments with no \"published\" date and no author" (dpBody (distill True (createInput commentNoDateNoAuthor)) @?= expectedNoDateNoAuthor) commentNoDateNoAuthor = ( Atom.nullEntry "https://example.com/entry#comment1" (Atom.TextString "Nice") "2003-12-13T20:00:03Z" ) { Atom.entryContent = Just (Atom.HTMLContent "

Nice post.

") } expectedNoDateNoAuthor = "

Hello, world!

\n\n\ \

Comments

\n\ \
\n\ \

On unknown date, wrote:

\n\ \
\n\ \

Nice post.

\n\ \
\n\ \
" dateNoAuthor = testCase "comments with a \"published\" date but no author" (dpBody (distill True (createInput commentDateNoAuthor)) @?= expectedDateNoAuthor) commentDateNoAuthor = commentNoDateNoAuthor { Atom.entryPublished = Just "2019-01-02T03:04:05Z" } expectedDateNoAuthor = "

Hello, world!

\n\n\ \

Comments

\n\ \
\n\ \

On 2019-01-02T03:04:05Z, wrote:

\n\ \
\n\ \

Nice post.

\n\ \
\n\ \
" noDateAuthor = testCase "comments with no \"published\" date but with an author" (dpBody (distill True (createInput commentNoDateAuthor)) @?= expectedNoDateAuthor) commentNoDateAuthor = commentNoDateNoAuthor { Atom.entryAuthors = [Atom.nullPerson {Atom.personName = "John Doe"}] } expectedNoDateAuthor = "

Hello, world!

\n\n\ \

Comments

\n\ \
\n\ \

On unknown date, John Doe wrote:

\n\ \
\n\ \

Nice post.

\n\ \
\n\ \
" dateAuthor = testCase "comments with a \"published\" date and an author" (dpBody (distill True (createInput commentDateAuthor)) @?= expectedDateAuthor) commentDateAuthor = commentNoDateNoAuthor { Atom.entryPublished = Just "2019-01-02T03:04:05Z", Atom.entryAuthors = [Atom.nullPerson {Atom.personName = "John Doe"}] } expectedDateAuthor = "

Hello, world!

\n\n\ \

Comments

\n\ \
\n\ \

On 2019-01-02T03:04:05Z, John Doe wrote:

\n\ \
\n\ \

Nice post.

\n\ \
\n\ \
" enumeratesAllCommentAuthors :: TestTree enumeratesAllCommentAuthors = testCase "enumerates all authors of a multi-author comment" (dpBody (distill True input) @?= expected) where input = FullPost { fpPost = entry, fpComments = [comment], fpUri = "https://example.com/feed" } entry = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.HTMLContent "

Hello, world!

"), Atom.entryPublished = Just "2003-12-13T18:30:02Z" } comment = ( Atom.nullEntry "https://example.com/entry#comment1" (Atom.TextString "Nice") "2103-05-11T18:37:49Z" ) { Atom.entryContent = Just (Atom.HTMLContent "

Nice post.

"), Atom.entryAuthors = [ Atom.nullPerson {Atom.personName = "First Author"}, Atom.nullPerson {Atom.personName = "Second Author"} ] } expected = "

Hello, world!

\n\n\ \

Comments

\n\ \
\n\ \

On unknown date, First Author Second Author wrote:

\n\ \
\n\ \

Nice post.

\n\ \
\n\ \
" nullDistilledPost :: DistilledPost nullDistilledPost = DistilledPost { dpUri = "", dpBody = "", dpTitle = Nothing, dpTags = [], dpCategories = [], dpDate = fromGregorian 2003 12 13 18 30 2 } errorsOnNonHtmlPost :: TestTree errorsOnNonHtmlPost = expectFail $ testCase "`error`s if post has non-HTML body" (distill False input @?= nullDistilledPost) where input = FullPost { fpPost = entry, fpComments = [], fpUri = "https://example.com/feed" } entry = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.TextContent "oops, this will fail") } errorsOnNonHtmlComment :: TestTree errorsOnNonHtmlComment = expectFail $ testCase "`error`s if comment has non-HTML body" (distill False input @?= nullDistilledPost) where input = FullPost { fpPost = entry, fpComments = [comment], fpUri = "https://example.com/feed" } entry = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.TextContent "testing...") } comment = ( Atom.nullEntry "https://example.com/entry#2" (Atom.TextString "test comment") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.TextContent "oops, this will fail") } turnsIncorrectDatesIntoEpochStart :: TestTree turnsIncorrectDatesIntoEpochStart = testGroup "turns incorrect \"published\" dates into Unix epoch start date" [ testCase (T.unpack date) (dpDate (distill False (createInput date)) @?= expected) | date <- [ "First of April", "2020.07.30", "2020.07.30 00:01", "2020-07-30 00:01", "2020-07-30T00:01", "2020-07-30T00:01Z", "Sun, 31st July, 2020" ] ] where createInput date = FullPost { fpPost = createEntry date, fpComments = [], fpUri = "https://example.com/feed" } createEntry date = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") date ) { Atom.entryContent = Just (Atom.HTMLContent ""), Atom.entryPublished = Just date } expected = fromGregorian 1970 1 1 0 0 0 parsesDates :: TestTree parsesDates = testGroup "parses \"published\" dates" [ testCase (T.unpack dateStr) (dpDate (distill False (createInput dateStr)) @?= expected) | (dateStr, expected) <- [ ("2020-07-30T15:50:21Z", fromGregorian 2020 7 30 15 50 21), ("1015-02-18T01:04:13Z", fromGregorian 1015 2 18 1 4 13), ("2020-07-30T15:50:21+0000", fromGregorian 2020 7 30 15 50 21), ("1015-02-18T01:04:13+0000", fromGregorian 1015 2 18 1 4 13), ("1015-02-18T01:04:13+0001", fromGregorian 1015 2 18 1 (4 -1) 13), ("1015-02-18T01:04:13-0001", fromGregorian 1015 2 18 1 (4 + 1) 13), ("1015-02-18T01:04:13+0100", fromGregorian 1015 2 18 (1 -1) 4 13), ("1015-02-18T01:04:13-0100", fromGregorian 1015 2 18 (1 + 1) 4 13) ] ] where createInput date = FullPost { fpPost = createEntry date, fpComments = [], fpUri = "https://example.com/feed" } createEntry date = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") date ) { Atom.entryContent = Just (Atom.HTMLContent ""), Atom.entryPublished = Just date } extractsPostTags :: TestTree extractsPostTags = testCase "extracts post's tags" (dpTags (distill False input) @?= expected) where input = FullPost { fpPost = entry, fpComments = [], fpUri = "https://example.com/feed" } entry = ( Atom.nullEntry "https://example.com/entry" (Atom.TextString "First post") "2003-12-13T18:30:02Z" ) { Atom.entryContent = Just (Atom.HTMLContent ""), Atom.entryCategories = [ Atom.newCategory "first tag", Atom.newCategory "second tag", Atom.newCategory "third tag", (Atom.newCategory "blogger category (should be ignored)") { Atom.catScheme = Just "http://schemas.google.com/g/2005#kind" } ] } expected = ["first tag", "second tag", "third tag"]