cursor-gen-0.0.0.0: test/Cursor/Simple/List/NonEmptySpec.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Cursor.Simple.List.NonEmptySpec
( spec
) where
import Test.Hspec
import Test.QuickCheck
import Test.Validity
import Test.Validity.Optics
import Control.Monad
import Cursor.Simple.List.NonEmpty
import Cursor.Simple.List.NonEmpty.Gen
spec :: Spec
spec = do
eqSpec @(NonEmptyCursor Int)
genValidSpec @(NonEmptyCursor Double)
shrinkValidSpec @(NonEmptyCursor Double)
describe "makeNonEmptyCursor" $
it "produces valid cursors" $
producesValidsOnValids (makeNonEmptyCursor @Double)
describe "makeNonEmptyCursorWithSelection" $ do
it "produces valid cursors" $
producesValidsOnValids2 (makeNonEmptyCursorWithSelection @Double)
it
"is the inverse of rebuildNonEmptyCursor when using the current selection" $
forAllValid $ \lec ->
makeNonEmptyCursorWithSelection
(nonEmptyCursorSelection @Double lec)
(rebuildNonEmptyCursor lec) `shouldBe`
Just lec
describe "singletonNonEmptyCursor" $
it "produces valid cursors" $
producesValidsOnValids (singletonNonEmptyCursor @Double @Double)
describe "rebuildNonEmptyCursor" $ do
it "produces valid nonempty lists" $
producesValidsOnValids (rebuildNonEmptyCursor @Double)
it "is the inverse of makeNonEmptyCursor for integers" $
inverseFunctions (makeNonEmptyCursor @Int) rebuildNonEmptyCursor
it
"is the inverse of makeNonEmptyCursorWithSelection for integers, for any index" $
forAll genUnchecked $ \i ->
inverseFunctionsIfFirstSucceedsOnValid
(makeNonEmptyCursorWithSelection @Int i)
rebuildNonEmptyCursor
describe "nonEmptyCursorElemL" $
lensSpecOnValid (nonEmptyCursorElemL @Double @Double)
describe "nonEmptyCursorSelectPrev" $ do
it "produces valid cursors" $
producesValidsOnValids (nonEmptyCursorSelectPrev @Double)
it "is a movement" $ isMovementM nonEmptyCursorSelectPrev
it "selects the previous element" pending
describe "nonEmptyCursorSelectNext" $ do
it "produces valid cursors" $
producesValidsOnValids (nonEmptyCursorSelectNext @Double)
it "is a movement" $ isMovementM nonEmptyCursorSelectNext
it "selects the next element" pending
describe "nonEmptyCursorSelectFirst" $ do
it "produces valid cursors" $
producesValidsOnValids (nonEmptyCursorSelectFirst @Double)
it "is a movement" $ isMovement nonEmptyCursorSelectFirst
it "is idempotent" $
idempotentOnValid (nonEmptyCursorSelectFirst @Double)
it "selects the first element" pending
describe "nonEmptyCursorSelectLast" $ do
it "produces valid cursors" $
producesValidsOnValids (nonEmptyCursorSelectLast @Double)
it "is a movement" $ isMovement nonEmptyCursorSelectLast
it "is idempotent" $
idempotentOnValid (nonEmptyCursorSelectLast @Double)
it "selects the last element" pending
describe "nonEmptyCursorSelection" $ do
it "produces valid ints" $
producesValidsOnValids (nonEmptyCursorSelection @Double @Double)
it "returns the index of the currently selected element" pending
describe "nonEmptyCursorSelectIndex" $ do
it "produces valid cursors" $
producesValidsOnValids2 (nonEmptyCursorSelectIndex @Double)
it "is the identity function when given the current selection" $
forAllValid $ \nec ->
nonEmptyCursorSelectIndex (nonEmptyCursorSelection nec) nec `shouldBe`
Just (nec :: NonEmptyCursor Double)
it "returns selects the element at the given index" pending
describe "nonEmptyCursorInsert" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids (nonEmptyCursorInsert @Double @Double d)
it "inserts a character before the cursor" pending
describe "nonEmptyCursorAppend" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids (nonEmptyCursorAppend @Double @Double d)
it "inserts a character after the cursor" pending
describe "nonEmptyCursorInsertAndSelect" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids (nonEmptyCursorInsertAndSelect @Double d)
it "inserts a character before the cursor and selects it" pending
describe "nonEmptyCursorAppendAndSelect" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids (nonEmptyCursorAppendAndSelect @Double d)
it "appends a character before the cursor and selects it" pending
describe "nonEmptyCursorInsertAtStart" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids
(nonEmptyCursorInsertAtStart @Double @Double d)
it "inserts a character at the start of the list" pending
describe "nonEmptyCursorAppendAtEnd" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids
(nonEmptyCursorAppendAtEnd @Double @Double d)
it "inserts a character at the end of the list" pending
describe "nonEmptyCursorInsertAtStartAndSelect" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids
(nonEmptyCursorInsertAtStartAndSelect @Double d)
it "inserts a character at the start of the list and selects it" pending
describe "nonEmptyCursorAppendAtEndAndSelect" $ do
it "produces valid cursors" $
forAllValid $ \d ->
producesValidsOnValids
(nonEmptyCursorAppendAtEndAndSelect @Double d)
it "appends a character at the end of the list and selects it" pending
describe "nonEmptyCursorRemoveElem" $ do
it "produces valid cursors" $
producesValidsOnValids (nonEmptyCursorRemoveElem @Double)
it "removes an element" pending
describe "nonEmptyCursorDeleteElem" $ do
it "produces valid cursors" $
producesValidsOnValids (nonEmptyCursorDeleteElem @Double)
describe "nonEmptyCursorSearch" $ do
it "produces valid cursors when looking for an equal element" $
forAllValid $ \a ->
producesValidsOnValids $ nonEmptyCursorSearch (== (a :: Double))
it
"is indeed the right value when it finds a value and is looking for an equal element" $
forAllValid $ \a ->
forAllValid $ \nec ->
case nonEmptyCursorSearch (== (a :: Double)) nec of
Nothing -> pure ()
Just e -> nonEmptyCursorCurrent e `shouldBe` a
it "finds an element if it is in there" $
forAllValid $ \a ->
forAll (nonEmptyWith a genValid) $ \nec ->
case nonEmptyCursorSearch (== (a :: Double)) nec of
Nothing ->
expectationFailure
"Should not have failed to find the element."
Just e -> nonEmptyCursorCurrent e `shouldBe` a
describe "nonEmptyCursorSelectOrAdd" $ do
it "produces valid cursors when looking for an equal element" $
forAllValid $ \a ->
producesValidsOnValids $
nonEmptyCursorSelectOrAdd (== a) (a :: Double)
isMovementM ::
(forall a. NonEmptyCursor a -> Maybe (NonEmptyCursor a)) -> Property
isMovementM func =
forAllValid $ \lec ->
case func (lec :: NonEmptyCursor Double) of
Nothing -> pure () -- Fine
Just lec' ->
let ne = rebuildNonEmptyCursor lec
ne' = rebuildNonEmptyCursor lec'
in unless (ne == ne') $
expectationFailure $
unlines
[ "Cursor before:\n" ++ show lec
, "List before: \n" ++ show ne
, "Cursor after: \n" ++ show lec'
, "List after: \n" ++ show ne'
]
isMovement :: (forall a. NonEmptyCursor a -> NonEmptyCursor a) -> Property
isMovement func =
forAllValid $ \lec ->
rebuildNonEmptyCursor (lec :: NonEmptyCursor Double) `shouldBe`
rebuildNonEmptyCursor (func lec)