module Core.Test.Descript.Spec
  ( shouldFailTo_
  , shouldFailToSummaryIn
  , shouldFailToSummaries
  , shouldBeReducePrintOf
  ) where

import Test.Hspec
import Test.HUnit
import Descript.Misc
import Data.List
import Control.Monad

-- | Asserts the result should be a failure, and the error should be the
-- given value.
shouldFailTo_ :: (HasCallStack, Eq e, Show e, Summary a) => Result e a -> e -> Expectation
shouldFailTo_ = shouldFailToGen id

-- | Asserts the result should be a failure, and the error's summary
-- should be the given value.
shouldFailToSummaryIn :: (HasCallStack, FileSummary e, Summary a) => SFile -> Result e a -> String -> Expectation
shouldFailToSummaryIn = shouldFailToGen . summaryF

-- | Asserts the result should be a failure, and the errors' summaries
-- should be the given values.
shouldFailToSummaries :: (HasCallStack, Summary e, Summary a) => Result [e] a -> [String] -> Expectation
shouldFailToSummaries = shouldFailToGen $ map summary

shouldFailToGen :: (HasCallStack, Eq ee, Show ee, Summary a) => (ae -> ee) -> Result ae a -> ee -> Expectation
shouldFailToGen f (Failure aerr) eerr = f aerr `shouldBe` eerr
shouldFailToGen _ (Success val) _ = assertFailure $ "Unexpected success: " ++ summary val

-- | Specifies that the left string should be a subsequence of the right.
shouldBeReducePrintOf :: (HasCallStack) => String -> String -> Expectation
rp `shouldBeReducePrintOf` full
  = unless (rp `isSubsequenceOf` full) $ assertFailure failMsg
  where failMsg
           = "not a reduce print:\n"
          ++ rp
          ++ "\n----- isn't a reduce print of -----\n"
          ++ full