content: {-# LANGUAGE TypeApplications #-}
  module Main where
  
  import           Test.Hspec
  
  import           Versioning.Base
  import           Versioning.JSON
  import           Versioning.Upgrade
  
  import           Tests.Versioning.Fixtures (Foo (..), SumType (..), foo0, foo2,
                                              fooJsonV0, fooJsonV2, sumType)
  
  main :: IO ()
  main = hspec $ do
      describe "Versioning" $ do
          it "Can get the version number of a record" $
              versionNumber foo0 `shouldBe` 0
  
          it "Can read versioned record fields if present at given version" $
              sinceV2 foo2 `shouldBe` "hello"
  
          it "Can read versioned sum-type constructors if present at given version" $
              sumType `shouldBe` MkFoo ()
  
      describe "Upgrade" $ do
          it "Can upgrade across two versions" $
              upgrade foo0 `shouldBe` foo2
  
      describe "Downgrade" $ do
          it "Can downgrade across two versions" $
              downgrade foo2 `shouldBe` foo0
  
      describe "DecodeAnyVersion" $ do
          it "Can decode from V0" $
              fromJsonAnyVersion @V2 fooJsonV0 `shouldBe` Just foo2
  
          it "Can decode from V2" $
              fromJsonAnyVersion @V2 fooJsonV2 `shouldBe` Just foo2
  
      describe "DecodeAnyVersionFrom" $ do
          it "Can decode from V1" $
              fromJsonAnyVersionFrom @V1 @V2 fooJsonV2 `shouldBe` Just foo2
  
          it "Should not decode V0" $
              fromJsonAnyVersionFrom @V1 @V2 fooJsonV0 `shouldBe` (Nothing :: Maybe (Foo V2))
  
      describe "WithAnyVersion" $ do
          -- Decode a Foo and return its string representation without upgrading it
          it "Can apply a function on the decoded object" $ do
              let Just res = withJsonAnyVersion @Show @Foo @V2 show fooJsonV0
              res `shouldBe` show foo0
  
      describe "WithAnyVersionFrom" $ do
          it "Can apply a function on the decoded object" $ do
              let Just res = withJsonAnyVersionFrom @V1 @Show @Foo @V2 show fooJsonV2
              res `shouldBe` show foo2
  
          it "Should not decode V0" $ do
              let res = withJsonAnyVersionFrom @V1 @Show @Foo @V2 show fooJsonV0
              res `shouldBe` (Nothing :: Maybe String)
  