geojson-4.1.0: test/Data/LineStringTests.hs
module Data.LineStringTests where
-- Local
import Arbitrary ()
import qualified Data.Geospatial.Internal.BasicTypes as BasicTypes
import qualified Data.LineString as LineString
import qualified Data.Sequence as Sequence
import Data.Validation (Validation (..))
import Test.Tasty
import Test.Tasty.Hspec
( Spec,
context,
describe,
it,
shouldBe,
testSpec,
)
import Test.Tasty.QuickCheck
( Property,
property,
testProperty,
)
-- Tests
tests :: IO TestTree
tests = do
specs <- specTests
pure $ testGroup "Data.LineStringTests" [qcTests, specs]
qcTests :: TestTree
qcTests =
testGroup
"Data.LineStringTests.QuickCheck"
[ testProperty "Data.LineString.lineStringLength" testLineStringLength,
testProperty "Data.LineString.fromLineString" testFromLineString,
testProperty "Data.LineString.Foldable" testFoldable
]
specTests :: IO TestTree
specTests = do
specs <-
sequence
[ testSpec "Data.LineString.fromList" testFromList,
testSpec "Data.LineString.fromSeq" testFromSequence,
testSpec "Data.LineString.toSeq" testToSequence,
testSpec "Data.LineString.combineToSequence" testCombineToSequence
]
pure $ testGroup "Data.LineStringTests.Spec" specs
-- QuickCheck
-- (\xs -> lineStringLength xs == (length (fromLineString xs))) (xs :: LineString Int)
--
testLineStringLength :: LineString.LineString Int -> Property
testLineStringLength xs = property $ LineString.lineStringLength xs == length (LineString.fromLineString xs)
-- (\xs -> length (fromLineString xs) >= 4) (xs :: LineString Int)
--
testFromLineString :: LineString.LineString Int -> Property
testFromLineString xs = property $ length (LineString.fromLineString xs) >= 2
-- > (\xs -> (foldr (:) [] xs) == (fromLineString xs)) (xs :: LineString Int)
--
-- > (\xs -> (lineStringHead xs) == (foldr (\a -> const a) 0 xs)) (xs :: LineString Int)
--
testFoldable :: LineString.LineString Int -> Property
testFoldable xs = property $ (foldr (:) [] xs == LineString.fromLineString xs) && (LineString.lineStringHead xs == foldr const 0 xs)
-- Spec
-- >>> fromList [] :: Validation ListToLineStringError (LineString Int)
-- Failure List Empty
--
-- >>> fromList [0] :: Validation ListToLineStringError (LineString Int)
-- Failure Singleton List
--
-- >>> fromList [0, 1] :: Validation ListToLineStringError (LineString Int)
-- Success [0,1]
--
-- >>> fromList [0, 1, 2] :: Validation ListToLineStringError (LineString Int)
-- Success [0,1,2]
--
-- >>> fromList [0, 1, 2, 4, 5, 0] :: Validation ListToLineStringError (LineString Int)
-- Success [0,1,2,4,5,0]
--
testFromList :: Spec
testFromList =
describe "fromList" $ do
it "creates a LineString out of a list of elements" $ do
LineString.fromList ([0, 1] :: [Int]) `shouldBe` Success (LineString.makeLineString 0 1 Sequence.empty)
LineString.fromList ([0, 1, 2] :: [Int]) `shouldBe` Success (LineString.makeLineString 0 1 (Sequence.fromList [2]))
LineString.fromList ([0, 1, 2, 4, 5, 0] :: [Int]) `shouldBe` Success (LineString.makeLineString 0 1 (Sequence.fromList [2, 4, 5, 0]))
context "when provided with invalid input" $
it "fails" $ do
LineString.fromList ([] :: [Int]) `shouldBe` Failure LineString.ListEmpty
LineString.fromList ([0] :: [Int]) `shouldBe` Failure LineString.SingletonList
testFromSequence :: Spec
testFromSequence =
describe "fromSeq" $ do
it "creates a LineString out of a Sequence of elements" $ do
LineString.fromSeq (Sequence.fromList [0, 1] :: (Sequence.Seq Int)) `shouldBe` Success (LineString.makeLineString 0 1 Sequence.empty)
LineString.fromSeq (Sequence.fromList [0, 1, 2] :: (Sequence.Seq Int)) `shouldBe` Success (LineString.makeLineString 0 1 (Sequence.fromList [2]))
LineString.fromSeq (Sequence.fromList [0, 1, 2, 4, 5, 0] :: (Sequence.Seq Int)) `shouldBe` Success (LineString.makeLineString 0 1 (Sequence.fromList [2, 4, 5, 0]))
context "when provided with invalid input" $
it "fails" $ do
LineString.fromSeq (Sequence.fromList [] :: (Sequence.Seq Int)) `shouldBe` Failure LineString.SequenceEmpty
LineString.fromSeq (Sequence.fromList [0] :: (Sequence.Seq Int)) `shouldBe` Failure LineString.SingletonSequence
testCombineToSequence :: Spec
testCombineToSequence =
describe "combineToSeq" $
it "combine a LineString using PointXY" $ do
LineString.combineToSeq BasicTypes.PointXY (LineString.makeLineString 0 1 Sequence.empty) `shouldBe` Sequence.fromList [BasicTypes.PointXY 0 1]
LineString.combineToSeq BasicTypes.PointXY (LineString.makeLineString 0 1 (Sequence.fromList [2])) `shouldBe` Sequence.fromList [BasicTypes.PointXY 0 1, BasicTypes.PointXY 1 2]
LineString.combineToSeq BasicTypes.PointXY (LineString.makeLineString 0 1 (Sequence.fromList [2, 4, 5, 0])) `shouldBe` Sequence.fromList [BasicTypes.PointXY 0 1, BasicTypes.PointXY 1 2, BasicTypes.PointXY 2 4, BasicTypes.PointXY 4 5, BasicTypes.PointXY 5 0]
testToSequence :: Spec
testToSequence =
describe "toSeq" $
it "from a LineString to a Sequence" $ do
LineString.toSeq (LineString.makeLineString 0 1 Sequence.empty) `shouldBe` Sequence.fromList ([0, 1] :: [Int])
LineString.toSeq (LineString.makeLineString 0 1 (Sequence.fromList [2])) `shouldBe` Sequence.fromList ([0, 1, 2] :: [Int])
LineString.toSeq (LineString.makeLineString 0 1 (Sequence.fromList [2, 4, 5, 0])) `shouldBe` Sequence.fromList ([0, 1, 2, 4, 5, 0] :: [Int])
-- TODO
-- (\xs -> safeLast (fromLineString xs) == Just (lineStringHead xs)) (xs :: LineString Int)