packages feed

kmonad-0.4.5: test/KMonad/ComposeSeqSpec.hs

module KMonad.ComposeSeqSpec (spec) where

import KMonad.Args.Parser
import KMonad.Args.Types
import KMonad.Keyboard.ComposeSeq
import KMonad.Keyboard.Keycode
import KMonad.Parsing
import KMonad.Prelude
import KMonad.Util

import Test.Hspec

import RIO.List (repeat)
import qualified RIO.Text as T

spec :: Spec
spec = describe "compose-sequences" $ do
  validSeqs
  noDuplicates
 where
  noDuplicates = describe "No duplicate compose sequence definitions" $ do
    noDuplicates' _1 "Compose sequences"
    noDuplicates' _2 "Characters"
    noDuplicates' _3 "Character names"
  noDuplicates' field desc = it desc $ duplicatesWith (view field) ssComposed `shouldBe` []
  validSeqs = describe "Compose sequences are valid" $
    case foldr (zipWith (++)) (repeat []) $ checkComposeSeq <$> ssComposed of
      [notCmpSeqs, notAsExpected, notAsExpectedE2E] -> do
        it "All are compose sequences" $ notCmpSeqs `shouldBe` []
        it "All match as expected" $ notAsExpected `shouldBe` []
        it "All parse in E2E" $ notAsExpectedE2E `shouldBe` []
      _ -> error "Invalid number of conditions in compose sequence checks"

  checkComposeSeq :: (Text, Char, Text) -> [[Text]]
  checkComposeSeq (expected, c, name) =
    [ parsesAsValidComposeSeq actualSeq
    , actualSeq == expectedSeq
    , actualE2E == expectedE2E
    ] <&> bool [name] []
   where
    actualSeq = runParser buttonP "" c'
    expectedSeq = runParser (KComposeSeq <$> some buttonP <* eof) "" expected
    actualE2E = parseTokens $ "(deflayer <test> " <> c' <> " )"
    expectedE2E = first ParseError expectedSeq <&> \x -> [KDefLayer (DefLayer "<test>" [LButton x])]
    c' = T.singleton c

  parsesAsValidComposeSeq (Right (KComposeSeq seq')) = all isSimple seq'
  parsesAsValidComposeSeq _ = False
  isSimple (KEmit _) = True
  isSimple (KAroundImplicit (KEmit KeyLeftShift) (KEmit _)) = True
  isSimple _ = False