packages feed

hob-0.0.1.0: test/Hob/Ui/SidebarSearchSpec.hs

module Hob.Ui.SidebarSearchSpec (main, spec) where

import Data.Tree
import Graphics.UI.Gtk

import qualified Hob.Context              as HC
import qualified Hob.Context.FileContext  as HFC
import qualified Hob.Context.StyleContext as HSC
import qualified Hob.Context.UiContext    as HC
import           Hob.DirectoryTree
import           Hob.Ui
import           Hob.Ui.SidebarSearch

import Test.Hspec

import HobTest.Context.Default
import HobTest.Sidebar

main :: IO ()
main = hspec spec

spec :: Spec
spec =
  describe "sidebar search" $ do
    it "shows the named search box" $ do
      ctx <- sideBarSearchContext
      startSidebarSearch ctx ""
      name <- widgetGetName $ HC.sidebarTreeSearch . HC.uiContext $ ctx
      name `shouldBe` "sidebarSearchEntry"

    it "places the cursor on the first match on the search start" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "greenFile" [1]

    it "finds part even if start can be eaten" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "greenFileZ" [6]

    it "places the cursor on the first nested match on the search start" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]

    it "places the cursor on the first match on the search start even if started from the middle" $ do
      ctx <- sideBarSearchContext
      treeViewSetCursor (HC.sidebarTree . HC.uiContext $ ctx) [1] Nothing
      cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]

    it "places the cursor on the first match again on the search start even if had the same search text before" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]
      treeViewSetCursor (HC.sidebarTree . HC.uiContext $ ctx) [1] Nothing
      cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]

    it "only looks for the leaf nodes" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "red" [0, 0]

    it "uses fuzzy matching on file name" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "r d e" [0, 0]

    it "uses fuzzy matching on path" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "r dD r r d e" [0, 0]

    it "allows path separator while fuzzy matching on path" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "r/red e" [0, 0]

    it "stays on the same path when search is refined" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "r/r d" [0, 0]
      cursorShouldBeOnAfterRefine ctx "r/r d e" [0, 0]

    it "moves to the new match when search is refined" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearch ctx "r/r d" [0, 0]
      cursorShouldBeOnAfterRefine ctx "r/r d e2" [0, 1]

    it "focuses next file match when requested" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearchAndContinue ctx "r d e" [[0, 0], [0, 1]]

    it "focuses next path match when requested" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearchAndContinue ctx "r/r d e" [[0, 0], [0, 1]]

    it "focuses next multi-level path match when requested" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearchAndContinue ctx "/ Dir//r d e" [[3, 0, 0, 0], [4, 1, 0, 0]]

    it "collapses previously matched path after searching in next subtree" $ do
      ctx <- sideBarSearchContext
      startSidebarSearch ctx "/Dir//r d e"
      idx <- HC.runApp ctx initFileTreeIndex
      HC.runApp ctx $ continueSidebarSearch idx
      expanded <- treeViewRowExpanded (HC.sidebarTree . HC.uiContext $ ctx) [3]
      expanded `shouldBe` False

    it "allows case insensitive search" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearchAndContinue ctx "/ DIR//R D E" [[3, 0, 0, 0], [4, 1, 0, 0]]

    it "finds next top-level file" $ do
      ctx <- sideBarSearchContext
      cursorShouldBeOnAfterSearchAndContinue ctx "green file" [[1], [3,0,0,0], [5]]

    it "applies error style class if there are no matches" $ do
      ctx <- sideBarSearchContext
      startSidebarSearch ctx "AAA!!!AAA"
      ctx `sidebarTreeSearchErrorStateShouldBe` True

    it "removes error style on empty search text" $ do
      ctx <- sideBarSearchContext
      startSidebarSearch ctx "AAA!!!AAA"
      entrySetText (HC.sidebarTreeSearch . HC.uiContext $ ctx) ""
      ctx `sidebarTreeSearchErrorStateShouldBe` False

    it "removes error style on a match" $ do
      ctx <- sideBarSearchContext
      startSidebarSearch ctx "AAA!!!AAA"
      entrySetText (HC.sidebarTreeSearch . HC.uiContext $ ctx) "red"
      ctx `sidebarTreeSearchErrorStateShouldBe` False

sideBarSearchFileTreeStub :: IO (Forest DirectoryTreeElement)
sideBarSearchFileTreeStub = return [
    Node (DirectoryTreeElement "redDir" "/xxx/redDir" True) [
        Node (DirectoryTreeElement "redFile1" "/xxx/redDir/redFile1" False) [],
        Node (DirectoryTreeElement "redFile2" "/xxx/redDir/redFile2" False) []],
    Node (DirectoryTreeElement "greenFile" "/xxx/greenFile" False) [],
    Node (DirectoryTreeElement "redFile" "/xxx/redFile" False) [],
    Node (DirectoryTreeElement "greenDir" "/xxx/greenDir" True) [
        Node (DirectoryTreeElement "greenDir" "/xxx/greenDir/greenDir" True) [
            Node (DirectoryTreeElement "greenDir" "/xxx/greenDir/greenDir/greenDir" True) [
                Node (DirectoryTreeElement "redFile" "/xxx/greenDir/greenDir/greenDir/redFile" False) []]]],
    Node (DirectoryTreeElement "blueFolder" "/xxx/blueFolder" True) [
        Node (DirectoryTreeElement "blueFolder" "/xxx/blueFolder/blueFolder" True) [
            Node (DirectoryTreeElement "blueFolder" "/xxx/blueFolder/blueFolder/blueFolder" True) [
                Node (DirectoryTreeElement "redFile" "/xxx/blueFolder/blueFolder/blueFolder/redFile" False) []]],
        Node (DirectoryTreeElement "blueDir" "/xxx/blueFolder/blueDir" True) [
            Node (DirectoryTreeElement "blueDir" "/xxx/blueFolder/blueDir/blueDir" True) [
                Node (DirectoryTreeElement "redFile" "/xxx/blueFolder/blueDir/blueDir/redFile" False) []]]],
    Node (DirectoryTreeElement "greenFile2" "/xxx/greenFile2" False) [],
    Node (DirectoryTreeElement "greegreenFileZ" "/xxx/greegreenFileZ" False) []]

sideBarSearchContext :: IO HC.Context
sideBarSearchContext = do
    sc <- HSC.defaultStyleContext "app-data"
    fc <- HFC.defaultFileContext emptyFileLoader blackholeFileWriter sideBarSearchFileTreeStub
    loadGui fc sc