ribosome-test 0.3.0.1 → 0.4.0.0
raw patch · 30 files changed
+2203/−375 lines, 30 filesdep +aesondep +basedep +compositiondep −HTFdep −base-nopreludedep −unliftio-coredep ~bytestringdep ~chiasmadep ~cornea
Dependencies added: aeson, base, composition, composition-extra, conduit, containers, either, hedgehog, lens, lifted-async, path, path-io, prettyprinter, prettyprinter-ansi-terminal, ribosome-test, tasty, tasty-hedgehog, template-haskell
Dependencies removed: HTF, base-noprelude, unliftio-core
Dependency ranges changed: bytestring, chiasma, cornea, data-default, directory, exceptions, filepath, free, hslogger, lifted-base, messagepack, monad-control, mtl, nvim-hs, process, relude, resourcet, ribosome, text, transformers, typed-process, unix, unliftio
Files
- LICENSE +27/−48
- lib/Prelude.hs +0/−5
- lib/Ribosome/Test/Await.hs +25/−35
- lib/Ribosome/Test/Embed.hs +145/−77
- lib/Ribosome/Test/Exists.hs +1/−4
- lib/Ribosome/Test/File.hs +1/−2
- lib/Ribosome/Test/Input.hs +1/−0
- lib/Ribosome/Test/Orphans.hs +16/−18
- lib/Ribosome/Test/Run.hs +14/−0
- lib/Ribosome/Test/Screenshot.hs +25/−13
- lib/Ribosome/Test/Tmux.hs +162/−71
- lib/Ribosome/Test/Ui.hs +7/−13
- lib/Ribosome/Test/Unit.hs +42/−18
- readme.md +91/−0
- ribosome-test.cabal +277/−71
- test/Main.hs +42/−0
- test/Ribosome/Test/AutocmdTest.hs +49/−0
- test/Ribosome/Test/MappingTest.hs +71/−0
- test/Ribosome/Test/MenuTest.hs +324/−0
- test/Ribosome/Test/MsgpackTest.hs +170/−0
- test/Ribosome/Test/NvimMenuTest.hs +164/−0
- test/Ribosome/Test/PromptTest.hs +39/−0
- test/Ribosome/Test/RpcTest.hs +154/−0
- test/Ribosome/Test/ScratchTest.hs +95/−0
- test/Ribosome/Test/SettingTest.hs +51/−0
- test/Ribosome/Test/SyntaxTest.hs +48/−0
- test/Ribosome/Test/THTest.hs +45/−0
- test/Ribosome/Test/WatcherTest.hs +46/−0
- test/Ribosome/Test/WindowTest.hs +43/−0
- test/TestError.hs +28/−0
LICENSE view
@@ -1,55 +1,34 @@-# Blue Oak Model License--Version 1.0.0--## Purpose--This license gives everyone as much permission to work with-this software as possible, while protecting contributors-from liability.--## Acceptance--In order to receive this license, you must agree to its-rules. The rules of this license are both obligations-under that agreement and conditions to your license.-You must not do anything with this software that triggers-a rule that you cannot or will not follow.--## Copyright--Each contributor licenses you to do everything with this-software that would otherwise infringe that contributor's-copyright in it.--## Notices--You must ensure that everyone who gets a copy of-any part of this software from you, with or without-changes, also gets the text of this license or a link to-<https://blueoakcouncil.org/license/1.0.0>.--## Excuse+Copyright (c) 2020 Torsten Schmits -If anyone notifies you in writing that you have not-complied with [Notices](#notices), you can keep your-license by taking all practical steps to comply within 30-days after the notice. If you do not do so, your license-ends immediately.+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the+following conditions are met: -## Patent+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following+ disclaimer.+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided with the distribution. -Each contributor licenses you to do everything with this-software that would otherwise infringe any patent claims-they can license or become able to license.+Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those+receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except+for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell,+import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired+or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by: -## Reliability+ (a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of+ contributors, in source or binary form) alone; or+ (b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such+ copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to+ be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution. -No contributor can revoke this license.+Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this+license, whether expressly, by implication, estoppel or otherwise. -## No Liability+DISCLAIMER -***As far as the law allows, this software comes as is,-without any warranty or condition, and no contributor-will be liable to anyone for any damages related to this-software or this license, under any kind of legal claim.***+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
− lib/Prelude.hs
@@ -1,5 +0,0 @@-module Prelude (- module Ribosome.PreludeExport-) where--import Ribosome.PreludeExport
lib/Ribosome/Test/Await.hs view
@@ -1,47 +1,37 @@ module Ribosome.Test.Await where +import Hedgehog (TestT) import Control.Exception (throw)-import Control.Monad.Error.Class (MonadError, catchError)-import Control.Monad.IO.Class (MonadIO)-import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.Control (MonadBaseControl)-import Control.Monad.Trans.Except (ExceptT, runExceptT)-import Test.Framework.AssertM (AssertM)+import Control.Monad.Error.Class (MonadError (throwError), catchError)+import Hedgehog.Internal.Property (mkTestT, runTestT, Failure, Journal) -import Ribosome.Control.Concurrent.Wait (WaitError(Thrown), waitIODef)+import Ribosome.Control.Concurrent.Wait (WaitError(Thrown, ConditionUnmet, NotStarted), waitIODef) await ::- Show e =>+ ∀ e a b m . MonadError e m => MonadIO m =>- MonadFail m => MonadBaseControl IO m =>- AssertM m =>- (a -> m b) ->+ (a -> TestT m b) -> m a ->- m b+ TestT m b await assertion acquire = do- r <- waitIODef acquire' check'- either failure return r- where- acquire' = catchError (Right <$> acquire) (return . Left . show)- check' (Right a) = Right <$> assertion a- check' (Left e) = return (Left e)- failure (Thrown e) = throw e- failure e = fail $ "await failed with " <> show e--await' ::- ∀ a b m.- MonadIO m =>- MonadFail m =>- MonadBaseControl IO m =>- AssertM (ExceptT () m) =>- (a -> m b) ->- m a ->- m b-await' assertion acquire = do- r <- runExceptT $ await assertion' (lift acquire)- either (const $ fail "internal error") return r+ 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- assertion' :: a -> ExceptT () m b- assertion' = lift . assertion+ 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/Embed.hs view
@@ -1,15 +1,13 @@ module Ribosome.Test.Embed where -import Control.Concurrent (forkIO)-import Control.Monad.IO.Class (MonadIO, liftIO)-import Control.Monad.Reader (runReaderT)-import Control.Monad.Trans.Except (runExceptT)+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 Data.Default (Default(def))-import Data.Foldable (traverse_)-import Data.Functor (void)-import Data.Maybe (fromMaybe)-import GHC.IO.Handle (Handle)+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 (@@ -24,7 +22,7 @@ transitionTo, ) import Neovim.Main (standalone)-import Neovim.Plugin (Plugin, startPluginThreads)+import Neovim.Plugin (Plugin(Plugin), startPluginThreads) import Neovim.Plugin.Internal (NeovimPlugin, wrapPlugin) import Neovim.RPC.Common (RPCConfig, newRPCConfig) import Neovim.RPC.EventHandler (runEventHandler)@@ -44,15 +42,13 @@ proc, setStdin, setStdout,+ startProcess,+ stopProcess, unsafeProcessHandle,- withProcess, )-import UnliftIO.Async (async, cancel, race)-import UnliftIO.Exception (bracket, tryAny)-import UnliftIO.MVar (MVar)-import UnliftIO.STM (putTMVar) 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(..))@@ -62,12 +58,22 @@ import Ribosome.System.Time (sleep, sleepW) import Ribosome.Test.Orphans () -type Runner m = TestConfig -> m () -> m ()+type Runner m = ∀ a . TestConfig -> m a -> m a newtype Vars =- Vars [(Text, Object)]- deriving (Eq, Show, Semigroup, Monoid, Default)+ Vars (Map Text Object)+ deriving (Eq, Show)+ deriving newtype (Default, Semigroup, Monoid) +-- |left biased+varsUnion :: Vars -> Vars -> Vars+varsUnion (Vars v1) (Vars v2) =+ Vars (Map.union v1 v2)++varsFromList :: [(Text, Object)] -> Vars+varsFromList =+ Vars . Map.fromList+ data TestConfig = TestConfig { tcPluginName :: Text,@@ -80,23 +86,28 @@ } instance Default TestConfig where- def = TestConfig "ribosome" "test/f/fixtures/rtp" "test/f/temp/log" 10 def def (Vars [])+ def = TestConfig "ribosome" "test/u/fixtures/rtp" "test/u/temp/log" 10 def def def defaultTestConfigWith :: Text -> Vars -> TestConfig defaultTestConfigWith name vars = def { tcPluginName = name, tcVariables = vars } defaultTestConfig :: Text -> TestConfig-defaultTestConfig name = defaultTestConfigWith name (Vars [])+defaultTestConfig name = defaultTestConfigWith name def setVars :: ∀ m e. NvimE e m => Vars -> m () setVars (Vars vars) =- traverse_ set vars+ traverse_ set (Map.toList vars) where set :: (Text, Object) -> m ()- set = uncurry vimSetVar+ set =+ uncurry vimSetVar -setupPluginEnv :: (MonadIO m, NvimE e m) => TestConfig -> m ()+setupPluginEnv ::+ MonadIO m =>+ NvimE e m =>+ TestConfig ->+ m () setupPluginEnv (TestConfig _ rtp _ _ _ _ vars) = do absRtp <- liftIO $ makeAbsolute (toString rtp) rtpCat (toText absRtp)@@ -108,9 +119,10 @@ killProcess :: Process i o e -> IO () killProcess prc = do- let handle = unsafeProcessHandle prc- mayPid <- getPid handle- traverse_ killPid mayPid+ void $ try @_ @SomeException do+ let handle = unsafeProcessHandle prc+ mayPid <- getPid handle+ traverse_ killPid mayPid testNvimProcessConfig :: TestConfig -> ProcessConfig Handle Handle () testNvimProcessConfig TestConfig {..} =@@ -119,18 +131,29 @@ args = fromMaybe defaultArgs tcCmdline defaultArgs = ["--embed", "-n", "-u", "NONE", "-i", "NONE"] -startHandlers :: Handle -> Handle -> TestConfig -> Internal.Config RPCConfig -> IO (IO ())-startHandlers stdoutHandle stdinHandle TestConfig{..} nvimConf = do- socketReader <- run runSocketReader stdoutHandle- eventHandler <- run runEventHandler stdinHandle+startHandlers ::+ MonadIO m =>+ Handle ->+ Handle ->+ 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]+ let stopEventHandlers = traverse_ @[] cancel [socketReader, eventHandler] return stopEventHandlers where run runner hand = async . void $ runner hand emptyConf emptyConf = nvimConf { Internal.pluginSettings = Nothing } -startStdioHandlers :: NvimProc -> TestConfig -> Internal.Config RPCConfig -> IO (IO ())+startStdioHandlers ::+ MonadIO m =>+ NvimProc ->+ TestConfig ->+ Internal.Config RPCConfig ->+ m (IO ()) startStdioHandlers prc = startHandlers (getStdout prc) (getStdin prc) @@ -169,115 +192,160 @@ shutdownNvim _ prc stopEventHandlers = do stopEventHandlers killProcess prc- -- quitNvim testCfg prc runTest ::- RpcHandler e env m =>+ MonadIO m =>+ MonadFail m => ReportError e =>+ RpcHandler e env n =>+ MonadBaseControl IO m => TestConfig -> Internal.Config env ->- m () ->- IO ()+ n a ->+ m a runTest TestConfig{..} testCfg thunk = do- result <- race (sleepW tcTimeout) (runNeovimThunk testCfg (runExceptT $ native thunk))- case result of- Right (Right _) -> return ()+ 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" runEmbeddedNvim ::- RpcHandler e env m =>+ MonadIO m =>+ MonadFail m =>+ MonadBaseControl IO m =>+ RpcHandler e env n => ReportError e => TestConfig -> env ->- m () ->+ n a -> NvimProc ->- IO ()+ m a runEmbeddedNvim conf ribo thunk prc = do- nvimConf <- Internal.newConfig (pure Nothing) newRPCConfig+ nvimConf <- liftIO (Internal.newConfig (pure Nothing) newRPCConfig) let testCfg = Internal.retypeConfig ribo nvimConf- bracket (startStdioHandlers prc conf nvimConf) (shutdownNvim testCfg prc) (const $ runTest conf testCfg thunk)+ bracket (startStdioHandlers prc conf nvimConf) (liftIO . shutdownNvim testCfg prc) (const $ runTest conf testCfg thunk) +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)+ runEmbedded ::- RpcHandler e env m =>+ MonadIO m =>+ MonadFail m =>+ MonadBaseControl IO m =>+ RpcHandler e env n => ReportError e => TestConfig -> env ->- m () ->- IO ()+ n a ->+ m a runEmbedded conf ribo thunk = do let pc = testNvimProcessConfig conf- withProcess pc $ runEmbeddedNvim conf ribo thunk+ withProcessWait pc $ runEmbeddedNvim conf ribo thunk unsafeEmbeddedSpec ::- RpcHandler e env m =>+ MonadIO m =>+ MonadFail m =>+ MonadBaseControl IO m =>+ RpcHandler e env n => ReportError e =>- Runner m ->+ Runner n -> TestConfig -> env ->- m () ->- IO ()+ n a ->+ m a unsafeEmbeddedSpec runner conf s spec = runEmbedded conf s $ runner conf spec unsafeEmbeddedSpecR ::- RpcHandler e (Ribosome env) m =>+ MonadIO m =>+ MonadFail m => ReportError e =>- Runner m ->+ MonadBaseControl IO m =>+ RpcHandler e (Ribosome env) n =>+ Runner n -> TestConfig -> env ->- m () ->- IO ()+ n a ->+ m a unsafeEmbeddedSpecR runner conf env spec = do tv <- newRibosomeTMVar env let ribo = Ribosome (tcPluginName conf) tv unsafeEmbeddedSpec runner conf ribo spec runPlugin ::+ MonadIO m =>+ MonadBaseControl IO m => Handle -> Handle -> [Neovim () NeovimPlugin] -> Internal.Config c ->- IO (MVar Internal.StateTransition)+ m (MVar Internal.StateTransition) runPlugin evHandlerHandle sockreaderHandle plugins baseConf = do- updateGlobalLogger "Neovim.Plugin" (setLevel ERROR)- rpcConf <- newRPCConfig+ liftIO (updateGlobalLogger "Neovim.Plugin" (setLevel ERROR))+ rpcConf <- liftIO newRPCConfig let conf = Internal.retypeConfig rpcConf baseConf- ehTid <- async $ runEventHandler evHandlerHandle conf { Internal.pluginSettings = Nothing }- srTid <- async $ runSocketReader sockreaderHandle conf- void $ forkIO $ startPluginThreads (Internal.retypeConfig () baseConf) plugins >>= \case+ 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+ standalone (srTid : ehTid : pluginTids) conf return (Internal.transitionTo conf) -runEmbeddedWithPlugin ::- RpcHandler e () m =>+inTestT ::+ ∀ n m a .+ TestT n a ->+ (∀ x . n x -> m x) ->+ TestT m a+inTestT ma f =+ mkTestT (f (runTestT ma))++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 ->- m () ->- IO ()-runEmbeddedWithPlugin conf plugin thunk =- withProcess (testNvimProcessConfig conf) run+ TestT n a ->+ TestT m a+integrationSpec conf plugin@(Plugin env _) thunk =+ inTestT thunk \ na ->+ withProcessTerm (testNvimProcessConfig conf) (run na) where- run prc = do- nvimConf <- Internal.newConfig (pure Nothing) (pure ())- bracket (acquire prc nvimConf) release (const $ runTest conf nvimConf thunk)+ 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 =- runPlugin (getStdin prc) (getStdout prc) [wrapPlugin plugin] nvimConf <* sleep 0.5+ liftIO (runPlugin (getStdin prc) (getStdout prc) [wrapPlugin plugin] nvimConf <* sleep 0.5) release transitions = tryPutMVar transitions Internal.Quit *> sleep 0.5 integrationSpecDef ::- RpcHandler e () m =>+ NvimE e n =>+ MonadIO m =>+ MonadIO n =>+ MonadFail m => ReportError e =>+ RpcHandler e env n =>+ MonadBaseControl IO m => Plugin env ->- m () ->- IO ()+ TestT n a ->+ TestT m a integrationSpecDef =- runEmbeddedWithPlugin def+ integrationSpec def
lib/Ribosome/Test/Exists.hs view
@@ -1,8 +1,5 @@-module Ribosome.Test.Exists(- waitForPlugin,-) where+module Ribosome.Test.Exists where -import Control.Monad.IO.Class (MonadIO) import Data.MessagePack (Object(ObjectInt)) import Neovim (Neovim, toObject) import Neovim.API.Text (vim_call_function)
lib/Ribosome/Test/File.hs view
@@ -1,12 +1,11 @@ module Ribosome.Test.File where -import Control.Monad.IO.Class (MonadIO, liftIO) import qualified Data.ByteString as ByteString (readFile) import System.Directory (canonicalizePath, createDirectoryIfMissing, removePathForcibly) import System.FilePath ((</>)) testDir :: Text -> IO FilePath-testDir prefix = canonicalizePath $ "test" </> toString prefix+testDir = canonicalizePath . toString -- raises exception if cwd is not the package root so we don't damage anything tempDirIO :: Text -> FilePath -> IO FilePath
lib/Ribosome/Test/Input.hs view
@@ -4,6 +4,7 @@ import Control.Exception.Lifted (bracket) import Ribosome.Api.Input (syntheticInput)+import Ribosome.Control.Monad.Ribo (NvimE) withInput :: NvimE e m =>
lib/Ribosome/Test/Orphans.hs view
@@ -2,28 +2,26 @@ module Ribosome.Test.Orphans where -import Control.Monad.IO.Class (liftIO)-import Control.Monad.IO.Unlift (withRunInIO)-import Neovim (Neovim)-import Test.Framework.AssertM (AssertM(..))+-- import Control.Monad.IO.Unlift (withRunInIO)+-- import Neovim (Neovim) -import Ribosome.Control.Monad.Ribo (Ribo(Ribo, unRibo))+-- import Ribosome.Control.Monad.Ribo (Ribo(Ribo, unRibo)) -instance AssertM (Neovim e) where- genericAssertFailure__ l =- liftIO . genericAssertFailure__ l+-- instance AssertM (Neovim e) where+-- genericAssertFailure__ l =+-- liftIO . genericAssertFailure__ l - genericSubAssert l msg ma =- withRunInIO (\f -> genericSubAssert l msg (f ma))+-- genericSubAssert l msg ma =+-- withRunInIO (\f -> genericSubAssert l msg (f ma)) -instance AssertM (ExceptT e (Neovim s)) where- genericAssertFailure__ l = liftIO . genericAssertFailure__ l+-- instance AssertM (ExceptT e (Neovim s)) where+-- genericAssertFailure__ l = liftIO . genericAssertFailure__ l - genericSubAssert l msg =- ExceptT . genericSubAssert l msg . runExceptT+-- genericSubAssert l msg =+-- ExceptT . genericSubAssert l msg . runExceptT -instance AssertM (Ribo s e) where- genericAssertFailure__ l = liftIO . genericAssertFailure__ l+-- instance AssertM (Ribo s e) where+-- genericAssertFailure__ l = liftIO . genericAssertFailure__ l - genericSubAssert l msg =- Ribo . ExceptT . genericSubAssert l msg . runExceptT . unRibo+-- genericSubAssert l msg =+-- Ribo . ExceptT . genericSubAssert l msg . runExceptT . unRibo
+ lib/Ribosome/Test/Run.hs view
@@ -0,0 +1,14 @@+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,23 +1,19 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}- 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.DeepError (MonadDeepError) import Control.Monad.Free.Class (MonadFree)-import Control.Monad.IO.Class (MonadIO)-import Data.Text (Text)-import Test.Framework-import Test.Framework.AssertM (AssertM(..))+import Hedgehog (TestT, (===)) 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) screenshot :: MonadFree TmuxThunk m =>@@ -28,23 +24,39 @@ m (Maybe ([Text], [Text])) screenshot name record pane = do storage <- fixture "screenshots"- Chiasma.screenshot record storage (toString name) pane+ Chiasma.screenshot record storage name pane assertScreenshot ::- AssertM m => MonadIO m => MonadRibo m => MonadDeepError e TmuxError m =>+ MonadBaseControl IO m => MonadMask m => Nvim m => Text -> Bool -> Int ->- m ()-assertScreenshot name record pane =- runTmux (screenshot name record pane) >>= check+ TestT m ()+assertScreenshot name record pane = do+ lift (runTmux (screenshot name record pane)) >>= check where check (Just (current, existing)) =- gassertEqual existing current+ existing === current check Nothing = return ()++awaitScreenshot ::+ MonadIO m =>+ MonadMask m =>+ MonadRibo m =>+ MonadBaseControl IO m =>+ MonadDeepError e TmuxError m =>+ Nvim m =>+ Text ->+ Bool ->+ 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
lib/Ribosome/Test/Tmux.hs view
@@ -1,170 +1,203 @@ 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)+import Chiasma.Test.Tmux (TmuxTestConf, withSystemTempDir) import qualified Chiasma.Test.Tmux as Chiasma (tmuxGuiSpec, tmuxSpec, tmuxSpec')-import Control.Monad.Trans.Except (runExceptT)+import Control.Exception.Lifted (bracket) import Data.DeepPrisms (DeepPrisms)-import Data.Default (Default(def))-import Data.Functor (void)-import qualified Neovim.Context.Internal as Internal (Config, newConfig, retypeConfig)-import Neovim.RPC.Common (RPCConfig, SocketType(UnixSocket), createHandle, newRPCConfig)+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 UnliftIO (throwString)-import UnliftIO.Directory (doesPathExist)-import UnliftIO.Exception (bracket)-import UnliftIO.Temporary (withTempDirectory) import Ribosome.Config.Setting (updateSetting) import Ribosome.Config.Settings (tmuxSocket) import Ribosome.Control.Concurrent.Wait (waitIOPredDef)-import Ribosome.Control.Monad.Ribo (Ribo)+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.Test.Embed (Runner, TestConfig(..), runTest, startHandlers)+import Ribosome.System.Time (sleep)+import Ribosome.Test.Embed (+ Runner,+ TestConfig(..),+ inTestT,+ runPlugin,+ runTest,+ startHandlers,+ testNvimProcessConfig,+ withProcessTerm,+ ) import Ribosome.Test.Orphans ()-import Ribosome.Test.Unit (tempDir, uSpec)--startSocketHandlers :: FilePath -> TestConfig -> Internal.Config RPCConfig -> IO (IO ())-startSocketHandlers socket testConfig nvimConf = do- handle <- createHandle (UnixSocket socket)- startHandlers handle handle testConfig nvimConf+import Ribosome.Test.Run (UnitTest)+import Ribosome.Test.Unit (uSpec) -runTmuxNvim ::- (RpcHandler e env m, ReportError e) =>+runSocketNvimHs ::+ MonadIO m =>+ MonadFail m =>+ ReportError e =>+ RpcHandler e env n =>+ MonadBaseControl IO m => TestConfig -> env ->- m () ->- FilePath ->- IO ()-runTmuxNvim conf ribo specThunk socket = do- nvimConf <- Internal.newConfig (pure Nothing) newRPCConfig+ 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 (startSocketHandlers socket conf nvimConf) id (const $ runTest conf testCfg specThunk)+ 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 ::- (RpcHandler e env m, ReportError e) =>+ MonadIO m =>+ MonadFail m =>+ ReportError e =>+ RpcHandler e env n =>+ MonadBaseControl IO m => TmuxNative -> FilePath -> TestConfig -> env ->- m () ->- IO ()-runGui api temp conf ribo specThunk = do- void $ runExceptT @TmuxError $ runTmux api $ sendKeys (PaneId 0) [toString $ externalNvimCmdline socket]- _ <- waitIOPredDef (pure socket) doesPathExist- runTmuxNvim conf ribo specThunk socket- where- socket = temp </> "nvim-socket"+ n a ->+ m a+runGui api temp conf ribo specThunk =+ runSocketNvimHs conf ribo specThunk =<< liftIO (startNvimInTmux api temp) unsafeGuiSpec ::- (RpcHandler e env m, ReportError e) =>+ MonadIO m =>+ MonadFail m =>+ ReportError e =>+ RpcHandler e env n =>+ MonadBaseControl IO m => TmuxNative -> FilePath ->- Runner m ->+ Runner n -> TestConfig -> env ->- m () ->- IO ()+ n a ->+ m a unsafeGuiSpec api temp runner conf s specThunk = runGui api temp conf s $ runner conf specThunk unsafeGuiSpecR ::- (RpcHandler e (Ribosome env) m, ReportError e) =>+ MonadIO m =>+ MonadFail m =>+ ReportError e =>+ MonadBaseControl IO m =>+ RpcHandler e (Ribosome env) n => TmuxNative -> FilePath ->- Runner m ->+ Runner n -> TestConfig -> env ->- m () ->- IO ()+ 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 ::- DeepPrisms e RpcError =>+ MonadIO m =>+ MonadFail m => ReportError e =>+ MonadBaseControl IO m =>+ DeepPrisms e RpcError => TestConfig -> TmuxNative -> s ->- Ribo s e () ->- IO ()+ Ribo s e a ->+ m a guiSpec conf api env specThunk = do- socketDir <- tempDir "tmux-socket"- withTempDirectory socketDir "spec" run+ withSystemTempDir run where run tempdir = unsafeGuiSpecR api tempdir uSpec conf env specThunk withTmux :: DeepPrisms e RpcError =>- Ribo s e () ->+ Ribo s e a -> TmuxNative ->- Ribo s e ()+ Ribo s e a withTmux thunk (TmuxNative (Just socket)) = updateSetting tmuxSocket socket *> thunk withTmux _ _ =- throwString "no socket in test tmux"+ throwText "no socket in test tmux" tmuxSpec ::- Show s => DeepPrisms e RpcError => ReportError e =>- Default s => TestConfig -> s ->- Ribo s e () ->- IO ()+ TestT (Ribo s e) () ->+ UnitTest tmuxSpec conf env specThunk =- Chiasma.tmuxSpec run- where- run api = guiSpec conf api env (withTmux specThunk api)+ inTestT specThunk \ th ->+ Chiasma.tmuxSpec \ api -> guiSpec conf api env (withTmux th api) tmuxSpec' ::- Show s => DeepPrisms e RpcError => ReportError e =>- Default s => TmuxTestConf -> TestConfig -> s ->- Ribo s e () ->- IO ()+ TestT (Ribo s e) () ->+ UnitTest tmuxSpec' tmuxConf conf env specThunk =- Chiasma.tmuxSpec' tmuxConf run- where- run api = guiSpec conf api env (withTmux specThunk api)+ inTestT specThunk \ th ->+ Chiasma.tmuxSpec' tmuxConf \ api ->+ guiSpec conf api env (withTmux th api) tmuxSpecDef ::- Show s => DeepPrisms e RpcError => ReportError e => Default s =>- Ribo s e () ->- IO ()+ TestT (Ribo s e) () ->+ UnitTest tmuxSpecDef = tmuxSpec def def tmuxGuiSpec :: DeepPrisms e RpcError => ReportError e =>- Default s => TestConfig -> s -> Ribo s e () ->- IO ()+ UnitTest tmuxGuiSpec conf env specThunk = Chiasma.tmuxGuiSpec run where@@ -175,6 +208,64 @@ ReportError e => Default s => Ribo s e () ->- IO ()+ 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/Ui.hs view
@@ -1,9 +1,6 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}- module Ribosome.Test.Ui where -import Test.Framework-+import Hedgehog (TestT, (===)) import Ribosome.Api.Window (currentCursor, cursor) import Ribosome.Control.Monad.Ribo (NvimE) import Ribosome.Nvim.Api.Data (Window)@@ -11,28 +8,25 @@ windowCountIs :: NvimE e m =>- AssertM m => Int ->- m ()+ TestT m () windowCountIs count = do wins <- nvimListWins- gassertEqual count (length wins)+ count === (length wins) cursorIs :: NvimE e m =>- AssertM m => Int -> Int -> Window ->- m ()+ TestT m () cursorIs line col =- gassertEqual (line, col) <=< cursor+ ((line, col) ===) <=< lift . cursor currentCursorIs :: NvimE e m =>- AssertM m => Int -> Int ->- m ()+ TestT m () currentCursorIs line col =- gassertEqual (line, col) =<< currentCursor+ ((line, col) ===) =<< lift currentCursor
lib/Ribosome/Test/Unit.hs view
@@ -1,9 +1,11 @@ module Ribosome.Test.Unit where -import Control.Monad.IO.Class (MonadIO)-import Data.Default (def)+import Control.Exception.Lifted (bracket_)+import Hedgehog (TestT)+import Hedgehog.Internal.Property (mkTestT, runTestT) import System.FilePath (takeDirectory, takeFileName, (</>))-import System.Log.Logger (Priority(DEBUG), setLevel, updateGlobalLogger)+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)@@ -14,7 +16,7 @@ import Ribosome.Test.Orphans () uPrefix :: Text-uPrefix = "u"+uPrefix = "test" uSpec :: (MonadIO m, NvimE e m) => Runner m uSpec conf spec = do@@ -22,26 +24,44 @@ spec unitSpec ::- (RpcHandler e (Ribosome env) m, ReportError e, MonadIO m, NvimE e' m) =>+ MonadIO n =>+ MonadIO m =>+ NvimE e' n =>+ MonadFail m =>+ ReportError e =>+ MonadBaseControl IO m =>+ RpcHandler e (Ribosome env) n => TestConfig -> env ->- m () ->- IO ()-unitSpec =- unsafeEmbeddedSpecR uSpec+ TestT n a ->+ TestT m a+unitSpec cfg env t = do+ mkTestT (unsafeEmbeddedSpecR uSpec cfg env (runTestT t)) unitSpecDef ::- (RpcHandler e (Ribosome env) m, ReportError e, MonadIO m, NvimE e' m) =>+ MonadIO n =>+ MonadIO m =>+ NvimE e' n =>+ MonadFail m =>+ ReportError e =>+ MonadBaseControl IO m =>+ RpcHandler e (Ribosome env) n => env ->- m () ->- IO ()+ TestT n a ->+ TestT m a unitSpecDef = unitSpec def unitSpecDef' ::- (RpcHandler e (Ribosome ()) m, ReportError e, MonadIO m, NvimE e' m) =>- m () ->- IO ()+ 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 () @@ -61,15 +81,19 @@ withLogAs :: MonadIO m =>+ MonadBaseControl IO m => Text -> m a -> m a-withLogAs name thunk = do- liftIO $ updateGlobalLogger (toString name) (setLevel DEBUG)- thunk+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 =
+ readme.md view
@@ -0,0 +1,91 @@+# 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,75 +1,281 @@-cabal-version: 1.12-name: ribosome-test-version: 0.3.0.1-license: OtherLicense-license-file: LICENSE-copyright: 2019 Torsten Schmits-maintainer: tek@tryp.io-author: Torsten Schmits-homepage: https://github.com/tek/ribosome-hs#readme-bug-reports: https://github.com/tek/ribosome-hs/issues-synopsis: test helpers for ribosome-description:- Please see the README on GitHub at <https://github.com/tek/ribosome-hs>-category: Neovim-build-type: Simple+cabal-version: 2.2 +-- This file has been generated from package.yaml by hpack version 0.34.4.+--+-- 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>+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+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-hs+ type: git+ location: https://github.com/tek/ribosome library- exposed-modules:- Ribosome.Test.Await- Ribosome.Test.Embed- Ribosome.Test.Exists- Ribosome.Test.File- Ribosome.Test.Functional- Ribosome.Test.Input- Ribosome.Test.Orphans- Ribosome.Test.Screenshot- Ribosome.Test.Tmux- Ribosome.Test.Ui- Ribosome.Test.Unit- hs-source-dirs: lib- other-modules:- Prelude- default-language: Haskell2010- default-extensions: AutoDeriveTypeable BangPatterns BinaryLiterals- ConstraintKinds DataKinds DefaultSignatures DeriveDataTypeable- DeriveFoldable DeriveFunctor DeriveGeneric DeriveTraversable- DoAndIfThenElse EmptyDataDecls ExistentialQuantification- FlexibleContexts FlexibleInstances FunctionalDependencies GADTs- GeneralizedNewtypeDeriving InstanceSigs KindSignatures LambdaCase- MonadFailDesugaring MultiParamTypeClasses MultiWayIf NamedFieldPuns- OverloadedStrings PartialTypeSignatures PatternGuards PolyKinds- RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving- TupleSections TypeApplications TypeFamilies TypeSynonymInstances- UnicodeSyntax ViewPatterns- build-depends:- HTF >=0.13.2.5 && <0.14,- base-noprelude >=4.7 && <5,- bytestring >=0.10.8.2 && <0.11,- chiasma >=0.1.0.0 && <0.2,- cornea >=0.2.2.0 && <0.3,- data-default >=0.7.1.1 && <0.8,- directory >=1.3.1.5 && <1.4,- exceptions >=0.10.0 && <0.11,- filepath >=1.4.2 && <1.5,- free >=5.0.2 && <5.1,- hslogger >=1.2.12 && <1.3,- lifted-base >=0.2.3.12 && <0.3,- messagepack >=0.5.4 && <0.6,- monad-control >=1.0.2.3 && <1.1,- mtl >=2.2.2 && <2.3,- nvim-hs >=2.1.0.0 && <2.2,- process >=1.6.3.0 && <1.7,- relude >=0.1.1 && <0.2,- resourcet >=1.2.2 && <1.3,- ribosome >=0.3.0.1 && <0.4,- text >=1.2.3.1 && <1.3,- transformers >=0.5.5.0 && <0.6,- typed-process >=0.2.3.0 && <0.3,- unix >=2.7.2.2 && <2.8,- unliftio >=0.2.9.0 && <0.3,- unliftio-core >=0.1.2.0 && <0.2+ exposed-modules:+ Ribosome.Test.Await+ Ribosome.Test.Embed+ Ribosome.Test.Exists+ Ribosome.Test.File+ Ribosome.Test.Functional+ Ribosome.Test.Input+ Ribosome.Test.Orphans+ Ribosome.Test.Run+ Ribosome.Test.Screenshot+ Ribosome.Test.Tmux+ Ribosome.Test.Ui+ Ribosome.Test.Unit+ other-modules:+ Paths_ribosome_test+ autogen-modules:+ Paths_ribosome_test+ hs-source-dirs:+ lib+ default-extensions:+ AllowAmbiguousTypes+ ApplicativeDo+ BangPatterns+ BinaryLiterals+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveLift+ DeriveTraversable+ DerivingStrategies+ DisambiguateRecordFields+ DoAndIfThenElse+ DuplicateRecordFields+ EmptyDataDecls+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ InstanceSigs+ KindSignatures+ LambdaCase+ LiberalTypeSynonyms+ MultiParamTypeClasses+ MultiWayIf+ NamedFieldPuns+ OverloadedStrings+ OverloadedLists+ PackageImports+ PartialTypeSignatures+ PatternGuards+ PatternSynonyms+ PolyKinds+ QuantifiedConstraints+ QuasiQuotes+ RankNTypes+ RecordWildCards+ RecursiveDo+ ScopedTypeVariables+ StandaloneDeriving+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeFamilyDependencies+ TypeOperators+ TypeSynonymInstances+ UndecidableInstances+ UnicodeSyntax+ ViewPatterns+ ghc-options: -Wall -Wredundant-constraints -Wsimplifiable-class-constraints+ 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+ , ribosome+ , tasty+ , tasty-hedgehog+ , template-haskell+ , text+ , transformers+ , typed-process+ , unix+ , unliftio+ mixins:+ base hiding (Prelude)+ , ribosome hiding (Ribosome.Prelude)+ , ribosome (Ribosome.Prelude as Prelude)+ default-language: Haskell2010++test-suite ribosome-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.SyntaxTest+ Ribosome.Test.THTest+ Ribosome.Test.WatcherTest+ Ribosome.Test.WindowTest+ TestError+ Paths_ribosome_test+ hs-source-dirs:+ test+ default-extensions:+ AllowAmbiguousTypes+ ApplicativeDo+ BangPatterns+ BinaryLiterals+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveLift+ DeriveTraversable+ DerivingStrategies+ DisambiguateRecordFields+ DoAndIfThenElse+ DuplicateRecordFields+ EmptyDataDecls+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ InstanceSigs+ KindSignatures+ LambdaCase+ LiberalTypeSynonyms+ MultiParamTypeClasses+ MultiWayIf+ NamedFieldPuns+ OverloadedStrings+ OverloadedLists+ PackageImports+ PartialTypeSignatures+ PatternGuards+ PatternSynonyms+ PolyKinds+ QuantifiedConstraints+ QuasiQuotes+ RankNTypes+ RecordWildCards+ RecursiveDo+ ScopedTypeVariables+ StandaloneDeriving+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeFamilyDependencies+ TypeOperators+ TypeSynonymInstances+ UndecidableInstances+ UnicodeSyntax+ ViewPatterns+ ghc-options: -Wall -Wredundant-constraints -Wsimplifiable-class-constraints -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+ , ribosome+ , 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)+ default-language: Haskell2010
+ test/Main.hs view
@@ -0,0 +1,42 @@+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 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+ ]++main :: IO ()+main =+ defaultMain tests
+ test/Ribosome/Test/AutocmdTest.hs view
@@ -0,0 +1,49 @@+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/MappingTest.hs view
@@ -0,0 +1,71 @@+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 view
@@ -0,0 +1,324 @@+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 view
@@ -0,0 +1,170 @@+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 view
@@ -0,0 +1,164 @@+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 view
@@ -0,0 +1,39 @@+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/RpcTest.hs view
@@ -0,0 +1,154 @@+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 view
@@ -0,0 +1,95 @@+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 view
@@ -0,0 +1,51 @@+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/SyntaxTest.hs view
@@ -0,0 +1,48 @@+module Ribosome.Test.SyntaxTest where++import TestError (TestError)+import Hedgehog (TestT)+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Test.Tmux (TmuxTestConf(..))++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.Test.Screenshot (awaitScreenshot)+import Ribosome.Test.Tmux (tmuxSpec')++data SyntaxSpecError =+ Test TestError+ |+ Tmux TmuxError++deepPrisms ''SyntaxSpecError++instance ReportError SyntaxSpecError where+ errorReport _ =+ undefined++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++test_syntax :: UnitTest+test_syntax =+ tmuxSpec' def { ttcWidth = 300, ttcHeight = 51, ttcGui = False } (defaultTestConfig "syntax") def syntaxSpec
+ test/Ribosome/Test/THTest.hs view
@@ -0,0 +1,45 @@+{-# 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 view
@@ -0,0 +1,46 @@+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 view
@@ -0,0 +1,43 @@+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/TestError.hs view
@@ -0,0 +1,28 @@+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