content: {-# LANGUAGE CPP #-}
  module Test.Hspec.Core.SpecSpec (spec) where
  
  import           Prelude ()
  import           Helper
  
  import           Test.Hspec.Core.Spec (Item(..), Result(..), ResultStatus(..))
  import qualified Test.Hspec.Core.Runner as H
  import           Test.Hspec.Core.Spec (Tree(..))
  
  import qualified Test.Hspec.Core.Spec as H
  
  extract :: (Item () -> a) -> H.Spec -> IO [Tree () a]
  extract f = fmap (H.bimapForest (const ()) f) . fmap snd . H.runSpecM
  
  runSpec :: H.Spec -> IO [String]
  runSpec = captureLines . H.hspecResult
  
  spec :: Spec
  spec = do
    let
      runSpecM :: H.SpecWith a -> IO [H.SpecTree a]
      runSpecM = fmap snd . H.runSpecM
  
      runItem :: Item () -> IO Result
      runItem item = itemExample item defaultParams ($ ()) noOpProgressCallback
  
    describe "getSpecDescriptionPath" $ do
      it "returns the spec path" $ do
        let descriptionPathShouldBe xs =
              H.getSpecDescriptionPath >>= H.runIO . (`shouldBe` xs)
        void . runSpecM $ do
          descriptionPathShouldBe []
          H.describe "foo" $ do
            H.describe "bar" $ do
              descriptionPathShouldBe ["foo", "bar"]
              H.it "baz" True
  
    describe "describe" $ do
      it "can be nested" $ do
        [Node foo [Node bar [Leaf _]]] <- runSpecM $ do
          H.describe "foo" $ do
            H.describe "bar" $ do
              H.it "baz" True
        (foo, bar) `shouldBe` ("foo", "bar")
  
      context "when no description is given" $ do
        it "uses a default description" $ do
          [Node d _] <- runSpecM (H.describe "" (pure ()))
          d `shouldBe` "Test.Hspec.Core.SpecSpec[" ++ show (pred __LINE__ :: Int) ++ ":33]"
  
    describe "xdescribe" $ do
      it "creates a tree of pending spec items" $ do
        [Node _ [Leaf item]] <- runSpecM (H.xdescribe "" $ H.it "whatever" True)
        runItem item `shouldReturn` Result "" (Pending Nothing Nothing)
  
    describe "it" $ do
      it "takes a description of a desired behavior" $ do
        [Leaf item] <- runSpecM (H.it "whatever" True)
        itemRequirement item `shouldBe` "whatever"
  
      it "takes an example of that behavior" $ do
        [Leaf item] <- runSpecM (H.it "whatever" True)
        runItem item `shouldReturn` Result "" Success
  
      it "adds source locations" $ do
        [Leaf item] <- runSpecM (H.it "foo" True)
        let location = mkLocation __FILE__ (pred __LINE__) 32
        itemLocation item `shouldBe` location
  
    describe "xit" $ do
      it "creates a pending spec item" $ do
        [Leaf item] <- runSpecM (H.xit "whatever" True)
        runItem item `shouldReturn` Result "" (Pending Nothing Nothing)
  
    describe "pending" $ do
      it "specifies a pending example" $ do
        r <- runSpec $ do
          H.it "foo" H.pending
        r `shouldSatisfy` any (== "  # PENDING: No reason given")
  
    describe "pendingWith" $ do
      it "specifies a pending example with a reason for why it's pending" $ do
        r <- runSpec $ do
          H.it "foo" $ do
            H.pendingWith "for some reason"
        r `shouldSatisfy` any (== "  # PENDING: for some reason")
  
    describe "focus" $ do
      it "focuses spec items" $ do
        items <- extract itemIsFocused $ H.focus $ do
          H.it "is focused and will run" True
          H.it "is also focused and will also run" True
        items `shouldBe` [Leaf True, Leaf True]
  
      context "when applied to a spec with focused spec items" $ do
        it "has no effect" $ do
          items <- extract itemIsFocused $ H.focus $ do
            H.focus $ H.it "is focused and will run" True
            H.it "is not focused and will not run" True
          items `shouldBe` [Leaf True, Leaf False]
  
    describe "parallel" $ do
      it "marks examples for parallel execution" $ do
        items <- extract itemIsParallelizable . H.parallel $ H.it "whatever" H.pending
        items `shouldBe` [Leaf $ Just True]
  
      it "is applied recursively" $ do
        items <- extract itemIsParallelizable . H.parallel $ do
          H.describe "foo" $ do
            H.describe "bar" $ do
              H.it "baz" H.pending
        items `shouldBe` [Node "foo" [Node "bar" [Leaf $ Just True]]]
  
    describe "sequential" $ do
      it "marks examples for sequential execution" $ do
        items <- extract itemIsParallelizable . H.sequential $ H.it "whatever" H.pending
        items `shouldBe` [Leaf $ Just False]
  
      it "takes precedence over a later `parallel`" $ do
        items <- extract itemIsParallelizable . H.parallel . H.sequential $ H.it "whatever" H.pending
        items `shouldBe` [Leaf $ Just False]
  