xrefcheck-0.2.2: tests/Test/Xrefcheck/ConfigSpec.hs
{- SPDX-FileCopyrightText: 2019-2021 Serokell <https://serokell.io>
-
- SPDX-License-Identifier: MPL-2.0
-}
module Test.Xrefcheck.ConfigSpec where
import Universum
import Control.Concurrent (forkIO, killThread)
import Control.Exception qualified as E
import Data.ByteString qualified as BS
import Data.List (isInfixOf)
import Data.Yaml (ParseException (..), decodeEither')
import Network.HTTP.Types (Status (..))
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertFailure, testCase, (@?=))
import Test.Tasty.QuickCheck (ioProperty, testProperty)
import Xrefcheck.Config (Config, Config' (..), VerifyConfig' (..), defConfig, defConfigText)
import Xrefcheck.Core (Flavor (GitHub), allFlavors)
import Xrefcheck.Verify (VerifyError (..), VerifyResult (..), checkExternalResource)
import Test.Xrefcheck.Util (mockServer)
test_config :: [TestTree]
test_config =
[ testGroup "Default config is valid" [
testProperty (show flavor) $
ioProperty $ evaluateWHNF_ @_ @Config (defConfig flavor)
| flavor <- allFlavors]
, testGroup "Filled default config matches the expected format"
-- The config we match against can be regenerated with
-- stack exec xrefcheck -- dump-config -t GitHub -o tests/configs/github-config.yaml
[ testCase "Config matches" $ do
config <- BS.readFile "tests/configs/github-config.yaml"
when (config /= defConfigText GitHub) $
assertFailure $ toString $ unwords
[ "Config does not match the expected format."
, "Run"
, "`stack exec xrefcheck -- dump-config -t GitHub -o tests/configs/github-config.yaml`"
, "and verify changes"
]
]
, testGroup "`ignoreAuthFailures` working as expected" $
let config = (cVerification $ defConfig GitHub) { vcIgnoreRefs = [] }
in [ testCase "when True - assume 401 status is valid" $
checkLinkWithServer (config { vcIgnoreAuthFailures = True })
"http://127.0.0.1:3000/401" $ VerifyResult []
, testCase "when False - assume 401 status is invalid" $
checkLinkWithServer (config { vcIgnoreAuthFailures = False })
"http://127.0.0.1:3000/401" $ VerifyResult
[ ExternalHttpResourceUnavailable $
Status { statusCode = 401, statusMessage = "Unauthorized" }
]
, testCase "when True - assume 403 status is valid" $
checkLinkWithServer (config { vcIgnoreAuthFailures = True })
"http://127.0.0.1:3000/403" $ VerifyResult []
, testCase "when False - assume 403 status is invalid" $
checkLinkWithServer (config { vcIgnoreAuthFailures = False })
"http://127.0.0.1:3000/403" $ VerifyResult
[ ExternalHttpResourceUnavailable $
Status { statusCode = 403, statusMessage = "Forbidden" }
]
]
, testGroup "Config parser reject input with unknown fields"
[ testCase "throws error with useful messages" $ do
case decodeEither' @Config (defConfigText GitHub <> "strangeField: []") of
Left (AesonException str) ->
if "unknown fields: [\"strangeField\"]" `isInfixOf` str
then pure ()
else assertFailure $ "Bad error message: " <> str
_ -> assertFailure "Config parser accepted config with unknown field"
]
]
where
checkLinkWithServer config link expectation =
E.bracket (forkIO mockServer) killThread $ \_ -> do
result <- checkExternalResource config link
result @?= expectation