packages feed

hob-0.0.1.0: test/Hob/Command/ReplaceTextSpec.hs

module Hob.Command.ReplaceTextSpec (main, spec) where

import Control.Monad.State (liftIO)
import Data.IORef
import Data.Maybe
import Data.Text           (pack)
import Graphics.UI.Gtk
import Test.Hspec

import           Hob.Command.ReplaceText
import           Hob.Context
import qualified Hob.Context.UiContext   as HC
import           Hob.Ui.Editor           (getActiveEditor, newEditorForText)

import HobTest.Context.Default
import HobTest.Control

main :: IO ()
main = hspec spec

spec :: Spec
spec = do
  describe "replace text command matcher" $ do
    it "accepts when command starts with the configured letter" $ do
        let handler _ _ = CommandHandler Nothing (return())
        let matcher = createMatcherForReplace 's' handler
        isJust (matchCommand matcher "s//") `shouldBe` True

    it "does not accept when command starts with another than the configured letter" $ do
        let handler _ _ = CommandHandler Nothing (return())
        let matcher = createMatcherForReplace 's' handler
        isJust (matchCommand matcher "x//") `shouldBe` False

    it "does not accept when command is empty" $ do
        let handler _ _ = CommandHandler Nothing (return())
        let matcher = createMatcherForReplace 's' handler
        isJust (matchCommand matcher "") `shouldBe` False

    it "parses search and replace strings" $ do
        let handler "S" "R" = CommandHandler Nothing (return())
            handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""
            matcher = createMatcherForReplace 'x' handler
            matchResult = matchCommand matcher "x/S/R"
        ctx <- loadDefaultContext
        runCtxActions ctx $ commandExecute (fromJust matchResult)

    it "ignores options when parsing search and replace strings" $ do
        let handler "S" "R" = CommandHandler Nothing (return())
            handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""
            matcher = createMatcherForReplace 'x' handler
            matchResult = matchCommand matcher "x#S#R#options"
        ctx <- loadDefaultContext
        runCtxActions ctx $ commandExecute (fromJust matchResult)

    it "matches escaped separator char as text" $ do
        let handler "S/S" "R/R" = CommandHandler Nothing (return())
            handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""
            matcher = createMatcherForReplace 'x' handler
            matchResult = matchCommand matcher "x/S\\/S/R\\/R"
        ctx <- loadDefaultContext
        runCtxActions ctx $ commandExecute (fromJust matchResult)

    it "matches escaped any char as escape seq and text" $ do
        let handler "S\\xS" "R\\xR" = CommandHandler Nothing (return())
            handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""
            matcher = createMatcherForReplace 'x' handler
            matchResult = matchCommand matcher "x/S\\xS/R\\xR"
        ctx <- loadDefaultContext
        runCtxActions ctx $ commandExecute (fromJust matchResult)

    it "matches escaped end of string as text" $ do
        let handler "S" "R\\" = CommandHandler Nothing (return())
            handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""
            matcher = createMatcherForReplace 'x' handler
            matchResult = matchCommand matcher "x/S/R\\"
        ctx <- loadDefaultContext
        runCtxActions ctx $ commandExecute (fromJust matchResult)

  describe "replace text command handler" $ do
    it "focuses editor on execute" $ do
        (ctx, _) <- loadGuiWithEditor
        runCtxActions ctx $ commandExecute (replaceCommandHandler "text" ":)")
        editorFocused <- widgetGetIsFocus . fromJust =<< getActiveEditor ctx
        editorFocused `shouldBe` True

    it "sets replace mode" $ do
        (ctx, _) <- loadGuiWithEditor
        runCtxActions ctx $ commandExecute (replaceCommandHandler "text" ":)")
        ref <- newIORef Nothing
        runCtxActions ctx $ activeModes >>= (liftIO . writeIORef ref)
        modes <- readIORef ref
        (map modeName . fromJust) modes `shouldBe` ["replace"]

loadGuiWithEditor :: IO (Context, TextBuffer)
loadGuiWithEditor = do
    ctx <- loadDefaultContext
    let notebook = HC.mainNotebook . uiContext $ ctx
    runCtxActions ctx $ newEditorForText notebook Nothing $ pack "text - initial text! text"
    mEditor <- getActiveEditor ctx
    let editor = fromJust mEditor
    buffer <- textViewGetBuffer editor
    return (ctx, buffer)