cursor-gen-0.2.0.0: test/Cursor/TextFieldSpec.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Cursor.TextFieldSpec
( spec
) where
import Test.Hspec
import Test.QuickCheck
import Test.Validity
-- import Test.Validity.Optics
import Text.Show.Pretty (ppShow)
import qualified Data.Text as T
import qualified Data.List.NonEmpty as NE
import Control.Monad
import Cursor.List.NonEmpty
import Cursor.TextField
import Cursor.TextField.Gen ()
import Cursor.Types
spec :: Spec
spec = do
eqSpecOnValid @TextFieldCursor
genValidSpec @TextFieldCursor
describe "Validity TextFieldCursor" $ do
it "consider a textfield with a newline in the previous lines invalid" $
forAllValid $ \tc ->
shouldBeInvalid $
TextFieldCursor
{ textFieldCursorNonEmpty =
NonEmptyCursor
{nonEmptyCursorPrev = ["\n"], nonEmptyCursorCurrent = tc, nonEmptyCursorNext = []}
}
it "consider a textfield with a newline in the next lines invalid" $
forAllValid $ \tc ->
shouldBeInvalid $
TextFieldCursor
{ textFieldCursorNonEmpty =
NonEmptyCursor
{nonEmptyCursorPrev = [], nonEmptyCursorCurrent = tc, nonEmptyCursorNext = ["\n"]}
}
describe "makeTextFieldCursor" $ do
it "produces a valid cursor for \"\\n\"" $ shouldBeValid $ makeTextFieldCursor "\n"
it "produces a valid cursor for \"\\n\\n\"" $ shouldBeValid $ makeTextFieldCursor "\n\n"
it "produces valid cursors" $ producesValidsOnValids makeTextFieldCursor
describe "makeTextFieldCursorWithSelection" $ do
it "produces a valid cursor for \"\\n\"" $
forAllValid $ \x ->
forAllValid $ \y -> shouldBeValid $ makeTextFieldCursorWithSelection x y "\n"
it "produces a valid cursor for \"\\n\\n\"" $
forAllValid $ \x ->
forAllValid $ \y -> shouldBeValid $ makeTextFieldCursorWithSelection x y "\n\n"
it "produces valid cursors" $ producesValidsOnValids3 makeTextFieldCursorWithSelection
it "is the inverse of rebuildTextFieldCursor when using the current selection" $
forAllValid $ \tfc -> do
let (x, y) = textFieldCursorSelection tfc
t = rebuildTextFieldCursor tfc
case makeTextFieldCursorWithSelection x y t of
Nothing -> expectationFailure "makeTextFieldCursorWithSelection should not have failed."
Just tfc' ->
unless (tfc' == tfc) $
expectationFailure $
unlines
[ "expected"
, ppShow tfc
, "actual"
, ppShow tfc'
, "The selection of the original (expected) cursor was:"
, show (x, y)
, "The rebuild text was:"
, show t
]
describe "rebuildTextFieldCursorLines" $ do
it "produces valid lists" $ producesValidsOnValids rebuildTextFieldCursorLines
it "produces texts without newlines" $
forAllValid $ \tfc -> do
let ls = NE.toList $ rebuildTextFieldCursorLines tfc
unless (all (T.all (/= '\n')) ls) $
expectationFailure $
unlines $ "Some of the following lines contain a newline:" : map show ls
describe "rebuildTextFieldCursor" $ do
it "produces valid texts" $ producesValidsOnValids rebuildTextFieldCursor
it "is the inverse of makeTextFieldCursor" $
inverseFunctionsOnValid makeTextFieldCursor rebuildTextFieldCursor
it "is the inverse of makeTextFieldCursorWithSelection for integers, for any index" $
forAllValid $ \x ->
forAllValid $ \y ->
inverseFunctionsIfFirstSucceedsOnValid
(makeTextFieldCursorWithSelection x y)
rebuildTextFieldCursor
describe "textFieldCursorSelection" $
it "produces valid tuples" $ producesValidsOnValids textFieldCursorSelection
describe "emptyTextFieldCursor" $ it "is valid" $ shouldBeValid emptyTextFieldCursor
describe "nullTextFieldCursor" $ it "produces valid" $ producesValidsOnValids nullTextFieldCursor
describe "textFieldCursorSelectPrevLine" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectPrevLine
it "is a movement" $ isMovementM textFieldCursorSelectPrevLine
it "selects the previous line" pending
describe "textFieldCursorSelectNextLine" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectNextLine
it "is a movement" $ isMovementM textFieldCursorSelectNextLine
it "selects the next line" pending
describe "textFieldCursorSelectFirstLine" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectFirstLine
it "is a movement" $ isMovement textFieldCursorSelectFirstLine
it "is idempotent" $ idempotentOnValid textFieldCursorSelectFirstLine
it "selects the first line" pending
describe "textFieldCursorSelectLastLine" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectLastLine
it "is a movement" $ isMovement textFieldCursorSelectLastLine
it "is idempotent" $ idempotentOnValid textFieldCursorSelectLastLine
it "selects the last line" pending
describe "textFieldCursorSelectPrevChar" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectPrevChar
it "selects the previous character on the current line" pending
describe "textFieldCursorSelectNextChar" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectNextChar
it "selects the previous character on the current line" pending
describe "textFieldCursorIndexOnLine" $ do
it "produces valid indices" $ producesValidsOnValids textFieldCursorIndexOnLine
it "returns the index on the current line" pending
describe "textFieldCursorSelectIndexOnLine" $ do
it "produces valid cursors for any index" $
producesValidsOnValids2 textFieldCursorSelectIndexOnLine
it "selects the given index on the current line" pending
describe "textFieldCursorInsertChar" $ do
it "produces valid cursors" $
forAllValid $ \d -> producesValidsOnValids (textFieldCursorInsertChar d)
it "inserts a character before the cursor on the current line" pending
describe "textFieldCursorAppendChar" $ do
it "produces valid cursors" $
forAllValid $ \d -> producesValidsOnValids (textFieldCursorAppendChar d)
it "inserts a character after the cursor on the currrent line" pending
describe "textFieldCursorInsertNewline" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorInsertNewline
it "inserts a new line" pending
describe "textFieldCursorAppendNewline" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorAppendNewline
describe "textFieldCursorRemove" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorRemove
it "removes empty text field cursor" $
textFieldCursorRemove emptyTextFieldCursor `shouldBe` Just Deleted
it "removes a character or a line" pending
describe "textFieldCursorDelete" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorDelete
it "removes empty text field cursor" $
textFieldCursorDelete emptyTextFieldCursor `shouldBe` Just Deleted
it "deletes a character or a line" pending
describe "textFieldCursorSelectStartOfLine" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectStartOfLine
it "selects the start of the current line" pending
describe "textFieldCursorSelectEndOfLine" $ do
it "produces valid cursors" $ producesValidsOnValids textFieldCursorSelectEndOfLine
it "selects the end of the current line" pending
isMovementM :: (TextFieldCursor -> Maybe TextFieldCursor) -> Property
isMovementM func =
forAllValid $ \tfc ->
case func tfc of
Nothing -> pure () -- Fine
Just tfc' ->
let tf = rebuildTextFieldCursor tfc
tf' = rebuildTextFieldCursor tfc'
in unless (tf == tf') $
expectationFailure $
unlines
[ "Cursor before:\n" ++ show tfc
, "TextField before: \n" ++ show tf
, "Cursor after: \n" ++ show tfc'
, "TextField after: \n" ++ show tf'
]
isMovement :: (TextFieldCursor -> TextFieldCursor) -> Property
isMovement func =
forAllValid $ \tfc -> rebuildTextFieldCursor tfc `shouldBe` rebuildTextFieldCursor (func tfc)