packages feed

ribosome-test 0.4.0.0 → 0.9.9.9

raw patch · 45 files changed

+1178/−2572 lines, 45 filesdep +chiasma-testdep +exondep +lens-regex-pcredep −aesondep −bytestringdep −compositiondep ~basesetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: chiasma-test, exon, lens-regex-pcre, polysemy, polysemy-chronos, polysemy-plugin, polysemy-test, prelate, ribosome-host, ribosome-host-test

Dependencies removed: aeson, bytestring, composition, composition-extra, conduit, containers, cornea, data-default, directory, either, exceptions, filepath, free, hslogger, lens, lifted-async, lifted-base, messagepack, monad-control, mtl, nvim-hs, prettyprinter, prettyprinter-ansi-terminal, process, relude, resourcet, tasty-hedgehog, template-haskell, text, transformers, typed-process, unix, unliftio

Dependency ranges changed: base

API changes (from Hackage documentation)

- Ribosome.Test.Await: await :: forall e a b m. MonadError e m => MonadIO m => MonadBaseControl IO m => (a -> TestT m b) -> m a -> TestT m b
- Ribosome.Test.Embed: TestConfig :: Text -> Text -> FilePath -> Word -> Maybe [Text] -> [Text] -> Vars -> TestConfig
- Ribosome.Test.Embed: Vars :: Map Text Object -> Vars
- Ribosome.Test.Embed: [$sel:tcCmdArgs:TestConfig] :: TestConfig -> [Text]
- Ribosome.Test.Embed: [$sel:tcCmdline:TestConfig] :: TestConfig -> Maybe [Text]
- Ribosome.Test.Embed: [$sel:tcExtraRtp:TestConfig] :: TestConfig -> Text
- Ribosome.Test.Embed: [$sel:tcLogPath:TestConfig] :: TestConfig -> FilePath
- Ribosome.Test.Embed: [$sel:tcPluginName:TestConfig] :: TestConfig -> Text
- Ribosome.Test.Embed: [$sel:tcTimeout:TestConfig] :: TestConfig -> Word
- Ribosome.Test.Embed: [$sel:tcVariables:TestConfig] :: TestConfig -> Vars
- Ribosome.Test.Embed: data TestConfig
- Ribosome.Test.Embed: defaultTestConfig :: Text -> TestConfig
- Ribosome.Test.Embed: defaultTestConfigWith :: Text -> Vars -> TestConfig
- Ribosome.Test.Embed: inTestT :: forall n m a. TestT n a -> (forall x. n x -> m x) -> TestT m a
- Ribosome.Test.Embed: instance Data.Default.Class.Default Ribosome.Test.Embed.TestConfig
- Ribosome.Test.Embed: instance Data.Default.Class.Default Ribosome.Test.Embed.Vars
- Ribosome.Test.Embed: instance GHC.Base.Monoid Ribosome.Test.Embed.Vars
- Ribosome.Test.Embed: instance GHC.Base.Semigroup Ribosome.Test.Embed.Vars
- Ribosome.Test.Embed: instance GHC.Classes.Eq Ribosome.Test.Embed.Vars
- Ribosome.Test.Embed: instance GHC.Show.Show Ribosome.Test.Embed.Vars
- Ribosome.Test.Embed: integrationSpec :: forall n m e env a. NvimE e n => MonadIO n => MonadIO m => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => TestConfig -> Plugin env -> TestT n a -> TestT m a
- Ribosome.Test.Embed: integrationSpecDef :: NvimE e n => MonadIO m => MonadIO n => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => Plugin env -> TestT n a -> TestT m a
- Ribosome.Test.Embed: killPid :: Integral a => a -> IO ()
- Ribosome.Test.Embed: killProcess :: Process i o e -> IO ()
- Ribosome.Test.Embed: newtype Vars
- Ribosome.Test.Embed: quitNvim :: Config e -> NvimProc -> IO ()
- Ribosome.Test.Embed: runEmbedded :: MonadIO m => MonadFail m => MonadBaseControl IO m => RpcHandler e env n => ReportError e => TestConfig -> env -> n a -> m a
- Ribosome.Test.Embed: runEmbeddedNvim :: MonadIO m => MonadFail m => MonadBaseControl IO m => RpcHandler e env n => ReportError e => TestConfig -> env -> n a -> NvimProc -> m a
- Ribosome.Test.Embed: runNeovimThunk :: Config e -> Neovim e a -> IO a
- Ribosome.Test.Embed: runPlugin :: MonadIO m => MonadBaseControl IO m => Handle -> Handle -> [Neovim () NeovimPlugin] -> Config c -> m (MVar StateTransition)
- Ribosome.Test.Embed: setVars :: forall m e. NvimE e m => Vars -> m ()
- Ribosome.Test.Embed: setupPluginEnv :: MonadIO m => NvimE e m => TestConfig -> m ()
- Ribosome.Test.Embed: shutdownNvim :: Config e -> NvimProc -> IO () -> IO ()
- Ribosome.Test.Embed: startHandlers :: MonadIO m => Handle -> Handle -> TestConfig -> Config RPCConfig -> m (IO ())
- Ribosome.Test.Embed: startStdioHandlers :: MonadIO m => NvimProc -> TestConfig -> Config RPCConfig -> m (IO ())
- Ribosome.Test.Embed: testNvimProcessConfig :: TestConfig -> ProcessConfig Handle Handle ()
- Ribosome.Test.Embed: type NvimProc = Process Handle Handle ()
- Ribosome.Test.Embed: type Runner m = forall a. TestConfig -> m a -> m a
- Ribosome.Test.Embed: unsafeEmbeddedSpec :: MonadIO m => MonadFail m => MonadBaseControl IO m => RpcHandler e env n => ReportError e => Runner n -> TestConfig -> env -> n a -> m a
- Ribosome.Test.Embed: unsafeEmbeddedSpecR :: MonadIO m => MonadFail m => ReportError e => MonadBaseControl IO m => RpcHandler e (Ribosome env) n => Runner n -> TestConfig -> env -> n a -> m a
- Ribosome.Test.Embed: varsFromList :: [(Text, Object)] -> Vars
- Ribosome.Test.Embed: varsUnion :: Vars -> Vars -> Vars
- Ribosome.Test.Embed: waitQuit :: NvimProc -> IO (Maybe ExitCode)
- Ribosome.Test.Embed: withProcessTerm :: MonadIO m => MonadBaseControl IO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
- Ribosome.Test.Exists: retry :: MonadIO m => MonadFail m => Double -> Int -> m a -> (a -> m (Either Text b)) -> m b
- Ribosome.Test.Exists: waitForPlugin :: Text -> Double -> Int -> Neovim env ()
- Ribosome.Test.File: fixture :: MonadIO m => Text -> FilePath -> m FilePath
- Ribosome.Test.File: fixtureContent :: MonadIO m => Text -> FilePath -> m Text
- Ribosome.Test.File: tempDir :: MonadIO m => Text -> FilePath -> m FilePath
- Ribosome.Test.File: tempDirIO :: Text -> FilePath -> IO FilePath
- Ribosome.Test.File: testDir :: Text -> IO FilePath
- Ribosome.Test.Input: withInput :: NvimE e m => MonadIO m => MonadBaseControl IO m => Maybe Double -> [Text] -> m a -> m a
- Ribosome.Test.Run: type UnitTest = TestT IO ()
- Ribosome.Test.Run: unitTest :: TestName -> UnitTest -> TestTree
- Ribosome.Test.Tmux: externalNvimCmdline :: FilePath -> Text
- Ribosome.Test.Tmux: guiSpec :: MonadIO m => MonadFail m => ReportError e => MonadBaseControl IO m => DeepPrisms e RpcError => TestConfig -> TmuxNative -> s -> Ribo s e a -> m a
- Ribosome.Test.Tmux: runGui :: MonadIO m => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => TmuxNative -> FilePath -> TestConfig -> env -> n a -> m a
- Ribosome.Test.Tmux: runSocketNvimHs :: MonadIO m => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => TestConfig -> env -> n a -> Handle -> m a
- Ribosome.Test.Tmux: runTmuxWithPlugin :: MonadIO m => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => TmuxNative -> TestConfig -> Plugin env -> n () -> m ()
- Ribosome.Test.Tmux: startNvimInTmux :: TmuxNative -> FilePath -> IO Handle
- Ribosome.Test.Tmux: tmuxGuiSpec :: DeepPrisms e RpcError => ReportError e => TestConfig -> s -> Ribo s e () -> UnitTest
- Ribosome.Test.Tmux: tmuxGuiSpecDef :: DeepPrisms e RpcError => ReportError e => Default s => Ribo s e () -> UnitTest
- Ribosome.Test.Tmux: tmuxIntegrationSpecDef :: NvimE e n => MonadIO m => MonadIO n => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => Text -> Plugin env -> n () -> m ()
- Ribosome.Test.Tmux: tmuxSpec :: DeepPrisms e RpcError => ReportError e => TestConfig -> s -> TestT (Ribo s e) () -> UnitTest
- Ribosome.Test.Tmux: tmuxSpec' :: DeepPrisms e RpcError => ReportError e => TmuxTestConf -> TestConfig -> s -> TestT (Ribo s e) () -> UnitTest
- Ribosome.Test.Tmux: tmuxSpecDef :: DeepPrisms e RpcError => ReportError e => Default s => TestT (Ribo s e) () -> UnitTest
- Ribosome.Test.Tmux: unsafeGuiSpec :: MonadIO m => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => TmuxNative -> FilePath -> Runner n -> TestConfig -> env -> n a -> m a
- Ribosome.Test.Tmux: unsafeGuiSpecR :: MonadIO m => MonadFail m => ReportError e => MonadBaseControl IO m => RpcHandler e (Ribosome env) n => TmuxNative -> FilePath -> Runner n -> TestConfig -> env -> n a -> m a
- Ribosome.Test.Tmux: withTmux :: DeepPrisms e RpcError => Ribo s e a -> TmuxNative -> Ribo s e a
- Ribosome.Test.Tmux: withTmuxInt :: NvimE e m => MonadIO m => Text -> m () -> TmuxNative -> m ()
- Ribosome.Test.Unit: fixture :: MonadIO m => FilePath -> m FilePath
- Ribosome.Test.Unit: fixtureContent :: MonadIO m => FilePath -> m Text
- Ribosome.Test.Unit: tempDir :: MonadIO m => FilePath -> m FilePath
- Ribosome.Test.Unit: tempFile :: MonadIO m => FilePath -> m FilePath
- Ribosome.Test.Unit: uPrefix :: Text
- Ribosome.Test.Unit: uSpec :: (MonadIO m, NvimE e m) => Runner m
- Ribosome.Test.Unit: unitSpec :: MonadIO n => MonadIO m => NvimE e' n => MonadFail m => ReportError e => MonadBaseControl IO m => RpcHandler e (Ribosome env) n => TestConfig -> env -> TestT n a -> TestT m a
- Ribosome.Test.Unit: unitSpecDef :: MonadIO n => MonadIO m => NvimE e' n => MonadFail m => ReportError e => MonadBaseControl IO m => RpcHandler e (Ribosome env) n => env -> TestT n a -> TestT m a
- Ribosome.Test.Unit: unitSpecDef' :: MonadIO n => MonadIO m => NvimE e' n => MonadFail m => ReportError e => MonadBaseControl IO m => RpcHandler e (Ribosome ()) n => TestT n a -> TestT m a
- Ribosome.Test.Unit: withLog :: MonadRibo m => MonadBaseControl IO m => m a -> m a
- Ribosome.Test.Unit: withLogAs :: MonadIO m => MonadBaseControl IO m => Text -> m a -> m a
+ Ribosome.Handler: Autocmd :: AutocmdEvents -> AutocmdOptions -> RpcType
+ Ribosome.Handler: AutocmdEvents :: [Text] -> AutocmdEvents
+ Ribosome.Handler: AutocmdGroup :: Text -> AutocmdGroup
+ Ribosome.Handler: AutocmdOptions :: Either AutocmdBuffer AutocmdPatterns -> Bool -> Bool -> Maybe AutocmdGroup -> AutocmdOptions
+ Ribosome.Handler: AutocmdPatterns :: [Text] -> AutocmdPatterns
+ Ribosome.Handler: Command :: CommandOptions -> CommandArgs -> RpcType
+ Ribosome.Handler: CommandOptions :: Map Text Object -> Maybe CommandCompletion -> CommandOptions
+ Ribosome.Handler: CompleteBuiltin :: Text -> CommandCompletion
+ Ribosome.Handler: CompleteFiltered :: CompleteStyle
+ Ribosome.Handler: CompleteHandler :: CompleteStyle -> RpcName -> CommandCompletion
+ Ribosome.Handler: CompleteUnfiltered :: CompleteStyle
+ Ribosome.Handler: Function :: RpcType
+ Ribosome.Handler: [$sel:basic:CommandOptions] :: CommandOptions -> Map Text Object
+ Ribosome.Handler: [$sel:completion:CommandOptions] :: CommandOptions -> Maybe CommandCompletion
+ Ribosome.Handler: [$sel:group:AutocmdOptions] :: AutocmdOptions -> Maybe AutocmdGroup
+ Ribosome.Handler: [$sel:nested:AutocmdOptions] :: AutocmdOptions -> Bool
+ Ribosome.Handler: [$sel:once:AutocmdOptions] :: AutocmdOptions -> Bool
+ Ribosome.Handler: [$sel:target:AutocmdOptions] :: AutocmdOptions -> Either AutocmdBuffer AutocmdPatterns
+ Ribosome.Handler: [$sel:unAutocmdEvent:AutocmdEvents] :: AutocmdEvents -> [Text]
+ Ribosome.Handler: [$sel:unAutocmdGroup:AutocmdGroup] :: AutocmdGroup -> Text
+ Ribosome.Handler: [$sel:unAutocmdPattern:AutocmdPatterns] :: AutocmdPatterns -> [Text]
+ Ribosome.Handler: complete :: forall (r :: [(Type -> Type) -> Type -> Type]). CommandCompletion -> RpcHandler r -> RpcHandler r
+ Ribosome.Handler: completeBuiltin :: forall (r :: [(Type -> Type) -> Type -> Type]). Text -> RpcHandler r -> RpcHandler r
+ Ribosome.Handler: completeCustom :: forall (r :: [(Type -> Type) -> Type -> Type]). RpcName -> (Text -> Text -> Int -> Handler r [Text]) -> CompleteStyle -> RpcHandler r
+ Ribosome.Handler: completeWith :: forall (r :: [(Type -> Type) -> Type -> Type]). CompleteStyle -> (Text -> Text -> Int -> Handler r [Text]) -> RpcHandler r -> [RpcHandler r]
+ Ribosome.Handler: data AutocmdOptions
+ Ribosome.Handler: data CommandCompletion
+ Ribosome.Handler: data CommandOptions
+ Ribosome.Handler: data CompleteStyle
+ Ribosome.Handler: data RpcType
+ Ribosome.Handler: newtype AutocmdEvents
+ Ribosome.Handler: newtype AutocmdGroup
+ Ribosome.Handler: newtype AutocmdPatterns
+ Ribosome.Test: TestConfig :: Bool -> PluginConfig () -> TestConfig
+ Ribosome.Test: TmuxTestConfig :: TestConfig -> TmuxTestConfig -> TmuxTestConfig
+ Ribosome.Test: assertWait :: Monad m => HasCallStack => Members [Hedgehog m, Time t d, Race, Error Failure, Embed IO] r => Sem r a -> (a -> Sem r b) -> Sem r b
+ Ribosome.Test: assertWaitFor :: Monad m => HasCallStack => Members [Hedgehog m, Time t d, Race, Error Failure, Embed IO] r => TimeUnit t1 => TimeUnit t2 => t1 -> t2 -> Sem r a -> (a -> Sem r b) -> Sem r b
+ Ribosome.Test: awaitScreenshot :: HasCallStack => Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r => Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, StderrLog, Race, Embed IO] r => Bool -> Text -> Int -> Sem r ()
+ Ribosome.Test: currentCursorIs :: Monad m => Members [Rpc, Hedgehog m] r => Int -> Int -> Sem r ()
+ Ribosome.Test: cursorIs :: Monad m => Members [Rpc, Hedgehog m] r => Int -> Int -> Window -> Sem r ()
+ Ribosome.Test: data TestConfig
+ Ribosome.Test: data TmuxTestConfig
+ Ribosome.Test: resumeReportFail :: forall (eff :: (Type -> Type) -> Type -> Type) err (r :: EffectRow). (Members '[Fail :: (Type -> Type) -> Type -> Type, eff !! err] r, Reportable err) => InterpreterFor eff r
+ Ribosome.Test: runEmbedTest :: HasCallStack => TestConfig -> Sem EmbedHandlerStack () -> UnitTest
+ Ribosome.Test: runTest :: HasCallStack => Sem EmbedHandlerStack () -> UnitTest
+ Ribosome.Test: runTestConf :: HasCallStack => TestConfig -> Sem (Reader PluginName : TestStack) () -> UnitTest
+ Ribosome.Test: runTestLogConf :: Members [Error BootError, Resource, Race, Async, Embed IO] r => TestConfig -> InterpretersFor (Reader PluginName : TestConfStack) r
+ Ribosome.Test: stopReportToFail :: forall e (r :: EffectRow). (Member (Fail :: (Type -> Type) -> Type -> Type) r, Reportable e) => InterpreterFor (Stop e) r
+ Ribosome.Test: testEmbed :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test: testEmbedConf :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => TestConfig -> InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test: testEmbedDebug :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test: testEmbedDebug_ :: HasCallStack => Sem EmbedStack () -> UnitTest
+ Ribosome.Test: testEmbedLevel :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => Severity -> InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test: testEmbedLevel_ :: HasCallStack => Severity -> Sem EmbedStack () -> UnitTest
+ Ribosome.Test: testEmbedTrace :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test: testEmbedTrace_ :: HasCallStack => Sem EmbedStack () -> UnitTest
+ Ribosome.Test: testEmbed_ :: HasCallStack => Sem EmbedStack () -> UnitTest
+ Ribosome.Test: testPlugin :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> [RpcHandler (r ++ EmbedHandlerStack)] -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test: testPluginConf :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => TestConfig -> InterpretersFor r EmbedHandlerStack -> [RpcHandler (r ++ EmbedHandlerStack)] -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test: testPluginEmbed :: Members (HostDeps er) r => Members BuiltinHandlersDeps r => Members [Settings !! SettingError, Error TestError] r => InterpretersFor TestEffects r
+ Ribosome.Test: testPlugin_ :: HasCallStack => [RpcHandler EmbedHandlerStack] -> Sem EmbedStack () -> UnitTest
+ Ribosome.Test: type EmbedHandlerStack = HandlerEffects ++ Reader PluginName : TestStack
+ Ribosome.Test: type EmbedStack = EmbedStackWith '[]
+ Ribosome.Test: type EmbedStackWith r = TestEffects ++ r ++ EmbedHandlerStack
+ Ribosome.Test: type TestEffects = [Stop Report, Stop RpcError, Scratch, Settings, Rpc]
+ Ribosome.Test: windowCountIs :: Monad m => Members [Rpc, Hedgehog m] r => Int -> Sem r ()
+ Ribosome.Test.Data.TestConfig: TestConfig :: Bool -> PluginConfig () -> TestConfig
+ Ribosome.Test.Data.TestConfig: TmuxTestConfig :: TestConfig -> TmuxTestConfig -> TmuxTestConfig
+ Ribosome.Test.Data.TestConfig: [$sel:core:TmuxTestConfig] :: TmuxTestConfig -> TestConfig
+ Ribosome.Test.Data.TestConfig: [$sel:freeze:TestConfig] :: TestConfig -> Bool
+ Ribosome.Test.Data.TestConfig: [$sel:plugin:TestConfig] :: TestConfig -> PluginConfig ()
+ Ribosome.Test.Data.TestConfig: [$sel:tmux:TmuxTestConfig] :: TmuxTestConfig -> TmuxTestConfig
+ Ribosome.Test.Data.TestConfig: data TestConfig
+ Ribosome.Test.Data.TestConfig: data TmuxTestConfig
+ Ribosome.Test.Data.TestConfig: instance Data.Default.Class.Default Ribosome.Test.Data.TestConfig.TestConfig
+ Ribosome.Test.Data.TestConfig: instance Data.Default.Class.Default Ribosome.Test.Data.TestConfig.TmuxTestConfig
+ Ribosome.Test.Data.TestConfig: instance GHC.Classes.Eq Ribosome.Test.Data.TestConfig.TestConfig
+ Ribosome.Test.Data.TestConfig: instance GHC.Classes.Eq Ribosome.Test.Data.TestConfig.TmuxTestConfig
+ Ribosome.Test.Data.TestConfig: instance GHC.Generics.Generic Ribosome.Test.Data.TestConfig.TestConfig
+ Ribosome.Test.Data.TestConfig: instance GHC.Generics.Generic Ribosome.Test.Data.TestConfig.TmuxTestConfig
+ Ribosome.Test.Data.TestConfig: instance GHC.Show.Show Ribosome.Test.Data.TestConfig.TestConfig
+ Ribosome.Test.Data.TestConfig: instance GHC.Show.Show Ribosome.Test.Data.TestConfig.TmuxTestConfig
+ Ribosome.Test.Embed: runEmbedTest :: HasCallStack => TestConfig -> Sem EmbedHandlerStack () -> UnitTest
+ Ribosome.Test.Embed: runTestConf :: HasCallStack => TestConfig -> Sem (Reader PluginName : TestStack) () -> UnitTest
+ Ribosome.Test.Embed: runTestLogConf :: Members [Error BootError, Resource, Race, Async, Embed IO] r => TestConfig -> InterpretersFor (Reader PluginName : TestConfStack) r
+ Ribosome.Test.Embed: testEmbed :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test.Embed: testEmbedConf :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => TestConfig -> InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test.Embed: testEmbedDebug :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test.Embed: testEmbedDebug_ :: HasCallStack => Sem EmbedStack () -> UnitTest
+ Ribosome.Test.Embed: testEmbedLevel :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => Severity -> InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test.Embed: testEmbedLevel_ :: HasCallStack => Severity -> Sem EmbedStack () -> UnitTest
+ Ribosome.Test.Embed: testEmbedTrace :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test.Embed: testEmbedTrace_ :: HasCallStack => Sem EmbedStack () -> UnitTest
+ Ribosome.Test.Embed: testEmbed_ :: HasCallStack => Sem EmbedStack () -> UnitTest
+ Ribosome.Test.Embed: testPlugin :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => InterpretersFor r EmbedHandlerStack -> [RpcHandler (r ++ EmbedHandlerStack)] -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test.Embed: testPluginConf :: forall r. HasCallStack => HigherOrder r EmbedHandlerStack => TestConfig -> InterpretersFor r EmbedHandlerStack -> [RpcHandler (r ++ EmbedHandlerStack)] -> Sem (EmbedStackWith r) () -> UnitTest
+ Ribosome.Test.Embed: testPluginEmbed :: Members (HostDeps er) r => Members BuiltinHandlersDeps r => Members [Settings !! SettingError, Error TestError] r => InterpretersFor TestEffects r
+ Ribosome.Test.Embed: testPlugin_ :: HasCallStack => [RpcHandler EmbedHandlerStack] -> Sem EmbedStack () -> UnitTest
+ Ribosome.Test.Embed: type EmbedHandlerStack = HandlerEffects ++ Reader PluginName : TestStack
+ Ribosome.Test.Embed: type EmbedStack = EmbedStackWith '[]
+ Ribosome.Test.Embed: type EmbedStackWith r = TestEffects ++ r ++ EmbedHandlerStack
+ Ribosome.Test.Embed: type TestEffects = [Stop Report, Stop RpcError, Scratch, Settings, Rpc]
+ Ribosome.Test.EmbedTmux: runEmbedTmuxGuiTest :: HasCallStack => Sem HandlerStack () -> UnitTest
+ Ribosome.Test.EmbedTmux: runEmbedTmuxTest :: HasCallStack => Sem HandlerStack () -> UnitTest
+ Ribosome.Test.EmbedTmux: runEmbedTmuxTestConf :: HasCallStack => TmuxTestConfig -> Sem HandlerStack () -> UnitTest
+ Ribosome.Test.EmbedTmux: testEmbedTmux :: HasCallStack => Sem EmbedTmux () -> UnitTest
+ Ribosome.Test.EmbedTmux: testPluginEmbedTmux :: forall r. HasCallStack => Members HandlerStack (r ++ HandlerStack) => InterpretersFor r HandlerStack -> [RpcHandler (r ++ HandlerStack)] -> Sem (EmbedTmuxWith r) () -> UnitTest
+ Ribosome.Test.EmbedTmux: testPluginEmbedTmuxConf :: forall r. HasCallStack => Members HandlerStack (r ++ HandlerStack) => TmuxTestConfig -> InterpretersFor r HandlerStack -> [RpcHandler (r ++ HandlerStack)] -> Sem (EmbedTmuxWith r) () -> UnitTest
+ Ribosome.Test.EmbedTmux: testPluginEmbedTmux_ :: HasCallStack => [RpcHandler HandlerStack] -> Sem EmbedTmux () -> UnitTest
+ Ribosome.Test.EmbedTmux: type EmbedTmux = EmbedTmuxWith '[]
+ Ribosome.Test.EmbedTmux: type EmbedTmuxWith r = TestEffects ++ r ++ HandlerStack
+ Ribosome.Test.EmbedTmux: type HandlerStack = HandlerEffects ++ TmuxStack
+ Ribosome.Test.Error: resumeTestError :: forall eff err r. Show err => Members [eff !! err, Error TestError] r => InterpreterFor eff r
+ Ribosome.Test.Error: testError :: forall err r a. Reportable err => Member (Error TestError) r => Sem (Stop err : r) a -> Sem r a
+ Ribosome.Test.Error: testHandler :: Member (Error TestError) r => Handler r a -> Sem r a
+ Ribosome.Test.Error: testHandlerAsync :: Members [Error TestError, Async] r => Handler r a -> Sem r (Sem r a)
+ Ribosome.Test.Log: testLogLevel :: HasCallStack => Severity -> (TestConfig -> a) -> a
+ Ribosome.Test.Log: testLogLevelConf :: HasCallStack => Severity -> (TestConfig -> a) -> TestConfig -> a
+ Ribosome.Test.Screenshot: awaitScreenshot' :: HasCallStack => Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r => Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, StderrLog, Race, Embed IO] r => Bool -> Bool -> Text -> Int -> Sem r ()
+ Ribosome.Test.Screenshot: sanitize :: Text -> Text
+ Ribosome.Test.Screenshot: updateScreeshot :: HasCallStack => Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r => Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, StderrLog, Race, Embed IO] r => Bool -> Text -> Int -> Sem r ()
+ Ribosome.Test.SocketTmux: nvimCmdline :: Path Abs File -> Text
+ Ribosome.Test.SocketTmux: runSocketTmuxGuiTest :: HasCallStack => Sem TmuxHandlerStack () -> UnitTest
+ Ribosome.Test.SocketTmux: runSocketTmuxTest :: HasCallStack => Sem TmuxHandlerStack () -> UnitTest
+ Ribosome.Test.SocketTmux: runSocketTmuxTestConf :: HasCallStack => TmuxTestConfig -> Sem TmuxHandlerStack () -> UnitTest
+ Ribosome.Test.SocketTmux: testHandlersSocketTmux :: HasCallStack => [RpcHandler TmuxHandlerStack] -> Sem SocketTmux () -> UnitTest
+ Ribosome.Test.SocketTmux: testHandlersSocketTmuxGui :: HasCallStack => [RpcHandler TmuxHandlerStack] -> Sem SocketTmux () -> UnitTest
+ Ribosome.Test.SocketTmux: testPluginSocketTmux :: forall r. HasCallStack => Members TmuxHandlerStack (r ++ TmuxHandlerStack) => InterpretersFor r TmuxHandlerStack -> [RpcHandler (r ++ TmuxHandlerStack)] -> Sem (SocketTmuxWith r) () -> UnitTest
+ Ribosome.Test.SocketTmux: testPluginSocketTmuxConf :: forall r. HasCallStack => Members TmuxHandlerStack (r ++ TmuxHandlerStack) => TmuxTestConfig -> InterpretersFor r TmuxHandlerStack -> [RpcHandler (r ++ TmuxHandlerStack)] -> Sem (SocketTmuxWith r) () -> UnitTest
+ Ribosome.Test.SocketTmux: testPluginSocketTmuxGui :: forall r. HasCallStack => Members TmuxHandlerStack (r ++ TmuxHandlerStack) => InterpretersFor r TmuxHandlerStack -> [RpcHandler (r ++ TmuxHandlerStack)] -> Sem (SocketTmuxWith r) () -> UnitTest
+ Ribosome.Test.SocketTmux: testSocketTmux :: HasCallStack => Sem SocketTmux () -> UnitTest
+ Ribosome.Test.SocketTmux: testSocketTmuxGui :: HasCallStack => Sem SocketTmux () -> UnitTest
+ Ribosome.Test.SocketTmux: type SocketTmux = SocketTmuxWith '[]
+ Ribosome.Test.SocketTmux: type SocketTmuxWith r = TestEffects ++ r ++ TmuxHandlerStack
+ Ribosome.Test.SocketTmux: type TmuxHandlerStack = SocketHandlerEffects ++ Reader (CustomConfig ()) : Reader NvimSocket : TmuxStack
+ Ribosome.Test.SocketTmux: withSocketTmuxNvim :: Members [Test, Hedgehog IO, ChronosTime, Error Failure, Race, Embed IO] r => Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r => InterpreterFor (Reader NvimSocket) r
+ Ribosome.Test.TmuxCommon: interpretTmuxErrors :: Member (Error BootError) r => InterpretersFor TmuxErrors r
+ Ribosome.Test.TmuxCommon: runTmuxNvim :: HasCallStack => TmuxTestConfig -> Sem TmuxStack () -> UnitTest
+ Ribosome.Test.TmuxCommon: type TmuxBaseStack = TestTmuxEffects ++ TmuxErrors
+ Ribosome.Test.TmuxCommon: type TmuxErrors = [Stop CodecError, Error CodecError, Stop RenderError, Error RenderError, Stop TmuxError, Error TmuxError, Error Text]
+ Ribosome.Test.TmuxCommon: type TmuxStack = NativeTmux : TmuxBaseStack ++ Reader PluginName : TestStack
+ Ribosome.Test.TmuxCommon: withTmuxTest :: Members TestStack r => TmuxTestConfig -> InterpretersFor TmuxBaseStack r
+ Ribosome.Test.Wait: assertWait :: Monad m => HasCallStack => Members [Hedgehog m, Time t d, Race, Error Failure, Embed IO] r => Sem r a -> (a -> Sem r b) -> Sem r b
+ Ribosome.Test.Wait: assertWaitFor :: Monad m => HasCallStack => Members [Hedgehog m, Time t d, Race, Error Failure, Embed IO] r => TimeUnit t1 => TimeUnit t2 => t1 -> t2 -> Sem r a -> (a -> Sem r b) -> Sem r b
- Ribosome.Test.Embed: runTest :: MonadIO m => MonadFail m => ReportError e => RpcHandler e env n => MonadBaseControl IO m => TestConfig -> Config env -> n a -> m a
+ Ribosome.Test.Embed: runTest :: HasCallStack => Sem EmbedHandlerStack () -> UnitTest
- Ribosome.Test.Screenshot: assertScreenshot :: MonadIO m => MonadRibo m => MonadDeepError e TmuxError m => MonadBaseControl IO m => MonadMask m => Nvim m => Text -> Bool -> Int -> TestT m ()
+ Ribosome.Test.Screenshot: assertScreenshot :: HasCallStack => Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r => Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, Race, Embed IO] r => Bool -> Text -> Int -> Sem r ()
- Ribosome.Test.Screenshot: awaitScreenshot :: MonadIO m => MonadMask m => MonadRibo m => MonadBaseControl IO m => MonadDeepError e TmuxError m => Nvim m => Text -> Bool -> Int -> TestT m ()
+ Ribosome.Test.Screenshot: awaitScreenshot :: HasCallStack => Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r => Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, StderrLog, Race, Embed IO] r => Bool -> Text -> Int -> Sem r ()
- Ribosome.Test.Screenshot: screenshot :: MonadFree TmuxThunk m => MonadIO m => Text -> Bool -> Int -> m (Maybe ([Text], [Text]))
+ Ribosome.Test.Screenshot: screenshot :: Members [Tmux, Test, Error TestError, Embed IO] r => Bool -> Bool -> Text -> Int -> Sem r (Maybe ([Text], [Text]))
- Ribosome.Test.Ui: currentCursorIs :: NvimE e m => Int -> Int -> TestT m ()
+ Ribosome.Test.Ui: currentCursorIs :: Monad m => Members [Rpc, Hedgehog m] r => Int -> Int -> Sem r ()
- Ribosome.Test.Ui: cursorIs :: NvimE e m => Int -> Int -> Window -> TestT m ()
+ Ribosome.Test.Ui: cursorIs :: Monad m => Members [Rpc, Hedgehog m] r => Int -> Int -> Window -> Sem r ()
- Ribosome.Test.Ui: windowCountIs :: NvimE e m => Int -> TestT m ()
+ Ribosome.Test.Ui: windowCountIs :: Monad m => Members [Rpc, Hedgehog m] r => Int -> Sem r ()

