packages feed

hpack-0.29.4: test/Hpack/Syntax/DependencySpec.hs

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ConstraintKinds #-}
module Hpack.Syntax.DependencySpec (spec) where

import           Helper

import           Data.Aeson.Config.FromValueSpec (shouldDecodeTo, shouldDecodeTo_)

import           Data.Aeson.Config.FromValue
import           Hpack.Syntax.Dependency

left :: String -> Result Dependencies
left = Left

spec :: Spec
spec = do
  describe "fromValue" $ do
    context "when parsing Dependencies" $ do
      context "with a scalar" $ do
        it "accepts dependencies without constraints" $ do
          [yaml|
            hpack
          |] `shouldDecodeTo_` Dependencies [("hpack", AnyVersion)]

        it "accepts dependencies with constraints" $ do
          [yaml|
            hpack >= 2 && < 3
          |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange ">=2 && <3")]

        context "with invalid constraint" $ do
          it "returns an error message" $ do
            [yaml|
              hpack ==
            |] `shouldDecodeTo` left "Error while parsing $ - invalid dependency \"hpack ==\""

      context "with a list" $ do
        it "accepts dependencies without constraints" $ do
          [yaml|
            - hpack
          |] `shouldDecodeTo_` Dependencies [("hpack", AnyVersion)]

        it "accepts dependencies with constraints" $ do
          [yaml|
            - hpack >= 2 && < 3
          |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange ">=2 && <3")]

        it "accepts ^>=" $ do
          [yaml|
            - hpack ^>= 1.2.3.4
          |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange ">=1.2.3.4 && <1.3")]

        it "accepts git dependencies" $ do
          let source = GitRef "https://github.com/sol/hpack" "master" Nothing
          [yaml|
            - name: hpack
              git: https://github.com/sol/hpack
              ref: master
          |] `shouldDecodeTo_` Dependencies [("hpack", SourceDependency source)]

        it "accepts github dependencies" $ do
          let source = GitRef "https://github.com/sol/hpack" "master" Nothing
          [yaml|
            - name: hpack
              github: sol/hpack
              ref: master
          |] `shouldDecodeTo_` Dependencies [("hpack", SourceDependency source)]

        it "accepts an optional subdirectory for git dependencies" $ do
          let source = GitRef "https://github.com/yesodweb/wai" "master" (Just "warp")
          [yaml|
            - name: warp
              github: yesodweb/wai
              ref: master
              subdir: warp
          |] `shouldDecodeTo_` Dependencies [("warp", SourceDependency source)]

        it "accepts local dependencies" $ do
          let source = Local "../hpack"
          [yaml|
            - name: hpack
              path: ../hpack
          |] `shouldDecodeTo_` Dependencies [("hpack", SourceDependency source)]

        context "when ref is missing" $ do
          it "produces accurate error messages" $ do
            [yaml|
              - name: hpack
                git: sol/hpack
                ef: master
            |] `shouldDecodeTo` left "Error while parsing $[0] - key \"ref\" not present"

        context "when both git and github are missing" $ do
          it "produces accurate error messages" $ do
            [yaml|
              - name: hpack
                gi: sol/hpack
                ref: master
            |] `shouldDecodeTo` left "Error while parsing $[0] - neither key \"git\" nor key \"github\" present"

      context "with a mapping from dependency names to constraints" $ do
        it "accepts dependencies without constraints" $ do
          [yaml|
            array:
          |] `shouldDecodeTo_` Dependencies [("array", AnyVersion)]

        it "rejects invalid values" $ do
          [yaml|
            hpack: []
          |] `shouldDecodeTo` left "Error while parsing $.hpack - expected Null, Object, Number, or String, encountered Array"

        context "when the constraint is a Number" $ do
          it "accepts 1" $ do
            [yaml|
              hpack: 1
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange "==1")]

          it "accepts 1.0" $ do
            [yaml|
              hpack: 1.0
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange "==1.0")]

          it "accepts 0.11" $ do
            [yaml|
              hpack: 0.11
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange "==0.11")]

          it "accepts 0.110" $ do
            [yaml|
              hpack: 0.110
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange "==0.110")]

          it "accepts 1e2" $ do
            [yaml|
              hpack: 1e2
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange "==100")]

        context "when the constraint is a String" $ do
          it "accepts version ranges" $ do
            [yaml|
              hpack: '>=2'
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange ">=2")]

          it "accepts specific versions" $ do
            [yaml|
              hpack: 0.10.8.2
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange "==0.10.8.2")]

          it "accepts wildcard versions" $ do
            [yaml|
              hpack: 2.*
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange "==2.*")]

          it "accepts ^>=" $ do
            [yaml|
              hpack: ^>= 1.2.3.4
            |] `shouldDecodeTo_` Dependencies [("hpack", VersionRange ">=1.2.3.4 && <1.3")]

          it "reports parse errors" $ do
            [yaml|
              hpack: foo
            |] `shouldDecodeTo` left "Error while parsing $.hpack - invalid constraint \"foo\""

        context "when the constraint is an Object" $ do
          it "accepts github dependencies" $ do
            [yaml|
              Cabal:
                github: haskell/cabal
                ref: d53b6e0d908dfedfdf4337b2935519fb1d689e76
                subdir: Cabal
            |] `shouldDecodeTo_` Dependencies [("Cabal", SourceDependency (GitRef "https://github.com/haskell/cabal" "d53b6e0d908dfedfdf4337b2935519fb1d689e76" (Just "Cabal")))]

          it "ignores names in nested hashes" $ do
            [yaml|
              outer-name:
                name: inner-name
                path: somewhere
            |] `shouldDecodeTo` Right (Dependencies [("outer-name", SourceDependency (Local "somewhere"))], ["$.outer-name.name"])