Files

LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2020 Torsten Schmits+Copyright (c) 2022 Torsten Schmits  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ lib/Ribosome/Handler.hs view
@@ -0,0 +1,21 @@+module Ribosome.Handler (+  module Ribosome.Host.Data.RpcType,+  module Ribosome.Host.Handler,+) where++import Ribosome.Host.Data.RpcType (+  AutocmdEvents (..),+  AutocmdGroup (..),+  AutocmdOptions (..),+  AutocmdPatterns (..),+  CommandCompletion (..),+  CommandOptions (..),+  CompleteStyle (..),+  RpcType (..),+  )+import Ribosome.Host.Handler (+  complete,+  completeBuiltin,+  completeCustom,+  completeWith,+  )
+ lib/Ribosome/Test.hs view
@@ -0,0 +1,164 @@+module Ribosome.Test (+  -- * Introduction+  -- $intro++  -- * Embedded testing+  -- $embed++  -- * tmux testing+  -- $tmux++  -- * Embedded test API+  testPlugin,+  testEmbed,+  testPluginEmbed,+  runEmbedTest,+  runTest,+  testPluginConf,+  testPlugin_,+  testEmbedConf,+  testEmbed_,+  testEmbedLevel,+  testEmbedLevel_,+  testEmbedDebug,+  testEmbedDebug_,+  testEmbedTrace,+  testEmbedTrace_,+  runTestConf,+  runTestLogConf,+  EmbedStackWith,+  EmbedStack,+  EmbedHandlerStack,+  TestEffects,+  TestConfig (TestConfig),+  TmuxTestConfig (TmuxTestConfig),+  -- * Error handling+  module Ribosome.Test.Error,+  module Ribosome.Host.Data.Report,+  -- * Assertions for Neovim UI elements+  windowCountIs,+  cursorIs,+  currentCursorIs,+  awaitScreenshot,+  -- * Assertions that are made repeatedly until the succeed+  assertWait,+  assertWaitFor,+) where++import Ribosome.Host.Data.Report (resumeReportFail, stopReportToFail)+import Ribosome.Test.Data.TestConfig (TestConfig (TestConfig), TmuxTestConfig (TmuxTestConfig))+import Ribosome.Test.Embed (+  EmbedHandlerStack,+  EmbedStack,+  EmbedStackWith,+  TestEffects,+  runEmbedTest,+  runTest,+  runTestConf,+  runTestLogConf,+  testEmbed,+  testEmbedConf,+  testEmbedLevel,+  testEmbedLevel_,+  testEmbedTrace,+  testEmbedDebug,+  testEmbedTrace_,+  testEmbedDebug_,+  testEmbed_,+  testPlugin,+  testPluginConf,+  testPluginEmbed,+  testPlugin_,+  )+import Ribosome.Test.Error+import Ribosome.Test.Screenshot (awaitScreenshot)+import Ribosome.Test.Ui+import Ribosome.Test.Wait++-- $intro+-- This is the test library for the "Ribosome" Neoivm plugin framework.+--+-- Three different test environments are available:+--+-- - "Ribosome.Test.Embed" runs Neovim as a subprocess and connects over stdio+--+-- - "Ribosome.Test.EmbedTmux" is like "Ribosome.Test.Embed", but provides a tmux server+--+-- - "Ribosome.Test.SocketTmux" runs Neovim in a window in a fresh tmux server, either headless in a pseudo terminal+-- or in an @xterm@ instance+--+-- This module reexports "Ribosome.Test.Embed".++-- $embed+-- Running a test against an embedded Neovim process is the simplest approach that is suited for unit testing plugin+-- logic where the integration with Neovim startup isn't important.+--+-- Handlers can be registered in Neovim and triggered via RPC API functions like 'nvimCallFunction' and 'nvimCommand'.+-- Most of the time this is only interesting if a handler has complex parameters and you want to test that they are+-- decoded correctly, or that the handler is triggered properly by an autocmd.+-- In more basic cases, where only the interaction with Neovim from within the handler is relevant, it can simply be run+-- directly.+--+-- > import Polysemy.Test+-- > import Ribosome+-- > import Ribosome.Api+-- > import Ribosome.Test+-- >+-- > store ::+-- >   Member (Rpc !! RpcError) r =>+-- >   Args ->+-- >   Handler r ()+-- > store (Args msg) =+-- >   ignoreRpcError do+-- >     nvimSetVar "message" msg+-- >+-- > test_direct :: UnitTest+-- > test_direct =+-- >   testEmbed_ do+-- >     store "test directly"+-- >     assertEq "test directly" =<< nvimGetVar @Text "message"+-- >+-- > test_rpc :: UnitTest+-- > test_rpc =+-- >   testPlugin_ [rpcCommand "Store" Sync store] do+-- >     nvimCommand "Store test RPC"+-- >     assertEq "test RPC" =<< nvimGetVar @Text "message"+--+-- See [Ribosome.Test.Embed]("Ribosome.Test.Embed") for more options.++-- $tmux+-- It is possible to run a standalone Neovim instance to test against.+-- This is useful to observe the UI's behaviour for debugging purposes, but might also be desired to test a feature in+-- the full environment that is used in production.+--+-- Ribosome provides a testing mode that starts a terminal with a tmux server, in which Neovim is executed as a regular+-- shell process.+-- Variants of this that run tmux in a pseudo terminal that is not rendered, or simply run a tmux server for use in an+-- embedded test, are also available.+--+-- In the terminal case, the test connects the plugin over a socket.+-- It is possible to take \"screenshots\" (capturing the tmux pane running Neovim) that are automatically stored in the+-- @fixtures@ directory of the test suite and compared to previous recordings on subsequent runs, as in this example+-- that runs tmux in a terminal and tests some syntax rules:+--+-- > import Polysemy.Test+-- > import Ribosome.Api+-- > import Ribosome.Syntax+-- > import Ribosome.Test+-- > import Ribosome.Test.SocketTmux+-- >+-- > syntax :: Syntax+-- > syntax =+-- >   Syntax [syntaxMatch "TestColons" "::"] [+-- >     syntaxHighlight "TestColons" [("cterm", "reverse"), ("ctermfg", "1"), ("gui", "reverse"), ("guifg", "#dc322f")]+-- >   ] []+-- >+-- > test_syntax :: UnitTest+-- > test_syntax =+-- >   testSocketTmuxGui do+-- >     setCurrentBufferContent ["function :: String -> Int", "function _ = 5"]+-- >     _ <- executeSyntax syntax+-- >     awaitScreenshot False "syntax" 0+-- >+-- > See [Ribosome.Test.SocketTmux]("Ribosome.Test.SocketTmux") and [Ribosome.Test.EmbedTmux]("Ribosome.Test.EmbedTmux")+-- > for more options.
− lib/Ribosome/Test/Await.hs
@@ -1,37 +0,0 @@-module Ribosome.Test.Await where--import Hedgehog (TestT)-import Control.Exception (throw)-import Control.Monad.Error.Class (MonadError (throwError), catchError)-import Hedgehog.Internal.Property (mkTestT, runTestT, Failure, Journal)--import Ribosome.Control.Concurrent.Wait (WaitError(Thrown, ConditionUnmet, NotStarted), waitIODef)--await ::-  ∀ e a b m .-  MonadError e m =>-  MonadIO m =>-  MonadBaseControl IO m =>-  (a -> TestT m b) ->-  m a ->-  TestT m b-await assertion acquire = do-  lift (waitIODef acquire' check') >>= \case-    Right a -> pure a-    Left (ConditionUnmet (Left (err, journal))) ->-      mkTestT (pure (Left err, journal))-    Left (ConditionUnmet (Right e)) ->-      throwError e-    Left (Thrown e) ->-      throw e-    Left NotStarted -> fail "await was not started"-  where-    acquire' :: m (Either e a)-    acquire' =-      catchError (Right <$> acquire) (pure . Left)-    check' :: Either e a -> m (Either (Either (Failure, Journal) e) b)-    check' (Right a) = do-      (result, journal) <- runTestT (assertion a)-      pure (mapLeft (Left . (,journal)) result)-    check' (Left e) = do-      pure (Left (Right e))
+ lib/Ribosome/Test/Data/TestConfig.hs view
@@ -0,0 +1,28 @@+module Ribosome.Test.Data.TestConfig where++import qualified Chiasma.Test.Data.TmuxTestConfig as Chiasma++import Ribosome.Data.PluginConfig (PluginConfig (PluginConfig))+import Ribosome.Host.Data.HostConfig (HostConfig (HostConfig), dataLogConc)++data TestConfig =+  TestConfig {+    freeze :: Bool,+    plugin :: PluginConfig ()+  }+  deriving stock (Eq, Show, Generic)++instance Default TestConfig where+  def =+    TestConfig False (PluginConfig "test" (HostConfig def { dataLogConc = False }) unit)++data TmuxTestConfig =+  TmuxTestConfig {+    core :: TestConfig,+    tmux :: Chiasma.TmuxTestConfig+  }+  deriving stock (Eq, Show, Generic)++instance Default TmuxTestConfig where+  def =+    TmuxTestConfig def def { Chiasma.gui = False }
lib/Ribosome/Test/Embed.hs view
@@ -1,351 +1,278 @@-module Ribosome.Test.Embed where--import Chiasma.Test.Tmux (withProcessWait)-import Control.Concurrent.Async.Lifted (async, cancel, race)-import Control.Concurrent.Lifted (fork)-import Control.Exception.Lifted (bracket, try)-import Control.Monad.Trans.Resource (runResourceT)-import qualified Data.Map.Strict as Map (fromList, toList, union)-import Hedgehog (TestT)-import Hedgehog.Internal.Property (mkTestT, runTestT)-import Neovim (Neovim, Object)-import Neovim.API.Text (vim_command)-import qualified Neovim.Context.Internal as Internal (-  Config,-  Neovim(Neovim),-  StateTransition(Failure, InitSuccess, Quit),-  globalFunctionMap,-  mkFunctionMap,-  newConfig,-  pluginSettings,-  retypeConfig,-  transitionTo,-  )-import Neovim.Main (standalone)-import Neovim.Plugin (Plugin(Plugin), startPluginThreads)-import Neovim.Plugin.Internal (NeovimPlugin, wrapPlugin)-import Neovim.RPC.Common (RPCConfig, newRPCConfig)-import Neovim.RPC.EventHandler (runEventHandler)-import Neovim.RPC.SocketReader (runSocketReader)-import System.Directory (makeAbsolute)-import System.Exit (ExitCode)-import System.Log.Logger (Priority(ERROR), setLevel, updateGlobalLogger)-import qualified System.Posix.Signals as Signal (killProcess, signalProcess)-import System.Process (getPid)-import System.Process.Typed (-  Process,-  ProcessConfig,-  createPipe,-  getExitCode,-  getStdin,-  getStdout,-  proc,-  setStdin,-  setStdout,-  startProcess,-  stopProcess,-  unsafeProcessHandle,-  )--import Ribosome.Api.Option (rtpCat)-import Ribosome.Control.Exception (tryAny)-import Ribosome.Control.Monad.Ribo (NvimE)-import Ribosome.Control.Ribosome (Ribosome(Ribosome), newRibosomeTMVar)-import qualified Ribosome.Data.ErrorReport as ErrorReport (ErrorReport(..))-import Ribosome.Error.Report.Class (ReportError(errorReport))-import Ribosome.Nvim.Api.IO (vimSetVar)-import Ribosome.Plugin.RpcHandler (RpcHandler(native))-import Ribosome.System.Time (sleep, sleepW)-import Ribosome.Test.Orphans ()--type Runner m = ∀ a . TestConfig -> m a -> m a+module Ribosome.Test.Embed (+  -- * Embedded Neovim testing+  -- $intro -newtype Vars =-  Vars (Map Text Object)-  deriving (Eq, Show)-  deriving newtype (Default, Semigroup, Monoid)+  testPlugin,+  testEmbed,+  testPluginEmbed,+  runEmbedTest,+  runTest,+  testPluginConf,+  testPlugin_,+  testEmbedConf,+  testEmbed_,+  testEmbedLevel,+  testEmbedLevel_,+  testEmbedTrace,+  testEmbedDebug,+  testEmbedTrace_,+  testEmbedDebug_,+  runTestConf,+  runTestLogConf,+  EmbedStackWith,+  EmbedStack,+  EmbedHandlerStack,+  TestEffects,+) where --- |left biased-varsUnion :: Vars -> Vars -> Vars-varsUnion (Vars v1) (Vars v2) =-  Vars (Map.union v1 v2)+import Log (Severity (Debug, Trace))+import Polysemy.Test (TestError, UnitTest) -varsFromList :: [(Text, Object)] -> Vars-varsFromList =-  Vars . Map.fromList+import Ribosome.Data.PluginConfig (PluginConfig (PluginConfig))+import Ribosome.Data.PluginName (PluginName)+import Ribosome.Data.SettingError (SettingError)+import Ribosome.Effect.Scratch (Scratch)+import Ribosome.Effect.Settings (Settings)+import Ribosome.Embed (HandlerEffects, embedPlugin, interpretPluginEmbed)+import Ribosome.Host.Data.BootError (BootError)+import Ribosome.Host.Data.HostConfig (setStderr)+import Ribosome.Host.Data.Report (Report)+import Ribosome.Host.Data.RpcError (RpcError)+import Ribosome.Host.Data.RpcHandler (RpcHandler)+import Ribosome.Host.Effect.Rpc (Rpc)+import Ribosome.Host.Error (resumeBootError)+import Ribosome.Host.Interpret (HigherOrder)+import Ribosome.Host.Interpreter.Handlers (withHandlers)+import Ribosome.Host.Interpreter.Host (HostDeps)+import qualified Ribosome.Host.Test.Data.TestConfig as Host+import qualified Ribosome.Host.Test.Run as Host+import Ribosome.Host.Test.Run (TestConfStack, TestStack, runUnitTest)+import Ribosome.Plugin.Builtin (BuiltinHandlersDeps)+import Ribosome.Test.Data.TestConfig (TestConfig (TestConfig))+import Ribosome.Test.Error (testError, testHandler)+import Ribosome.Test.Log (testLogLevel) -data TestConfig =-  TestConfig {-    tcPluginName :: Text,-    tcExtraRtp :: Text,-    tcLogPath :: FilePath,-    tcTimeout :: Word,-    tcCmdline :: Maybe [Text],-    tcCmdArgs :: [Text],-    tcVariables :: Vars-  }+-- $intro+-- The function 'testPluginEmbed' starts an embedded Neovim subprocess and a Ribosome main loop, then executes the+-- supplied 'Sem'.+--+-- This can be interpreted into a "Hedgehog" 'Hedgehog.TestT' by using the functions 'runEmbedTest' and 'runTest'.+--+-- The functions 'testPluginConf' and 'testPlugin' run a full Ribosome plugin with RPC handlers and extra effects in+-- addition to the above.+-- This can be used to test calling RPC handlers from Neovim, which usually shouldn't be necessary but may be helpful+-- for some edge cases.+--+-- The functions 'testEmbedConf' and 'testEmbed' run tests with extra effects, but no handlers.+-- This is the most advisable way to test plugins, running handlers directly as Haskell functions instead of routing+-- them through Neovim, in particular for those that don't have any parameters. -instance Default TestConfig where-  def = TestConfig "ribosome" "test/u/fixtures/rtp" "test/u/temp/log" 10 def def def+-- |The extra effects that tests are expected to use, related to errors.+--+-- The plugin effects 'Scratch', 'Settings' and 'Rpc' are allowed without 'Resume', causing tests to terminate+-- immediately if one of these effects is used and throws an error.+--+-- Additionally, the two core errors, 'LogReport' and 'RpcError' are executed directly via 'Stop'.+type TestEffects =+  [+    Stop Report,+    Stop RpcError,+    Scratch,+    Settings,+    Rpc+  ] -defaultTestConfigWith :: Text -> Vars -> TestConfig-defaultTestConfigWith name vars =-  def { tcPluginName = name, tcVariables = vars }+-- |The full test stack below test effects and extra effects.+type EmbedHandlerStack =+  HandlerEffects ++ Reader PluginName : TestStack -defaultTestConfig :: Text -> TestConfig-defaultTestConfig name = defaultTestConfigWith name def+-- |The full test stack with additional effects.+type EmbedStackWith r =+  TestEffects ++ r ++ EmbedHandlerStack -setVars :: ∀ m e. NvimE e m => Vars -> m ()-setVars (Vars vars) =-  traverse_ set (Map.toList vars)-  where-    set :: (Text, Object) -> m ()-    set =-      uncurry vimSetVar+-- |The full test stack with no additional effects.+type EmbedStack =+  EmbedStackWith '[] -setupPluginEnv ::-  MonadIO m =>-  NvimE e m =>+-- |Interpret the basic test effects without 'IO' related effects.+runTestLogConf ::+  Members [Error BootError, Resource, Race, Async, Embed IO] r =>   TestConfig ->-  m ()-setupPluginEnv (TestConfig _ rtp _ _ _ _ vars) = do-  absRtp <- liftIO $ makeAbsolute (toString rtp)-  rtpCat (toText absRtp)-  setVars vars--killPid :: Integral a => a -> IO ()-killPid =-  void . tryAny . Signal.signalProcess Signal.killProcess . fromIntegral--killProcess :: Process i o e -> IO ()-killProcess prc = do-  void $ try @_ @SomeException do-    let handle = unsafeProcessHandle prc-    mayPid <- getPid handle-    traverse_ killPid mayPid--testNvimProcessConfig :: TestConfig -> ProcessConfig Handle Handle ()-testNvimProcessConfig TestConfig {..} =-  setStdin createPipe . setStdout createPipe . proc "nvim" . fmap toString $ args <> tcCmdArgs-  where-    args = fromMaybe defaultArgs tcCmdline-    defaultArgs = ["--embed", "-n", "-u", "NONE", "-i", "NONE"]+  InterpretersFor (Reader PluginName : TestConfStack) r+runTestLogConf (TestConfig freezeTime (PluginConfig name conf _)) =+  Host.runTestLogConf (Host.TestConfig freezeTime conf) .+  runReader name -startHandlers ::-  MonadIO m =>-  Handle ->-  Handle ->+-- |Run the basic test effects as a "Hedgehog" test.+runTestConf ::+  HasCallStack =>   TestConfig ->-  Internal.Config RPCConfig ->-  m (IO ())-startHandlers stdoutHandle stdinHandle TestConfig{} nvimConf = do-  socketReader <- liftIO (run runSocketReader stdoutHandle)-  eventHandler <- liftIO (run runEventHandler stdinHandle)-  atomically $ putTMVar (Internal.globalFunctionMap nvimConf) (Internal.mkFunctionMap [])-  let stopEventHandlers = traverse_ @[] cancel [socketReader, eventHandler]-  return stopEventHandlers-  where-    run runner hand = async . void $ runner hand emptyConf-    emptyConf = nvimConf { Internal.pluginSettings = Nothing }+  Sem (Reader PluginName : TestStack) () ->+  UnitTest+runTestConf conf =+  runUnitTest .+  runTestLogConf conf -startStdioHandlers ::-  MonadIO m =>-  NvimProc ->+-- |Run the plugin stack and the test stack, using the supplied config.+runEmbedTest ::+  HasCallStack =>   TestConfig ->-  Internal.Config RPCConfig ->-  m (IO ())-startStdioHandlers prc =-  startHandlers (getStdout prc) (getStdin prc)--runNeovimThunk :: Internal.Config e -> Neovim e a -> IO a-runNeovimThunk cfg (Internal.Neovim thunk) =-  runReaderT (runResourceT thunk) cfg+  Sem EmbedHandlerStack () ->+  UnitTest+runEmbedTest conf =+  runTestConf conf .+  interpretPluginEmbed -type NvimProc = Process Handle Handle ()+-- |Run the plugin stack and the test stack, using the default config.+runTest ::+  HasCallStack =>+  Sem EmbedHandlerStack () ->+  UnitTest+runTest =+  runEmbedTest def -waitQuit :: NvimProc -> IO (Maybe ExitCode)-waitQuit prc =-  wait 30-  where-    wait :: Int -> IO (Maybe ExitCode)-    wait 0 = return Nothing-    wait count = do-      code <- getExitCode prc-      case code of-        Just a -> return $ Just a-        Nothing -> do-          sleep 0.1-          wait $ count - 1+-- |Run the test plugin effects, 'TestEffects', and start an embedded Neovim subprocess.+testPluginEmbed ::+  Members (HostDeps er) r =>+  Members BuiltinHandlersDeps r =>+  Members [Settings !! SettingError, Error TestError] r =>+  InterpretersFor TestEffects r+testPluginEmbed =+  embedPlugin .+  resumeBootError @Rpc .+  resumeBootError @Settings .+  resumeBootError @Scratch .+  testError .+  testHandler .+  insertAt @4 -quitNvim :: Internal.Config e -> NvimProc -> IO ()-quitNvim testCfg prc = do-  quitThread <- async $ runNeovimThunk testCfg quit-  result <- waitQuit prc-  case result of-    Just _ -> return ()-    Nothing -> killProcess prc-  cancel quitThread-  where-    quit = vim_command "qall!"+-- |Run a full plugin test, using extra effects and RPC handlers.+testPluginConf ::+  ∀ r .+  HasCallStack =>+  HigherOrder r EmbedHandlerStack =>+  TestConfig ->+  InterpretersFor r EmbedHandlerStack ->+  [RpcHandler (r ++ EmbedHandlerStack)] ->+  Sem (EmbedStackWith r) () ->+  UnitTest+testPluginConf conf effs handlers =+  runEmbedTest conf .+  effs .+  withHandlers handlers .+  testPluginEmbed -shutdownNvim :: Internal.Config e -> NvimProc -> IO () -> IO ()-shutdownNvim _ prc stopEventHandlers = do-  stopEventHandlers-  killProcess prc+-- |Run a full plugin test, using extra effects and RPC handlers.+testPlugin ::+  ∀ r .+  HasCallStack =>+  HigherOrder r EmbedHandlerStack =>+  InterpretersFor r EmbedHandlerStack ->+  [RpcHandler (r ++ EmbedHandlerStack)] ->+  Sem (EmbedStackWith r) () ->+  UnitTest+testPlugin =+  testPluginConf @r def -runTest ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  TestConfig ->-  Internal.Config env ->-  n a ->-  m a-runTest TestConfig{..} testCfg thunk = do-  race (sleepW tcTimeout) (liftIO (runNeovimThunk testCfg (runExceptT $ native thunk))) >>= \case-    Right (Right a) -> pure a-    Right (Left e) -> fail . toString . unlines . ErrorReport._log . errorReport $ e-    Left _ -> fail $ "test exceeded timeout of " <> show tcTimeout <> " seconds"+-- |Run a plugin test with RPC handlers.+testPlugin_ ::+  HasCallStack =>+  [RpcHandler EmbedHandlerStack] ->+  Sem EmbedStack () ->+  UnitTest+testPlugin_ =+  testPlugin @'[] id -runEmbeddedNvim ::-  MonadIO m =>-  MonadFail m =>-  MonadBaseControl IO m =>-  RpcHandler e env n =>-  ReportError e =>+-- |Run a plugin test with extra effects but no RPC handlers.+testEmbedConf ::+  ∀ r .+  HasCallStack =>+  HigherOrder r EmbedHandlerStack =>   TestConfig ->-  env ->-  n a ->-  NvimProc ->-  m a-runEmbeddedNvim conf ribo thunk prc = do-  nvimConf <- liftIO (Internal.newConfig (pure Nothing) newRPCConfig)-  let testCfg = Internal.retypeConfig ribo nvimConf-  bracket (startStdioHandlers prc conf nvimConf) (liftIO . shutdownNvim testCfg prc) (const $ runTest conf testCfg thunk)+  InterpretersFor r EmbedHandlerStack ->+  Sem (EmbedStackWith r) () ->+  UnitTest+testEmbedConf conf effs =+  testPluginConf @r conf effs mempty -withProcessTerm ::-  MonadIO m =>-  MonadBaseControl IO m =>-  ProcessConfig stdin stdout stderr ->-  (Process stdin stdout stderr -> m a) ->-  m a-withProcessTerm config =-  bracket (startProcess config) (try @_ @SomeException . stopProcess)+-- |Run a plugin test with extra effects but no RPC handlers.+testEmbed ::+  ∀ r .+  HasCallStack =>+  HigherOrder r EmbedHandlerStack =>+  InterpretersFor r EmbedHandlerStack ->+  Sem (EmbedStackWith r) () ->+  UnitTest+testEmbed =+  testEmbedConf @r def -runEmbedded ::-  MonadIO m =>-  MonadFail m =>-  MonadBaseControl IO m =>-  RpcHandler e env n =>-  ReportError e =>-  TestConfig ->-  env ->-  n a ->-  m a-runEmbedded conf ribo thunk = do-  let pc = testNvimProcessConfig conf-  withProcessWait pc $ runEmbeddedNvim conf ribo thunk+-- |Run a plugin test with extra effects but no RPC handlers.+--+-- Takes a log level, for which the default is to only print critical errors.+testEmbedLevel ::+  ∀ r .+  HasCallStack =>+  HigherOrder r EmbedHandlerStack =>+  Severity ->+  InterpretersFor r EmbedHandlerStack ->+  Sem (EmbedStackWith r) () ->+  UnitTest+testEmbedLevel level =+  testEmbedConf @r (def & #plugin . #host %~ setStderr level) -unsafeEmbeddedSpec ::-  MonadIO m =>-  MonadFail m =>-  MonadBaseControl IO m =>-  RpcHandler e env n =>-  ReportError e =>-  Runner n ->-  TestConfig ->-  env ->-  n a ->-  m a-unsafeEmbeddedSpec runner conf s spec =-  runEmbedded conf s $ runner conf spec+-- |Run a plugin test with extra effects but no RPC handlers at the 'Debug' log level.+testEmbedDebug ::+  ∀ r .+  HasCallStack =>+  HigherOrder r EmbedHandlerStack =>+  InterpretersFor r EmbedHandlerStack ->+  Sem (EmbedStackWith r) () ->+  UnitTest+testEmbedDebug effs =+  testLogLevel Debug \ conf -> testEmbedConf @r conf effs -unsafeEmbeddedSpecR ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  MonadBaseControl IO m =>-  RpcHandler e (Ribosome env) n =>-  Runner n ->-  TestConfig ->-  env ->-  n a ->-  m a-unsafeEmbeddedSpecR runner conf env spec = do-  tv <- newRibosomeTMVar env-  let ribo = Ribosome (tcPluginName conf) tv-  unsafeEmbeddedSpec runner conf ribo spec+-- |Run a plugin test with extra effects but no RPC handlers at the 'Trace' log level for debugging RPC traffic.+testEmbedTrace ::+  ∀ r .+  HasCallStack =>+  HigherOrder r EmbedHandlerStack =>+  InterpretersFor r EmbedHandlerStack ->+  Sem (EmbedStackWith r) () ->+  UnitTest+testEmbedTrace effs =+  testLogLevel Trace \ conf -> testEmbedConf @r conf effs -runPlugin ::-  MonadIO m =>-  MonadBaseControl IO m =>-  Handle ->-  Handle ->-  [Neovim () NeovimPlugin] ->-  Internal.Config c ->-  m (MVar Internal.StateTransition)-runPlugin evHandlerHandle sockreaderHandle plugins baseConf = do-  liftIO (updateGlobalLogger "Neovim.Plugin" (setLevel ERROR))-  rpcConf <- liftIO newRPCConfig-  let conf = Internal.retypeConfig rpcConf baseConf-  ehTid <- (fmap void . async . liftIO) (runEventHandler evHandlerHandle conf { Internal.pluginSettings = Nothing })-  srTid <- (fmap void . async . liftIO) (runSocketReader sockreaderHandle conf)-  void $ fork $ liftIO $ startPluginThreads (Internal.retypeConfig () baseConf) plugins >>= \case-    Left e -> do-      putMVar (Internal.transitionTo conf) $ Internal.Failure e-      standalone [ehTid, srTid] conf-    Right (funMapEntries, pluginTids) -> do-      atomically $ putTMVar (Internal.globalFunctionMap conf) (Internal.mkFunctionMap funMapEntries)-      putMVar (Internal.transitionTo conf) Internal.InitSuccess-      standalone (srTid : ehTid : pluginTids) conf-  return (Internal.transitionTo conf)+-- |Run a plugin test without extra effects and RPC handlers.+testEmbed_ ::+  HasCallStack =>+  Sem EmbedStack () ->+  UnitTest+testEmbed_ =+  testPlugin_ mempty -inTestT ::-  ∀ n m a .-  TestT n a ->-  (∀ x . n x -> m x) ->-  TestT m a-inTestT ma f =-  mkTestT (f (runTestT ma))+-- |Run a plugin test without extra effects and RPC handlers.+--+-- Takes a log level, for which the default is to only print critical errors.+testEmbedLevel_ ::+  HasCallStack =>+  Severity ->+  Sem EmbedStack () ->+  UnitTest+testEmbedLevel_ level =+  testEmbedConf @'[] (def & #plugin . #host %~ setStderr level) id -integrationSpec ::-  ∀ n m e env a .-  NvimE e n =>-  MonadIO n =>-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  TestConfig ->-  Plugin env ->-  TestT n a ->-  TestT m a-integrationSpec conf plugin@(Plugin env _) thunk =-  inTestT thunk \ na ->-    withProcessTerm (testNvimProcessConfig conf) (run na)-  where-    run :: ∀ x . n x -> Process Handle Handle () -> m x-    run na prc = do-      nvimConf <- liftIO (Internal.newConfig (pure Nothing) (pure env))-      bracket (acquire prc nvimConf) release (const $ runTest conf nvimConf (setupPluginEnv conf *> na))-    acquire prc nvimConf =-      liftIO (runPlugin (getStdin prc) (getStdout prc) [wrapPlugin plugin] nvimConf <* sleep 0.5)-    release transitions =-      tryPutMVar transitions Internal.Quit *> sleep 0.5+-- |Run a plugin test without extra effects and RPC handlers at the 'Debug' log level.+testEmbedDebug_ ::+  HasCallStack =>+  Sem EmbedStack () ->+  UnitTest+testEmbedDebug_ =+  testEmbedLevel_ Debug -integrationSpecDef ::-  NvimE e n =>-  MonadIO m =>-  MonadIO n =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  Plugin env ->-  TestT n a ->-  TestT m a-integrationSpecDef =-  integrationSpec def+-- |Run a plugin test without extra effects and RPC handlers at the 'Trace' log level for debugging RPC traffic.+testEmbedTrace_ ::+  HasCallStack =>+  Sem EmbedStack () ->+  UnitTest+testEmbedTrace_ =+  testEmbedLevel_ Trace
+ lib/Ribosome/Test/EmbedTmux.hs view
@@ -0,0 +1,83 @@+module Ribosome.Test.EmbedTmux where++import Polysemy.Test (UnitTest)++import Ribosome.Embed (HandlerEffects, interpretPluginEmbed)+import Ribosome.Host.Data.RpcHandler (RpcHandler)+import Ribosome.Host.Interpreter.Handlers (withHandlers)+import Ribosome.Test.Data.TestConfig (TmuxTestConfig)+import Ribosome.Test.Embed (TestEffects, testPluginEmbed)+import Ribosome.Test.TmuxCommon (TmuxStack, runTmuxNvim)++type HandlerStack =+  HandlerEffects ++ TmuxStack++type EmbedTmuxWith r =+  TestEffects ++ r ++ HandlerStack++type EmbedTmux =+  EmbedTmuxWith '[]++runEmbedTmuxTestConf ::+  HasCallStack =>+  TmuxTestConfig ->+  Sem HandlerStack () ->+  UnitTest+runEmbedTmuxTestConf conf =+  runTmuxNvim conf .+  interpretPluginEmbed++runEmbedTmuxTest ::+  HasCallStack =>+  Sem HandlerStack () ->+  UnitTest+runEmbedTmuxTest =+  runEmbedTmuxTestConf def++runEmbedTmuxGuiTest ::+  HasCallStack =>+  Sem HandlerStack () ->+  UnitTest+runEmbedTmuxGuiTest =+  runEmbedTmuxTestConf (def & #tmux . #gui .~ True)++testPluginEmbedTmuxConf ::+  ∀ r .+  HasCallStack =>+  Members HandlerStack (r ++ HandlerStack) =>+  TmuxTestConfig ->+  InterpretersFor r HandlerStack ->+  [RpcHandler (r ++ HandlerStack)] ->+  Sem (EmbedTmuxWith r) () ->+  UnitTest+testPluginEmbedTmuxConf conf effs handlers =+  runEmbedTmuxTestConf conf .+  effs .+  withHandlers handlers .+  testPluginEmbed++testPluginEmbedTmux ::+  ∀ r .+  HasCallStack =>+  Members HandlerStack (r ++ HandlerStack) =>+  InterpretersFor r HandlerStack ->+  [RpcHandler (r ++ HandlerStack)] ->+  Sem (EmbedTmuxWith r) () ->+  UnitTest+testPluginEmbedTmux =+  testPluginEmbedTmuxConf @r def++testPluginEmbedTmux_ ::+  HasCallStack =>+  [RpcHandler HandlerStack] ->+  Sem EmbedTmux () ->+  UnitTest+testPluginEmbedTmux_ =+  testPluginEmbedTmux @'[] id++testEmbedTmux ::+  HasCallStack =>+  Sem EmbedTmux () ->+  UnitTest+testEmbedTmux =+  testPluginEmbedTmux_ mempty
+ lib/Ribosome/Test/Error.hs view
@@ -0,0 +1,47 @@+{-# options_haddock not-home #-}++module Ribosome.Test.Error where++import Polysemy.Test (TestError (TestError))++import Ribosome.Host.Data.Report (Reportable, mapReport, reportMessages)+import Ribosome.Host.Data.RpcHandler (Handler)++-- |Resume an effect and convert its error from @'Stop' err@ to @'Error' 'TestError'@.+resumeTestError ::+  ∀ eff err r .+  Show err =>+  Members [eff !! err, Error TestError] r =>+  InterpreterFor eff r+resumeTestError =+  resumeHoistError (TestError . show)++-- |Run a 'Handler', converting the @'Stop' 'Report'@ at its head to @'Error' 'TestError'@.+testHandler ::+  Member (Error TestError) r =>+  Handler r a ->+  Sem r a+testHandler =+  stopToErrorWith (TestError . reportMessages)++-- |Run a 'Handler' in a new thread and return an action that waits for the thread to terminate when sequenced.+-- Converts the @'Stop' 'Report'@ at its head to @'Error' 'TestError'@ when it is awaited.+testHandlerAsync ::+  Members [Error TestError, Async] r =>+  Handler r a ->+  Sem r (Sem r a)+testHandlerAsync h = do+  thread <- async do+    runStop h+  pure do+    testHandler . stopEither =<< note (TestError "async handler didn't produce result") =<< await thread++-- |Interpret @'Stop' err@ to @'Error' 'TestError'@ by using @err@'s instance of 'Reportable'.+testError ::+  ∀ err r a .+  Reportable err =>+  Member (Error TestError) r =>+  Sem (Stop err : r) a ->+  Sem r a+testError =+  testHandler . mapReport . raiseUnder
+ lib/Ribosome/Test/Examples/Example1.hs view
@@ -0,0 +1,30 @@+{-# options_haddock prune, hide #-}++-- |An example for the docs.+module Ribosome.Test.Examples.Example1 where++import Polysemy.Test++import Ribosome+import Ribosome.Api+import Ribosome.Test++store ::+  Member (Rpc !! RpcError) r =>+  Args ->+  Handler r ()+store (Args msg) =+  ignoreRpcError do+    nvimSetVar "message" msg++test_direct :: UnitTest+test_direct =+  testEmbed_ do+    store "test directly"+    assertEq "test directly" =<< nvimGetVar @Text "message"++test_rpc :: UnitTest+test_rpc =+  testPlugin_ [rpcCommand "Store" Sync store] do+    nvimCommand "Store test RPC"+    assertEq "test RPC" =<< nvimGetVar @Text "message"
− lib/Ribosome/Test/Exists.hs
@@ -1,44 +0,0 @@-module Ribosome.Test.Exists where--import Data.MessagePack (Object(ObjectInt))-import Neovim (Neovim, toObject)-import Neovim.API.Text (vim_call_function)-import UnliftIO.Exception (tryAny)--import Ribosome.Data.Text (capitalize)-import Ribosome.System.Time (epochSeconds, sleep)--retry ::-  MonadIO m =>-  MonadFail m =>-  Double ->-  Int ->-  m a ->-  (a -> m (Either Text b)) ->-  m b-retry interval timeout thunk check = do-  start <- epochSeconds-  step start-  where-    step start = do-      result <- thunk-      checked <- check result-      recurse start checked-    recurse _ (Right b) = return b-    recurse start (Left e) = do-      current <- epochSeconds-      if (current - start) < timeout-      then do-        sleep interval-        step start-      else fail (toString e)--waitForPlugin :: Text -> Double -> Int -> Neovim env ()-waitForPlugin name interval timeout =-  retry interval timeout thunk check-  where-    thunk = tryAny $ vim_call_function "exists" $ fromList [toObject $ "*" <> capitalize name <> "Poll"]-    check (Right (ObjectInt 1)) = return $ Right ()-    check (Right a) = return $ Left $ errormsg <> "weird return type " <> show a-    check (Left e) = return $ Left $ errormsg <> show e-    errormsg = "plugin didn't start within " <> show timeout <> " seconds: "
− lib/Ribosome/Test/File.hs
@@ -1,41 +0,0 @@-module Ribosome.Test.File where--import qualified Data.ByteString as ByteString (readFile)-import System.Directory (canonicalizePath, createDirectoryIfMissing, removePathForcibly)-import System.FilePath ((</>))--testDir :: Text -> IO FilePath-testDir = canonicalizePath . toString---- raises exception if cwd is not the package root so we don't damage anything-tempDirIO :: Text -> FilePath -> IO FilePath-tempDirIO prefix path = do-  base <- testDir prefix-  let dir = base </> "temp"-  removePathForcibly dir-  createDirectoryIfMissing False dir-  let absPath = dir </> path-  createDirectoryIfMissing True absPath-  return absPath--tempDir :: MonadIO m => Text -> FilePath -> m FilePath-tempDir prefix path =-  liftIO $ tempDirIO prefix path--fixture ::-  MonadIO m =>-  Text ->-  FilePath ->-  m FilePath-fixture prefix path = do-  base <- liftIO $ testDir prefix-  return $ base </> "fixtures" </> path--fixtureContent ::-  MonadIO m =>-  Text ->-  FilePath ->-  m Text-fixtureContent prefix subPath = do-  path <- fixture prefix subPath-  decodeUtf8 <$> liftIO (ByteString.readFile path)
− lib/Ribosome/Test/Functional.hs
@@ -1,74 +0,0 @@-module Ribosome.Test.Functional where---- import Control.Exception (finally)--- import Control.Monad (when)--- import Control.Monad.IO.Class--- import Data.Foldable (traverse_)--- import Neovim (Neovim, vim_command')--- import System.Console.ANSI (Color(Green), ColorIntensity(Dull), ConsoleLayer(Foreground), SGR(SetColor, Reset), setSGR)--- import System.Directory (createDirectoryIfMissing, doesFileExist, getCurrentDirectory, makeAbsolute, removePathForcibly)--- import System.FilePath (takeDirectory, takeFileName, (</>))---- import Ribosome.Control.Ribo (Ribo)--- import Ribosome.Test.Embed (TestConfig(..), setupPluginEnv, unsafeEmbeddedSpec)--- import Ribosome.Test.Exists (waitForPlugin)--- import qualified Ribosome.Test.File as F (fixture, tempDir)---- jobstart :: MonadIO f => Text -> f Text--- jobstart cmd = do---   dir <- liftIO getCurrentDirectory---   return $ "call jobstart('" <> cmd <> "', { 'rpc': v:true, 'cwd': '" <> dir <> "' })"---- logFile :: TestConfig -> IO FilePath--- logFile TestConfig{..} = makeAbsolute $ tcLogPath <> "-spec"---- startPlugin :: TestConfig -> Neovim env ()--- startPlugin tc@TestConfig{..} = do---   absLogPath <- liftIO $ makeAbsolute tcLogPath---   absLogFile <- liftIO $ logFile tc---   liftIO $ createDirectoryIfMissing True (takeDirectory absLogPath)---   liftIO $ removePathForcibly absLogFile---   setupPluginEnv tc---   cmd <- jobstart $ "stack run -- -l " <> absLogFile <> " -v INFO"---   vim_command' cmd---   waitForPlugin tcPluginName 0.1 3---- fSpec :: TestConfig -> Neovim env () -> Neovim env ()--- fSpec conf spec = startPlugin conf >> spec---- showLog' :: Text -> IO ()--- showLog' output = do---   putStrLn ""---   setSGR [SetColor Foreground Dull Green]---   putStrLn "plugin output:"---   setSGR [Reset]---   traverse_ putStrLn (lines output)---   putStrLn ""---- showLog :: TestConfig -> IO ()--- showLog conf = do---   file <- logFile conf---   exists <- doesFileExist file---   when exists $ do---     output <- readFile file---     case output of---       [] -> return ()---       o -> showLog' o---- functionalSpec :: TestConfig -> Ribo () () -> IO ()--- functionalSpec conf spec =---   finally (unsafeEmbeddedSpec fSpec conf () spec) (showLog conf)---- fPrefix :: Text--- fPrefix = "f"---- tempDir :: FilePath -> Neovim e FilePath--- tempDir = F.tempDir fPrefix---- tempFile :: FilePath -> Neovim e FilePath--- tempFile file = do---   absDir <- tempDir $ takeDirectory file---   return $ absDir </> takeFileName file---- fixture :: MonadIO m => FilePath -> m FilePath--- fixture = F.fixture fPrefix
− lib/Ribosome/Test/Input.hs
@@ -1,21 +0,0 @@-module Ribosome.Test.Input where--import Control.Concurrent.Lifted (fork, killThread)-import Control.Exception.Lifted (bracket)--import Ribosome.Api.Input (syntheticInput)-import Ribosome.Control.Monad.Ribo (NvimE)--withInput ::-  NvimE e m =>-  MonadIO m =>-  MonadBaseControl IO m =>-  Maybe Double ->-  [Text] ->-  m a ->-  m a-withInput interval chars thunk =-  bracket (fork input) killThread (const thunk)-  where-    input =-      syntheticInput interval chars
+ lib/Ribosome/Test/Log.hs view
@@ -0,0 +1,22 @@+module Ribosome.Test.Log where++import Log (Severity)++import Ribosome.Test.Data.TestConfig (TestConfig)++testLogLevelConf ::+  HasCallStack =>+  Severity ->+  (TestConfig -> a) ->+  TestConfig ->+  a+testLogLevelConf =+  undefined++testLogLevel ::+  HasCallStack =>+  Severity ->+  (TestConfig -> a) ->+  a+testLogLevel level f =+  testLogLevelConf level f def
− lib/Ribosome/Test/Orphans.hs
@@ -1,27 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Ribosome.Test.Orphans where---- import Control.Monad.IO.Unlift (withRunInIO)--- import Neovim (Neovim)---- import Ribosome.Control.Monad.Ribo (Ribo(Ribo, unRibo))---- instance AssertM (Neovim e) where---   genericAssertFailure__ l =---     liftIO . genericAssertFailure__ l----   genericSubAssert l msg ma =---     withRunInIO (\f -> genericSubAssert l msg (f ma))---- instance AssertM (ExceptT e (Neovim s)) where---   genericAssertFailure__ l = liftIO . genericAssertFailure__ l----   genericSubAssert l msg =---     ExceptT . genericSubAssert l msg . runExceptT---- instance AssertM (Ribo s e) where---   genericAssertFailure__ l = liftIO . genericAssertFailure__ l----   genericSubAssert l msg =---     Ribo . ExceptT . genericSubAssert l msg . runExceptT . unRibo
− lib/Ribosome/Test/Run.hs
@@ -1,14 +0,0 @@-module Ribosome.Test.Run where--import Hedgehog (TestT, property, test, withTests)-import Test.Tasty (TestName, TestTree)-import Test.Tasty.Hedgehog (testProperty)--type UnitTest = TestT IO ()--unitTest ::-  TestName ->-  UnitTest ->-  TestTree-unitTest desc =-  testProperty desc . withTests 1 . property . test
lib/Ribosome/Test/Screenshot.hs view
@@ -1,62 +1,95 @@ module Ribosome.Test.Screenshot where -import Chiasma.Data.TmuxError (TmuxError)-import Chiasma.Data.TmuxThunk (TmuxThunk)-import qualified Chiasma.Test.Screenshot as Chiasma (screenshot)-import Control.Monad.Catch (MonadMask)-import Control.Monad.Free.Class (MonadFree)-import Hedgehog (TestT, (===))+import Chiasma.Data.CodecError (CodecError)+import Chiasma.Effect.Codec (NativeCommandCodecE)+import Chiasma.Effect.TmuxClient (NativeTmux)+import qualified Chiasma.Test.Screenshot as Chiasma+import Chiasma.Tmux (withTmux)+import Chiasma.TmuxApi (Tmux)+import Control.Lens.Regex.Text (group, regex)+import Exon (exon)+import Hedgehog.Internal.Property (Failure)+import qualified Log+import Path (reldir)+import Polysemy.Chronos (ChronosTime)+import qualified Polysemy.Test as Test+import Polysemy.Test (Hedgehog, Test, TestError (TestError), (===))+import Prelude hiding (group)+import qualified Time+import Time (Seconds (Seconds)) -import Ribosome.Control.Monad.Ribo (MonadRibo, Nvim)-import Ribosome.Orphans ()-import Ribosome.Test.Orphans ()-import Ribosome.Test.Unit (fixture)-import Ribosome.Tmux.Run (runTmux)-import Ribosome.System.Time (sleep)-import Ribosome.Test.Await (await)+import Ribosome.Host.Effect.Log (StderrLog, stderrLog)+import Ribosome.Test.Wait (assertWait) +-- |Nvim appears to add random whitespace sequences, optionally interspersed with color codes, to empty lines.+-- This remotes that noise from lines starting with `~\ESC[39m` or `\ESC[94m~\ESC[39m`.+sanitize :: Text -> Text+sanitize =+  [regex|(\x{1b}\[94m)?~((\s|\x{1b}\[94m|\x{1b}\[39m)*)$|] . group 1 .~ ""+ screenshot ::-  MonadFree TmuxThunk m =>-  MonadIO m =>-  Text ->+  Members [Tmux, Test, Error TestError, Embed IO] r =>   Bool ->+  Bool ->+  Text ->   Int ->-  m (Maybe ([Text], [Text]))-screenshot name record pane = do-  storage <- fixture "screenshots"-  Chiasma.screenshot record storage name pane+  Sem r (Maybe ([Text], [Text]))+screenshot record sane name pane = do+  storage <- Test.fixturePath [reldir|screenshots|]+  mapError TestError (Chiasma.screenshotSanitized (if sane then sanitize else id) record storage name pane)  assertScreenshot ::-  MonadIO m =>-  MonadRibo m =>-  MonadDeepError e TmuxError m =>-  MonadBaseControl IO m =>-  MonadMask m =>-  Nvim m =>-  Text ->+  HasCallStack =>+  Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r =>+  Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, Race, Embed IO] r =>   Bool ->+  Text ->   Int ->-  TestT m ()-assertScreenshot name record pane = do-  lift (runTmux (screenshot name record pane)) >>= check+  Sem r ()+assertScreenshot sane name pane =+  withFrozenCallStack $ withTmux $ restop do+    assertWait (screenshot False sane name pane) (traverse_ check)   where-    check (Just (current, existing)) =+    check (current, existing) =       existing === current-    check Nothing =-      return () -awaitScreenshot ::-  MonadIO m =>-  MonadMask m =>-  MonadRibo m =>-  MonadBaseControl IO m =>-  MonadDeepError e TmuxError m =>-  Nvim m =>+updateScreeshot ::+  HasCallStack =>+  Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r =>+  Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, StderrLog, Race, Embed IO] r =>+  Bool ->   Text ->+  Int ->+  Sem r ()+updateScreeshot sane name pane =+  withTmux $ restop do+    stderrLog (Log.info [exon|Waiting for one second before storing new screenshot for '#{name}'|])+    Time.sleep (Seconds 1)+    void (screenshot sane True name pane)++awaitScreenshot' ::+  HasCallStack =>+  Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r =>+  Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, StderrLog, Race, Embed IO] r =>   Bool ->+  Bool ->+  Text ->   Int ->-  TestT m ()-awaitScreenshot name True pane =-  sleep 1 <* lift (runTmux (screenshot name True pane))-awaitScreenshot name False pane =-  await (const (assertScreenshot name False pane)) unit+  Sem r ()+awaitScreenshot' = \case+  True ->+    updateScreeshot+  False ->+    withFrozenCallStack assertScreenshot++awaitScreenshot ::+  HasCallStack =>+  Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r =>+  Members [Hedgehog IO, Test, Error TestError, Error Failure, ChronosTime, StderrLog, Race, Embed IO] r =>+  Bool ->+  Text ->+  Int ->+  Sem r ()+awaitScreenshot record =+  withFrozenCallStack do+    awaitScreenshot' record True
+ lib/Ribosome/Test/SocketTmux.hs view
@@ -0,0 +1,172 @@+-- |Socket tmux tests start a tmux server, then run a regular Neovim session in a pane and connect to Neovim over a+-- socket.+module Ribosome.Test.SocketTmux where++import Chiasma.Command.Pane (sendKeys)+import Chiasma.Data.CodecError (CodecError)+import Chiasma.Data.SendKeysParams (Key (Lit))+import Chiasma.Effect.Codec (NativeCommandCodecE)+import Chiasma.Effect.TmuxApi (Tmux)+import Chiasma.Effect.TmuxClient (NativeTmux)+import Chiasma.Tmux (withTmux)+import Exon (exon)+import Hedgehog.Internal.Property (Failure)+import Path (Abs, File, Path, reldir, relfile, (</>))+import Path.IO (doesPathExist)+import Polysemy.Chronos (ChronosTime)+import qualified Polysemy.Test as Test+import Polysemy.Test (Hedgehog, Test, UnitTest, assert)++import Ribosome.Host.Data.NvimSocket (NvimSocket (NvimSocket))+import Ribosome.Host.Data.RpcHandler (RpcHandler)+import Ribosome.Host.Interpreter.Handlers (withHandlers)+import Ribosome.Host.Path (pathText)+import Ribosome.Socket (SocketHandlerEffects, interpretPluginSocket)+import Ribosome.Test.Data.TestConfig (TmuxTestConfig)+import Ribosome.Test.Embed (TestEffects, testPluginEmbed)+import Ribosome.Test.TmuxCommon (TmuxStack, runTmuxNvim)+import Ribosome.Test.Wait (assertWait)+import Ribosome.Data.CustomConfig (CustomConfig (CustomConfig))++-- |The stack of internal effects for socket tmux tests.+type TmuxHandlerStack =+  SocketHandlerEffects ++ Reader (CustomConfig ()) : Reader NvimSocket : TmuxStack++-- |The socket tmux test stack with additional effects.+type SocketTmuxWith r =+  TestEffects ++ r ++ TmuxHandlerStack++-- |The socket tmux test stack with no additional effects.+type SocketTmux =+  SocketTmuxWith '[]++nvimCmdline :: Path Abs File -> Text+nvimCmdline socket =+  [exon|nvim --listen #{pathText socket} -n -u NONE -i NONE --clean|]++-- |Create a socket for Neovim to listen on and run a 'Reader' with it.+withSocketTmuxNvim ::+  Members [Test, Hedgehog IO, ChronosTime, Error Failure, Race, Embed IO] r =>+  Members [NativeTmux, NativeCommandCodecE, Stop CodecError] r =>+  InterpreterFor (Reader NvimSocket) r+withSocketTmuxNvim sem = do+  dir <- Test.tempDir [reldir|tmux-test|]+  let socket = dir </> [relfile|nvim-socket|]+  withTmux do+    restop @CodecError @Tmux $ sendKeys 0 [Lit (nvimCmdline socket)]+  assertWait (pure socket) (assert <=< doesPathExist)+  runReader (NvimSocket socket) sem++-- |Run the tmux test stack.+runSocketTmuxTestConf ::+  HasCallStack =>+  TmuxTestConfig ->+  Sem TmuxHandlerStack () ->+  UnitTest+runSocketTmuxTestConf conf =+  runTmuxNvim conf .+  withSocketTmuxNvim .+  runReader (CustomConfig ()) .+  interpretPluginSocket++-- |Run the tmux test stack, using a pty to host tmux.+runSocketTmuxTest ::+  HasCallStack =>+  Sem TmuxHandlerStack () ->+  UnitTest+runSocketTmuxTest =+  runSocketTmuxTestConf def++-- |Run the tmux test stack, using a terminal to tmux tmux.+runSocketTmuxGuiTest ::+  HasCallStack =>+  Sem TmuxHandlerStack () ->+  UnitTest+runSocketTmuxGuiTest =+  runSocketTmuxTestConf (def & #tmux . #gui .~ True)++-- |Run a plugin test against a Neovim process running in a fresh tmux session, connected over a socket.+testPluginSocketTmuxConf ::+  ∀ r .+  HasCallStack =>+  Members TmuxHandlerStack (r ++ TmuxHandlerStack) =>+  -- |Regular test config combined with tmux config+  TmuxTestConfig ->+  -- |Interpreter for custom effects+  InterpretersFor r TmuxHandlerStack ->+  -- |RPC handlers+  [RpcHandler (r ++ TmuxHandlerStack)] ->+  Sem (SocketTmuxWith r) () ->+  UnitTest+testPluginSocketTmuxConf conf effs handlers =+  runSocketTmuxTestConf conf .+  effs .+  withHandlers handlers .+  testPluginEmbed++-- |Run a plugin test against a Neovim process running in a fresh tmux session, connected over a socket.+testPluginSocketTmux ::+  ∀ r .+  HasCallStack =>+  Members TmuxHandlerStack (r ++ TmuxHandlerStack) =>+  -- |Interpreter for custom effects+  InterpretersFor r TmuxHandlerStack ->+  -- |RPC handlers+  [RpcHandler (r ++ TmuxHandlerStack)] ->+  Sem (SocketTmuxWith r) () ->+  UnitTest+testPluginSocketTmux =+  testPluginSocketTmuxConf @r def++-- |Run a plugin test against a Neovim process running in a fresh tmux session, connected over a socket.+testHandlersSocketTmux ::+  HasCallStack =>+  -- |RPC handlers+  [RpcHandler TmuxHandlerStack] ->+  Sem SocketTmux () ->+  UnitTest+testHandlersSocketTmux =+  testPluginSocketTmux @'[] id++-- |Run a plugin test against a Neovim process running in a fresh tmux session, connected over a socket.+testSocketTmux ::+  HasCallStack =>+  Sem SocketTmux () ->+  UnitTest+testSocketTmux =+  testHandlersSocketTmux mempty++-- |Run a plugin test against a Neovim process running in a fresh tmux session displayed in a terminal, connected over a+-- socket.+testPluginSocketTmuxGui ::+  ∀ r .+  HasCallStack =>+  Members TmuxHandlerStack (r ++ TmuxHandlerStack) =>+  -- |Interpreter for custom effects+  InterpretersFor r TmuxHandlerStack ->+  -- |RPC handlers+  [RpcHandler (r ++ TmuxHandlerStack)] ->+  Sem (SocketTmuxWith r) () ->+  UnitTest+testPluginSocketTmuxGui =+  testPluginSocketTmuxConf @r (def & #tmux . #gui .~ True)++-- |Run a plugin test against a Neovim process running in a fresh tmux session displayed in a terminal, connected over a+-- socket.+testHandlersSocketTmuxGui ::+  HasCallStack =>+  -- |RPC handlers+  [RpcHandler TmuxHandlerStack] ->+  Sem SocketTmux () ->+  UnitTest+testHandlersSocketTmuxGui =+  testPluginSocketTmuxGui @'[] id++-- |Run a plugin test against a Neovim process running in a fresh tmux session displayed in a terminal, connected over a+-- socket.+testSocketTmuxGui ::+  HasCallStack =>+  Sem SocketTmux () ->+  UnitTest+testSocketTmuxGui =+  testHandlersSocketTmuxGui mempty
− lib/Ribosome/Test/Tmux.hs
@@ -1,271 +0,0 @@-module Ribosome.Test.Tmux where--import Hedgehog (TestT)-import Chiasma.Command.Pane (sendKeys)-import Chiasma.Data.TmuxError (TmuxError)-import Chiasma.Data.TmuxId (PaneId(PaneId))-import Chiasma.Monad.Stream (runTmux)-import Chiasma.Native.Api (TmuxNative(TmuxNative))-import Chiasma.Test.Tmux (TmuxTestConf, withSystemTempDir)-import qualified Chiasma.Test.Tmux as Chiasma (tmuxGuiSpec, tmuxSpec, tmuxSpec')-import Control.Exception.Lifted (bracket)-import Data.DeepPrisms (DeepPrisms)-import qualified Data.Text.IO as Text-import qualified Neovim.Context.Internal as Internal (-  StateTransition(Quit),-  newConfig,-  retypeConfig,-  )-import Neovim.Plugin (Plugin(Plugin))-import Neovim.Plugin.Internal (wrapPlugin)-import Neovim.RPC.Common (SocketType(UnixSocket), createHandle, newRPCConfig)-import System.Directory (doesPathExist)-import System.FilePath ((</>))--import Ribosome.Config.Setting (updateSetting)-import Ribosome.Config.Settings (tmuxSocket)-import Ribosome.Control.Concurrent.Wait (waitIOPredDef)-import Ribosome.Control.Exception (catchAny, tryAny)-import Ribosome.Control.Monad.Ribo (NvimE, Ribo)-import Ribosome.Control.Ribosome (Ribosome(Ribosome), newRibosomeTMVar)-import Ribosome.Error.Report.Class (ReportError)-import Ribosome.Msgpack.Encode (toMsgpack)-import Ribosome.Nvim.Api.IO (vimSetVar)-import Ribosome.Nvim.Api.RpcCall (RpcError)-import Ribosome.Plugin.RpcHandler (RpcHandler)-import Ribosome.System.Time (sleep)-import Ribosome.Test.Embed (-  Runner,-  TestConfig(..),-  inTestT,-  runPlugin,-  runTest,-  startHandlers,-  testNvimProcessConfig,-  withProcessTerm,-  )-import Ribosome.Test.Orphans ()-import Ribosome.Test.Run (UnitTest)-import Ribosome.Test.Unit (uSpec)--runSocketNvimHs ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  TestConfig ->-  env ->-  n a ->-  Handle ->-  m a-runSocketNvimHs conf ribo specThunk socket = do-  nvimConf <- liftIO (Internal.newConfig (pure Nothing) newRPCConfig)-  let testCfg = Internal.retypeConfig ribo nvimConf-  bracket (startHandlers socket socket conf nvimConf) liftIO (const $ runTest conf testCfg specThunk)--externalNvimCmdline :: FilePath -> Text-externalNvimCmdline socket =-  "nvim --listen " <> toText socket <> " -n -u NONE -i NONE"--startNvimInTmux ::-  TmuxNative ->-  FilePath ->-  IO Handle-startNvimInTmux api temp = do-  void $ runExceptT @TmuxError $ runTmux api $ sendKeys (PaneId 0) [externalNvimCmdline socket]-  _ <- waitIOPredDef (pure socket) doesPathExist-  catchAny err (createHandle (UnixSocket socket))-  where-    socket =-      temp </> "nvim-socket"-    err (SomeException e) =-      fail ("startNvimInTmux: createHandle failed: " <> show e)--runGui ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  TmuxNative ->-  FilePath ->-  TestConfig ->-  env ->-  n a ->-  m a-runGui api temp conf ribo specThunk =-  runSocketNvimHs conf ribo specThunk =<< liftIO (startNvimInTmux api temp)--unsafeGuiSpec ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  TmuxNative ->-  FilePath ->-  Runner n ->-  TestConfig ->-  env ->-  n a ->-  m a-unsafeGuiSpec api temp runner conf s specThunk =-  runGui api temp conf s $ runner conf specThunk--unsafeGuiSpecR ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  MonadBaseControl IO m =>-  RpcHandler e (Ribosome env) n =>-  TmuxNative ->-  FilePath ->-  Runner n ->-  TestConfig ->-  env ->-  n a ->-  m a-unsafeGuiSpecR api temp runner conf s specThunk = do-  tv <- newRibosomeTMVar s-  let ribo = Ribosome (tcPluginName conf) tv-  unsafeGuiSpec api temp runner conf ribo specThunk--guiSpec ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  MonadBaseControl IO m =>-  DeepPrisms e RpcError =>-  TestConfig ->-  TmuxNative ->-  s ->-  Ribo s e a ->-  m a-guiSpec conf api env specThunk = do-  withSystemTempDir run-  where-    run tempdir =-      unsafeGuiSpecR api tempdir uSpec conf env specThunk--withTmux ::-  DeepPrisms e RpcError =>-  Ribo s e a ->-  TmuxNative ->-  Ribo s e a-withTmux thunk (TmuxNative (Just socket)) =-  updateSetting tmuxSocket socket *> thunk-withTmux _ _ =-  throwText "no socket in test tmux"--tmuxSpec ::-  DeepPrisms e RpcError =>-  ReportError e =>-  TestConfig ->-  s ->-  TestT (Ribo s e) () ->-  UnitTest-tmuxSpec conf env specThunk =-  inTestT specThunk \ th ->-    Chiasma.tmuxSpec \ api -> guiSpec conf api env (withTmux th api)--tmuxSpec' ::-  DeepPrisms e RpcError =>-  ReportError e =>-  TmuxTestConf ->-  TestConfig ->-  s ->-  TestT (Ribo s e) () ->-  UnitTest-tmuxSpec' tmuxConf conf env specThunk =-  inTestT specThunk \ th ->-    Chiasma.tmuxSpec' tmuxConf \ api ->-      guiSpec conf api env (withTmux th api)--tmuxSpecDef ::-  DeepPrisms e RpcError =>-  ReportError e =>-  Default s =>-  TestT (Ribo s e) () ->-  UnitTest-tmuxSpecDef =-  tmuxSpec def def--tmuxGuiSpec ::-  DeepPrisms e RpcError =>-  ReportError e =>-  TestConfig ->-  s ->-  Ribo s e () ->-  UnitTest-tmuxGuiSpec conf env specThunk =-  Chiasma.tmuxGuiSpec run-  where-    run api = guiSpec conf api env (withTmux specThunk api)--tmuxGuiSpecDef ::-  DeepPrisms e RpcError =>-  ReportError e =>-  Default s =>-  Ribo s e () ->-  UnitTest-tmuxGuiSpecDef =-  tmuxGuiSpec def def--withTmuxInt ::-  NvimE e m =>-  MonadIO m =>-  Text ->-  m () ->-  TmuxNative ->-  m ()-withTmuxInt name thunk (TmuxNative (Just socket)) = do-  () <- vimSetVar (name <> "_tmux_socket") (toMsgpack socket)-  thunk-withTmuxInt _ _ _ =-  throwText "no socket in test tmux"--runTmuxWithPlugin ::-  MonadIO m =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  TmuxNative ->-  TestConfig ->-  Plugin env ->-  n () ->-  m ()-runTmuxWithPlugin api conf plugin@(Plugin env _) thunk = do-  withSystemTempDir runProc-  where-    runProc temp =-      either logError pure =<< (tryAny (withProcessTerm (testNvimProcessConfig conf) (run temp)))-    run temp prc = do-      nvimConf <- liftIO (Internal.newConfig (pure Nothing) (pure env))-      bracket (acquire prc nvimConf temp) release (const $ runTest conf nvimConf thunk)-    acquire _ nvimConf temp = do-      socket <- liftIO (startNvimInTmux api temp)-      runPlugin socket socket [wrapPlugin plugin] nvimConf <* sleep 0.5-    release transitions =-      tryPutMVar transitions Internal.Quit *> sleep 0.5-    logError (SomeException e) =-      liftIO (Text.hPutStr stderr ("runTmuxWithPlugin: nvim process failed with: " <> show e))--tmuxIntegrationSpecDef ::-  NvimE e n =>-  MonadIO m =>-  MonadIO n =>-  MonadFail m =>-  ReportError e =>-  RpcHandler e env n =>-  MonadBaseControl IO m =>-  Text ->-  Plugin env ->-  n () ->-  m ()-tmuxIntegrationSpecDef name plugin specThunk =-  Chiasma.tmuxGuiSpec run-  where-    run api =-      runTmuxWithPlugin api def plugin (withTmuxInt name specThunk api)
+ lib/Ribosome/Test/TmuxCommon.hs view
@@ -0,0 +1,63 @@+module Ribosome.Test.TmuxCommon where++import Chiasma.Data.CodecError (CodecError)+import Chiasma.Data.RenderError (RenderError)+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Effect.TmuxClient (NativeTmux)+import qualified Chiasma.Test.Data.TmuxTestConfig as Chiasma+import Chiasma.Test.Tmux (TestTmuxEffects, withSystemTempDir, withTestTmux)+import Polysemy.Test (UnitTest)++import Ribosome.Data.PluginName (PluginName)+import Ribosome.Host.Data.BootError (BootError (BootError))+import Ribosome.Host.Test.Run (TestStack)+import Ribosome.Test.Data.TestConfig (TmuxTestConfig (TmuxTestConfig))+import Ribosome.Test.Embed (runTestConf)++type TmuxErrors =+  [+    Stop CodecError,+    Error CodecError,+    Stop RenderError,+    Error RenderError,+    Stop TmuxError,+    Error TmuxError,+    Error Text+  ]++type TmuxBaseStack =+  TestTmuxEffects ++ TmuxErrors++type TmuxStack =+  NativeTmux : TmuxBaseStack ++ Reader PluginName : TestStack++interpretTmuxErrors ::+  Member (Error BootError) r =>+  InterpretersFor TmuxErrors r+interpretTmuxErrors =+  mapError BootError .+  mapError @TmuxError (BootError . show) .+  stopToError .+  mapError @RenderError (BootError . show) .+  stopToError .+  mapError @CodecError (BootError . show) .+  stopToError++withTmuxTest ::+  Members TestStack r =>+  Chiasma.TmuxTestConfig ->+  InterpretersFor TmuxBaseStack r+withTmuxTest conf =+  interpretTmuxErrors .+  withSystemTempDir .+  withTestTmux conf++runTmuxNvim ::+  HasCallStack =>+  TmuxTestConfig ->+  Sem TmuxStack () ->+  UnitTest+runTmuxNvim (TmuxTestConfig conf tmuxConf) =+  runTestConf conf .+  withTmuxTest tmuxConf .+  restop @TmuxError @NativeTmux
lib/Ribosome/Test/Ui.hs view
@@ -1,32 +1,40 @@+-- |Assertions for Neovim UI elements module Ribosome.Test.Ui where -import Hedgehog (TestT, (===))+import Polysemy.Test (Hedgehog, assertEq, (===))+ import Ribosome.Api.Window (currentCursor, cursor)-import Ribosome.Control.Monad.Ribo (NvimE)-import Ribosome.Nvim.Api.Data (Window)-import Ribosome.Nvim.Api.IO (nvimListWins)+import Ribosome.Host.Api.Data (Window)+import Ribosome.Host.Api.Effect (nvimListWins)+import Ribosome.Host.Effect.Rpc (Rpc) +-- |Assert the number of windows. windowCountIs ::-  NvimE e m =>+  Monad m =>+  Members [Rpc, Hedgehog m] r =>   Int ->-  TestT m ()+  Sem r () windowCountIs count = do   wins <- nvimListWins-  count === (length wins)+  count === length wins +-- |Assert the cursor position in a window. cursorIs ::-  NvimE e m =>+  Monad m =>+  Members [Rpc, Hedgehog m] r =>   Int ->   Int ->   Window ->-  TestT m ()+  Sem r () cursorIs line col =-  ((line, col) ===) <=< lift . cursor+  assertEq (line, col) <=< cursor +-- |Assert the cursor position in the current window. currentCursorIs ::-  NvimE e m =>+  Monad m =>+  Members [Rpc, Hedgehog m] r =>   Int ->   Int ->-  TestT m ()+  Sem r () currentCursorIs line col =-  ((line, col) ===) =<< lift currentCursor+  assertEq (line, col) =<< currentCursor
− lib/Ribosome/Test/Unit.hs
@@ -1,100 +0,0 @@-module Ribosome.Test.Unit where--import Control.Exception.Lifted (bracket_)-import Hedgehog (TestT)-import Hedgehog.Internal.Property (mkTestT, runTestT)-import System.FilePath (takeDirectory, takeFileName, (</>))-import System.Log ()-import System.Log.Logger (Priority(DEBUG, WARNING), setLevel, updateGlobalLogger)--import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE, pluginName)-import Ribosome.Control.Ribosome (Ribosome)-import Ribosome.Error.Report.Class (ReportError)-import Ribosome.Plugin.RpcHandler (RpcHandler)-import Ribosome.Test.Embed (Runner, TestConfig(..), setupPluginEnv, unsafeEmbeddedSpecR)-import qualified Ribosome.Test.File as F (fixture, fixtureContent, tempDir)-import Ribosome.Test.Orphans ()--uPrefix :: Text-uPrefix = "test"--uSpec :: (MonadIO m, NvimE e m) => Runner m-uSpec conf spec = do-  setupPluginEnv conf-  spec--unitSpec ::-  MonadIO n =>-  MonadIO m =>-  NvimE e' n =>-  MonadFail m =>-  ReportError e =>-  MonadBaseControl IO m =>-  RpcHandler e (Ribosome env) n =>-  TestConfig ->-  env ->-  TestT n a ->-  TestT m a-unitSpec cfg env t = do-  mkTestT (unsafeEmbeddedSpecR uSpec cfg env (runTestT t))--unitSpecDef ::-  MonadIO n =>-  MonadIO m =>-  NvimE e' n =>-  MonadFail m =>-  ReportError e =>-  MonadBaseControl IO m =>-  RpcHandler e (Ribosome env) n =>-  env ->-  TestT n a ->-  TestT m a-unitSpecDef =-  unitSpec def--unitSpecDef' ::-  MonadIO n =>-  MonadIO m =>-  NvimE e' n =>-  MonadFail m =>-  ReportError e =>-  MonadBaseControl IO m =>-  RpcHandler e (Ribosome ()) n =>-  TestT n a ->-  TestT m a-unitSpecDef' =-  unitSpecDef ()--tempDir :: MonadIO m => FilePath -> m FilePath-tempDir = F.tempDir uPrefix--tempFile :: MonadIO m => FilePath -> m FilePath-tempFile file = do-  absDir <- tempDir $ takeDirectory file-  return $ absDir </> takeFileName file--fixture :: MonadIO m => FilePath -> m FilePath-fixture = F.fixture uPrefix--fixtureContent :: MonadIO m => FilePath -> m Text-fixtureContent = F.fixtureContent uPrefix--withLogAs ::-  MonadIO m =>-  MonadBaseControl IO m =>-  Text ->-  m a ->-  m a-withLogAs name =-  bracket_ (logLevel DEBUG) (logLevel WARNING)-  where-    logLevel =-      liftIO . updateGlobalLogger (toString name) . setLevel--withLog ::-  MonadRibo m =>-  MonadBaseControl IO m =>-  m a ->-  m a-withLog thunk =-  (`withLogAs` thunk) =<< pluginName
+ lib/Ribosome/Test/Wait.hs view
@@ -0,0 +1,46 @@+module Ribosome.Test.Wait where++import Hedgehog.Internal.Property (Failure, failWith, liftTest, mkTest)+import qualified Conc+import Conc (interpretAtomic)+import Polysemy.Test (Hedgehog, liftH)+import qualified Polysemy.Time as Time+import Polysemy.Time (MilliSeconds (MilliSeconds), Seconds (Seconds))++assertWaitFor ::+  Monad m =>+  HasCallStack =>+  Members [Hedgehog m, Time t d, Race, Error Failure, Embed IO] r =>+  TimeUnit t1 =>+  TimeUnit t2 =>+  t1 ->+  t2 ->+  Sem r a ->+  (a -> Sem r b) ->+  Sem r b+assertWaitFor timeout interval acquire test =+  withFrozenCallStack do+    interpretAtomic Nothing do+      Conc.timeout_ timeoutError timeout spin+  where+    spin = do+      a <- raise acquire+      catch (raise (test a)) \ e -> do+        atomicPut (Just e)+        Time.sleep interval+        spin+    timeoutError =+      atomicGet >>= liftH . \case+        Just e -> liftTest (mkTest (Left e, mempty))+        Nothing -> failWith Nothing "timed out before an assertion was made"++assertWait ::+  Monad m =>+  HasCallStack =>+  Members [Hedgehog m, Time t d, Race, Error Failure, Embed IO] r =>+  Sem r a ->+  (a -> Sem r b) ->+  Sem r b+assertWait acquire test =+  withFrozenCallStack do+    assertWaitFor (Seconds 3) (MilliSeconds 100) acquire test
− readme.md
@@ -1,91 +0,0 @@-# About--*ribosome* is an extension framework for [nvim-hs], a [Haskell] library that-provides a [Neovim] plugin engine.--*ribosome*'s structure is similar to that of vanilla [nvim-hs] plugins and is-intended to provide a more comfortable API on top of it.--# Basic Plugin--*ribosome* comes with a companion plugin manager, [chromatin], but you can-start plugins regularly with `jobstart()`.--First, add `ribosome` to your `myplugin.cabal`'s dependencies.--Your project should have an executable that looks like this:--```haskell-import Neovim (neovim, plugins, defaultConfig)-import MyPlugin.Plugin (plugin)--main :: IO ()-main =-  neovim defaultConfig {plugins = [plugin]}-```--In `MyPlugin.Plugin`, you should write a plugin definition like this:--```haskell-module MyPlugin.Plugin where--import Data.Default.Class (Default(def))-import Neovim (Neovim, NeovimPlugin, Plugin, wrapPlugin)-import Neovim.Context.Internal (Config(customConfig), asks')-import Ribosome.Api.Echo (echom)-import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE, Ribo)-import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import Ribosome.Error.Report (reportError)-import Ribosome.Internal.IO (retypeNeovim)-import Ribosome.Plugin (RpcDef, autocmd, cmd, riboPlugin, rpcHandler)-import System.Log.Logger (Priority(ERROR), setLevel, updateGlobalLogger)--handleError :: Text -> Ribo () Text ()-handleError err =-  echom err--hello :: NvimE e m => MonadRibo m => m ()-hello ::-  echom "hello"--bufEnter :: NvimE e m => MonadRibo m => m ()-bufEnter ::-  echom "BufEnter"--rpcHandlers :: [[RpcDef (Ribo () Error)]]-rpcHandlers =-  [-    $(rpcHandler (cmd []) 'hello),-    $(rpcHandler (autocmd "BufEnter") 'bufEnter)-  ]--plugin' :: Ribosome () -> Plugin (Ribosome ())-plugin' env =-  riboPlugin "myplugin" env rpcHandlers def handleError def--initialize :: Neovim e (Ribosome Env)-initialize = do-  liftIO $ updateGlobalLogger "Neovim.Plugin" (setLevel ERROR)-  ribo <- newRibosome "myplugin" def-  retypeNeovim (const ribo) (asks' customConfig)--plugin :: Neovim e NeovimPlugin-plugin =-  wrapPlugin . plugin' =<< initialize-```--Follow the instructions for the bootstrapping vim config in the documentation-for [chromatin].-Now you can execute the command `:Hello`.--For more inspiration, check out some example projects: [proteome], [myo],-[uracil].--[nvim-hs]: https://github.com/neovimhaskell/nvim-hs-[Haskell]: https://www.haskell.org-[proteome]: https://github.com/tek/proteome-[myo]: https://github.com/tek/myo-[uracil]: https://github.com/tek/uracil-[chromatin]: https://github.com/tek/chromatin-[nvim-hs]: https://github.com/neovimhaskell/nvim-hs-[Neovim]: https://github.com/neovim/neovim
ribosome-test.cabal view
@@ -1,49 +1,36 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.34.6. -- -- see: https://github.com/sol/hpack------ hash: d204ea32a519247a24754414a535360674e998d19dd95ea48b7fd7d7ab1044dc  name:           ribosome-test-version:        0.4.0.0-synopsis:       test helpers for ribosome-description:    Please see the README on GitHub at <https://github.com/tek/ribosome>+version:        0.9.9.9+synopsis:       Test tools for Ribosome+description:    See https://hackage.haskell.org/package/ribosome-test/docs/Ribosome-Test.html category:       Neovim-homepage:       https://github.com/tek/ribosome#readme-bug-reports:    https://github.com/tek/ribosome/issues author:         Torsten Schmits-maintainer:     tek@tryp.io-copyright:      2021 Torsten Schmits+maintainer:     hackage@tryp.io+copyright:      2022 Torsten Schmits license:        BSD-2-Clause-Patent license-file:   LICENSE build-type:     Simple-extra-source-files:-    readme.md -source-repository head-  type: git-  location: https://github.com/tek/ribosome- library   exposed-modules:-      Ribosome.Test.Await+      Ribosome.Handler+      Ribosome.Test+      Ribosome.Test.Data.TestConfig       Ribosome.Test.Embed-      Ribosome.Test.Exists-      Ribosome.Test.File-      Ribosome.Test.Functional-      Ribosome.Test.Input-      Ribosome.Test.Orphans-      Ribosome.Test.Run+      Ribosome.Test.EmbedTmux+      Ribosome.Test.Error+      Ribosome.Test.Examples.Example1+      Ribosome.Test.Log       Ribosome.Test.Screenshot-      Ribosome.Test.Tmux+      Ribosome.Test.SocketTmux+      Ribosome.Test.TmuxCommon       Ribosome.Test.Ui-      Ribosome.Test.Unit-  other-modules:-      Paths_ribosome_test-  autogen-modules:-      Paths_ribosome_test+      Ribosome.Test.Wait   hs-source-dirs:       lib   default-extensions:@@ -63,9 +50,11 @@       DeriveLift       DeriveTraversable       DerivingStrategies+      DerivingVia       DisambiguateRecordFields       DoAndIfThenElse       DuplicateRecordFields+      EmptyCase       EmptyDataDecls       ExistentialQuantification       FlexibleContexts@@ -80,8 +69,9 @@       MultiParamTypeClasses       MultiWayIf       NamedFieldPuns-      OverloadedStrings+      OverloadedLabels       OverloadedLists+      OverloadedStrings       PackageImports       PartialTypeSignatures       PatternGuards@@ -92,6 +82,7 @@       RankNTypes       RecordWildCards       RecursiveDo+      RoleAnnotations       ScopedTypeVariables       StandaloneDeriving       TemplateHaskell@@ -104,73 +95,41 @@       UndecidableInstances       UnicodeSyntax       ViewPatterns-  ghc-options: -Wall -Wredundant-constraints -Wsimplifiable-class-constraints+      StandaloneKindSignatures+      OverloadedLabels+  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -Wunused-packages -fplugin=Polysemy.Plugin   build-depends:-      aeson-    , base ==4.*-    , bytestring+      base >=4.12 && <5     , chiasma-    , composition-    , composition-extra-    , conduit-    , containers-    , cornea-    , data-default-    , directory-    , either-    , exceptions-    , filepath-    , free+    , chiasma-test+    , exon     , hedgehog-    , hslogger-    , lens-    , lifted-async-    , lifted-base-    , messagepack-    , monad-control-    , mtl-    , nvim-hs+    , lens-regex-pcre     , path     , path-io-    , prettyprinter-    , prettyprinter-ansi-terminal-    , process-    , relude >=0.7 && <1.2-    , resourcet+    , polysemy+    , polysemy-chronos+    , polysemy-plugin+    , polysemy-test+    , prelate >=0.1     , ribosome-    , tasty-    , tasty-hedgehog-    , template-haskell-    , text-    , transformers-    , typed-process-    , unix-    , unliftio+    , ribosome-host+    , ribosome-host-test   mixins:       base hiding (Prelude)-    , ribosome hiding (Ribosome.Prelude)-    , ribosome (Ribosome.Prelude as Prelude)+    , prelate (Prelate as Prelude)+    , prelate hiding (Prelate)   default-language: Haskell2010 -test-suite ribosome-unit+test-suite ribosome-test-unit   type: exitcode-stdio-1.0   main-is: Main.hs   other-modules:-      Ribosome.Test.AutocmdTest-      Ribosome.Test.MappingTest-      Ribosome.Test.MenuTest-      Ribosome.Test.MsgpackTest-      Ribosome.Test.NvimMenuTest-      Ribosome.Test.PromptTest-      Ribosome.Test.RpcTest-      Ribosome.Test.ScratchTest-      Ribosome.Test.SettingTest+      Ribosome.Test.EmbedTmuxTest+      Ribosome.Test.ReportTest+      Ribosome.Test.SocketTmuxTest       Ribosome.Test.SyntaxTest-      Ribosome.Test.THTest-      Ribosome.Test.WatcherTest-      Ribosome.Test.WindowTest-      TestError-      Paths_ribosome_test+      Skip   hs-source-dirs:       test   default-extensions:@@ -190,9 +149,11 @@       DeriveLift       DeriveTraversable       DerivingStrategies+      DerivingVia       DisambiguateRecordFields       DoAndIfThenElse       DuplicateRecordFields+      EmptyCase       EmptyDataDecls       ExistentialQuantification       FlexibleContexts@@ -207,8 +168,9 @@       MultiParamTypeClasses       MultiWayIf       NamedFieldPuns-      OverloadedStrings+      OverloadedLabels       OverloadedLists+      OverloadedStrings       PackageImports       PartialTypeSignatures       PatternGuards@@ -219,6 +181,7 @@       RankNTypes       RecordWildCards       RecursiveDo+      RoleAnnotations       ScopedTypeVariables       StandaloneDeriving       TemplateHaskell@@ -231,51 +194,21 @@       UndecidableInstances       UnicodeSyntax       ViewPatterns-  ghc-options: -Wall -Wredundant-constraints -Wsimplifiable-class-constraints -threaded -rtsopts -with-rtsopts=-N+      StandaloneKindSignatures+      OverloadedLabels+  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -Wunused-packages -fplugin=Polysemy.Plugin -threaded -rtsopts -with-rtsopts=-N   build-depends:-      aeson-    , base ==4.*-    , bytestring-    , chiasma-    , composition-    , composition-extra-    , conduit-    , containers-    , cornea-    , data-default-    , directory-    , either-    , exceptions-    , filepath-    , free-    , hedgehog-    , hslogger-    , lens-    , lifted-async-    , lifted-base-    , messagepack-    , monad-control-    , mtl-    , nvim-hs-    , path-    , path-io-    , prettyprinter-    , prettyprinter-ansi-terminal-    , process-    , relude >=0.7 && <1.2-    , resourcet+      base >=4.12 && <5+    , polysemy+    , polysemy-plugin+    , polysemy-test+    , prelate >=0.1     , ribosome+    , ribosome-host     , ribosome-test     , tasty-    , tasty-hedgehog-    , template-haskell-    , text-    , transformers-    , typed-process-    , unix-    , unliftio   mixins:       base hiding (Prelude)-    , ribosome hiding (Ribosome.Prelude)-    , ribosome (Ribosome.Prelude as Prelude)+    , prelate (Prelate as Prelude)+    , prelate hiding (Prelate)   default-language: Haskell2010
test/Main.hs view
@@ -1,40 +1,20 @@ module Main where -import Ribosome.Test.AutocmdTest (test_autocmd)-import Ribosome.Test.MappingTest (test_mapping)-import Ribosome.Test.MenuTest (test_menu)-import Ribosome.Test.MsgpackTest (test_msgpack)-import Ribosome.Test.NvimMenuTest (test_nvimMenu)-import Ribosome.Test.PromptTest (test_promptSet)-import Ribosome.Test.RpcTest (test_rpc)-import Ribosome.Test.Run (unitTest)-import Ribosome.Test.ScratchTest (test_regularScratch, test_floatScratch)-import Ribosome.Test.SettingTest (test_settingSuccess, test_settingFail)--- import Ribosome.Test.SyntaxTest (test_syntax)-import Ribosome.Test.THTest ()-import Ribosome.Test.WatcherTest (test_varWatcher)-import Ribosome.Test.WindowTest (test_findMainWindowCreate, test_findMainWindowExisting)+import Polysemy.Test (unitTest)+import Ribosome.Test.EmbedTmuxTest (test_embedTmux)+import Ribosome.Test.ReportTest (test_report)+import Ribosome.Test.SocketTmuxTest (test_socketTmux)+import Ribosome.Test.SyntaxTest (test_syntax)+import Skip (skipUnlessX) import Test.Tasty (TestTree, defaultMain, testGroup)  tests :: TestTree tests =-  testGroup "all" [-    unitTest "autocmd handler" test_autocmd,-    unitTest "mapping for scratch buffer" test_mapping,-    test_menu,-    test_msgpack,-    test_nvimMenu,-    unitTest "set the prompt text" test_promptSet,-    unitTest "rpc handlers" test_rpc,-    unitTest "scratch buffer" test_regularScratch,-    unitTest "floating scratch buffer" test_floatScratch,-    unitTest "successfully read a setting" test_settingSuccess,-    unitTest "read an unset setting" test_settingFail,-    -- TODO flaky test-    -- unitTest "syntax" test_syntax,-    unitTest "variable watcher" test_varWatcher,-    unitTest "find the existing main window" test_findMainWindowExisting,-    unitTest "create the main window" test_findMainWindowCreate+  testGroup "ribosome" [+    unitTest "socket tmux" (skipUnlessX test_socketTmux),+    unitTest "embed tmux" (skipUnlessX test_embedTmux),+    unitTest "syntax" (skipUnlessX test_syntax),+    unitTest "report" (skipUnlessX test_report)   ]  main :: IO ()
− test/Ribosome/Test/AutocmdTest.hs
@@ -1,49 +0,0 @@-module Ribosome.Test.AutocmdTest where--import Hedgehog ((===))-import Neovim (Plugin(..))-import TestError (RiboTest, handleTestError)--import Ribosome.Control.Monad.Ribo (NvimE)-import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import Ribosome.Msgpack.Encode (MsgpackEncode(toMsgpack))-import Ribosome.Nvim.Api.IO (vimCommand, vimGetVar, vimSetVar)-import Ribosome.Orphans ()-import Ribosome.Plugin (autocmd, riboPlugin, rpcHandler)-import Ribosome.Test.Await (await)-import Ribosome.Test.Embed (integrationSpecDef)-import Ribosome.Test.Orphans ()-import Ribosome.Test.Run (UnitTest)--varName :: Text-varName =-  "result"--result :: Int-result =-  5--testAuto ::-  NvimE e m =>-  m ()-testAuto =-  vimSetVar varName (toMsgpack result)--$(return [])--autocmdPlugin :: IO (Plugin (Ribosome ()))-autocmdPlugin = do-  env <- newRibosome "test" ()-  return $ riboPlugin "test" env funcs [] handleTestError def-  where-    funcs = [$(rpcHandler (autocmd "BufWritePre") 'testAuto)]--autocmdSpec :: RiboTest ()-autocmdSpec = do-  () <- vimCommand "doautocmd BufWritePre"-  await (result ===) (vimGetVar varName)--test_autocmd :: UnitTest-test_autocmd = do-  plug <- liftIO autocmdPlugin-  integrationSpecDef plug autocmdSpec
+ test/Ribosome/Test/EmbedTmuxTest.hs view
@@ -0,0 +1,12 @@+module Ribosome.Test.EmbedTmuxTest where++import Polysemy.Test (UnitTest, assert)++import Ribosome.Host.Api.Effect (nvimGetVar, nvimSetVar)+import Ribosome.Test.EmbedTmux (testEmbedTmux)++test_embedTmux :: UnitTest+test_embedTmux =+  testEmbedTmux do+    nvimSetVar "test" True+    assert =<< nvimGetVar "test"
− test/Ribosome/Test/MappingTest.hs
@@ -1,71 +0,0 @@-module Ribosome.Test.MappingTest where--import qualified Data.Map.Strict as Map (empty)-import Hedgehog ((===))-import Neovim (Plugin(..))-import TestError (RiboTest, handleTestError)--import Ribosome.Api.Buffer (currentBufferContent)-import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE)-import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import Ribosome.Data.Mapping (Mapping(Mapping), MappingIdent(MappingIdent))-import Ribosome.Data.ScratchOptions (ScratchOptions(ScratchOptions))-import Ribosome.Msgpack.Encode (MsgpackEncode(toMsgpack))-import Ribosome.Msgpack.Error (DecodeError)-import Ribosome.Nvim.Api.IO (nvimFeedkeys, vimCallFunction, vimGetVar, vimSetVar)-import Ribosome.Plugin (riboPlugin, rpcHandlerDef)-import Ribosome.Plugin.Mapping (MappingHandler, mappingHandler)-import Ribosome.Scratch (showInScratch)-import Ribosome.Test.Await (await)-import Ribosome.Test.Embed (integrationSpecDef)-import Ribosome.Test.Orphans ()-import Ribosome.Test.Run (UnitTest)--target :: [Text]-target = ["line 1", "line 2"]--go :: NvimE e m => m ()-go =-  vimSetVar "number" (toMsgpack (13 :: Int))--mapping :: Mapping-mapping =-  Mapping (MappingIdent "go") "a" "n" False True--mapHandler :: NvimE e m => MappingHandler m-mapHandler =-  mappingHandler "go" go--setupMappingScratch ::-  NvimE e m =>-  MonadRibo m =>-  MonadBaseControl IO m =>-  MonadDeepError e DecodeError m =>-  m ()-setupMappingScratch = do-  _ <- showInScratch target options-  return ()-  where-    options =-      ScratchOptions False True False True True True False Nothing Nothing Nothing [] [mapping] "buffi"--$(return [])--mappingPlugin :: IO (Plugin (Ribosome ()))-mappingPlugin = do-  env <- newRibosome "mapping" ()-  return $ riboPlugin "mapping" env funcs [mapHandler] handleTestError Map.empty-  where-    funcs = [$(rpcHandlerDef 'setupMappingScratch)]--mappingSpec :: RiboTest ()-mappingSpec = do-  () <- vimCallFunction "SetupMappingScratch" []-  await (target ===) currentBufferContent-  nvimFeedkeys "a" "x" False-  await ((13 :: Int) ===) (vimGetVar "number")--test_mapping :: UnitTest-test_mapping = do-  plug <- liftIO mappingPlugin-  integrationSpecDef plug mappingSpec
− test/Ribosome/Test/MenuTest.hs
@@ -1,324 +0,0 @@-module Ribosome.Test.MenuTest where--import Conduit (ConduitT, yield, yieldMany)-import Control.Concurrent.MVar.Lifted (modifyMVar_)-import Control.Lens (view)-import Control.Monad.Trans.Resource (ResourceT, runResourceT)-import qualified Data.Map.Strict as Map (fromList)-import Hedgehog ((===))-import Test.Tasty (TestTree, testGroup)--import Ribosome.Control.StrictRibosome (StrictRibosome)-import Ribosome.Menu.Action (menuContinue, menuExecute, menuQuit)-import Ribosome.Menu.Data.FilteredMenuItem (FilteredMenuItem(FilteredMenuItem))-import qualified Ribosome.Menu.Data.FilteredMenuItem as FilteredMenuItem (item)-import Ribosome.Menu.Data.Menu (Menu(Menu), MenuFilter(MenuFilter))-import qualified Ribosome.Menu.Data.Menu as Menu (items)-import Ribosome.Menu.Data.MenuAction (MenuAction)-import Ribosome.Menu.Data.MenuConfig (MenuConfig(MenuConfig))-import Ribosome.Menu.Data.MenuConsumer (MenuConsumer(MenuConsumer))-import Ribosome.Menu.Data.MenuConsumerAction (MenuConsumerAction)-import qualified Ribosome.Menu.Data.MenuEvent as MenuEvent (MenuEvent(..))-import Ribosome.Menu.Data.MenuItem (MenuItem(MenuItem), simpleMenuItem)-import qualified Ribosome.Menu.Data.MenuItem as MenuItem (MenuItem(_text), text)-import Ribosome.Menu.Data.MenuRenderEvent (MenuRenderEvent)-import qualified Ribosome.Menu.Data.MenuRenderEvent as MenuRenderEvent (MenuRenderEvent(..))-import Ribosome.Menu.Data.MenuUpdate (MenuUpdate(MenuUpdate))-import Ribosome.Menu.Prompt.Data.Prompt (Prompt(Prompt))-import Ribosome.Menu.Prompt.Data.PromptConfig (PromptConfig(PromptConfig), PromptFlag(StartInsert))-import Ribosome.Menu.Prompt.Data.PromptEvent (PromptEvent)-import qualified Ribosome.Menu.Prompt.Data.PromptEvent as PromptEvent (PromptEvent(..))-import qualified Ribosome.Menu.Prompt.Data.PromptState as PromptState (PromptState(..))-import Ribosome.Menu.Prompt.Run (basicTransition, noPromptRenderer)-import Ribosome.Menu.Run (runMenu)-import Ribosome.Menu.Simple (-  basicMenu,-  defaultMenu,-  deleteByFilteredIndex,-  fuzzyMenuItemMatcher,-  markedMenuItems,-  markedMenuItemsOnly,-  selectedMenuItem,-  simpleMenu,-  )-import Ribosome.System.Time (sleep)-import Ribosome.Test.Run (UnitTest, unitTest)--promptInput ::-  MonadIO m =>-  [Text] ->-  ConduitT () PromptEvent m ()-promptInput chars = do-  lift $ sleep 0.1-  yieldMany (PromptEvent.Character <$> chars)--menuItems ::-  Monad m =>-  [Text] ->-  ConduitT () [MenuItem Text] m ()-menuItems =-  yield . fmap (simpleMenuItem "name")--storePrompt ::-  MonadBaseControl IO m =>-  MVar [Prompt] ->-  MenuUpdate m a Text ->-  m (MenuConsumerAction m a, Menu Text)-storePrompt prompts (MenuUpdate event menu) =-  check event-  where-    check (MenuEvent.PromptChange prompt) =-      store prompt-    check (MenuEvent.Mapping _ prompt) =-      store prompt-    check (MenuEvent.Quit _) =-      menuQuit menu-    check _ =-      menuContinue menu-    store prompt =-      modifyMVar_ prompts (return . (prompt :)) *> menuContinue menu--render ::-  MonadIO m =>-  MonadBaseControl IO m =>-  MVar [[FilteredMenuItem Text]] ->-  MenuRenderEvent m a Text ->-  m ()-render varItems (MenuRenderEvent.Render _ (Menu _ items _ _ _ _)) = do-  modifyMVar_ varItems (return . (items :))-  sleep 0.01-render _ (MenuRenderEvent.Quit _) =-  return ()--type TestM = StateT (StrictRibosome ()) (ResourceT IO)--menuTest ::-  (MenuUpdate TestM a Text -> TestM (MenuAction TestM a, Menu Text)) ->-  [Text] ->-  [Text] ->-  IO [[FilteredMenuItem Text]]-menuTest handler items chars = do-  itemsVar <- newMVar []-  void $ runResourceT $ runMenu (conf itemsVar) `execStateT` def-  readMVar itemsVar-  where-    conf itemsVar =-      MenuConfig (menuItems items) (MenuConsumer handler) (render itemsVar) promptConfig def-    promptConfig =-      PromptConfig (promptInput chars) basicTransition noPromptRenderer [StartInsert]--promptTest :: [Text] -> [Text] -> IO ([[FilteredMenuItem Text]], [Prompt])-promptTest items chars = do-  prompts <- newMVar []-  itemsResult <- menuTest (basicMenu fuzzyMenuItemMatcher (storePrompt prompts)) items chars-  (itemsResult,) <$> readMVar prompts--promptsTarget1 :: [Prompt]-promptsTarget1 =-  uncurry one' <$> [-    (1, PromptState.Insert),-    (0, PromptState.Normal),-    (0, PromptState.Normal),-    (1, PromptState.Insert)-    ]-  where-    one' c s = Prompt c s "i"--items1 :: [Text]-items1 =-  [-    "i1",-    "j1",-    "i2",-    "i3",-    "j2",-    "i4"-    ]--chars1 :: [Text]-chars1 =-  [-    "i",-    "esc",-    "k",-    "a",-    "2"-    ]--itemsTarget1 :: [[MenuItem Text]]-itemsTarget1 =-  [-    item <$> ["i2"],-    item <$> ["i1", "i2", "i3", "i4"]-    ]-  where-    item =-      simpleMenuItem "name"--test_pureMenuModeChange :: UnitTest-test_pureMenuModeChange = do-  (items, prompts) <- liftIO (promptTest items1 chars1)-  itemsTarget1 === (view FilteredMenuItem.item <$$> take 2 items)-  promptsTarget1 === (take 4 $ reverse prompts)--chars2 :: [Text]-chars2 =-  ["l", "o", "n", "g", "-", "i", "t", "e", "m"]--items2 :: [Text]-items2 =-  [-    "long",-    "short",-    "long-item",-    "longitem"-    ]--itemsTarget :: [MenuItem Text]-itemsTarget =-  [simpleMenuItem "name" "long-item"]--test_pureMenuFilter :: UnitTest-test_pureMenuFilter = do-  items <- liftIO (fst <$> promptTest items2 chars2)-  [itemsTarget] === (view FilteredMenuItem.item <$$> take 1 items)--chars3 :: [Text]-chars3 =-  ["i", "esc", "cr"]--items3 :: [Text]-items3 =-  [-    "item1",-    "item2"-    ]--exec ::-  MonadIO m =>-  MVar [Text] ->-  Menu Text ->-  Prompt ->-  m (MenuConsumerAction m a, Menu Text)-exec var m@(Menu _ items _ _ _ _) _ =-  swapMVar var (view (FilteredMenuItem.item . MenuItem.text) <$> items) *> menuQuit m--test_pureMenuExecute :: UnitTest-test_pureMenuExecute = do-  var <- newMVar []-  _ <- liftIO (menuTest (simpleMenu (Map.fromList [("cr", exec var)])) items3 chars3)-  (items3 ===) =<< readMVar var--charsMulti :: [Text]-charsMulti =-  ["esc", "k", "k", "space", "space", "space", "space", "j", "space", "cr"]--itemsMulti :: [Text]-itemsMulti =-  [-    "item1",-    "item2",-    "item3",-    "item4",-    "item5",-    "item6"-    ]--execMulti ::-  MonadIO m =>-  MVar (Maybe (NonEmpty Text)) ->-  Menu Text ->-  Prompt ->-  m (MenuConsumerAction m a, Menu Text)-execMulti var m _ =-  swapMVar var (MenuItem._text <$$> markedMenuItems m) *> menuQuit m--test_menuMultiMark :: UnitTest-test_menuMultiMark = do-  var <- newMVar Nothing-  _ <- liftIO (menuTest (defaultMenu (Map.fromList [("cr", execMulti var)])) itemsMulti charsMulti)-  (Just ("item3" :| ["item4", "item5"]) ===) =<< readMVar var--charsToggle :: [Text]-charsToggle =-  ["esc", "k", "space", "*", "i", "a", "b", "cr"]--itemsToggle :: [Text]-itemsToggle =-  [-    "a",-    "ab",-    "abc"-    ]--execToggle ::-  MonadIO m =>-  MVar (Maybe (NonEmpty Text)) ->-  Menu Text ->-  Prompt ->-  m (MenuConsumerAction m a, Menu Text)-execToggle var m _ =-  swapMVar var (MenuItem._text <$$> markedMenuItemsOnly m) *> menuQuit m--test_menuToggle :: UnitTest-test_menuToggle = do-  var <- newMVar Nothing-  _ <- liftIO (menuTest (defaultMenu (Map.fromList [("cr", execToggle var)])) itemsToggle charsToggle)-  (Nothing ===) =<< readMVar var--charsExecuteThunk :: [Text]-charsExecuteThunk =-  ["esc", "cr", "k", "cr", "esc"]--itemsExecuteThunk :: [Text]-itemsExecuteThunk =-  [-    "a",-    "b"-    ]--execExecuteThunk ::-  MonadIO m =>-  MonadBaseControl IO m =>-  MVar [Text] ->-  Menu Text ->-  Prompt ->-  m (MenuConsumerAction m a, Menu Text)-execExecuteThunk var m _ =-  menuExecute (modifyMVar_ var prepend) m-  where-    prepend a =-      pure $ a ++ maybeToList (MenuItem._text <$> selectedMenuItem m)--test_menuExecuteThunk :: UnitTest-test_menuExecuteThunk = do-  var <- newMVar []-  _ <- liftIO (menuTest (defaultMenu (Map.fromList [("cr", execExecuteThunk var)])) itemsExecuteThunk charsExecuteThunk)-  (["a", "b"] ===) =<< readMVar var--test_menuDeleteByFilteredIndex :: UnitTest-test_menuDeleteByFilteredIndex =-  (target ===) . fmap (view MenuItem.text) . view Menu.items . deleteByFilteredIndex [1, 2] $ menu-  where-    target =-      ["1", "2", "3", "5", "7", "8"]-    menu =-      Menu items filtered 0 [] (MenuFilter "") Nothing-    items =-      simpleMenuItem () <$> ["1", "2", "3", "4", "5", "6", "7", "8"]-    filtered =-      uncurry FilteredMenuItem . second menuItem <$> [(1, "2"), (3, "4"), (5, "6"), (7, "8")]-    menuItem t =-      MenuItem () t t--test_menu :: TestTree-test_menu =-  testGroup "menu" [-    unitTest "change mode" test_pureMenuModeChange,-    unitTest "filter items" test_pureMenuFilter,-    unitTest "execute an action" test_pureMenuExecute,-    unitTest "mark multiple items" test_menuMultiMark,-    unitTest "toggle marked items" test_menuToggle,-    unitTest "execute a thunk action" test_menuExecuteThunk,-    unitTest "delete by filtered index" test_menuDeleteByFilteredIndex-    ]
− test/Ribosome/Test/MsgpackTest.hs
@@ -1,170 +0,0 @@-module Ribosome.Test.MsgpackTest where--import qualified Data.Map.Strict as Map (fromList)-import Data.MessagePack (Object(..))-import Data.Text.Prettyprint.Doc (Doc, defaultLayoutOptions, layoutPretty)-import Data.Text.Prettyprint.Doc.Render.Terminal (AnsiStyle, renderStrict)-import Hedgehog ((===))-import Path (Abs, Dir, File, Path, Rel, absfile, relfile)-import Test.Tasty (TestTree, testGroup)--import Ribosome.Msgpack.Decode (MsgpackDecode(..), fromMsgpack)-import Ribosome.Msgpack.Encode (MsgpackEncode(..))-import qualified Ribosome.Msgpack.Util as Util (string)-import Ribosome.Test.Run (UnitTest, unitTest)--newtype NT =-  NT Text-  deriving (Eq, Show, Generic)-  deriving newtype (MsgpackEncode, MsgpackDecode)--data Blob =-  Blob {-    key4 :: [[Int]],-    key5 :: Map Int Text,-    key6 :: NT,-    key7 :: (Int, String)-  }-  deriving (Eq, Show, Generic, MsgpackEncode, MsgpackDecode)--data Prod =-  Prod Text Int-  deriving (Eq, Show, Generic, MsgpackEncode, MsgpackDecode)--data Dat =-  Dat {-    key1 :: Blob,-    key2 :: Bool,-    key3 :: Maybe Prod-  }-  deriving (Eq, Show, Generic, MsgpackEncode, MsgpackDecode)--dat :: Dat-dat = Dat (Blob [[1, 2], [3]] (Map.fromList [(1, "1"), (2, "2")]) (NT "nt") (91, "pair")) False (Just $ Prod "dat" 27)--os :: String -> Object-os = Util.string--i :: Int64 -> Object-i = ObjectInt--encodedBlob :: Object-encodedBlob =-  ObjectMap $ Map.fromList [-    (os "key4", ObjectArray [ObjectArray [i 1, i 2], ObjectArray [i 3]]),-    (os "key5", ObjectMap $ Map.fromList [(i 1, os "1"), (i 2, os "2")]),-    (os "key6", os "nt"),-    (os "key7", ObjectArray [ObjectInt 91, ObjectString "pair"])-    ]--encoded :: Object-encoded =-  ObjectMap $ Map.fromList [-    (os "key1", encodedBlob),-    (os "key2", ObjectBool False),-    (ObjectString "key3", ObjectArray [os "dat", i 27])-    ]--test_encode :: UnitTest-test_encode =-  encoded === toMsgpack dat--doc2Text :: Either (Doc AnsiStyle) a -> Either Text a-doc2Text =-  mapLeft (renderStrict . layoutPretty defaultLayoutOptions)--decodeSubject :: Object-decodeSubject =-  ObjectMap $ Map.fromList [-    (os "key1", encodedBlob),-    (os "key2", ObjectBool False),-    (ObjectBinary "key3", ObjectArray [os "dat", i 27])-    ]--test_decodeBasic :: UnitTest-test_decodeBasic =-  Right dat === doc2Text (fromMsgpack decodeSubject)--data Nope =-  Nope {-    present :: Int,-    absent :: Maybe Int-  }-  deriving (Eq, Show, Generic, MsgpackDecode)--encodedNope :: Object-encodedNope =-  ObjectMap $ Map.fromList [(os "present", i 5)]--test_maybeMissing :: UnitTest-test_maybeMissing =-  Right (Nope 5 Nothing) === doc2Text (fromMsgpack encodedNope)--test_decodeEither :: UnitTest-test_decodeEither =-  Right (Left "text" :: Either Text Int) === doc2Text (fromMsgpack (ObjectBinary "text"))--data ST =-  STL {-    stName :: Text,-    stCount :: Int-  }-  |-  STR {-    stName :: Text,-    stDesc :: Text-  }-  deriving (Eq, Show, Generic, MsgpackEncode, MsgpackDecode)--sumName :: Text-sumName =-  "sumName"--sumCount :: Int-sumCount =-  1313--encodedSum :: Object-encodedSum =-  ObjectMap $ Map.fromList [-    (toMsgpack @Text "stName", toMsgpack sumName),-    (toMsgpack @Text "stCount", toMsgpack sumCount)-    ]--test_encodeSum :: UnitTest-test_encodeSum =-  encodedSum === toMsgpack (STL sumName sumCount)--test_decodeSum :: UnitTest-test_decodeSum =-  Right (STL sumName sumCount) === doc2Text (fromMsgpack encodedSum)--encodedPath :: Object-encodedPath =-  ObjectString "/path/to/file"--test_decodePath :: UnitTest-test_decodePath =-  Right [absfile|/path/to/file|] === doc2Text (fromMsgpack @(Path Abs File) encodedPath)--test_failDecodePath :: UnitTest-test_failDecodePath =-  Left "InvalidRelDir \"/path/to/file\"" === doc2Text (fromMsgpack @(Path Rel Dir) encodedPath)--test_encodePath :: UnitTest-test_encodePath =-  ObjectString "path/to/file" === toMsgpack [relfile|path/to/file|]--test_msgpack :: TestTree-test_msgpack =-  testGroup "msgpack" [-    unitTest "encode" test_encode,-    unitTest "decode" test_decodeBasic,-    unitTest "decode Nothing" test_maybeMissing,-    unitTest "decode Right" test_decodeEither,-    unitTest "encode sum type" test_encodeSum,-    unitTest "decode sum type" test_decodeSum,-    unitTest "decode Path" test_decodePath,-    unitTest "decode invalid Path" test_failDecodePath,-    unitTest "encode Path" test_encodePath-  ]
− test/Ribosome/Test/NvimMenuTest.hs
@@ -1,164 +0,0 @@-module Ribosome.Test.NvimMenuTest where--import Conduit (ConduitT, yield, yieldMany)-import Control.Concurrent.Lifted (fork, killThread)-import Control.Exception.Lifted (bracket)-import Control.Lens (element, (^?))-import qualified Data.Map.Strict as Map (empty, fromList)-import Hedgehog ((===))-import Test.Tasty (TestTree, testGroup)-import TestError (RiboTest, TestError)--import Ribosome.Api.Input (syntheticInput)-import Ribosome.Control.Monad.Ribo (Ribo)-import Ribosome.Menu.Action (menuReturn)-import qualified Ribosome.Menu.Data.FilteredMenuItem as FilteredMenuItem (item)-import Ribosome.Menu.Data.Menu (Menu(Menu))-import Ribosome.Menu.Data.MenuConsumerAction (MenuConsumerAction)-import Ribosome.Menu.Data.MenuItem (MenuItem, simpleMenuItem)-import qualified Ribosome.Menu.Data.MenuItem as MenuItem (text)-import Ribosome.Menu.Data.MenuResult (MenuResult)-import qualified Ribosome.Menu.Data.MenuResult as MenuResult (MenuResult(..))-import Ribosome.Menu.Prompt.Data.Prompt (Prompt(Prompt))-import Ribosome.Menu.Prompt.Data.PromptConfig (PromptConfig(PromptConfig), PromptFlag(StartInsert))-import Ribosome.Menu.Prompt.Data.PromptEvent (PromptEvent)-import qualified Ribosome.Menu.Prompt.Data.PromptEvent as PromptEvent (PromptEvent(..))-import Ribosome.Menu.Prompt.Nvim (getCharC, nvimPromptRenderer)-import Ribosome.Menu.Prompt.Run (basicTransition)-import Ribosome.Menu.Run (nvimMenu)-import Ribosome.Menu.Simple (Mappings, defaultMenu)-import Ribosome.Nvim.Api.IO (vimGetWindows)-import Ribosome.System.Time (sleep)-import Ribosome.Test.Run (UnitTest, unitTest)-import Ribosome.Test.Tmux (tmuxSpecDef)--promptInput ::-  MonadIO m =>-  [Text] ->-  ConduitT () PromptEvent m ()-promptInput chars' = do-  lift $ sleep 0.1-  yieldMany (PromptEvent.Character <$> chars')--menuItems ::-  Monad m =>-  [Text] ->-  ConduitT () [MenuItem Text] m ()-menuItems =-  yield . fmap (simpleMenuItem "name")--chars :: [Text]-chars =-  ["i", "t", "e", "esc", "k", "k", "k", "cr"]--items :: [Text]-items =-  ("item" <>) . show <$> [(1 :: Int)..8]--exec ::-  MonadIO m =>-  Menu Text ->-  Prompt ->-  m (MenuConsumerAction m (Maybe Text), Menu Text)-exec m@(Menu _ items' selected _ _ _) _ =-  menuReturn item m-  where-    item =-      items' ^? element selected . FilteredMenuItem.item . MenuItem.text--promptConfig ::-  ConduitT () PromptEvent (Ribo () TestError) () ->-  PromptConfig (Ribo () TestError)-promptConfig source =-  PromptConfig source basicTransition nvimPromptRenderer [StartInsert]--runNvimMenu ::-  Mappings (Ribo () TestError) a Text ->-  ConduitT () PromptEvent (Ribo () TestError) () ->-  Ribo () TestError (MenuResult a)-runNvimMenu maps source =-  nvimMenu def (menuItems items) (defaultMenu maps) (promptConfig source) Nothing--mappings :: Mappings (Ribo () TestError) (Maybe Text) Text-mappings =-  Map.fromList [("cr", exec)]--nvimMenuSpec ::-  ConduitT () PromptEvent (Ribo () TestError) () ->-  RiboTest ()-nvimMenuSpec =-  (MenuResult.Return (Just "item4") ===) <=< lift . runNvimMenu mappings--nvimMenuPureSpec :: RiboTest ()-nvimMenuPureSpec =-  nvimMenuSpec (promptInput chars)--test_nvimMenuPure :: UnitTest-test_nvimMenuPure =-  tmuxSpecDef nvimMenuPureSpec--nativeChars :: [Text]-nativeChars =-  ["i", "t", "e", "<esc>", "k", "<c-k>", "k", "<cr>"]--nvimMenuNativeSpec :: RiboTest ()-nvimMenuNativeSpec =-  bracket (fork input) killThread (const $ nvimMenuSpec (getCharC 0.1))-  where-    input =-      syntheticInput (Just 0.2) nativeChars--test_nvimMenuNative :: UnitTest-test_nvimMenuNative =-  tmuxSpecDef nvimMenuNativeSpec--nvimMenuInterruptSpec :: RiboTest ()-nvimMenuInterruptSpec = do-  (MenuResult.Aborted ===) =<< spec-  (1 ===) =<< length <$> vimGetWindows-  where-    spec :: RiboTest (MenuResult ())-    spec =-      lift (bracket (fork input) killThread (const run))-    run =-      nvimMenu def (menuItems items) (defaultMenu Map.empty) (promptConfig (getCharC 0.1)) Nothing-    input =-      syntheticInput (Just 0.2) ["<c-c>", "<cr>"]--test_nvimMenuInterrupt :: UnitTest-test_nvimMenuInterrupt =-  tmuxSpecDef nvimMenuInterruptSpec--returnPrompt ::-  MonadIO m =>-  Menu Text ->-  Prompt ->-  m (MenuConsumerAction m Text, Menu Text)-returnPrompt m (Prompt _ _ text) =-  menuReturn text m--navChars :: [Text]-navChars =-  ["i", "t", "e", "m", "1", "<bs>", "<esc>", "h", "h", "h", "h", "h", "x", "a", "o", "<cr>"]--nvimMenuNavSpec :: RiboTest ()-nvimMenuNavSpec =-  (MenuResult.Return "toem" ===) =<< lift run-  where-    run =-      bracket (fork input) killThread (const $ runNvimMenu (Map.fromList [("cr", returnPrompt)]) (getCharC 0.1))-    input =-      syntheticInput (Just 0.2) navChars--test_nvimMenuNav :: UnitTest-test_nvimMenuNav =-  tmuxSpecDef nvimMenuNavSpec--test_nvimMenu :: TestTree-test_nvimMenu =-  testGroup "nvim menu" [-    unitTest "pure" test_nvimMenuPure,-    unitTest "native" test_nvimMenuNative,-    unitTest "interrupt" test_nvimMenuInterrupt,-    unitTest "navigation" test_nvimMenuNav-  ]
− test/Ribosome/Test/PromptTest.hs
@@ -1,39 +0,0 @@-module Ribosome.Test.PromptTest where--import Conduit (awaitForever, evalStateC, runConduit, yield, (.|))-import qualified Data.Conduit.Combinators as Conduit (last)-import Hedgehog (TestT, (===))-import TestError (TestError)--import Ribosome.Control.Monad.Ribo (Ribo)-import Ribosome.Menu.Prompt.Data.Prompt (Prompt(Prompt))-import Ribosome.Menu.Prompt.Data.PromptConfig (PromptConfig(PromptConfig), PromptFlag(StartInsert))-import Ribosome.Menu.Prompt.Data.PromptConsumed (PromptConsumed(Yes))-import Ribosome.Menu.Prompt.Data.PromptConsumerUpdate (PromptConsumerUpdate(PromptConsumerUpdate))-import qualified Ribosome.Menu.Prompt.Data.PromptEvent as PromptEvent (PromptEvent(..))-import qualified Ribosome.Menu.Prompt.Data.PromptState as PromptState (PromptState(..))-import Ribosome.Menu.Prompt.Run (basicTransition, noPromptRenderer, processPromptEvent)-import Ribosome.Test.Run (UnitTest)-import Ribosome.Test.Unit (unitSpecDef')--promptSetSpec :: TestT (Ribo () TestError) ()-promptSetSpec = do-  update <- runConduit $ yield event .| exec .| Conduit.last-  Just target === update-  where-    exec =-      evalStateC initialPrompt (awaitForever (processPromptEvent config))-    initialPrompt =-      Prompt 1 PromptState.Normal "abc"-    config =-      PromptConfig (return ()) basicTransition noPromptRenderer [StartInsert]-    event =-      PromptEvent.Set (Prompt 10 PromptState.Normal text)-    text =-      "12345678"-    target =-      PromptConsumerUpdate event (Prompt 8 PromptState.Normal text) Yes--test_promptSet :: UnitTest-test_promptSet =-  unitSpecDef' promptSetSpec
+ test/Ribosome/Test/ReportTest.hs view
@@ -0,0 +1,37 @@+module Ribosome.Test.ReportTest where++import qualified Log+import Log (Severity (Error, Info))+import Polysemy.Test (UnitTest)++import Ribosome.Host.Api.Effect (nvimCommand, nvimInput)+import Ribosome.Host.Data.Execution (Execution (Sync))+import Ribosome.Host.Data.Report (Report (Report))+import Ribosome.Host.Data.RpcHandler (Handler)+import Ribosome.Host.Handler (rpcFunction)+import qualified Ribosome.Report as Report+import Ribosome.Test.Screenshot (awaitScreenshot)+import Ribosome.Test.SocketTmux (testHandlersSocketTmux)++stopInfo :: Handler r ()+stopInfo =+  stop (Report "report an info Stop by echoing" [] Info)++stopError :: Handler r ()+stopError =+  stop (Report "report an error Stop by responding" [] Error)++test_report :: UnitTest+test_report =+  testHandlersSocketTmux [rpcFunction "StopInfo" Sync stopInfo, rpcFunction "StopError" Sync stopError] do+    nvimCommand "mode"+    Log.debug "don't report Log.debug message"+    awaitScreenshot False "report-1" 0+    Log.info "report Log.info message"+    awaitScreenshot False "report-2" 0+    Report.warn "report Report.warn message" []+    awaitScreenshot False "report-3" 0+    nvimInput ":call StopInfo()<cr>"+    awaitScreenshot False "report-4" 0+    nvimInput ":call StopError()<cr>"+    awaitScreenshot False "report-5" 0
− test/Ribosome/Test/RpcTest.hs
@@ -1,154 +0,0 @@-module Ribosome.Test.RpcTest where--import Data.DeepPrisms (DeepPrisms)-import qualified Data.List as List (lines)-import qualified Data.Map.Strict as Map (empty)-import Hedgehog ((===))-import Language.Haskell.TH hiding (reportError)-import Neovim (CommandArguments, Plugin(..))-import System.Log.Logger (Priority(DEBUG), setLevel, updateGlobalLogger)-import TestError (RiboTest, TestError)--import Ribosome.Api.Variable (setVar)-import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE, Ribo)-import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import Ribosome.Error.Report (reportError)-import Ribosome.Nvim.Api.IO (vimCommand, vimGetVar)-import Ribosome.Nvim.Api.RpcCall (RpcError)-import Ribosome.Plugin (RpcDef, cmd, riboPlugin, rpcHandler, sync)-import Ribosome.System.Time (sleep)-import Ribosome.Test.Embed (integrationSpecDef)-import Ribosome.Test.Run (UnitTest)--handleError ::-  DeepPrisms e RpcError =>-  TestError ->-  Ribo s e ()-handleError =-  reportError "test"--target :: Int-target =-  13--resultVar :: Text-resultVar =-  "test_result"--handler ::-  NvimE e m =>-  m Int-handler = do-  setVar resultVar target-  return target--handlerCmdCmdArgs ::-  NvimE e m =>-  CommandArguments ->-  Text ->-  Text ->-  Text ->-  m Int-handlerCmdCmdArgs _ _ _ _ =-  handler--handlerCmdNoCmdArgs ::-  NvimE e m =>-  Text ->-  Text ->-  Text ->-  m Int-handlerCmdNoCmdArgs _ _ _ =-  handler--handlerCmdNoArgs ::-  NvimE e m =>-  m Int-handlerCmdNoArgs =-  handler--handlerCmdOneArg ::-  NvimE e m =>-  Text ->-  m Int-handlerCmdOneArg _ =-  handler--handlerCmdMaybeArg ::-  NvimE e m =>-  Maybe Text ->-  m Int-handlerCmdMaybeArg _ =-  handler--handlerCmdListArg ::-  NvimE e m =>-  [Text] ->-  m Int-handlerCmdListArg _ =-  handler--$(return [])--handlers ::-  MonadRibo m =>-  NvimE e m =>-  [[RpcDef m]]-handlers =-  [-    $(rpcHandler (sync . cmd []) 'handlerCmdCmdArgs),-    $(rpcHandler (sync . cmd []) 'handlerCmdNoCmdArgs),-    $(rpcHandler (sync . cmd []) 'handlerCmdNoArgs),-    $(rpcHandler (sync . cmd []) 'handlerCmdOneArg),-    $(rpcHandler (sync . cmd []) 'handlerCmdMaybeArg),-    $(rpcHandler (sync . cmd []) 'handlerCmdListArg)-    ]--plugin :: IO (Plugin (Ribosome ()))-plugin = do-  ribo <- newRibosome "test" def-  pure $ riboPlugin "test" ribo handlers [] handleError Map.empty--successCommand ::-  Text ->-  RiboTest ()-successCommand cmd' = do-  setVar resultVar (0 :: Int)-  vimCommand cmd'-  (target ===) =<< vimGetVar resultVar--failureCommand ::-  Text ->-  RiboTest ()-failureCommand cmd' = do-  lift (setVar resultVar (0 :: Int))-  catchAt recoverRpc (vimCommand cmd')-  ((0 :: Int) ===) =<< vimGetVar resultVar-  where-    recoverRpc (_ :: RpcError) =-      return ()--rpcSpec :: RiboTest ()-rpcSpec = do-  successCommand "HandlerCmdCmdArgs a b c"-  successCommand "HandlerCmdNoCmdArgs a b c"-  successCommand "HandlerCmdNoArgs"-  successCommand "HandlerCmdOneArg a"-  successCommand "HandlerCmdMaybeArg a"-  successCommand "HandlerCmdMaybeArg"-  successCommand "HandlerCmdListArg"-  successCommand "HandlerCmdListArg a b c"-  failureCommand "HandlerCmdCmdArgs a b"-  failureCommand "HandlerCmdNoCmdArgs a b"-  failureCommand "HandlerCmdNoArgs a"-  sleep 1--test_rpc :: UnitTest-test_rpc = do-  liftIO $ updateGlobalLogger "test" (setLevel DEBUG)-  plug <- liftIO plugin-  when debug $ traverse_ putStrLn . List.lines $ $(stringE . pprint =<< rpcHandler (sync . cmd []) 'handlerCmdListArg)-  integrationSpecDef plug rpcSpec-  where-    debug =-      False
− test/Ribosome/Test/ScratchTest.hs
@@ -1,95 +0,0 @@-module Ribosome.Test.ScratchTest where--import qualified Data.Map.Strict as Map (toList)-import Hedgehog ((===))-import Neovim (Plugin(..))-import TestError (RiboTest, handleTestError)--import Ribosome.Api.Buffer (currentBufferContent)-import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE, pluginInternalL)-import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import qualified Ribosome.Control.Ribosome as Ribosome (scratch)-import Ribosome.Data.FloatOptions (FloatOptions(FloatOptions), FloatRelative(Cursor))-import Ribosome.Data.ScratchOptions (ScratchOptions(ScratchOptions))-import Ribosome.Msgpack.Error (DecodeError)-import Ribosome.Nvim.Api.IO (vimCallFunction, vimCommand)-import Ribosome.Plugin (riboPlugin, rpcHandler, rpcHandlerDef, sync)-import Ribosome.Scratch (showInScratch)-import Ribosome.Test.Await (await)-import Ribosome.Test.Embed (integrationSpecDef)-import Ribosome.Test.Run (UnitTest)--target :: [Text]-target = ["line 1", "line 2"]--name :: Text-name =-  "buffi"--makeScratch ::-  NvimE e m =>-  MonadRibo m =>-  MonadBaseControl IO m =>-  MonadDeepError e DecodeError m =>-  m ()-makeScratch =-  void $ showInScratch target (ScratchOptions False True False True True True False Nothing Nothing Nothing [] [] name)--floatOptions :: FloatOptions-floatOptions =-  FloatOptions Cursor 30 2 1 1 True def Nothing--makeFloatScratch ::-  NvimE e m =>-  MonadRibo m =>-  MonadBaseControl IO m =>-  MonadDeepError e DecodeError m =>-  m ()-makeFloatScratch =-  void $ showInScratch target options-  where-    options =-      ScratchOptions False True False True True True False (Just floatOptions) Nothing (Just 0) [] [] name--scratchCount ::-  MonadRibo m =>-  m Int-scratchCount =-  length . Map.toList <$> pluginInternalL Ribosome.scratch--$(return [])--scratchPlugin :: IO (Plugin (Ribosome ()))-scratchPlugin = do-  env <- newRibosome "test" ()-  return $ riboPlugin "test" env funcs [] handleTestError def-  where-    funcs = [$(rpcHandlerDef 'makeScratch), $(rpcHandlerDef 'makeFloatScratch), $(rpcHandler sync 'scratchCount)]--scratchSpec :: Text -> RiboTest ()-scratchSpec fun = do-  () <- vimCallFunction fun []-  await ((1 :: Int) ===) scratches-  await (target ===) currentBufferContent-  vimCommand "bdelete"-  await (0 ===) scratches-  where-    scratches = vimCallFunction "ScratchCount" []--regularScratchSpec :: RiboTest ()-regularScratchSpec =-  scratchSpec "MakeScratch"--test_regularScratch :: UnitTest-test_regularScratch = do-  plug <- liftIO scratchPlugin-  integrationSpecDef plug regularScratchSpec--floatScratchSpec :: RiboTest ()-floatScratchSpec =-  scratchSpec "MakeFloatScratch"--test_floatScratch :: UnitTest-test_floatScratch = do-  plug <- liftIO scratchPlugin-  integrationSpecDef plug floatScratchSpec
− test/Ribosome/Test/SettingTest.hs
@@ -1,51 +0,0 @@-module Ribosome.Test.SettingTest where--import Data.Either.Combinators (swapEither)-import Hedgehog (TestT, evalEither, (===))--import Ribosome.Config.Setting (setting, updateSetting)-import Ribosome.Control.Monad.Ribo (Ribo)-import Ribosome.Data.Setting (Setting(Setting))-import Ribosome.Data.SettingError (SettingError)-import Ribosome.Error.Report.Class (ReportError(..))-import Ribosome.Nvim.Api.RpcCall (RpcError)-import Ribosome.Test.Run (UnitTest)-import Ribosome.Test.Unit (unitSpec)--data SettingSpecError =-  Sett SettingError-  |-  Rpc RpcError-  deriving Show--instance ReportError SettingSpecError where-  errorReport = undefined--deepPrisms ''SettingSpecError--sett :: Setting Int-sett = Setting "name" True Nothing--settingSuccessSpec :: TestT (Ribo s SettingSpecError) ()-settingSuccessSpec = do-  updateSetting sett 5-  r <- lift (setting sett)-  5 === r--test_settingSuccess :: UnitTest-test_settingSuccess =-  unitSpec def () settingSuccessSpec--settingFailSpec :: TestT (Ribo s SettingSpecError) ()-settingFailSpec = do-  ea <- lift (catchAt catch $ Right <$> result)-  void $ evalEither (swapEither ea)-  where-    result :: Ribo s SettingSpecError Int-    result = setting sett-    catch :: SettingError -> Ribo s SettingSpecError (Either SettingError Int)-    catch = return . Left--test_settingFail :: UnitTest-test_settingFail =-  unitSpec def () settingFailSpec
+ test/Ribosome/Test/SocketTmuxTest.hs view
@@ -0,0 +1,12 @@+module Ribosome.Test.SocketTmuxTest where++import Polysemy.Test (UnitTest, assert)++import Ribosome.Host.Api.Effect (nvimGetVar, nvimSetVar)+import Ribosome.Test.SocketTmux (testSocketTmux)++test_socketTmux :: UnitTest+test_socketTmux =+  testSocketTmux do+    nvimSetVar "test" True+    assert =<< nvimGetVar "test"
test/Ribosome/Test/SyntaxTest.hs view
@@ -1,48 +1,22 @@ module Ribosome.Test.SyntaxTest where -import TestError (TestError)-import Hedgehog (TestT)-import Chiasma.Data.TmuxError (TmuxError)-import Chiasma.Test.Tmux (TmuxTestConf(..))+import Polysemy.Test (UnitTest)  import Ribosome.Api.Buffer (setCurrentBufferContent) import Ribosome.Api.Syntax (executeSyntax)-import Ribosome.Control.Monad.Ribo (Ribo)-import Ribosome.Data.Syntax (-  Syntax(Syntax),-  syntaxHighlight,-  syntaxMatch,-  )-import Ribosome.Error.Report.Class (ReportError(..))-import Ribosome.System.Time (sleep)-import Ribosome.Test.Embed (defaultTestConfig)-import Ribosome.Test.Run (UnitTest)+import Ribosome.Syntax (Syntax (Syntax), syntaxHighlight, syntaxMatch) import Ribosome.Test.Screenshot (awaitScreenshot)-import Ribosome.Test.Tmux (tmuxSpec')--data SyntaxSpecError =-  Test TestError-  |-  Tmux TmuxError--deepPrisms ''SyntaxSpecError--instance ReportError SyntaxSpecError where-  errorReport _ =-    undefined+import Ribosome.Test.SocketTmux (testSocketTmux)  syntax :: Syntax syntax =-  Syntax [syntaxMatch "TestColons" "::"] [syntaxHighlight "TestColons"-    [("cterm", "reverse"), ("ctermfg", "1"), ("gui", "reverse"), ("guifg", "#dc322f")]] []--syntaxSpec :: TestT (Ribo () SyntaxSpecError) ()-syntaxSpec = do-  lift (setCurrentBufferContent ["function :: String -> Int", "function _ = 5"])-  _ <- lift (executeSyntax syntax)-  sleep 1-  awaitScreenshot "syntax" False 0+  Syntax [syntaxMatch "TestColons" "::"] [+    syntaxHighlight "TestColons" [("cterm", "reverse"), ("ctermfg", "1"), ("gui", "reverse"), ("guifg", "#dc322f")]+  ] []  test_syntax :: UnitTest test_syntax =-  tmuxSpec' def { ttcWidth = 300, ttcHeight = 51, ttcGui = False } (defaultTestConfig "syntax") def syntaxSpec+  testSocketTmux do+    setCurrentBufferContent ["function :: String -> Int", "function _ = 5"]+    _ <- executeSyntax syntax+    awaitScreenshot False "syntax" 0
− test/Ribosome/Test/THTest.hs
@@ -1,45 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_GHC -Wno-unused-imports #-}-{-# OPTIONS_GHC -Wno-unused-top-binds #-}-{- HLINT ignore -}--module Ribosome.Test.THTest where--import Data.Aeson (FromJSON)--- import Data.Default (def)-import GHC.Generics (Generic)-import Language.Haskell.TH-import Neovim (Plugin(..))--- import TestError (handleTestError)---- import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import Ribosome.Msgpack.Decode (MsgpackDecode)-import Ribosome.Msgpack.Encode (MsgpackEncode)-import Ribosome.Plugin-import Ribosome.Test.Run (UnitTest)--data Par =-  Par {-    parA :: Int,-    parB :: Int-  }-  deriving (Eq, Show, Generic, MsgpackDecode, MsgpackEncode, FromJSON)--handler :: Text -> m ()-handler =-  undefined--$(return [])--plugin' :: IO (Plugin (Ribosome Int))-plugin' = do-  -- ribo <- newRibosome ("test" :: Text) 1-  undefined-  -- return $ riboPlugin "test" ribo [$(rpcHandler (cmd []) 'handler)] [] handleTestError def--test_plug :: UnitTest-test_plug = do-  return ()-  -- _ <- plugin'-  -- traverse_ putStrLn $ lines $(stringE . pprint =<< rpcHandler (sync . cmd []) 'handler)
− test/Ribosome/Test/WatcherTest.hs
@@ -1,46 +0,0 @@-module Ribosome.Test.WatcherTest where--import qualified Data.Map.Strict as Map (singleton)-import Data.MessagePack (Object)-import Hedgehog ((===))-import Neovim (Plugin(..))-import TestError (RiboTest, handleTestError)--import Ribosome.Api.Autocmd (doautocmd)-import Ribosome.Api.Variable (setVar)-import Ribosome.Control.Monad.Ribo (NvimE)-import Ribosome.Control.Ribosome (Ribosome, newRibosome)-import Ribosome.Nvim.Api.IO (vimGetVar)-import Ribosome.Plugin (riboPlugin)-import Ribosome.Test.Await (await)-import Ribosome.Test.Embed (integrationSpecDef)-import Ribosome.Test.Orphans ()-import Ribosome.Test.Run (UnitTest)--changed :: NvimE e m => Object -> m ()-changed _ =-  setVar "number" =<< ((+) (1 :: Int)) <$> vimGetVar "number"--varWatcherPlugin :: IO (Plugin (Ribosome ()))-varWatcherPlugin = do-  env <- newRibosome "varwatcher" ()-  return $ riboPlugin "varwatcher" env [] [] handleTestError (Map.singleton "trigger" changed)--varWatcherSpec :: RiboTest ()-varWatcherSpec = do-  setVar "number" (10 :: Int)-  setVar "trigger" (5 :: Int)-  await ((10 :: Int) ===) (vimGetVar "number")-  await ((5 :: Int) ===) (vimGetVar "trigger")-  doautocmd True "CmdlineLeave"-  doautocmd True "CmdlineLeave"-  await ((11 :: Int) ===) (vimGetVar "number")-  setVar "trigger" (6 :: Int)-  await ((6 :: Int) ===) (vimGetVar "trigger")-  doautocmd True "CmdlineLeave"-  await ((12 :: Int) ===) (vimGetVar "number")--test_varWatcher :: UnitTest-test_varWatcher = do-  plug <- liftIO varWatcherPlugin-  integrationSpecDef plug varWatcherSpec
− test/Ribosome/Test/WindowTest.hs
@@ -1,43 +0,0 @@-module Ribosome.Test.WindowTest where--import Hedgehog ((===))-import TestError (RiboTest)--import Ribosome.Api.Window (ensureMainWindow)-import Ribosome.Msgpack.Encode (toMsgpack)-import Ribosome.Nvim.Api.Data (Window)-import Ribosome.Nvim.Api.IO (bufferSetOption, vimCommand, vimGetCurrentBuffer, vimGetCurrentWindow, vimGetWindows)-import Ribosome.Test.Run (UnitTest)-import Ribosome.Test.Unit (unitSpecDef')--setCurrentNofile :: RiboTest ()-setCurrentNofile = do-  buf <- vimGetCurrentBuffer-  bufferSetOption buf "buftype" (toMsgpack ("nofile" :: Text))--createNofile :: RiboTest Window-createNofile = do-  initialWindow <- vimGetCurrentWindow-  vimCommand "new"-  setCurrentNofile-  return initialWindow--findMainWindowExistingSpec :: RiboTest ()-findMainWindowExistingSpec = do-  initialWindow <- createNofile-  (initialWindow ===) =<< ensureMainWindow--test_findMainWindowExisting :: UnitTest-test_findMainWindowExisting =-  unitSpecDef' findMainWindowExistingSpec--findMainWindowCreateSpec :: RiboTest ()-findMainWindowCreateSpec = do-  setCurrentNofile-  void createNofile-  void ensureMainWindow-  (3 ===) =<< length <$> vimGetWindows--test_findMainWindowCreate :: UnitTest-test_findMainWindowCreate =-  unitSpecDef' findMainWindowCreateSpec
+ test/Skip.hs view
@@ -0,0 +1,11 @@+module Skip where++import qualified Data.Text.IO as Text+import Polysemy.Test (UnitTest)+import System.Environment (lookupEnv)++skipUnlessX :: UnitTest -> UnitTest+skipUnlessX test = do+  liftIO (lookupEnv "DISPLAY") >>= \case+    Just _ -> test+    Nothing -> liftIO (Text.putStrLn "Skipping test due to lack of display")
− test/TestError.hs
@@ -1,28 +0,0 @@-module TestError where--import Hedgehog (TestT)-import Ribosome.Control.Monad.Ribo (Nvim, NvimE, Ribo)-import Ribosome.Data.Mapping (MappingError)-import Ribosome.Error.Report.Class (ReportError(..))-import Ribosome.Log (showError)-import Ribosome.Msgpack.Error (DecodeError)-import Ribosome.Nvim.Api.RpcCall (RpcError)--data TestError =-  Rpc RpcError-  |-  Decode DecodeError-  |-  Mapping MappingError-  deriving (Show, Generic, ReportError)--deepPrisms ''TestError--handleTestError :: TestError -> Ribo s TestError ()-handleTestError =-  showError "error in test:"--type RiboTest a = TestT (Ribo () TestError) a-type RiboT a = Ribo () TestError a--instance (Nvim m, MonadDeepError TestError RpcError m) => NvimE TestError (TestT m) where