diff --git a/.coveragerc b/.coveragerc index 7d8d594b7a..9ed88302e9 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,6 +1,6 @@ [run] omit = - */testsuite/* + test/* */_vendor/* */_* pkg/* diff --git a/.gitignore b/.gitignore index 24a7737f57..14eb1cb9ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ *.pyc *.pyo -.venv -.venv3 +*env*/ +.cache/ +.eggs/ dist *.egg *.egg-info diff --git a/.travis.yml b/.travis.yml index 57347c2828..0e45b1e1ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,8 @@ env: - TMUX_VERSION=1.9a before_install: - export PIP_USE_MIRRORS=true + - pip install --upgrade pytest # https://github.com/travis-ci/travis-ci/issues/4873 + - pip install --upgrade pip wheel virtualenv setuptools - pip install coveralls install: - pip install -e . diff --git a/MANIFEST.in b/MANIFEST.in index 516b4e5b2a..5d9592a584 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,3 @@ -include README.rst LICENSE CHANGES run-tests.py .tmuxp.yaml +include README.rst LICENSE CHANGES .tmuxp.yaml include requirements.pip package_metadata.py recursive-include doc *.rst diff --git a/Makefile b/Makefile index cbd207dad7..95687fb687 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ test: - ./run-tests.py + py.test watch_test: if command -v entr > /dev/null; then find . -type f -not -path '*/\.*' | grep -i '.*[.]py' | entr -c make test; else make test; echo "\nInstall entr(1) to automatically run tests on file change.\n See http://entrproject.org/"; fi @@ -17,7 +17,7 @@ watch_docs: cd doc && $(MAKE) watch_docs flake8: - flake8 tmuxp + flake8 tmuxp tests watch_flake8: if command -v entr > /dev/null; then find . -type f -not -path '*/\.*' | grep -i '.*[.][py]' | entr -c make flake8; else make flake8; echo "\nInstall entr(1) to automatically run tests on file change.\n See http://entrproject.org/"; fi diff --git a/README.rst b/README.rst index 7ba7145d09..d5f5494cbf 100644 --- a/README.rst +++ b/README.rst @@ -105,7 +105,7 @@ install dev .. code-block:: bash more. tests .. code-block:: bash - $ python ./run-tests.py + $ make test ============== ========================================================== .. _BSD: http://opensource.org/licenses/BSD-3-Clause diff --git a/doc/about.rst b/doc/about.rst index be918c17c1..caf7d8f295 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -105,7 +105,6 @@ More details .. _attempt at 1.7 test: https://travis-ci.org/tony/tmuxp/jobs/12348263 .. _kaptan: https://github.com/emre/kaptan -.. _unittest: http://docs.python.org/2/library/unittest.html .. _BSD-licensed: http://opensource.org/licenses/BSD-2-Clause .. _tmuxinator: https://github.com/aziz/tmuxinator .. _teamocil: https://github.com/remiprev/teamocil diff --git a/doc/developing.rst b/doc/developing.rst index 10e2285621..5006ba7cea 100644 --- a/doc/developing.rst +++ b/doc/developing.rst @@ -9,12 +9,14 @@ Developing and Testing .. todo:: link to sliderepl or ipython notebook slides -Our tests are inside ``./tmuxp/testsuite``. Tests are implemented using -:py:mod:`unittest`. +Our tests are inside ``tests/``. Tests are implemented using +`pytest`_. -``./run-tests.py`` will create a tmux server on a separate ``socket_name`` +``make test`` will create a tmux server on a separate ``socket_name`` using ``$ tmux -L test_case``. +.. _pytest: http://pytest.org/ + .. _install_dev_env: Install the latest code from git @@ -64,7 +66,7 @@ folder with its own packages. .. code-block:: bash - $ ./run-tests.py + $ make test You probably didn't see anything but tests scroll by. @@ -76,35 +78,32 @@ If you found a problem or are trying to write a test, you can file an Test runner options ~~~~~~~~~~~~~~~~~~~ -.. note:: - - As of v0.1.1, the old way of using ``--tests`` is now deprecated. - Testing specific TestSuites and TestCase. .. code-block:: bash - $ ./run-tests.py config + $ py.test tests/test_config.py -will test the ``testsuite.config`` :py:class:`unittest.TestSuite`. +will test the ``tests/test_config.py`` tests. .. code-block:: bash - $ ./run-tests.py config.ImportExportTest + $ py.test tests/test_config::ImportExportTest -tests ``testsuite.config.ImportExportTest`` :py:class:`unittest.TestCase`. +tests ``ImportExportTest`` :py:class:`unittest.TestCase` inside of +``tests/test_config.py``. individual tests: .. code-block:: bash - $ ./run-tests.py config.ImportExportTest.test_export_json + $ py.test tests/test_config::ImportExportTest::test_export_Json Multiple can be separated by spaces: .. code-block:: bash - $ ./run-tests.py window pane config.ImportExportTest + $ py.test tests/test_{window,pane}.py tests/test_config.py::ImportExportTest::test_export_json .. _test_builder_visually: @@ -123,7 +122,7 @@ Create two terminals: .. code-block:: bash - $ python ./run-tests.py --tests tests_workspacebuilder + $ py.test tests/test_workspacebuilder.py Terminal 1 should have flickered and built the session before your eyes. tmuxp hides this building from normal users. @@ -143,7 +142,7 @@ To run all tests upon editing any ``.py`` file: .. code-block:: bash - $ find . -type f -not -path '*/\.*' | grep -i '.*[.]py$' | entr -c ./run-tests.py + $ make watch_test .. _entr: http://entrproject.org/ @@ -152,7 +151,7 @@ Rebuild the documentation when an ``.rst`` file is edited: .. code-block:: bash $ cd doc - $ find .. -print | grep -i '.*[.]rst' | entr -c make html + $ make watch .. _tmuxp developer config: diff --git a/requirements/test.txt b/requirements/test.txt new file mode 100644 index 0000000000..91ff012602 --- /dev/null +++ b/requirements/test.txt @@ -0,0 +1,2 @@ +flaky==3.1.1 +pytest==2.9.1 diff --git a/run-tests.py b/run-tests.py deleted file mode 100755 index 6284fd95da..0000000000 --- a/run-tests.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from tmuxp.testsuite import main - -main() diff --git a/setup.py b/setup.py index 5ae6b6d93a..38a2a8cc49 100644 --- a/setup.py +++ b/setup.py @@ -9,6 +9,7 @@ import sys from setuptools import setup +from setuptools.command.test import test as TestCommand about = {} with open("tmuxp/__about__.py") as fp: @@ -16,11 +17,12 @@ with open('requirements/base.txt') as f: install_reqs = [line for line in f.read().split('\n') if line] - tests_reqs = [] + +with open('requirements/test.txt') as f: + tests_reqs = [line for line in f.read().split('\n') if line] if sys.version_info < (2, 7): install_reqs += ['argparse'] - tests_reqs += ['unittest2'] if sys.version_info[0] > 2: readme = open('README.rst', encoding='utf-8').read() @@ -29,6 +31,20 @@ history = open('CHANGES').read().replace('.. :changelog:', '') + +class PyTest(TestCommand): + user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")] + + def initialize_options(self): + TestCommand.initialize_options(self) + self.pytest_args = [] + + def run_tests(self): + import pytest + errno = pytest.main(self.pytest_args) + sys.exit(errno) + + setup( name=about['__title__'], version=about['__version__'], @@ -39,11 +55,11 @@ author_email=about['__email__'], description=about['__description__'], long_description=readme, - packages=['tmuxp', 'tmuxp.testsuite'], + packages=['tmuxp'], include_package_data=True, install_requires=install_reqs, tests_require=tests_reqs, - test_suite='tmuxp.testsuite', + cmdclass={'test': PyTest}, zip_safe=False, keywords=about['__title__'], scripts=['pkg/tmuxp.bash', 'pkg/tmuxp.zsh', 'pkg/tmuxp.tcsh'], diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000..b0196279c5 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +"""Tests for tmuxp. + +tmuxp.tests +~~~~~~~~~~~ + +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000000..f7d3977888 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +import pytest + +import logging +from tmuxp import exc +from tmuxp.server import Server + +from .helpers import get_test_session_name, TEST_SESSION_PREFIX, namer + +logger = logging.getLogger(__name__) + + +@pytest.fixture(scope='function') +def server(): + t = Server() + t.socket_name = 'tmuxp_test%s' % next(namer) + + return t + + +@pytest.fixture(scope='function') +def session(request, server): + session_name = 'tmuxp' + + if not server.has_session(session_name): + server.cmd('new-session', '-d', '-s', session_name) + + # find current sessions prefixed with tmuxp + old_test_sessions = [ + s.get('session_name') for s in server._sessions + if s.get('session_name').startswith(TEST_SESSION_PREFIX) + ] + + TEST_SESSION_NAME = get_test_session_name(server=server) + + try: + session = server.new_session( + session_name=TEST_SESSION_NAME, + ) + except exc.TmuxpException as e: + raise e + + """ + Make sure that tmuxp can :ref:`test_builder_visually` and switches to + the newly created session for that testcase. + """ + try: + server.switch_client(session.get('session_id')) + pass + except exc.TmuxpException as e: + # server.attach_session(session.get('session_id')) + pass + + for old_test_session in old_test_sessions: + logger.debug( + 'Old test test session %s found. Killing it.' % + old_test_session + ) + server.kill_session(old_test_session) + assert TEST_SESSION_NAME == session.get('session_name') + assert TEST_SESSION_NAME != 'tmuxp' + + def fin(): + server.kill_server() + request.addfinalizer(fin) + + return session + + +@pytest.fixture() +def tmpdir(tmpdir_factory): + fn = tmpdir_factory.mktemp('tmuxp') + return fn diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py new file mode 100644 index 0000000000..3e227e3c07 --- /dev/null +++ b/tests/fixtures/__init__.py @@ -0,0 +1 @@ +from . import _util # noqa diff --git a/tests/fixtures/_util.py b/tests/fixtures/_util.py new file mode 100644 index 0000000000..67d2d05e22 --- /dev/null +++ b/tests/fixtures/_util.py @@ -0,0 +1,9 @@ +import os + + +def curjoin(_file): # return filepath relative to __file__ (this file) + return os.path.join(os.path.dirname(__file__), _file) + + +def loadfixture(_file): # return fixture data, relative to __file__ + return open(curjoin(_file)).read() diff --git a/tests/fixtures/config/__init__.py b/tests/fixtures/config/__init__.py new file mode 100644 index 0000000000..2c908611bf --- /dev/null +++ b/tests/fixtures/config/__init__.py @@ -0,0 +1,2 @@ +from . import (expand1, expand2, expand_blank, sampleconfig, # noqa + shell_command_before, shell_command_before_session, trickle) diff --git a/tests/fixtures/config/expand1.py b/tests/fixtures/config/expand1.py new file mode 100644 index 0000000000..bd90ce4547 --- /dev/null +++ b/tests/fixtures/config/expand1.py @@ -0,0 +1,135 @@ +import os + +before_config = { + 'session_name': 'sampleconfig', + 'start_directory': '~', + 'windows': [ + { + 'window_name': 'editor', + 'panes': [ + { + 'shell_command': [ + 'vim', + 'top' + ] + }, + { + 'shell_command': ['vim'], + }, + { + 'shell_command': 'cowsay "hey"' + } + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + } + ] + }, + { + 'start_directory': '/var/log', + 'options': {'automatic_rename': True, }, + 'panes': [ + { + 'shell_command': 'htop' + }, + 'vim', + ] + }, + { + 'start_directory': './', + 'panes': [ + 'pwd' + ] + }, + { + 'start_directory': './asdf/', + 'panes': [ + 'pwd' + ] + }, + { + 'start_directory': '../', + 'panes': [ + 'pwd' + ] + }, + { + 'panes': [ + 'top' + ] + } + ] +} + +after_config = { + 'session_name': 'sampleconfig', + 'start_directory': os.path.expanduser('~'), + 'windows': [ + { + 'window_name': 'editor', + 'panes': [ + { + 'shell_command': ['vim', 'top'], + }, + { + 'shell_command': ['vim'], + }, + { + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + } + ] + }, + { + 'start_directory': '/var/log', + 'options': {'automatic_rename': True}, + 'panes': [ + {'shell_command': ['htop']}, + {'shell_command': ['vim']} + ] + }, + { + 'start_directory': os.path.normpath( + os.path.join(os.path.expanduser('~'), './') + ), + 'panes': [ + {'shell_command': ['pwd']} + ] + }, + { + 'start_directory': os.path.normpath( + os.path.join(os.path.expanduser('~'), './asdf') + ), + 'panes': [ + {'shell_command': ['pwd']} + ] + }, + { + 'start_directory': os.path.normpath( + os.path.join(os.path.expanduser('~'), '../') + ), + 'panes': [ + {'shell_command': ['pwd']} + ] + }, + + { + 'panes': [ + {'shell_command': ['top']} + ] + } + ] +} diff --git a/tests/fixtures/config/expand2-expanded.yaml b/tests/fixtures/config/expand2-expanded.yaml new file mode 100644 index 0000000000..0fe5bbd3d9 --- /dev/null +++ b/tests/fixtures/config/expand2-expanded.yaml @@ -0,0 +1,32 @@ +session_name: sampleconfig +start_directory: {HOME} +windows: +- window_name: focused window + layout: main-horizontal + focus: true + panes: + - shell_command: + - cd ~ + - shell_command: + - cd /usr + focus: true + - shell_command: + - cd ~ + - echo "moo" + - top +- window_name: window 2 + panes: + - shell_command: + - top + focus: true + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: window 3 + panes: + - shell_command: + - cd / + focus: true + - shell_command: [] + - shell_command: [] diff --git a/tests/fixtures/config/expand2-unexpanded.yaml b/tests/fixtures/config/expand2-unexpanded.yaml new file mode 100644 index 0000000000..6e70f42f89 --- /dev/null +++ b/tests/fixtures/config/expand2-unexpanded.yaml @@ -0,0 +1,32 @@ +session_name: sampleconfig +start_directory: '~' +windows: +- window_name: focused window + layout: main-horizontal + focus: true + panes: + - shell_command: + - cd ~ + - shell_command: + - cd /usr + focus: true + - shell_command: + - cd ~ + - echo "moo" + - top +- window_name: window 2 + panes: + - shell_command: + - top + focus: true + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: window 3 + panes: + - shell_command: cd / + focus: true + - pane + - pane + diff --git a/tests/fixtures/config/expand2.py b/tests/fixtures/config/expand2.py new file mode 100644 index 0000000000..502ed04248 --- /dev/null +++ b/tests/fixtures/config/expand2.py @@ -0,0 +1,8 @@ +import os + +from .._util import loadfixture + +unexpanded_yaml = loadfixture('config/expand2-unexpanded.yaml') +expanded_yaml = loadfixture('config/expand2-expanded.yaml').format( + HOME=os.path.expanduser('~') +) diff --git a/tests/fixtures/config/expand_blank.py b/tests/fixtures/config/expand_blank.py new file mode 100644 index 0000000000..b1a62ee5cb --- /dev/null +++ b/tests/fixtures/config/expand_blank.py @@ -0,0 +1,66 @@ +expected = { + 'session_name': 'Blank pane test', + 'windows': [ + { + 'window_name': 'Blank pane test', + 'panes': [ + { + 'shell_command': [], + }, + { + 'shell_command': [], + }, + { + 'shell_command': [], + } + ] + }, + { + 'window_name': 'More blank panes', + 'panes': [ + { + 'shell_command': [], + }, + { + 'shell_command': [], + }, + { + 'shell_command': [], + } + ] + }, + { + 'window_name': 'Empty string (return)', + 'panes': [ + { + 'shell_command': [ + '' + ], + }, + { + 'shell_command': [ + '' + ], + }, + { + 'shell_command': [ + '' + ], + } + ] + }, + { + 'window_name': 'Blank with options', + 'panes': [ + { + 'shell_command': [], + 'focus': True, + }, + { + 'shell_command': [], + 'start_directory': '/tmp', + } + ] + } + ] +} diff --git a/tests/fixtures/config/sampleconfig.py b/tests/fixtures/config/sampleconfig.py new file mode 100644 index 0000000000..13ac219466 --- /dev/null +++ b/tests/fixtures/config/sampleconfig.py @@ -0,0 +1,33 @@ +sampleconfigdict = { + 'session_name': 'sampleconfig', + 'start_directory': '~', + 'windows': [ + { + 'window_name': 'editor', + 'panes': [ + { + 'start_directory': '~', + 'shell_command': ['vim'], + }, { + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'panes': [{ + 'shell_command': ['tail -F /var/log/syslog'], + 'start_directory':'/var/log' + }] + }, + { + 'options': { + 'automatic_rename': True, + }, + 'panes': [ + {'shell_command': ['htop']} + ] + } + ] +} diff --git a/tests/fixtures/config/shell_command_before.py b/tests/fixtures/config/shell_command_before.py new file mode 100644 index 0000000000..f4d9107799 --- /dev/null +++ b/tests/fixtures/config/shell_command_before.py @@ -0,0 +1,174 @@ +import os + +config_unexpanded = { # shell_command_before is string in some areas + 'session_name': 'sampleconfig', + 'start_directory': '/', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': '~', + 'shell_command_before': 'source .venv/bin/activate', + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'shell_command_before': 'rbenv local 2.0.0-p0', + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + }, + { + } + ] + }, + { + 'window_name': 'shufu', + 'panes': [ + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'shell_command': ['htop'], + } + ] + }, + { + 'options': {'automatic_rename': True, }, + 'panes': [ + {'shell_command': ['htop']} + ] + }, + { + 'panes': ['top'] + } + ] +} + +config_expanded = { # shell_command_before is string in some areas + 'session_name': 'sampleconfig', + 'start_directory': '/', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': os.path.expanduser('~'), + 'shell_command_before': ['source .venv/bin/activate'], + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + }, + { + 'shell_command': [] + } + ] + }, + { + 'window_name': 'shufu', + 'panes': [ + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'shell_command': ['htop'], + } + ] + }, + { + 'options': {'automatic_rename': True, }, + 'panes': [ + {'shell_command': ['htop']} + ] + }, + { + 'panes': [{ + 'shell_command': ['top'] + }] + }, + ] +} + +config_after = { # shell_command_before is string in some areas + 'session_name': 'sampleconfig', + 'start_directory': '/', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': os.path.expanduser('~'), + 'shell_command_before': ['source .venv/bin/activate'], + 'panes': [ + { + 'shell_command': ['source .venv/bin/activate', 'vim'], + }, + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'shell_command': [ + 'source .venv/bin/activate', + 'rbenv local 2.0.0-p0', 'cowsay "hey"' + ] + }, + ], + 'layout': 'main-verticle' + }, + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'start_directory': '/', + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': [ + 'rbenv local 2.0.0-p0', + 'tail -F /var/log/syslog' + ], + }, + { + 'shell_command': ['rbenv local 2.0.0-p0'] + } + ] + }, + { + 'start_directory': '/', + 'window_name': 'shufu', + 'panes': [ + { + 'shell_command_before': ['rbenv local 2.0.0-p0'], + 'shell_command': ['rbenv local 2.0.0-p0', 'htop'], + } + ] + }, + { + 'start_directory': '/', + 'options': {'automatic_rename': True, }, + 'panes': [ + { + 'shell_command': ['htop'] + } + ] + }, + { + 'start_directory': '/', + 'panes': [ + { + 'shell_command': ['top'] + } + ] + } + ] +} diff --git a/tests/fixtures/config/shell_command_before_session-expected.yaml b/tests/fixtures/config/shell_command_before_session-expected.yaml new file mode 100644 index 0000000000..4e1e3eb49a --- /dev/null +++ b/tests/fixtures/config/shell_command_before_session-expected.yaml @@ -0,0 +1,23 @@ +shell_command_before: + - 'echo "hi"' +session_name: 'test' +windows: +- window_name: editor + panes: + - shell_command: + - 'echo "hi"' + - vim + - :Ex + - shell_command: + - 'echo "hi"' + - shell_command: + - 'echo "hi"' + - cd /usr +- window_name: logging + panes: + - shell_command: + - 'echo "hi"' + - shell_command: + - 'echo "hi"' + - top + - emacs diff --git a/tests/fixtures/config/shell_command_before_session.py b/tests/fixtures/config/shell_command_before_session.py new file mode 100644 index 0000000000..ef1e89e60c --- /dev/null +++ b/tests/fixtures/config/shell_command_before_session.py @@ -0,0 +1,4 @@ +from .._util import loadfixture + +before = loadfixture("config/shell_command_before_session.yaml") +expected = loadfixture("config/shell_command_before_session-expected.yaml") diff --git a/tests/fixtures/config/shell_command_before_session.yaml b/tests/fixtures/config/shell_command_before_session.yaml new file mode 100644 index 0000000000..09976f0ede --- /dev/null +++ b/tests/fixtures/config/shell_command_before_session.yaml @@ -0,0 +1,18 @@ +shell_command_before: + - 'echo "hi"' +session_name: 'test' +windows: +- window_name: editor + panes: + - shell_command: + - vim + - :Ex + - pane + - cd /usr +- window_name: logging + panes: + - shell_command: + - + - shell_command: + - top + - emacs diff --git a/tests/fixtures/config/trickle.py b/tests/fixtures/config/trickle.py new file mode 100644 index 0000000000..da67df5d1b --- /dev/null +++ b/tests/fixtures/config/trickle.py @@ -0,0 +1,65 @@ +before = { # shell_command_before is string in some areas + 'session_name': 'sampleconfig', + 'start_directory': '/var', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': 'log', + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'start_directory': '~', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + }, + { + 'shell_command': [] + } + ] + }, + ] +} + +expected = { # shell_command_before is string in some areas + 'session_name': 'sampleconfig', + 'start_directory': '/var', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': '/var/log', + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command': [ + 'cowsay "hey"' + ] + }, + ], + 'layout': 'main-verticle' + }, + { + 'start_directory': '~', + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + }, + { + 'shell_command': [] + } + ] + }, + ] +} diff --git a/tests/fixtures/config_teamocil/__init__.py b/tests/fixtures/config_teamocil/__init__.py new file mode 100644 index 0000000000..822441fa3e --- /dev/null +++ b/tests/fixtures/config_teamocil/__init__.py @@ -0,0 +1 @@ +from . import test1, test2, test3, test4, layouts # noqa diff --git a/tests/fixtures/config_teamocil/layouts.py b/tests/fixtures/config_teamocil/layouts.py new file mode 100644 index 0000000000..a40bcd3d7a --- /dev/null +++ b/tests/fixtures/config_teamocil/layouts.py @@ -0,0 +1,275 @@ +from .._util import loadfixture + +teamocil_yaml = loadfixture('config_teamocil/layouts.yaml') + +teamocil_dict = { + 'two-windows': { + 'windows': [ + { + 'name': 'foo', + 'clear': True, + 'root': '/foo', + 'layout': 'tiled', + 'panes': [ + { + 'cmd': "echo 'foo'" + }, + { + 'cmd': "echo 'foo again'" + } + ] + }, + { + 'name': 'bar', + 'root': '/bar', + 'splits': [ + { + 'cmd': [ + "echo 'bar'", + "echo 'bar in an array'" + ], + 'target': 'bottom-right' + }, + { + 'cmd': "echo 'bar again'", + 'focus': True, + 'width': 50 + } + ] + + } + ] + }, + + 'two-windows-with-filters': { + 'windows': [ + { + 'name': 'foo', + 'root': '/foo', + 'filters': + { + 'before': [ + 'echo first before filter', + 'echo second before filter' + ], + 'after': [ + 'echo first after filter', + 'echo second after filter', + ] + }, + 'panes': [ + { + 'cmd': "echo 'foo'" + }, + { + 'cmd': "echo 'foo again'", + 'width': 50 + } + ] + } + ] + }, + + 'two-windows-with-custom-command-options': { + 'windows': [ + { + 'name': 'foo', + 'cmd_separator': '\n', + 'with_env_var': False, + 'clear': True, + 'root': '/foo', + 'layout': 'tiled', + 'panes': [ + { + 'cmd': "echo 'foo'" + }, + { + 'cmd': "echo 'foo again'" + } + ] + }, { + 'name': 'bar', + 'cmd_separator': ' && ', + 'with_env_var': True, + 'root': '/bar', + 'splits': [ + { + 'cmd': [ + "echo 'bar'", + "echo 'bar in an array'" + ], + 'target': 'bottom-right' + }, + { + 'cmd': "echo 'bar again'", + 'focus': True, + 'width': 50 + } + ] + }] + }, + + 'three-windows-within-a-session': { + 'session': { + 'name': 'my awesome session', + 'windows': [ + { + 'name': 'first window', + 'panes': [ + { + 'cmd': "echo 'foo'" + } + ] + }, { + 'name': 'second window', + 'panes': [ + { + 'cmd': "echo 'foo'"} + ] + }, { + 'name': 'third window', + 'panes': [ + { + 'cmd': "echo 'foo'" + } + ] + } + ] + } + } +} + + +two_windows = \ + { + 'session_name': None, + 'windows': [ + { + 'window_name': 'foo', + 'start_directory': '/foo', + 'clear': True, + 'layout': 'tiled', + 'panes': [ + { + 'shell_command': "echo 'foo'" + }, + { + 'shell_command': "echo 'foo again'" + } + ] + }, + { + 'window_name': 'bar', + 'start_directory': '/bar', + 'panes': [ + { + 'shell_command': [ + "echo 'bar'", + "echo 'bar in an array'" + ], + 'target': 'bottom-right' + }, + { + 'shell_command': "echo 'bar again'", + 'focus': True, + } + ] + } + ] + } + +two_windows_with_filters = \ + { + 'session_name': None, + 'windows': [ + { + 'window_name': 'foo', + 'start_directory': '/foo', + 'shell_command_before': [ + 'echo first before filter', + 'echo second before filter', + ], + 'shell_command_after': [ + 'echo first after filter', + 'echo second after filter', + ], + 'panes': [ + { + 'shell_command': "echo 'foo'" + }, + { + 'shell_command': "echo 'foo again'", + } + ] + } + ] + } + +two_windows_with_custom_command_options = { + 'session_name': None, + 'windows': [ + { + 'window_name': 'foo', + 'start_directory': '/foo', + 'clear': True, + 'layout': 'tiled', + 'panes': [ + { + 'shell_command': "echo 'foo'", + }, + { + 'shell_command': "echo 'foo again'", + } + ] + }, + { + 'window_name': 'bar', + 'start_directory': '/bar', + 'panes': [ + { + 'shell_command': [ + "echo 'bar'", + "echo 'bar in an array'" + ], + 'target': 'bottom-right' + }, + { + 'shell_command': "echo 'bar again'", + 'focus': True, + } + ] + + } + ] + +} + +three_windows_within_a_session = { + 'session_name': 'my awesome session', + 'windows': [ + { + 'window_name': 'first window', + 'panes': [ + { + 'shell_command': "echo 'foo'" + }, + ] + }, + { + 'window_name': 'second window', + 'panes': [ + { + 'shell_command': "echo 'foo'" + }, + ] + }, + { + 'window_name': 'third window', + 'panes': [ + { + 'shell_command': "echo 'foo'" + }, + ] + }, + ] +} diff --git a/tests/fixtures/config_teamocil/layouts.yaml b/tests/fixtures/config_teamocil/layouts.yaml new file mode 100644 index 0000000000..46b3905460 --- /dev/null +++ b/tests/fixtures/config_teamocil/layouts.yaml @@ -0,0 +1,75 @@ +# Simple two windows layout +two-windows: + windows: + - name: "foo" + clear: true + root: "/foo" + layout: "tiled" + panes: + - cmd: "echo 'foo'" + - cmd: "echo 'foo again'" + - name: "bar" + root: "/bar" + splits: + - cmd: + - "echo 'bar'" + - "echo 'bar in an array'" + target: bottom-right + - cmd: "echo 'bar again'" + focus: true + width: 50 + +# Simple two windows layout with filters +two-windows-with-filters: + windows: + - name: "foo" + root: "/foo" + filters: + before: + - "echo first before filter" + - "echo second before filter" + after: + - "echo first after filter" + - "echo second after filter" + panes: + - cmd: "echo 'foo'" + - cmd: "echo 'foo again'" + width: 50 + +two-windows-with-custom-command-options: + windows: + - name: "foo" + cmd_separator: "\n" + with_env_var: false + clear: true + root: "/foo" + layout: "tiled" + panes: + - cmd: "echo 'foo'" + - cmd: "echo 'foo again'" + - name: "bar" + cmd_separator: " && " + with_env_var: true + root: "/bar" + splits: + - cmd: + - "echo 'bar'" + - "echo 'bar in an array'" + target: bottom-right + - cmd: "echo 'bar again'" + focus: true + width: 50 + +three-windows-within-a-session: + session: + name: "my awesome session" + windows: + - name: "first window" + panes: + - cmd: "echo 'foo'" + - name: "second window" + panes: + - cmd: "echo 'foo'" + - name: "third window" + panes: + - cmd: "echo 'foo'" diff --git a/tests/fixtures/config_teamocil/test1.py b/tests/fixtures/config_teamocil/test1.py new file mode 100644 index 0000000000..f504344217 --- /dev/null +++ b/tests/fixtures/config_teamocil/test1.py @@ -0,0 +1,43 @@ +from .._util import loadfixture + +teamocil_yaml = loadfixture('config_teamocil/test1.yaml') +teamocil_conf = { + 'windows': [{ + 'name': 'sample-two-panes', + 'root': '~/Code/sample/www', + 'layout': 'even-horizontal', + 'panes': [ + { + 'cmd': [ + 'pwd', + 'ls -la' + ] + }, + { + 'cmd': 'rails server --port 3000' + } + ] + }] +} + +expected = { + 'session_name': None, + 'windows': [ + { + 'window_name': 'sample-two-panes', + 'layout': 'even-horizontal', + 'start_directory': '~/Code/sample/www', + 'panes': [ + { + 'shell_command': [ + 'pwd', + 'ls -la' + ] + }, + { + 'shell_command': 'rails server --port 3000' + } + ] + } + ] +} diff --git a/tests/fixtures/config_teamocil/test1.yaml b/tests/fixtures/config_teamocil/test1.yaml new file mode 100644 index 0000000000..33ffc491cc --- /dev/null +++ b/tests/fixtures/config_teamocil/test1.yaml @@ -0,0 +1,7 @@ +windows: +- name: "sample-two-panes" + root: "~/Code/sample/www" + layout: even-horizontal + panes: + - cmd: ["pwd", "ls -la"] + - cmd: "rails server --port 3000" diff --git a/tests/fixtures/config_teamocil/test2.py b/tests/fixtures/config_teamocil/test2.py new file mode 100644 index 0000000000..7c9c083098 --- /dev/null +++ b/tests/fixtures/config_teamocil/test2.py @@ -0,0 +1,41 @@ +from .._util import loadfixture + +teamocil_yaml = loadfixture('config_teamocil/test2.yaml') +teamocil_dict = { + 'windows': [{ + 'name': 'sample-four-panes', + 'root': '~/Code/sample/www', + 'layout': 'tiled', + 'panes': [ + {'cmd': 'pwd'}, + {'cmd': 'pwd'}, + {'cmd': 'pwd'}, + {'cmd': 'pwd'}, + ] + }] +} + +expected = { + 'session_name': None, + 'windows': [ + { + 'window_name': 'sample-four-panes', + 'layout': 'tiled', + 'start_directory': '~/Code/sample/www', + 'panes': [ + { + 'shell_command': 'pwd' + }, + { + 'shell_command': 'pwd' + }, + { + 'shell_command': 'pwd' + }, + { + 'shell_command': 'pwd' + }, + ] + } + ] +} diff --git a/tests/fixtures/config_teamocil/test2.yaml b/tests/fixtures/config_teamocil/test2.yaml new file mode 100644 index 0000000000..9c69c560ca --- /dev/null +++ b/tests/fixtures/config_teamocil/test2.yaml @@ -0,0 +1,9 @@ +windows: +- name: "sample-four-panes" + root: "~/Code/sample/www" + layout: tiled + panes: + - cmd: "pwd" + - cmd: "pwd" + - cmd: "pwd" + - cmd: "pwd" diff --git a/tests/fixtures/config_teamocil/test3.py b/tests/fixtures/config_teamocil/test3.py new file mode 100644 index 0000000000..6a33d07e97 --- /dev/null +++ b/tests/fixtures/config_teamocil/test3.py @@ -0,0 +1,56 @@ +from .._util import loadfixture + +teamocil_yaml = loadfixture('config_teamocil/test3.yaml') + +teamocil_dict = { + 'windows': [{ + 'name': 'my-first-window', + 'root': '~/Projects/foo-www', + 'layout': 'even-vertical', + 'filters': { + 'before': 'rbenv local 2.0.0-p0', + 'after': 'echo \'I am done initializing this pane.\'' + }, + 'panes': [ + {'cmd': 'git status'}, + {'cmd': 'bundle exec rails server --port 40', + 'focus': True}, + {'cmd': [ + 'sudo service memcached start', + 'sudo service mongodb start', + ]} + ] + }] +} + +expected = { + 'session_name': None, + 'windows': [ + { + 'window_name': 'my-first-window', + 'layout': 'even-vertical', + 'start_directory': "~/Projects/foo-www", + 'shell_command_before': 'rbenv local 2.0.0-p0', + 'shell_command_after': ( + 'echo ' + '\'I am done initializing this pane.\'' + ), + 'panes': [ + { + 'shell_command': 'git status' + }, + { + 'shell_command': 'bundle exec rails server --port 40', + 'focus': True + }, + { + 'shell_command': [ + 'sudo service memcached start', + 'sudo service mongodb start' + ] + } + ] + } + + ] +} diff --git a/tests/fixtures/config_teamocil/test3.yaml b/tests/fixtures/config_teamocil/test3.yaml new file mode 100644 index 0000000000..f3d2b144f5 --- /dev/null +++ b/tests/fixtures/config_teamocil/test3.yaml @@ -0,0 +1,14 @@ +windows: +- name: "my-first-window" + root: "~/Projects/foo-www" + layout: even-vertical + filters: + before: "rbenv local 2.0.0-p0" + after: "echo 'I am done initializing this pane.'" + panes: + - cmd: "git status" + - cmd: "bundle exec rails server --port 40" + focus: true + - cmd: + - "sudo service memcached start" + - "sudo service mongodb start" diff --git a/tests/fixtures/config_teamocil/test4.py b/tests/fixtures/config_teamocil/test4.py new file mode 100644 index 0000000000..0ef912b574 --- /dev/null +++ b/tests/fixtures/config_teamocil/test4.py @@ -0,0 +1,28 @@ +from .._util import loadfixture + +teamocil_yaml = loadfixture('config_teamocil/test4.yaml') + +teamocil_dict = { + 'windows': [{ + 'name': 'erb-example', + 'root': "<%= ENV['MY_PROJECT_ROOT'] %>", + 'panes': [ + {'cmd': 'pwd'} + ] + }] +} + +expected = { + 'session_name': None, + 'windows': [ + { + 'window_name': 'erb-example', + 'start_directory': "<%= ENV['MY_PROJECT_ROOT'] %>", + 'panes': [ + { + 'shell_command': 'pwd' + } + ] + } + ] +} diff --git a/tests/fixtures/config_teamocil/test4.yaml b/tests/fixtures/config_teamocil/test4.yaml new file mode 100644 index 0000000000..a2f679e8aa --- /dev/null +++ b/tests/fixtures/config_teamocil/test4.yaml @@ -0,0 +1,5 @@ +windows: +- name: "erb-example" + root: <%= ENV['MY_PROJECT_ROOT'] %> + panes: + - cmd: "pwd" diff --git a/tests/fixtures/config_tmuxinator/__init__.py b/tests/fixtures/config_tmuxinator/__init__.py new file mode 100644 index 0000000000..bbdbf699ad --- /dev/null +++ b/tests/fixtures/config_tmuxinator/__init__.py @@ -0,0 +1 @@ +from . import test1, test2, test3 # noqa diff --git a/tests/fixtures/config_tmuxinator/test1.py b/tests/fixtures/config_tmuxinator/test1.py new file mode 100644 index 0000000000..46fb53296d --- /dev/null +++ b/tests/fixtures/config_tmuxinator/test1.py @@ -0,0 +1,49 @@ +from .._util import loadfixture + + +tmuxinator_yaml = loadfixture('config_tmuxinator/test1.yaml') +tmuxinator_dict = { + 'windows': [ + { + 'editor': { + 'layout': 'main-vertical', + 'panes': [ + 'vim', + 'guard' + ] + } + }, + { + 'server': 'bundle exec rails s', + }, + { + 'logs': 'tail -f logs/development.log' + } + ] +} + +expected = { + 'session_name': None, + 'windows': [ + { + 'window_name': 'editor', + 'layout': 'main-vertical', + 'panes': [ + 'vim', + 'guard' + ] + }, + { + 'window_name': 'server', + 'panes': [ + 'bundle exec rails s' + ] + }, + { + 'window_name': 'logs', + 'panes': [ + 'tail -f logs/development.log' + ] + } + ] +} diff --git a/tests/fixtures/config_tmuxinator/test1.yaml b/tests/fixtures/config_tmuxinator/test1.yaml new file mode 100644 index 0000000000..8905c608b3 --- /dev/null +++ b/tests/fixtures/config_tmuxinator/test1.yaml @@ -0,0 +1,8 @@ +windows: +- editor: + layout: main-vertical + panes: + - vim + - guard +- server: bundle exec rails s +- logs: tail -f logs/development.log diff --git a/tests/fixtures/config_tmuxinator/test2.py b/tests/fixtures/config_tmuxinator/test2.py new file mode 100644 index 0000000000..535d7ddddf --- /dev/null +++ b/tests/fixtures/config_tmuxinator/test2.py @@ -0,0 +1,132 @@ +from .._util import loadfixture + + +tmuxinator_yaml = loadfixture('config_tmuxinator/test2.yaml') + +tmuxinator_dict = { + 'project_name': 'sample', + 'project_root': '~/test', + 'socket_name': 'foo', + 'pre': 'sudo /etc/rc.d/mysqld start', + 'rbenv': '2.0.0-p247', + 'cli_args': '-f ~/.tmux.mac.conf', + 'tabs': [ + { + 'editor': { + 'pre': [ + 'echo "I get run in each pane, ' + 'before each pane command!"', + None + ], + 'layout': 'main-vertical', + 'panes': [ + 'vim', + None, + 'top' + ] + } + }, + {'shell': 'git pull', }, + { + 'guard': { + 'layout': 'tiled', + 'pre': [ + 'echo "I get run in each pane."', + 'echo "Before each pane command!"' + ], + 'panes': [ + None, + None, + None + ] + } + }, + {'database': 'bundle exec rails db'}, + {'server': 'bundle exec rails s'}, + {'logs': 'tail -f log/development.log'}, + {'console': 'bundle exec rails c'}, + {'capistrano': None}, + {'server': 'ssh user@example.com'} + ] +} + +expected = { + 'session_name': 'sample', + 'socket_name': 'foo', + 'config': '~/.tmux.mac.conf', + 'start_directory': '~/test', + 'shell_command_before': [ + 'sudo /etc/rc.d/mysqld start', + 'rbenv shell 2.0.0-p247' + ], + 'windows': [ + { + 'window_name': 'editor', + 'shell_command_before': [ + 'echo "I get run in each pane, before each pane command!"', + None + ], + 'layout': 'main-vertical', + 'panes': [ + 'vim', + None, + 'top' + ] + }, + { + 'window_name': 'shell', + 'panes': [ + 'git pull' + ] + }, + { + 'window_name': 'guard', + 'layout': 'tiled', + 'shell_command_before': [ + 'echo "I get run in each pane."', + 'echo "Before each pane command!"' + ], + 'panes': [ + None, + None, + None + ] + }, + { + 'window_name': 'database', + 'panes': [ + 'bundle exec rails db' + ] + }, + { + 'window_name': 'server', + 'panes': [ + 'bundle exec rails s' + ] + }, + { + 'window_name': 'logs', + 'panes': [ + 'tail -f log/development.log' + ] + }, + { + 'window_name': 'console', + 'panes': [ + 'bundle exec rails c' + ] + }, + { + 'window_name': 'capistrano', + 'panes': [ + None + ] + }, + { + 'window_name': 'server', + 'panes': [ + 'ssh user@example.com' + ] + } + ] +} diff --git a/tests/fixtures/config_tmuxinator/test2.yaml b/tests/fixtures/config_tmuxinator/test2.yaml new file mode 100644 index 0000000000..91f99969b2 --- /dev/null +++ b/tests/fixtures/config_tmuxinator/test2.yaml @@ -0,0 +1,32 @@ +project_name: sample +project_root: ~/test +socket_name: foo # Remove to use default socket +pre: sudo /etc/rc.d/mysqld start # Runs before everything +rbenv: 2.0.0-p247 +cli_args: -f ~/.tmux.mac.conf # Pass arguments to tmux +tabs: +- editor: + pre: + - echo "I get run in each pane, before each pane command!" + - + layout: main-vertical + panes: + - vim + - #empty, will just run plain bash + - top +- shell: git pull +- guard: + layout: tiled + pre: + - echo "I get run in each pane." + - echo "Before each pane command!" + panes: + - + - #empty, will just run plain bash + - +- database: bundle exec rails db +- server: bundle exec rails s +- logs: tail -f log/development.log +- console: bundle exec rails c +- capistrano: +- server: ssh user@example.com diff --git a/tests/fixtures/config_tmuxinator/test3.py b/tests/fixtures/config_tmuxinator/test3.py new file mode 100644 index 0000000000..f089b4a864 --- /dev/null +++ b/tests/fixtures/config_tmuxinator/test3.py @@ -0,0 +1,137 @@ +from .._util import loadfixture + + +tmuxinator_yaml = loadfixture('config_tmuxinator/test3.yaml') + +tmuxinator_dict = { + 'name': 'sample', + 'root': '~/test', + 'socket_name': 'foo', + 'tmux_options': '-f ~/.tmux.mac.conf', + 'pre': 'sudo /etc/rc.d/mysqld start', + 'pre_window': 'rbenv shell 2.0.0-p247', + 'windows': [ + { + 'editor': { + 'pre': [ + 'echo "I get run in each pane, ' + 'before each pane command!"', + None + ], + 'layout': 'main-vertical', + 'panes': [ + 'vim', + None, + 'top' + ] + } + }, + { + 'shell': [ + 'git pull', + 'git merge' + ] + }, + { + 'guard': { + 'layout': 'tiled', + 'pre': [ + 'echo "I get run in each pane."', + 'echo "Before each pane command!"' + ], + 'panes': [ + None, + None, + None + ] + } + }, + {'database': 'bundle exec rails db'}, + {'server': 'bundle exec rails s'}, + {'logs': 'tail -f log/development.log'}, + {'console': 'bundle exec rails c'}, + {'capistrano': None}, + {'server': 'ssh user@example.com'} + ] +} + +expected = { + 'session_name': 'sample', + 'socket_name': 'foo', + 'config': '~/.tmux.mac.conf', + 'shell_command': 'sudo /etc/rc.d/mysqld start', + 'shell_command_before': [ + 'rbenv shell 2.0.0-p247' + ], + 'windows': [ + { + 'window_name': 'editor', + 'shell_command_before': [ + 'echo "I get run in each pane, before each pane command!"', + None + ], + 'layout': 'main-vertical', + 'panes': [ + 'vim', + None, + 'top' + ] + }, + { + 'window_name': 'shell', + 'panes': [ + 'git pull', + 'git merge' + ] + }, + { + 'window_name': 'guard', + 'layout': 'tiled', + 'shell_command_before': [ + 'echo "I get run in each pane."', + 'echo "Before each pane command!"' + ], + 'panes': [ + None, + None, + None + ] + }, + { + 'window_name': 'database', + 'panes': [ + 'bundle exec rails db' + ] + }, + { + 'window_name': 'server', + 'panes': [ + 'bundle exec rails s' + ] + }, + { + 'window_name': 'logs', + 'panes': [ + 'tail -f log/development.log' + ] + }, + { + 'window_name': 'console', + 'panes': [ + 'bundle exec rails c' + ] + }, + { + 'window_name': 'capistrano', + 'panes': [ + None + ] + }, + { + 'window_name': 'server', + 'panes': [ + 'ssh user@example.com' + ] + } + ] +} diff --git a/tests/fixtures/config_tmuxinator/test3.yaml b/tests/fixtures/config_tmuxinator/test3.yaml new file mode 100644 index 0000000000..d7776aeabb --- /dev/null +++ b/tests/fixtures/config_tmuxinator/test3.yaml @@ -0,0 +1,37 @@ +# ~/.tmuxinator/sample.yml +# you can make as many tabs as you wish... + +name: sample +root: ~/test +socket_name: foo # Remove to use default socket +pre: sudo /etc/rc.d/mysqld start # Runs before everything +pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane +tmux_options: -f ~/.tmux.mac.conf # Pass arguments to tmux +windows: +- editor: + pre: + - echo "I get run in each pane, before each pane command!" + - + layout: main-vertical + panes: + - vim + - #empty, will just run plain bash + - top +- shell: + - git pull + - git merge +- guard: + layout: tiled + pre: + - echo "I get run in each pane." + - echo "Before each pane command!" + panes: + - + - #empty, will just run plain bash + - +- database: bundle exec rails db +- server: bundle exec rails s +- logs: tail -f log/development.log +- console: bundle exec rails c +- capistrano: +- server: ssh user@example.com diff --git a/tmuxp/testsuite/fixtures/script_complete.sh b/tests/fixtures/script_complete.sh similarity index 100% rename from tmuxp/testsuite/fixtures/script_complete.sh rename to tests/fixtures/script_complete.sh diff --git a/tmuxp/testsuite/fixtures/script_failed.sh b/tests/fixtures/script_failed.sh similarity index 100% rename from tmuxp/testsuite/fixtures/script_failed.sh rename to tests/fixtures/script_failed.sh diff --git a/tests/fixtures/workspacebuilder/config_script_completes.yaml b/tests/fixtures/workspacebuilder/config_script_completes.yaml new file mode 100644 index 0000000000..baa539f06a --- /dev/null +++ b/tests/fixtures/workspacebuilder/config_script_completes.yaml @@ -0,0 +1,5 @@ +session_name: sampleconfig +before_script: {script_complete} +windows: +- panes: + - pane diff --git a/tests/fixtures/workspacebuilder/config_script_fails.yaml b/tests/fixtures/workspacebuilder/config_script_fails.yaml new file mode 100644 index 0000000000..3a317d2495 --- /dev/null +++ b/tests/fixtures/workspacebuilder/config_script_fails.yaml @@ -0,0 +1,5 @@ + session_name: sampleconfig + before_script: {script_failed} + windows: + - panes: + - pane diff --git a/tests/fixtures/workspacebuilder/config_script_not_exists.yaml b/tests/fixtures/workspacebuilder/config_script_not_exists.yaml new file mode 100644 index 0000000000..ca9f57c9dd --- /dev/null +++ b/tests/fixtures/workspacebuilder/config_script_not_exists.yaml @@ -0,0 +1,5 @@ +session_name: sampleconfig +before_script: {script_not_exists} +windows: +- panes: + - pane diff --git a/tests/fixtures/workspacebuilder/environment_vars.yaml b/tests/fixtures/workspacebuilder/environment_vars.yaml new file mode 100644 index 0000000000..eaee25684b --- /dev/null +++ b/tests/fixtures/workspacebuilder/environment_vars.yaml @@ -0,0 +1,10 @@ +session_name: test env vars +start_directory: '~' +environment: + FOO: BAR + PATH: /tmp +windows: +- layout: main-horizontal + panes: + - pane + window_name: editor diff --git a/tests/fixtures/workspacebuilder/focus_and_pane.yaml b/tests/fixtures/workspacebuilder/focus_and_pane.yaml new file mode 100644 index 0000000000..3a986dbf59 --- /dev/null +++ b/tests/fixtures/workspacebuilder/focus_and_pane.yaml @@ -0,0 +1,31 @@ +session_name: sampleconfig +start_directory: '~' +windows: +- window_name: focused window + layout: main-horizontal + focus: true + panes: + - shell_command: + - cd ~ + - shell_command: + - cd /usr + focus: true + - shell_command: + - cd ~ + - echo "moo" + - top +- window_name: window 2 + panes: + - shell_command: + - top + focus: true + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: window 3 + panes: + - shell_command: cd / + focus: true + - pane + - pane diff --git a/tests/fixtures/workspacebuilder/pane_ordering.yaml b/tests/fixtures/workspacebuilder/pane_ordering.yaml new file mode 100644 index 0000000000..52d4796a88 --- /dev/null +++ b/tests/fixtures/workspacebuilder/pane_ordering.yaml @@ -0,0 +1,11 @@ +session_name: sampleconfig +start_directory: {HOME} +windows: +- options: + - automatic_rename: on + layout: tiled + panes: + - cd /usr/bin + - cd /usr + - cd /usr/sbin + - cd {HOME} diff --git a/tests/fixtures/workspacebuilder/start_directory.yaml b/tests/fixtures/workspacebuilder/start_directory.yaml new file mode 100644 index 0000000000..0aeb8d31d7 --- /dev/null +++ b/tests/fixtures/workspacebuilder/start_directory.yaml @@ -0,0 +1,57 @@ +session_name: sampleconfig +start_directory: '/usr' +windows: +- window_name: supposed to be /usr/bin + window_index: 1 + start_directory: /usr/bin + layout: main-horizontal + options: + main-pane-height: 50 + panes: + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: support to be /dev + window_index: 2 + start_directory: /dev + layout: main-horizontal + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: cwd containing a space + window_index: 3 + start_directory: {TEST_DIR} + layout: main-horizontal + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: testsa3 + window_index: 4 + layout: main-horizontal + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo3" +- window_name: cwd relative to start_directory since no rel dir entered + window_index: 5 + layout: main-horizontal + start_directory: ./ + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo3" diff --git a/tests/fixtures/workspacebuilder/start_directory_relative.yaml b/tests/fixtures/workspacebuilder/start_directory_relative.yaml new file mode 100644 index 0000000000..bc197f1ea2 --- /dev/null +++ b/tests/fixtures/workspacebuilder/start_directory_relative.yaml @@ -0,0 +1,51 @@ +session_name: sampleconfig +start_directory: ./ +windows: +- window_name: supposed to be /usr/bin + start_directory: '/usr/bin' + options: + main-pane-height: 50 + panes: + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: support to be /dev + start_directory: '/dev' + layout: main-horizontal + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: cwd containing a space + start_directory: {TEST_DIR} + layout: main-horizontal + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" +- window_name: inherit start_directory which is rel to config file + layout: main-horizontal + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo3" +- window_name: cwd relative to config file + layout: main-horizontal + start_directory: ./ + panes: + - shell_command: + - pwd + - shell_command: + - echo "hey" + - shell_command: + - echo "moo3" diff --git a/tests/fixtures/workspacebuilder/suppress_history.yaml b/tests/fixtures/workspacebuilder/suppress_history.yaml new file mode 100644 index 0000000000..b480f5418a --- /dev/null +++ b/tests/fixtures/workspacebuilder/suppress_history.yaml @@ -0,0 +1,11 @@ +session_name: sampleconfig +start_directory: '~' +suppress_history: false +windows: +- window_name: inHistory + panes: + - echo inHistory +- window_name: isMissing + suppress_history: true + panes: + - echo isMissing diff --git a/tests/fixtures/workspacebuilder/three_pane.yaml b/tests/fixtures/workspacebuilder/three_pane.yaml new file mode 100644 index 0000000000..f883fc2b36 --- /dev/null +++ b/tests/fixtures/workspacebuilder/three_pane.yaml @@ -0,0 +1,12 @@ +session_name: sampleconfig +start_directory: '~' +windows: +- window_name: test + layout: main-horizontal + panes: + - shell_command: + - vim + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" diff --git a/tests/fixtures/workspacebuilder/two_pane.yaml b/tests/fixtures/workspacebuilder/two_pane.yaml new file mode 100644 index 0000000000..be083ff48b --- /dev/null +++ b/tests/fixtures/workspacebuilder/two_pane.yaml @@ -0,0 +1,18 @@ +session_name: sampleconfig +start_directory: '~' +windows: +- layout: main-vertical + panes: + - shell_command: + - vim + - shell_command: + - echo "hey" + window_name: editor +- panes: + - shell_command: + - tail | echo 'hi' + window_name: logging +- window_name: test + panes: + - shell_command: + - htop diff --git a/tests/fixtures/workspacebuilder/window_automatic_rename.yaml b/tests/fixtures/workspacebuilder/window_automatic_rename.yaml new file mode 100644 index 0000000000..9b74b4fe7f --- /dev/null +++ b/tests/fixtures/workspacebuilder/window_automatic_rename.yaml @@ -0,0 +1,14 @@ +session_name: test window options +start_directory: '~' +windows: +- layout: main-horizontal + options: + automatic-rename: on + panes: + - shell_command: + - sh + start_directory: '~' + - shell_command: + - echo "hey" + - shell_command: + - echo "moo" diff --git a/tests/fixtures/workspacebuilder/window_index.yaml b/tests/fixtures/workspacebuilder/window_index.yaml new file mode 100644 index 0000000000..3f6c080dcd --- /dev/null +++ b/tests/fixtures/workspacebuilder/window_index.yaml @@ -0,0 +1,12 @@ +session_name: sampleconfig +windows: +- window_name: zero + panes: + - echo 'zero' +- window_name: five + panes: + - echo 'five' + window_index: 5 +- window_name: one + panes: + - echo 'one' diff --git a/tests/fixtures/workspacebuilder/window_options.yaml b/tests/fixtures/workspacebuilder/window_options.yaml new file mode 100644 index 0000000000..714d234728 --- /dev/null +++ b/tests/fixtures/workspacebuilder/window_options.yaml @@ -0,0 +1,11 @@ +session_name: test window options +start_directory: '~' +windows: +- layout: main-horizontal + options: + main-pane-height: 5 + panes: + - pane + - pane + - pane + window_name: editor diff --git a/tests/fixtures/workspacebuilder/window_shell.yaml b/tests/fixtures/workspacebuilder/window_shell.yaml new file mode 100644 index 0000000000..f602b3e396 --- /dev/null +++ b/tests/fixtures/workspacebuilder/window_shell.yaml @@ -0,0 +1,12 @@ +session_name: test window options +start_directory: '~' +windows: +- layout: main-horizontal + options: + main-pane-height: 5 + panes: + - pane + - pane + - pane + window_name: editor + window_shell: top diff --git a/tests/fixtures/workspacefreezer/sampleconfig.yaml b/tests/fixtures/workspacefreezer/sampleconfig.yaml new file mode 100644 index 0000000000..b7a6d01070 --- /dev/null +++ b/tests/fixtures/workspacefreezer/sampleconfig.yaml @@ -0,0 +1,21 @@ +session_name: sampleconfig +start_directory: '~' +windows: +- layout: main-vertical + panes: + - shell_command: + - vim + start_directory: '~' + - shell_command: + - echo "hey" + - cd ../ + window_name: editor +- panes: + - shell_command: + - pane + start_directory: /usr/bin + window_name: logging +- window_name: test + panes: + - shell_command: + - top diff --git a/tests/helpers.py b/tests/helpers.py new file mode 100644 index 0000000000..17840f7cc7 --- /dev/null +++ b/tests/helpers.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +"""Helper methods for tmuxp tests. + +_CallableContext, WhateverIO, decorator and stdouts are from the case project, +https://github.com/celery/case, license BSD 3-clause. +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import contextlib +import logging +import os +import tempfile + +logger = logging.getLogger(__name__) + +TEST_SESSION_PREFIX = 'test tmuxp_' + +namer = tempfile._RandomNameSequence() +current_dir = os.path.abspath(os.path.dirname(__file__)) +example_dir = os.path.abspath(os.path.join(current_dir, '..', 'examples')) +fixtures_dir = os.path.realpath(os.path.join(current_dir, 'fixtures')) + + +def get_test_session_name(server, prefix=TEST_SESSION_PREFIX): + while True: + session_name = prefix + next(namer) + if not server.has_session(session_name): + break + return session_name + + +def get_test_window_name(session, prefix=TEST_SESSION_PREFIX): + while True: + window_name = prefix + next(namer) + if not session.findWhere(window_name=window_name): + break + return window_name + + +@contextlib.contextmanager +def temp_session(server, *args, **kwargs): + """Return a context manager with a temporary session. + + e.g.:: + + with temp_session(server) as session: + session.new_window(window_name='my window') + + The session will destroy itself upon closing with :meth:`Session. + kill_session()`. + + If no ``session_name`` is entered, :func:`get_test_session_name` will make + an unused session name. + + :args: Same arguments as :meth:`Server.new_session` + :yields: Temporary session + :rtype: :class:`Session` + """ + + if 'session_name' in kwargs: + session_name = kwargs.pop('session_name') + else: + session_name = get_test_session_name(server) + + session = server.new_session(session_name, *args, **kwargs) + + try: + yield session + finally: + if server.has_session(session_name): + session.kill_session() + return + + +@contextlib.contextmanager +def temp_window(session, *args, **kwargs): + """Return a context manager with a temporary window. + + e.g.:: + + with temp_window(session) as window: + my_pane = window.split_window() + + The window will destroy itself upon closing with :meth:`window. + kill_window()`. + + If no ``window_name`` is entered, :func:`get_test_window_name` will make + an unused window name. + + :args: Same arguments as :meth:`Session.new_window` + :yields: Temporary window + :rtype: :class:`Window` + """ + + if 'window_name' not in kwargs: + window_name = get_test_window_name(session) + else: + window_name = kwargs.pop('window_name') + + window = session.new_window(window_name, *args, **kwargs) + + # Get ``window_id`` before returning it, it may be killed within context. + window_id = window.get('window_id') + + try: + yield session + finally: + if session.findWhere(window_id=window_id): + window.kill_window() + return + + +class EnvironmentVarGuard(object): + + """Class to help protect the environment variable properly. Can be used as + a context manager. + Vendorize to fix issue with Anaconda Python 2 not + including test module, see #121. + """ + + def __init__(self): + self._environ = os.environ + self._unset = set() + self._reset = dict() + + def set(self, envvar, value): + if envvar not in self._environ: + self._unset.add(envvar) + else: + self._reset[envvar] = self._environ[envvar] + self._environ[envvar] = value + + def unset(self, envvar): + if envvar in self._environ: + self._reset[envvar] = self._environ[envvar] + del self._environ[envvar] + + def __enter__(self): + return self + + def __exit__(self, *ignore_exc): + for envvar, value in self._reset.items(): + self._environ[envvar] = value + for unset in self._unset: + del self._environ[unset] diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000000..59c5619065 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp command line interface.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import os + +from tmuxp import cli, config + +logger = logging.getLogger(__name__) + + +def test_creates_config_dir_not_exists(tmpdir): + """cli.startup() creates config dir if not exists.""" + + cli.startup(str(tmpdir)) + assert os.path.exists(str(tmpdir)) + + +def test_in_dir_from_config_dir(tmpdir): + """config.in_dir() finds configs config dir.""" + + cli.startup(str(tmpdir)) + tmpdir.join("myconfig.yaml").write("") + tmpdir.join("myconfig.json").write("") + configs_found = config.in_dir(str(tmpdir)) + + assert len(configs_found) == 2 + + +def test_ignore_non_configs_from_current_dir(tmpdir): + """cli.in_dir() ignore non-config from config dir.""" + + cli.startup(str(tmpdir)) + + tmpdir.join("myconfig.psd").write("") + tmpdir.join("watmyconfig.json").write("") + configs_found = config.in_dir(str(tmpdir)) + assert len(configs_found) == 1 + + +def test_get_configs_cwd(tmpdir): + """config.in_cwd() find config in shell current working directory.""" + + confdir = tmpdir.mkdir("tmuxpconf2") + with confdir.as_cwd(): + config1 = open('.tmuxp.json', 'w+b') + config1.close() + + configs_found = config.in_cwd() + assert len(configs_found) == 1 + assert '.tmuxp.json' in configs_found diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000000..e503a8571e --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,450 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp configuration import, inlining, expanding and export.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import os + +import kaptan +import pytest + +from tmuxp import config, exc + +from .fixtures import config as fixtures +from .helpers import EnvironmentVarGuard, example_dir + +logger = logging.getLogger(__name__) +TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') + + +def load_yaml(yaml): + return kaptan.Kaptan(handler='yaml').import_config(yaml).get() + + +def load_config(_file): + return kaptan.Kaptan().import_config(_file).get() + + +def test_export_json(tmpdir): + json_config_file = tmpdir.join('config.json') + + configparser = kaptan.Kaptan() + configparser.import_config(fixtures.sampleconfig.sampleconfigdict) + + json_config_data = configparser.export('json', indent=2) + + json_config_file.write(json_config_data) + + new_config = kaptan.Kaptan() + new_config_data = new_config.import_config(str(json_config_file)).get() + assert fixtures.sampleconfig.sampleconfigdict == new_config_data + + +def test_export_yaml(tmpdir): + yaml_config_file = tmpdir.join('config.yaml') + + configparser = kaptan.Kaptan() + sampleconfig = config.inline(fixtures.sampleconfig.sampleconfigdict) + configparser.import_config(sampleconfig) + + yaml_config_data = configparser.export( + 'yaml', indent=2, default_flow_style=False) + + yaml_config_file.write(yaml_config_data) + + new_config_data = load_config(str(yaml_config_file)) + assert fixtures.sampleconfig.sampleconfigdict == new_config_data + + +def test_scan_config(tmpdir): + configs = [] + + garbage_file = tmpdir.join('config.psd') + garbage_file.write('wat') + + for r, d, f in os.walk(str(tmpdir)): + for filela in ( + x for x in f if x.endswith(('.json', '.ini', 'yaml')) + ): + configs.append(str(tmpdir.join(filela))) + + files = 0 + if tmpdir.join('config.json').check(): + files += 1 + assert str(tmpdir.join('config.json')) in configs + + if tmpdir.join('config.yaml').check(): + files += 1 + assert str(tmpdir.join('config.yaml')) in configs + + if tmpdir.join('config.ini').check(): + files += 1 + assert str(tmpdir.join('config.ini')) in configs + + assert len(configs) == files + + +def test_config_expand1(): + """Expand shell commands from string to list.""" + test_config = config.expand(fixtures.expand1.before_config) + assert test_config == fixtures.expand1.after_config + + +def test_config_expand2(): + """Expand shell commands from string to list.""" + + unexpanded_dict = load_yaml(fixtures.expand2.unexpanded_yaml) + + expanded_dict = load_yaml(fixtures.expand2.expanded_yaml) + + assert config.expand(unexpanded_dict) == expanded_dict + + +"""Tests for :meth:`config.inline()`.""" + +ibefore_config = { # inline config + 'session_name': 'sampleconfig', + 'start_directory': '~', + 'windows': [ + { + 'shell_command': ['top'], + 'window_name': 'editor', + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + } + ] + }, + { + 'options': {'automatic_rename': True, }, + 'panes': [ + {'shell_command': ['htop']} + ] + } + ] +} + +iafter_config = { + 'session_name': 'sampleconfig', + 'start_directory': '~', + 'windows': [ + { + 'shell_command': 'top', + 'window_name': 'editor', + 'panes': [ + 'vim', + 'cowsay "hey"' + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'panes': [ + 'tail -F /var/log/syslog', + ] + }, + { + 'options': { + 'automatic_rename': True, + }, + 'panes': [ + 'htop' + ] + }, + + ] +} + + +def test_inline_config(): + """:meth:`config.inline()` shell commands list to string.""" + + test_config = config.inline(ibefore_config) + assert test_config == iafter_config + + +"""Test config inheritance for the nested 'start_command'.""" + +inheritance_config_before = { + 'session_name': 'sampleconfig', + 'start_directory': '/', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': '~', + 'panes': [ + { + 'shell_command': ['vim'], + }, + { + 'shell_command': ['cowsay "hey"'] + }, + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + } + ] + }, + { + 'window_name': 'shufu', + 'panes': [ + { + 'shell_command': ['htop'], + } + ] + }, + { + 'options': { + 'automatic_rename': True, + }, + 'panes': [ + { + 'shell_command': ['htop'] + } + ] + } + ] +} + +inheritance_config_after = { + 'session_name': 'sampleconfig', + 'start_directory': '/', + 'windows': [ + { + 'window_name': 'editor', + 'start_directory': '~', + 'panes': [ + { + 'shell_command': ['vim'], + }, { + 'shell_command': ['cowsay "hey"'], + }, + ], + 'layout': 'main-verticle' + }, + { + 'window_name': 'logging', + 'panes': [ + { + 'shell_command': ['tail -F /var/log/syslog'], + } + ] + }, + { + 'window_name': 'shufu', + 'panes': [ + { + 'shell_command': ['htop'], + } + ] + }, + { + 'options': {'automatic_rename': True, }, + 'panes': [ + { + 'shell_command': ['htop'], + } + ] + } + ] +} + + +def test_inheritance_config(): + config = inheritance_config_before + + # TODO: Look at verifying window_start_directory + # if 'start_directory' in config: + # session_start_directory = config['start_directory'] + # else: + # session_start_directory = None + + # for windowconfitem in config['windows']: + # window_start_directory = None + # + # if 'start_directory' in windowconfitem: + # window_start_directory = windowconfitem['start_directory'] + # elif session_start_directory: + # window_start_directory = session_start_directory + # + # for paneconfitem in windowconfitem['panes']: + # if 'start_directory' in paneconfitem: + # pane_start_directory = paneconfitem['start_directory'] + # elif window_start_directory: + # paneconfitem['start_directory'] = window_start_directory + # elif session_start_directory: + # paneconfitem['start_directory'] = session_start_directory + + assert config == inheritance_config_after + + +def test_shell_command_before(): + """Config inheritance for the nested 'start_command'.""" + test_config = fixtures.shell_command_before.config_unexpanded + test_config = config.expand(test_config) + + assert test_config == fixtures.shell_command_before.config_expanded + + test_config = config.trickle(test_config) + assert test_config == fixtures.shell_command_before.config_after + + +def test_in_session_scope(): + sconfig = load_yaml(fixtures.shell_command_before_session.before) + + config.validate_schema(sconfig) + + assert config.expand(sconfig) == sconfig + assert config.expand(config.trickle(sconfig)) == \ + load_yaml(fixtures.shell_command_before_session.expected) + + +def test_trickle_relative_start_directory(): + test_config = config.trickle(fixtures.trickle.before) + assert test_config == fixtures.trickle.expected + + +def test_expands_blank_panes(): + """Expand blank config into full form. + + Handle ``NoneType`` and 'blank':: + + # nothing, None, 'blank' + 'panes': [ + None, + 'blank' + ] + + # should be blank + 'panes': [ + 'shell_command': [] + ] + + Blank strings:: + + panes: [ + '' + ] + + # should output to: + panes: + 'shell_command': [''] + + """ + + yaml_config_file = os.path.join(example_dir, 'blank-panes.yaml') + test_config = load_config(yaml_config_file) + assert config.expand(test_config) == fixtures.expand_blank.expected + + +def test_no_session_name(): + yaml_config = """ + - window_name: editor + panes: + shell_command: + - tail -F /var/log/syslog + start_directory: /var/log + - window_name: logging + automatic_rename: true + panes: + - shell_command: + - htop + """ + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + with pytest.raises(exc.ConfigError) as excinfo: + config.validate_schema(sconfig) + assert excinfo.matches(r'requires "session_name"') + + +def test_no_windows(): + yaml_config = """ + session_name: test session + """ + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + with pytest.raises(exc.ConfigError) as excinfo: + config.validate_schema(sconfig) + assert excinfo.match(r'list of "windows"') + + +def test_no_window_name(): + yaml_config = """ + session_name: test session + windows: + - window_name: editor + panes: + shell_command: + - tail -F /var/log/syslog + start_directory: /var/log + - automatic_rename: true + panes: + - shell_command: + - htop + """ + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + with pytest.raises(exc.ConfigError) as excinfo: + config.validate_schema(sconfig) + assert excinfo.matches('missing "window_name"') + + +def test_replaces_start_directory(): + env_key = "TESTHEY92" + env_value = "HEYO1" + yaml_config = """ + start_directory: {TEST_VAR}/test + shell_command_before: {TEST_VAR}/test2 + before_script: {TEST_VAR}/test3 + session_name: hi - {TEST_VAR} + windows: + - window_name: editor + panes: + - shell_command: + - tail -F /var/log/syslog + start_directory: /var/log + - window_name: logging @ {TEST_VAR} + automatic_rename: true + panes: + - shell_command: + - htop + """.format( + TEST_VAR="${%s}" % env_key + ) + + sconfig = load_yaml(yaml_config) + + with EnvironmentVarGuard() as env: + env.set(env_key, env_value) + sconfig = config.expand(sconfig) + assert "%s/test" % env_value == sconfig['start_directory'] + assert "%s/test2" % env_value in sconfig['shell_command_before'] + assert "%s/test3" % env_value == sconfig['before_script'] + assert "hi - %s" % env_value == sconfig['session_name'] + assert "logging @ %s" % env_value == \ + sconfig['windows'][1]['window_name'] diff --git a/tests/test_config_teamocil.py b/tests/test_config_teamocil.py new file mode 100644 index 0000000000..af83fa2ab8 --- /dev/null +++ b/tests/test_config_teamocil.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp teamocil configuration.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import os + +import kaptan +import pytest + +from tmuxp import config + +from .fixtures import config_teamocil as fixtures + +logger = logging.getLogger(__name__) +TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') + + +@pytest.mark.parametrize("teamocil_yaml,teamocil_dict,tmuxp_dict", [ + (fixtures.test1.teamocil_yaml, fixtures.test1.teamocil_conf, + fixtures.test1.expected), + (fixtures.test2.teamocil_yaml, fixtures.test2.teamocil_dict, + fixtures.test2.expected), + (fixtures.test3.teamocil_yaml, fixtures.test3.teamocil_dict, + fixtures.test3.expected), + (fixtures.test4.teamocil_yaml, fixtures.test4.teamocil_dict, + fixtures.test4.expected), +]) +def test_config_to_dict(teamocil_yaml, teamocil_dict, tmuxp_dict): + configparser = kaptan.Kaptan(handler='yaml') + test_config = configparser.import_config(teamocil_yaml) + yaml_to_dict = test_config.get() + assert yaml_to_dict == teamocil_dict + + assert config.import_teamocil(teamocil_dict) == tmuxp_dict + + config.validate_schema( + config.import_teamocil( + teamocil_dict + ) + ) + + +@pytest.fixture(scope='module') +def multisession_config(): + """Return loaded multisession teamocil config as a dictionary. + + Also prevents re-running assertion the loads the yaml, since ordering of + deep list items like panes will be inconsistent.""" + teamocil_yaml = fixtures.layouts.teamocil_yaml + configparser = kaptan.Kaptan(handler='yaml') + test_config = configparser.import_config(teamocil_yaml) + teamocil_dict = fixtures.layouts.teamocil_dict + + assert test_config.get() == teamocil_dict + return teamocil_dict + + +@pytest.mark.parametrize("session_name,expected", [ + ('two-windows', fixtures.layouts.two_windows), + ('two-windows-with-filters', fixtures.layouts.two_windows_with_filters), + ('two-windows-with-custom-command-options', + fixtures.layouts.two_windows_with_custom_command_options), + ('three-windows-within-a-session', + fixtures.layouts.three_windows_within_a_session), +]) +def test_multisession_config(session_name, expected, multisession_config): + # teamocil can fit multiple sessions in a config + assert config.import_teamocil( + multisession_config[session_name] + ) == expected + + config.validate_schema( + config.import_teamocil( + multisession_config[session_name] + ) + ) diff --git a/tests/test_config_tmuxinator.py b/tests/test_config_tmuxinator.py new file mode 100644 index 0000000000..3e35b7756c --- /dev/null +++ b/tests/test_config_tmuxinator.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp tmuxinator configuration.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import os + +import kaptan +import pytest + +from tmuxp import config + +from .fixtures import config_tmuxinator as fixtures + +logger = logging.getLogger(__name__) +TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') + + +@pytest.mark.parametrize("tmuxinator_yaml,tmuxinator_dict,tmuxp_dict", [ + (fixtures.test1.tmuxinator_yaml, fixtures.test1.tmuxinator_dict, + fixtures.test1.expected), + (fixtures.test2.tmuxinator_yaml, fixtures.test2.tmuxinator_dict, + fixtures.test2.expected), # older vers use `tabs` instead of `windows` + (fixtures.test3.tmuxinator_yaml, fixtures.test3.tmuxinator_dict, + fixtures.test3.expected), # Test importing +]) +def test_config_to_dict(tmuxinator_yaml, tmuxinator_dict, tmuxp_dict): + configparser = kaptan.Kaptan(handler='yaml') + test_config = configparser.import_config(tmuxinator_yaml) + yaml_to_dict = test_config.get() + assert yaml_to_dict == tmuxinator_dict + + assert config.import_tmuxinator(tmuxinator_dict) == tmuxp_dict + + config.validate_schema( + config.import_tmuxinator( + tmuxinator_dict + ) + ) diff --git a/tests/test_pane.py b/tests/test_pane.py new file mode 100644 index 0000000000..52bfb932d8 --- /dev/null +++ b/tests/test_pane.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp Pane object.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging + +logger = logging.getLogger(__name__) + + +def test_resize_pane(session): + """ Test Pane.resize_pane(). """ + + window = session.attached_window() + window.rename_window('test_resize_pane') + + pane1 = window.attached_pane() + pane1_height = pane1['pane_height'] + window.split_window() + + pane1.resize_pane(height=4) + assert pane1['pane_height'] != pane1_height + assert int(pane1['pane_height']) == 4 + + pane1.resize_pane(height=3) + assert int(pane1['pane_height']) == 3 + + +def test_set_height(session): + window = session.new_window(window_name='test_set_height') + window.split_window() + pane1 = window.attached_pane() + pane1_height = pane1['pane_height'] + + pane1.set_height(2) + assert pane1['pane_height'] != pane1_height + assert int(pane1['pane_height']) == 2 + + +def test_set_width(session): + window = session.new_window(window_name='test_set_width') + window.split_window() + + window.select_layout('main-vertical') + pane1 = window.attached_pane() + pane1_width = pane1['pane_width'] + + pane1.set_width(10) + assert pane1['pane_width'] != pane1_width + assert int(pane1['pane_width']) == 10 + + pane1.reset() diff --git a/tests/test_server.py b/tests/test_server.py new file mode 100644 index 0000000000..dbb8353e70 --- /dev/null +++ b/tests/test_server.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp Server object.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging + +from tmuxp import Server + +logger = logging.getLogger(__name__) + + +def test_has_session(server, session): + assert server.has_session(session.get('session_name')) + assert not server.has_session('asdf2314324321') + + +def test_socket_name(server): + """ ``-L`` socket_name. + + ``-L`` socket_name file name of socket. which will be stored in + env TMUX_TMPDIR or /tmp if unset.) + + """ + myserver = Server(socket_name='test') + + assert myserver.socket_name == 'test' + + +def test_socket_path(server): + """ ``-S`` socket_path (alternative path for server socket). """ + myserver = Server(socket_path='test') + + assert myserver.socket_path == 'test' + + +def test_config(server): + """ ``-f`` file for tmux(1) configuration. """ + myserver = Server(config_file='test') + assert myserver.config_file == 'test' + + +def test_256_colors(server): + myserver = Server(colors=256) + assert myserver.colors == 256 + + proc = myserver.cmd('list-servers') + + assert '-2' in proc.cmd + assert '-8' not in proc.cmd + + +def test_88_colors(server): + myserver = Server(colors=88) + assert myserver.colors == 88 + + proc = myserver.cmd('list-servers') + + assert '-8' in proc.cmd + assert '-2' not in proc.cmd + + +def test_show_environment(server): + """Server.show_environment() returns dict.""" + _vars = server.show_environment() + assert isinstance(_vars, dict) + + +def test_set_show_environment_single(server, session): + """Set environment then Server.show_environment(key).""" + server.set_environment('FOO', 'BAR') + assert 'BAR' == server.show_environment('FOO') + + server.set_environment('FOO', 'DAR') + assert 'DAR' == server.show_environment('FOO') + + assert 'DAR' == server.show_environment()['FOO'] + + +def test_show_environment_not_set(server): + """Unset environment variable returns None.""" + assert server.show_environment('BAR') is None diff --git a/tests/test_session.py b/tests/test_session.py new file mode 100644 index 0000000000..1986ee6148 --- /dev/null +++ b/tests/test_session.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp Session object.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import pytest + +from tmuxp import Pane, Session, Window + +from .helpers import TEST_SESSION_PREFIX, namer + +logger = logging.getLogger(__name__) + + +def test_has_session(server, session): + """Server.has_session returns True if has session_name exists.""" + TEST_SESSION_NAME = session.get('session_name') + assert server.has_session(TEST_SESSION_NAME) + assert not server.has_session('asdf2314324321') + + +def test_select_window(session): + """Session.select_window moves window.""" + # get the current window_base_index, since different user tmux config + # may start at 0 or 1, or whatever they want. + window_base_index = int( + session.attached_window().get('window_index') + ) + + session.new_window(window_name='test_window') + window_count = len(session._windows) + + assert window_count >= 2 # 2 or more windows + + assert len(session._windows) == window_count + + # tmux selects a window, moves to it, shows it as attached_window + selected_window1 = session.select_window(window_base_index) + assert isinstance(selected_window1, Window) + attached_window1 = session.attached_window() + + assert selected_window1 == attached_window1 + assert selected_window1.__dict__ == attached_window1.__dict__ + + # again: tmux selects a window, moves to it, shows it as + # attached_window + selected_window2 = session.select_window(window_base_index + 1) + assert isinstance(selected_window2, Window) + attached_window2 = session.attached_window() + + assert selected_window2 == attached_window2 + assert selected_window2.__dict__ == attached_window2.__dict__ + + # assure these windows were really different + assert selected_window1 != selected_window2 + assert selected_window1.__dict__ != selected_window2.__dict__ + + +def test_select_window_returns_Window(session): + """Session.select_window returns Window object.""" + + window_count = len(session._windows) + assert len(session._windows) == window_count + window_base_index = int( + session.attached_window().get('window_index')) + + assert isinstance( + session.select_window(window_base_index), Window + ) + + +def test_attached_window(session): + """Session.attached_window() returns Window.""" + assert isinstance(session.attached_window(), Window) + + +def test_attached_pane(session): + """Session.attached_pane() returns Pane.""" + assert isinstance(session.attached_pane(), Pane) + + +def test_session_rename(session): + """Session.rename_session renames session.""" + TEST_SESSION_NAME = session.get('session_name') + test_name = 'testingdis_sessname' + session.rename_session(test_name) + assert session.get('session_name') == test_name + session.rename_session(TEST_SESSION_NAME) + assert session.get('session_name') == TEST_SESSION_NAME + + +def test_new_session(server): + """Server.new_session creates new session.""" + new_session_name = TEST_SESSION_PREFIX + next(namer) + new_session = server.new_session( + session_name=new_session_name, detach=True) + + assert isinstance(new_session, Session) + assert new_session.get('session_name') == new_session_name + + +def test_show_options(session): + """Session.show_options() returns dict.""" + + options = session.show_options() + assert isinstance(options, dict) + + +def test_set_show_options_single(session): + """Set option then Session.show_options(key).""" + + session.set_option('history-limit', 20) + assert session.show_options('history-limit') == 20 + + session.set_option('history-limit', 40) + assert session.show_options('history-limit') == 40 + + assert session.show_options()['history-limit'] == 40 + + +def test_set_show_option(session): + """Set option then Session.show_option(key).""" + session.set_option('history-limit', 20) + assert session.show_option('history-limit') == 20 + + session.set_option('history-limit', 40) + + assert session.show_option('history-limit') == 40 + + +def test_set_option_bad(session): + """Session.set_option raises ValueError for bad option key.""" + with pytest.raises(ValueError): + session.set_option('afewewfew', 43) + + +def test_show_environment(session): + """Session.show_environment() returns dict.""" + + _vars = session.show_environment() + assert isinstance(_vars, dict) + + +def test_set_show_environment_single(session): + """Set environment then Session.show_environment(key).""" + + session.set_environment('FOO', 'BAR') + assert session.show_environment('FOO') == 'BAR' + + session.set_environment('FOO', 'DAR') + assert session.show_environment('FOO') == 'DAR' + + assert session.show_environment()['FOO'] == 'DAR' + + +def test_show_environment_not_set(session): + """Not set environment variable returns None.""" + assert session.show_environment('BAR') is None + + +def test_remove_environment(session): + """Remove environment variable.""" + assert session.show_environment('BAM') is None + session.set_environment('BAM', 'OK') + assert session.show_environment('BAM') == 'OK' + session.remove_environment('BAM') + assert session.show_environment('BAM') is None + + +def test_unset_environment(session): + """Unset environment variable.""" + assert session.show_environment('BAM') is None + session.set_environment('BAM', 'OK') + assert session.show_environment('BAM') == 'OK' + session.unset_environment('BAM') + assert session.show_environment('BAM') is None diff --git a/tests/test_tmuxobject.py b/tests/test_tmuxobject.py new file mode 100644 index 0000000000..dab1b602e1 --- /dev/null +++ b/tests/test_tmuxobject.py @@ -0,0 +1,186 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp TmuxRelationalObject and TmuxMappingObject.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging + +from tmuxp import Pane, Session, Window +from .helpers import TEST_SESSION_PREFIX, namer + +logger = logging.getLogger(__name__) + + +"""Test the :class:`TmuxRelationalObject` base class object.""" + + +def test_findWhere(server, session): + """Test that findWhere() retrieves single matching object.""" + # server.findWhere + for session in server.sessions: + session_id = session.get('session_id') + + assert server.findWhere({'session_id': session_id}) == session + assert isinstance(server.findWhere({ + 'session_id': session_id + }), Session) + + # session.findWhere + for window in session.windows: + window_id = window.get('window_id') + + assert session.findWhere({'window_id': window_id}) == window + assert isinstance( + session.findWhere({'window_id': window_id}), Window + ) + + # window.findWhere + for pane in window.panes: + pane_id = pane.get('pane_id') + + assert window.findWhere({'pane_id': pane_id}) == pane + assert isinstance( + window.findWhere({'pane_id': pane_id}), Pane) + + +def test_findWhere_None(server, session): + """.findWhere returns None if no results found.""" + + while True: + nonexistant_session = TEST_SESSION_PREFIX + next(namer) + + if not server.has_session(nonexistant_session): + break + + assert server.findWhere({ + 'session_name': nonexistant_session + }) is None + + +def test_findWhere_multiple_attrs(server, session): + """.findWhere returns objects with multiple attributes.""" + + for session in server.sessions: + session_id = session.get('session_id') + session_name = session.get('session_name') + find_where = server.findWhere({ + 'session_id': session_id, + 'session_name': session_name + }) + + assert find_where == session + assert isinstance(find_where, Session) + + # session.findWhere + for window in session.windows: + window_id = window.get('window_id') + window_index = window.get('window_index') + + find_where = session.findWhere({ + 'window_id': window_id, + 'window_index': window_index + }) + + assert find_where == window + assert isinstance(find_where, Window) + + # window.findWhere + for pane in window.panes: + pane_id = pane.get('pane_id') + pane_tty = pane.get('pane_tty') + + find_where = window.findWhere({ + 'pane_id': pane_id, + 'pane_tty': pane_tty + }) + + assert find_where == pane + assert isinstance(find_where, Pane) + + +def test_where(server, session): + """Test self.where() returns matching objects.""" + + window = session.attached_window() + window.split_window() # create second pane + + for session in server.sessions: + session_id = session.get('session_id') + session_name = session.get('session_name') + where = server.where({ + 'session_id': session_id, + 'session_name': session_name + }) + + assert len(where) == 1 + assert isinstance(where, list) + assert where[0] == session + assert isinstance(where[0], Session) + + # session.where + for window in session.windows: + window_id = window.get('window_id') + window_index = window.get('window_index') + + where = session.where({ + 'window_id': window_id, + 'window_index': window_index + }) + + assert len(where) == 1 + assert isinstance(where, list) + assert where[0] == window + assert isinstance(where[0], Window) + + # window.where + for pane in window.panes: + pane_id = pane.get('pane_id') + pane_tty = pane.get('pane_tty') + + where = window.where({ + 'pane_id': pane_id, + 'pane_tty': pane_tty + }) + + assert len(where) == 1 + assert isinstance(where, list) + assert where[0] == pane + assert isinstance(where[0], Pane) + + +def test_getById(server, session): + """Test self.getById() retrieves child object.""" + + window = session.attached_window() + + window.split_window() # create second pane + + for session in server.sessions: + session_id = session.get('session_id') + get_by_id = server.getById(session_id) + + assert get_by_id == session + assert isinstance(get_by_id, Session) + assert server.getById('$' + next(namer)) is None + + # session.getById + for window in session.windows: + window_id = window.get('window_id') + + get_by_id = session.getById(window_id) + + assert get_by_id == window + assert isinstance(get_by_id, Window) + + assert session.getById('@' + next(namer)) is None + + # window.getById + for pane in window.panes: + pane_id = pane.get('pane_id') + + get_by_id = window.getById(pane_id) + + assert get_by_id == pane + assert isinstance(get_by_id, Pane) + assert window.getById('%' + next(namer)) is None diff --git a/tests/test_util.py b/tests/test_util.py new file mode 100644 index 0000000000..640528b99b --- /dev/null +++ b/tests/test_util.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +"""Tests for utility functions in tmux. + +tmuxp.tests.util +~~~~~~~~~~~~~~~~ + +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import os +import re +import pytest + +from tmuxp import exc +from tmuxp.exc import BeforeLoadScriptError, BeforeLoadScriptNotExists +from tmuxp.util import has_required_tmux_version, run_before_script + +from .helpers import fixtures_dir + +logger = logging.getLogger(__name__) + +version_regex = re.compile(r'[0-9]\.[0-9]') + + +def test_no_arg_uses_tmux_version(): + """Test the :meth:`has_required_tmux_version`.""" + result = has_required_tmux_version() + assert version_regex.match(result) is not None + + +def test_ignores_letter_versions(): + """Ignore letters such as 1.8b. + + See ticket https://github.com/tony/tmuxp/issues/55. + + In version 0.1.7 this is adjusted to use LooseVersion, in order to + allow letters. + + """ + result = has_required_tmux_version('1.9a') + assert version_regex.match(result) is not None + + result = has_required_tmux_version('1.8a') + assert result == r'1.8' + + +def test_error_version_less_1_7(): + with pytest.raises(exc.TmuxpException) as excinfo: + has_required_tmux_version('1.7') + excinfo.match(r'tmuxp only supports') + + with pytest.raises(exc.TmuxpException) as excinfo: + has_required_tmux_version('1.6a') + + excinfo.match(r'tmuxp only supports') + + has_required_tmux_version('1.9a') + + +def test_raise_BeforeLoadScriptNotExists_if_not_exists(): + script_file = os.path.join(fixtures_dir, 'script_noexists.sh') + + with pytest.raises(BeforeLoadScriptNotExists): + run_before_script(script_file) + + with pytest.raises(OSError): + run_before_script(script_file) + + +def test_raise_BeforeLoadScriptError_if_retcode(): + script_file = os.path.join(fixtures_dir, 'script_failed.sh') + + with pytest.raises(BeforeLoadScriptError): + run_before_script(script_file) + + +def test_return_stdout_if_ok(capsys): + script_file = os.path.join(fixtures_dir, 'script_complete.sh') + + run_before_script(script_file) + out, err = capsys.readouterr() + assert 'hello' in out + + +def test_beforeload_returncode(): + script_file = os.path.join(fixtures_dir, 'script_failed.sh') + + with pytest.raises(exc.BeforeLoadScriptError) as excinfo: + run_before_script(script_file) + assert excinfo.match(r'113') + + +def test_beforeload_returns_stderr_messages(): + script_file = os.path.join(fixtures_dir, 'script_failed.sh') + + with pytest.raises(exc.BeforeLoadScriptError) as excinfo: + run_before_script(script_file) + assert excinfo.match(r'failed with returncode') diff --git a/tests/test_window.py b/tests/test_window.py new file mode 100644 index 0000000000..d824233602 --- /dev/null +++ b/tests/test_window.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp Window object.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import pytest + +from tmuxp import Pane, Server, Window + + +logger = logging.getLogger(__name__) + + +def test_select_window(session): + window_count = len(session._windows) + # to do, get option for base-index from tmux + # for now hoever, let's get the index from the first window. + assert window_count == 1 + + window_base_index = int( + session.attached_window().get('window_index')) + + window = session.new_window(window_name='testing 3') + + # self.assertEqual(2, + # int(session.attached_window().get('window_index'))) + assert int(window_base_index) + 1 == int(window.get('window_index')) + + session.select_window(window_base_index) + assert window_base_index == \ + int(session.attached_window().get('window_index')) + + session.select_window('testing 3') + assert int(window_base_index) + 1 == \ + int(session.attached_window().get('window_index')) + + assert len(session._windows) == 2 + + +def test_zfresh_window_data(session): + pane_base_index = int( + session.attached_window().show_window_option( + 'pane-base-index', g=True + ) + ) + + assert len(session.windows) == 1 + + assert len(session.attached_window().panes) == 1 + current_windows = len(session._windows) + assert session.get('session_id') != '@0' + assert current_windows == 1 + + assert len(session.attached_window().panes) == 1 + assert isinstance(session.server, Server) + # len(session.attached_window().panes)) + + assert len(session.windows), 1 + assert len(session.attached_window().panes) == 1 + for w in session.windows: + assert isinstance(w, Window) + window = session.attached_window() + assert isinstance(window, Window) + assert len(session.attached_window().panes) == 1 + window.split_window() + session.attached_window().select_pane(pane_base_index) + session.attached_pane().send_keys('cd /srv/www/flaskr') + session.attached_window().select_pane(pane_base_index + 1) + session.attached_pane().send_keys('source .venv/bin/activate') + session.new_window(window_name='second') + current_windows += 1 + assert current_windows == len(session._windows) + session.new_window(window_name='hey') + current_windows += 1 + assert current_windows == len(session._windows) + + session.select_window(1) + session.kill_window(target_window='hey') + current_windows -= 1 + assert current_windows == len(session._windows) + + +def test_newest_pane_data(session): + window = session.new_window(window_name='test', attach=True) + assert isinstance(window, Window) + assert len(window.panes) == 1 + window.split_window(attach=True) + + assert len(window.panes) == 2 + # note: the below used to accept -h, removing because split_window now + # has attach as its only argument now + window.split_window(attach=True) + assert len(window.panes) == 3 + + +def test_attached_pane(session): + """Window.attached_window() returns active Pane.""" + + window = session.attached_window() # current window + assert isinstance(window.attached_pane(), Pane) + + +def test_split_window(session): + """Window.split_window() splits window, returns new Pane.""" + window_name = 'test split window' + window = session.new_window(window_name=window_name, attach=True) + pane = window.split_window() + assert len(window.panes) == 2 + assert isinstance(pane, Pane) + + +@pytest.mark.parametrize("window_name_before,window_name_after", [ + ('test', 'ha ha ha fjewlkjflwef'), + ('test', 'hello \\ wazzup 0'), +]) +def test_window_rename(session, window_name_before, window_name_after): + """Window.rename_window().""" + window_name_before = 'test' + window_name_after = 'ha ha ha fjewlkjflwef' + + session.set_option('automatic-rename', 'off') + window = session.new_window( + window_name=window_name_before, attach=True) + + assert window == session.attached_window() + assert window.get('window_name') == window_name_before + + window.rename_window(window_name_after) + + window = session.attached_window() + + assert window.get('window_name') == window_name_after + + window = session.attached_window() + + assert window.get('window_name') == window_name_after + + +def test_kill_window(session): + session.new_window() + # create a second window to not kick out the client. + # there is another way to do this via options too. + + w = session.attached_window() + + w.get('window_id') + + w.kill_window() + with pytest.raises(IndexError): + w.get('window_id') + + +def test_show_window_options(session): + """Window.show_window_options() returns dict.""" + window = session.new_window(window_name='test_window') + + options = window.show_window_options() + assert isinstance(options, dict) + + +def test_set_show_window_options(session): + """Set option then Window.show_window_options(key).""" + window = session.new_window(window_name='test_window') + + window.set_window_option('main-pane-height', 20) + assert window.show_window_options('main-pane-height') == 20 + + window.set_window_option('main-pane-height', 40) + assert window.show_window_options('main-pane-height') == 40 + assert window.show_window_options()['main-pane-height'] == 40 + + +def test_show_window_option(session): + """Set option then Window.show_window_option(key).""" + window = session.new_window(window_name='test_window') + + window.set_window_option('main-pane-height', 20) + assert window.show_window_option('main-pane-height') == 20 + + window.set_window_option('main-pane-height', 40) + assert window.show_window_option('main-pane-height') == 40 + assert window.show_window_option('main-pane-height') == 40 + + +def test_set_window_option_bad(session): + """Window.set_window_option raises ValueError for bad option key.""" + + window = session.new_window(window_name='test_window') + + with pytest.raises(ValueError): + window.set_window_option('afewewfew', 43) diff --git a/tests/test_workspacebuilder.py b/tests/test_workspacebuilder.py new file mode 100644 index 0000000000..10077a2c20 --- /dev/null +++ b/tests/test_workspacebuilder.py @@ -0,0 +1,619 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp workspacebuilder.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import os +import time + +import kaptan +import pytest +from flaky import flaky + +from tmuxp import Window, config, exc +from tmuxp._compat import text_type +from tmuxp.workspacebuilder import WorkspaceBuilder + +from .fixtures._util import loadfixture +from .helpers import example_dir, fixtures_dir, temp_session + +logger = logging.getLogger(__name__) + + +def test_split_windows(session): + yaml_config = loadfixture("workspacebuilder/two_pane.yaml") + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + builder = WorkspaceBuilder(sconf=sconfig) + + window_count = len(session._windows) # current window count + assert len(s._windows) == window_count + for w, wconf in builder.iter_create_windows(s): + for p in builder.iter_create_panes(w, wconf): + p = p + assert len(s._windows) == window_count + assert isinstance(w, Window) + + assert len(s._windows) == window_count + window_count += 1 + + +def test_split_windows_three_pane(session): + yaml_config = loadfixture("workspacebuilder/three_pane.yaml") + + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + builder = WorkspaceBuilder(sconf=sconfig) + + window_count = len(s._windows) # current window count + assert len(s._windows) == window_count + for w, wconf in builder.iter_create_windows(s): + for p in builder.iter_create_panes(w, wconf): + p = p + assert len(s._windows) == window_count + assert isinstance(w, Window) + + assert len(s._windows) == window_count + window_count += 1 + w.set_window_option('main-pane-height', 50) + w.select_layout(wconf['layout']) + + +def test_focus_pane_index(session): + yaml_config = loadfixture('workspacebuilder/focus_and_pane.yaml') + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + builder.build(session=session) + + assert session.attached_window().get('window_name') == \ + 'focused window' + + pane_base_index = int( + session.attached_window().show_window_option( + 'pane-base-index', g=True + ) + ) + + if not pane_base_index: + pane_base_index = 0 + else: + pane_base_index = int(pane_base_index) + + # get the pane index for each pane + pane_base_indexes = [] + for pane in session.attached_window().panes: + pane_base_indexes.append(int(pane.get('pane_index'))) + + pane_indexes_should_be = [pane_base_index + x for x in range(0, 3)] + assert pane_indexes_should_be == pane_base_indexes + + w = session.attached_window() + + assert w.get('window_name') != 'man' + + pane_path = '/usr' + for i in range(20): + p = w.attached_pane() + p.server._update_panes() + if p.get('pane_current_path') == pane_path: + break + time.sleep(.4) + + assert p.get('pane_current_path') == pane_path + + proc = session.cmd('show-option', '-gv', 'base-index') + base_index = int(proc.stdout[0]) + session.server._update_windows() + + window3 = session.findWhere({'window_index': str(base_index + 2)}) + assert isinstance(window3, Window) + + p = None + pane_path = '/' + for i in range(10): + p = window3.attached_pane() + p.server._update_panes() + if p.get('pane_current_path') == pane_path: + break + time.sleep(.4) + + assert p.get('pane_current_path') == pane_path + + +@flaky(max_runs=5, min_passes=1) +def test_suppress_history(session): + yaml_config = loadfixture("workspacebuilder/suppress_history.yaml") + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=session) + + inHistoryPane = session.findWhere( + {'window_name': 'inHistory'}).attached_pane() + isMissingPane = session.findWhere( + {'window_name': 'isMissing'}).attached_pane() + + def assertHistory(cmd, hist): + return 'inHistory' in cmd and cmd == hist + + def assertIsMissing(cmd, hist): + return 'isMissing' in cmd and cmd != hist + + for p, assertCase in [ + (inHistoryPane, assertHistory,), (isMissingPane, assertIsMissing,) + ]: + correct = False + p.window.select_window() + p.select_pane() + + # Print the last-in-history command in the pane + session.cmd('send-keys', ' fc -ln -1') + session.cmd('send-keys', 'Enter') + + for i in range(10): + time.sleep(0.1) + + # Get the contents of the pane + session.cmd('capture-pane') + captured_pane = session.cmd('show-buffer') + session.cmd('delete-buffer') + + # Parse the sent and last-in-history commands + sent_cmd = captured_pane.stdout[0].strip() + history_cmd = captured_pane.stdout[-2].strip() + + if assertCase(sent_cmd, history_cmd): + correct = True + break + assert correct, "Unknown sent command: [%s]" % sent_cmd + + +def test_window_options(session): + yaml_config = loadfixture("workspacebuilder/window_options.yaml") + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + window_count = len(session._windows) # current window count + assert len(s._windows) == window_count + for w, wconf in builder.iter_create_windows(s): + for p in builder.iter_create_panes(w, wconf): + p = p + assert len(s._windows) == window_count + assert isinstance(w, Window) + assert w.show_window_option('main-pane-height') == 5 + + assert len(s._windows) == window_count + window_count += 1 + w.select_layout(wconf['layout']) + + +def test_window_shell(session): + yaml_config = loadfixture("workspacebuilder/window_shell.yaml") + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + for w, wconf in builder.iter_create_windows(s): + if 'window_shell' in wconf: + assert wconf['window_shell'] == text_type('top') + for i in range(10): + session.server._update_windows() + if w['window_name'] != 'top': + break + time.sleep(.2) + + assert w.get('window_name') != text_type('top') + + +def test_environment_variables(session): + yaml_config = loadfixture("workspacebuilder/environment_vars.yaml") + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session) + + assert session.show_environment('FOO') == 'BAR' + assert session.show_environment('PATH') == '/tmp' + + +def test_automatic_rename_option(session): + """With option automatic-rename: on.""" + yaml_config = loadfixture("workspacebuilder/window_automatic_rename.yaml") + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + builder = WorkspaceBuilder(sconf=sconfig) + + window_count = len(session._windows) # current window count + assert len(s._windows) == window_count + for w, wconf in builder.iter_create_windows(s): + for p in builder.iter_create_panes(w, wconf): + p = p + assert len(s._windows), window_count + assert isinstance(w, Window) + assert w.show_window_option('automatic-rename') == 'on' + + assert len(s._windows) == window_count + + window_count += 1 + w.select_layout(wconf['layout']) + + assert s.get('session_name') != 'tmuxp' + w = s.windows[0] + + for i in range(10): + session.server._update_windows() + if w.get('window_name') != 'sh': + break + time.sleep(.2) + + assert w.get('window_name') != 'sh' + + pane_base_index = w.show_window_option('pane-base-index', g=True) + w.select_pane(pane_base_index) + + for i in range(10): + session.server._update_windows() + if w.get('window_name') == 'sh': + break + time.sleep(.3) + + assert w.get('window_name') == text_type('sh') + + w.select_pane('-D') + for i in range(10): + session.server._update_windows() + if w['window_name'] != 'sh': + break + time.sleep(.2) + + assert w.get('window_name') != text_type('sh') + + +def test_blank_pane_count(session): + """:todo: Verify blank panes of various types build into workspaces.""" + yaml_config_file = os.path.join(example_dir, 'blank-panes.yaml') + test_config = kaptan.Kaptan().import_config( + yaml_config_file).get() + test_config = config.expand(test_config) + builder = WorkspaceBuilder(sconf=test_config) + builder.build(session=session) + + assert session == builder.session + + window1 = session.findWhere({'window_name': 'Blank pane test'}) + assert len(window1._panes) == 3 + + window2 = session.findWhere({'window_name': 'More blank panes'}) + assert len(window2._panes) == 3 + + window3 = session.findWhere( + {'window_name': 'Empty string (return)'} + ) + assert len(window3._panes) == 3 + + window4 = session.findWhere({'window_name': 'Blank with options'}) + assert len(window4._panes) == 2 + + +def test_start_directory(session, tmpdir): + yaml_config = loadfixture("workspacebuilder/start_directory.yaml") + test_dir = str(tmpdir.mkdir('foo bar')) + test_config = yaml_config.format( + TMP_DIR=str(tmpdir), + TEST_DIR=test_dir + ) + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(test_config).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=session) + + assert session == builder.session + dirs = [ + '/usr/bin', '/dev', test_dir, + '/usr', + '/usr' + ] + + for path, window in zip(dirs, session.windows): + for p in window.panes: + for i in range(60): + p.server._update_panes() + pane_path = p.get('pane_current_path') + if pane_path is None: + pass + elif ( + path in pane_path or + pane_path == path + ): + result = ( + path == pane_path or + path in pane_path + ) + break + time.sleep(.2) + + # handle case with OS X adding /private/ to /tmp/ paths + assert result + + +def test_start_directory_relative(session, tmpdir): + """Same as above test, but with relative start directory, mimicing + loading it from a location of project file. Like:: + + $ tmuxp load ~/workspace/myproject/.tmuxp.yaml + + instead of:: + + $ cd ~/workspace/myproject/.tmuxp.yaml + $ tmuxp load . + + """ + yaml_config = \ + loadfixture("workspacebuilder/start_directory_relative.yaml") + + test_dir = str(tmpdir.mkdir('foo bar')) + config_dir = str(tmpdir.mkdir('testRelConfigDir')) + test_config = yaml_config.format( + TEST_DIR=test_dir, + ) + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(test_config).get() + # the second argument of os.getcwd() mimics the behavior + # the CLI loader will do, but it passes in the config file's location. + sconfig = config.expand(sconfig, config_dir) + + sconfig = config.trickle(sconfig) + + assert os.path.exists(config_dir) + assert os.path.exists(test_dir) + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=session) + + assert session == builder.session + + dirs = [ + '/usr/bin', + '/dev', + test_dir, + config_dir, + config_dir, + ] + + for path, window in zip(dirs, session.windows): + for p in window.panes: + for i in range(60): + p.server._update_panes() + # Handle case where directories resolve to /private/ in OSX + pane_path = p.get('pane_current_path') + if pane_path is None: + pass + elif ( + path in pane_path or + pane_path == path + ): + result = ( + path == pane_path or + path in pane_path + ) + + break + time.sleep(.2) + + assert result + + +def test_pane_order(session): + """Pane ordering based on position in config and ``pane_index``. + + Regression test for https://github.com/tony/tmuxp/issues/15. + + """ + + yaml_config = loadfixture("workspacebuilder/pane_ordering.yaml").format( + HOME=os.path.realpath(os.path.expanduser('~')) + ) + + # test order of `panes` (and pane_index) above aganist pane_dirs + pane_paths = [ + '/usr/bin', + '/usr', + '/usr/sbin', + os.path.realpath(os.path.expanduser('~')) + ] + + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + window_count = len(session._windows) # current window count + assert len(s._windows) == window_count + for w, wconf in builder.iter_create_windows(s): + for p in builder.iter_create_panes(w, wconf): + p = p + assert len(s._windows) == window_count + + assert isinstance(w, Window) + + assert len(s._windows) == window_count + window_count += 1 + + for w in session.windows: + pane_base_index = w.show_window_option('pane-base-index', g=True) + for p_index, p in enumerate(w.list_panes(), start=pane_base_index): + assert int(p_index) == int(p.get('pane_index')) + + # pane-base-index start at base-index, pane_paths always start + # at 0 since python list. + pane_path = pane_paths[p_index - pane_base_index] + + for i in range(60): + p.server._update_panes() + if p.get('pane_current_path') == pane_path: + break + time.sleep(.2) + + assert p.get('pane_current_path'), pane_path + + +def test_window_index(session): + yaml_config = loadfixture("workspacebuilder/window_index.yaml") + proc = session.cmd('show-option', '-gv', 'base-index') + base_index = int(proc.stdout[0]) + name_index_map = { + 'zero': 0 + base_index, + 'one': 1 + base_index, + 'five': 5, + } + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + for window, wconf in builder.iter_create_windows(session): + expected_index = name_index_map[window['window_name']] + assert int(window['window_index']) == expected_index + + +def test_before_load_throw_error_if_retcode_error(server): + config_script_fails = loadfixture( + "workspacebuilder/config_script_fails.yaml" + ) + sconfig = kaptan.Kaptan(handler='yaml') + yaml = config_script_fails.format( + fixtures_dir=fixtures_dir, + script_failed=os.path.join(fixtures_dir, 'script_failed.sh') + ) + + sconfig = sconfig.import_config(yaml).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + with temp_session(server) as sess: + session_name = sess.get('session_name') + + with pytest.raises(exc.BeforeLoadScriptError): + builder.build(session=sess) + + result = server.has_session(session_name) + assert not result, \ + "Kills session if before_script exits with errcode" + + +def test_before_load_throw_error_if_file_not_exists(server): + config_script_not_exists = loadfixture( + "workspacebuilder/config_script_not_exists.yaml" + ) + sconfig = kaptan.Kaptan(handler='yaml') + yaml = config_script_not_exists.format( + fixtures_dir=fixtures_dir, + script_not_exists=os.path.join( + fixtures_dir, 'script_not_exists.sh' + ) + ) + sconfig = sconfig.import_config(yaml).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + with temp_session(server) as sess: + session_name = sess.get('session_name') + temp_session_exists = server.has_session( + sess.get('session_name') + ) + assert temp_session_exists + with pytest.raises( + (exc.BeforeLoadScriptNotExists, OSError), + ) as excinfo: + builder.build(session=sess) + excinfo.match(r'No such file or directory') + result = server.has_session(session_name) + assert not result, "Kills session if before_script doesn't exist" + + +def test_before_load_true_if_test_passes(server): + config_script_completes = loadfixture( + "workspacebuilder/config_script_completes.yaml" + ) + assert os.path.exists( + os.path.join(fixtures_dir, 'script_complete.sh')) + sconfig = kaptan.Kaptan(handler='yaml') + yaml = config_script_completes.format( + fixtures_dir=fixtures_dir, + script_complete=os.path.join(fixtures_dir, 'script_complete.sh') + ) + + sconfig = sconfig.import_config(yaml).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + with temp_session(server) as session: + builder.build(session=session) + + +def test_before_load_true_if_test_passes_with_args(server): + config_script_completes = loadfixture( + "workspacebuilder/config_script_completes.yaml" + ) + + assert( + os.path.exists(os.path.join(fixtures_dir, 'script_complete.sh')) + ) + sconfig = kaptan.Kaptan(handler='yaml') + yaml = config_script_completes.format( + fixtures_dir=fixtures_dir, + script_complete=os.path.join( + fixtures_dir, 'script_complete.sh' + ) + ' -v' + ) + + sconfig = sconfig.import_config(yaml).get() + sconfig = config.expand(sconfig) + sconfig = config.trickle(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + + with temp_session(server) as session: + builder.build(session=session) diff --git a/tests/test_workspacefreezer.py b/tests/test_workspacefreezer.py new file mode 100644 index 0000000000..e3953153cc --- /dev/null +++ b/tests/test_workspacefreezer.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +"""Test for tmuxp workspacefreezer.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +import logging +import time + +import kaptan + +from tmuxp import config +from tmuxp.workspacebuilder import WorkspaceBuilder, freeze + +from .fixtures._util import loadfixture + +logger = logging.getLogger(__name__) + + +def test_freeze_config(session): + yaml_config = loadfixture("workspacefreezer/sampleconfig.yaml") + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=session) + assert session == builder.session + + time.sleep(.50) + + session = session + sconf = freeze(session) + + config.validate_schema(sconf) + + sconf = config.inline(sconf) + + kaptanconf = kaptan.Kaptan() + kaptanconf = kaptanconf.import_config(sconf) + kaptanconf.export( + 'json', + indent=2 + ) + kaptanconf.export( + 'yaml', + indent=2, + default_flow_style=False, + safe=True + ) diff --git a/tests/tests/__init__.py b/tests/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/tests/test_helpers.py b/tests/tests/test_helpers.py new file mode 100644 index 0000000000..68fbc675b1 --- /dev/null +++ b/tests/tests/test_helpers.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +"""Tests for .'s helper and utility functions.""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals, with_statement) + +from ..helpers import get_test_session_name, temp_session + + +def test_kills_session(server): + server = server + session_name = get_test_session_name(server=server) + + with temp_session( + server=server, session_name=session_name + ): + result = server.has_session(session_name) + assert result + + assert not server.has_session(session_name) + + +def test_if_session_killed_before(server): + """Handles situation where session already closed within context""" + + server = server + session_name = get_test_session_name(server=server) + + with temp_session(server=server, session_name=session_name): + + # an error or an exception within a temp_session kills the session + server.kill_session(session_name) + + result = server.has_session(session_name) + assert not result + + # really dead? + assert not server.has_session(session_name) diff --git a/tmuxp/testsuite/__init__.py b/tmuxp/testsuite/__init__.py deleted file mode 100644 index 4654dedf18..0000000000 --- a/tmuxp/testsuite/__init__.py +++ /dev/null @@ -1,241 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for tmuxp. - -tmuxp.tests -~~~~~~~~~~~ - -""" -from __future__ import absolute_import, division, print_function, \ - with_statement, unicode_literals - -import logging -import pkgutil -import sys - -from tmuxp import log -from tmuxp._compat import string_types, PY2, reraise -from tmuxp.server import Server - -if sys.version_info < (2, 7): - import unittest2 as unittest -else: - import unittest - -t = Server() -t.socket_name = 'tmuxp_test' - -from tmuxp.testsuite import helpers # NOQA - -logger = logging.getLogger() # Logger functionality - -if not logger.handlers: - channel = logging.StreamHandler() - channel.setFormatter(log.DebugLogFormatter()) - logger.addHandler(channel) - logger.setLevel('INFO') - - # enable DEBUG message if channel is at testsuite + testsuite.* packages. - testsuite_logger = logging.getLogger(__name__) - - testsuite_logger.setLevel('INFO') - - -class ImportStringError(ImportError): - """Provides information about a failed :func:`import_string` attempt.""" - - #: String in dotted notation that failed to be imported. - import_name = None - #: Wrapped exception. - exception = None - - def __init__(self, import_name, exception): - self.import_name = import_name - self.exception = exception - - msg = ( - 'import_string() failed for %r. Possible reasons are:\n\n' - '- missing __init__.py in a package;\n' - '- package or module path not included in sys.path;\n' - '- duplicated package or module name taking precedence in ' - 'sys.path;\n' - '- missing module, class, function or variable;\n\n' - 'Debugged import:\n\n%s\n\n' - 'Original exception:\n\n%s: %s') - - name = '' - tracked = [] - for part in import_name.replace(':', '.').split('.'): - name += (name and '.') + part - imported = import_string(name, silent=True) - if imported: - tracked.append((name, getattr(imported, '__file__', None))) - else: - track = ['- %r found in %r.' % (n, i) for n, i in tracked] - track.append('- %r not found.' % name) - msg = msg % (import_name, '\n'.join(track), - exception.__class__.__name__, str(exception)) - break - - ImportError.__init__(self, msg) - - def __repr__(self): - return '<%s(%r, %r)>' % (self.__class__.__name__, self.import_name, - self.exception) - - -def import_string(import_name, silent=False): - """Imports an object based on a string. This is useful if you want to - use import paths as endpoints or something similar. An import path can - be specified either in dotted notation (``xml.sax.saxutils.escape``) - or with a colon as object delimiter (``xml.sax.saxutils:escape``). - - If `silent` is True the return value will be `None` if the import fails. - - :param import_name: the dotted name for the object to import. - :param silent: if set to `True` import errors are ignored and - `None` is returned instead. - :return: imported object - """ - # XXX: py3 review needed - assert isinstance(import_name, string_types) - # force the import name to automatically convert to strings - import_name = str(import_name) - try: - if ':' in import_name: - module, obj = import_name.split(':', 1) - elif '.' in import_name: - module, obj = import_name.rsplit('.', 1) - else: - return __import__(import_name) - # __import__ is not able to handle unicode strings in the fromlist - # if the module is a package - if PY2 and isinstance(obj, unicode): - obj = obj.encode('utf-8') - try: - return getattr(__import__(module, None, None, [obj]), obj) - except (ImportError, AttributeError): - # support importing modules not yet set up by the parent module - # (or package for that matter) - modname = module + '.' + obj - __import__(modname) - return sys.modules[modname] - except ImportError as e: - if not silent: - reraise( - ImportStringError, - ImportStringError(import_name, e), - sys.exc_info()[2]) - - -def find_modules(import_path, include_packages=False, recursive=False): - """Find all the modules below a package. This can be useful to - automatically import all views / controllers so that their metaclasses / - function decorators have a chance to register themselves on the - application. - - Packages are not returned unless `include_packages` is `True`. This can - also recursively list modules but in that case it will import all the - packages to get the correct load path of that module. - - :param import_name: the dotted name for the package to find child modules. - :param include_packages: set to `True` if packages should be returned, too. - :param recursive: set to `True` if recursion should happen. - :return: generator - """ - module = import_string(import_path) - path = getattr(module, '__path__', None) - if path is None: - raise ValueError('%r is not a package' % import_path) - basename = module.__name__ + '.' - for importer, modname, ispkg in pkgutil.iter_modules(path): - modname = basename + modname - if ispkg: - if include_packages: - yield modname - if recursive: - for item in find_modules(modname, include_packages, True): - yield item - else: - yield modname - - -def iter_suites(package): - """Yields all testsuites.""" - for module in find_modules(package, include_packages=True): - mod = __import__(module, fromlist=['*']) - if hasattr(mod, 'suite'): - yield mod.suite() - - -def find_all_tests(suite): - """Yields all the tests and their names from a given suite.""" - suites = [suite] - while suites: - s = suites.pop() - try: - suites.extend(s) - except TypeError: - yield s, '%s.%s.%s' % ( - s.__class__.__module__, - s.__class__.__name__, - s._testMethodName - ) - - -class BetterLoader(unittest.TestLoader): - """A nicer loader that solves two problems. First of all we are setting - up tests from different sources and we're doing this programmatically - which breaks the default loading logic so this is required anyways. - Secondly this loader has a nicer interpolation for test names than the - default one so you can just do ``run-tests.py ViewTestCase`` and it - will work. - """ - - def getRootSuite(self): - return suite() - - def loadTestsFromName(self, name, module=None): - root = self.getRootSuite() - if name == 'suite': - return root - - all_tests = [] - for testcase, testname in find_all_tests(root): - if testname == name or \ - testname.endswith('.' + name) or \ - ('.' + name + '.') in testname or \ - testname.startswith(name + '.'): - all_tests.append(testcase) - - if not all_tests: - raise LookupError('could not find test case for "%s"' % name) - - if len(all_tests) == 1: - return all_tests[0] - rv = unittest.TestSuite() - for test in all_tests: - rv.addTest(test) - return rv - - -def suite(): - """A testsuite that has all the Flask tests. You can use this - function to integrate the Flask tests into your own testsuite - in case you want to test that monkeypatches to Flask do not - break it. - """ - suite = unittest.TestSuite() - for other_suite in iter_suites(__name__): - suite.addTest(other_suite) - return suite - - -def main(): - """Runs the testsuite as command line application.""" - try: - unittest.main(testLoader=BetterLoader(), defaultTest='suite') - except Exception: - import sys - import traceback - traceback.print_exc() - sys.exit(1) diff --git a/tmuxp/testsuite/cli.py b/tmuxp/testsuite/cli.py deleted file mode 100644 index c3149324f1..0000000000 --- a/tmuxp/testsuite/cli.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp command line interface. - -tmuxp.tests.cli -~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import os -import shutil -import tempfile -import unittest - -from tmuxp import cli, config -from tmuxp.testsuite.helpers import TestCase - -logger = logging.getLogger(__name__) - - -class StartupTest(TestCase): - - """test startup_cli().""" - - def setUp(self): - self.tmp_dir = tempfile.mkdtemp(suffix='tmuxp') - if os.path.isdir(self.tmp_dir): - shutil.rmtree(self.tmp_dir) - - def test_creates_config_dir_not_exists(self): - """cli.startup() creates config dir if not exists.""" - - self.assertFalse(os.path.exists(self.tmp_dir)) - cli.startup(self.tmp_dir) - - self.assertTrue(os.path.exists(self.tmp_dir)) - - def tearDown(self): - if os.path.isdir(self.tmp_dir): - shutil.rmtree(self.tmp_dir) - logger.debug('wiped %s' % self.tmp_dir) - - -class FindConfigsTest(TestCase): - - """test in_dir() test.""" - - def setUp(self): - self.tmp_dir = tempfile.mkdtemp(suffix='tmuxp') - if os.path.isdir(self.tmp_dir): - shutil.rmtree(self.tmp_dir) - - def test_in_dir_from_config_dir(self): - """config.in_dir() finds configs config dir.""" - - cli.startup(self.tmp_dir) - with tempfile.NamedTemporaryFile( - dir=self.tmp_dir, - prefix='myconfig', - suffix='.yaml' - ): - with tempfile.NamedTemporaryFile( - dir=self.tmp_dir, - prefix='myconfig', - suffix='.json' - ): - configs_found = config.in_dir(self.tmp_dir) - - self.assertEqual(len(configs_found), 2) - - def test_in_dir_from_current_dir(self): - """config.in_dir() find configs current dir.""" - pass # TODO - - def test_ignore_non_configs_from_current_dir(self): - """cli.in_dir() ignore non-config from config dir.""" - - cli.startup(self.tmp_dir) - with tempfile.NamedTemporaryFile( - dir=self.tmp_dir, - prefix='myconfig', - suffix='.psd' - ): - with tempfile.NamedTemporaryFile( - dir=self.tmp_dir, - prefix='watmyconfig', - suffix='.json' - ): - configs_found = config.in_dir(self.tmp_dir) - self.assertEqual(len(configs_found), 1) - - def test_get_configs_cwd(self): - """config.in_cwd() find config in shell current working directory.""" - - current_dir = os.getcwd() - - configs_found = config.in_cwd() - - # create a temporary folder and change dir into it - tmp_dir = tempfile.mkdtemp(suffix='tmuxp') - os.chdir(tmp_dir) - - try: - config1 = open('.tmuxp.json', 'w+b') - config1.close() - - configs_found = config.in_cwd() - finally: - os.remove(config1.name) - - self.assertEqual(len(configs_found), 1) - self.assertIn('.tmuxp.json', configs_found) - - # clean up - os.chdir(current_dir) - if os.path.isdir(tmp_dir): - shutil.rmtree(tmp_dir) - - def tearDown(self): - if os.path.isdir(self.tmp_dir): - shutil.rmtree(self.tmp_dir) - logger.debug('wiped %s' % self.tmp_dir) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(FindConfigsTest)) - suite.addTest(unittest.makeSuite(StartupTest)) - return suite diff --git a/tmuxp/testsuite/config.py b/tmuxp/testsuite/config.py deleted file mode 100644 index f22c53a463..0000000000 --- a/tmuxp/testsuite/config.py +++ /dev/null @@ -1,1124 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp configuration import, inlining, expanding and export. - -tmuxp.tests.config -~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import os -import shutil -import tempfile -import unittest - -import kaptan - -from tmuxp import config, exc -from tmuxp.testsuite.helpers import TestCase -from tmuxp.testsuite.util import EnvironmentVarGuard - -logger = logging.getLogger(__name__) -TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') -current_dir = os.path.abspath(os.path.dirname(__file__)) -example_dir = os.path.abspath(os.path.join( - current_dir, '..', '..', 'examples')) - - -sampleconfigdict = { - 'session_name': 'sampleconfig', - 'start_directory': '~', - 'windows': [ - { - 'window_name': 'editor', - 'panes': [ - { - 'start_directory': '~', - 'shell_command': ['vim'], - }, { - 'shell_command': ['cowsay "hey"'] - }, - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'panes': [{ - 'shell_command': ['tail -F /var/log/syslog'], - 'start_directory':'/var/log' - }] - }, - { - 'options': { - 'automatic_rename': True, - }, - 'panes': [ - {'shell_command': ['htop']} - ] - } - ] -} - - -class ImportExportTest(TestCase): - - def setUp(self): - self.tmp_dir = tempfile.mkdtemp(suffix='tmuxp') - - def tearDown(self): - if os.path.isdir(self.tmp_dir): - shutil.rmtree(self.tmp_dir) - logging.debug('wiped %s' % TMUXP_DIR) - - def test_export_json(self): - json_config_file = os.path.join(self.tmp_dir, 'config.json') - - configparser = kaptan.Kaptan() - configparser.import_config(sampleconfigdict) - - json_config_data = configparser.export('json', indent=2) - - with open(json_config_file, 'w') as buf: - buf.write(json_config_data) - - new_config = kaptan.Kaptan() - new_config_data = new_config.import_config(json_config_file).get() - self.assertDictEqual(sampleconfigdict, new_config_data) - - def test_export_yaml(self): - yaml_config_file = os.path.join(self.tmp_dir, 'config.yaml') - - configparser = kaptan.Kaptan() - sampleconfig = config.inline(sampleconfigdict) - configparser.import_config(sampleconfig) - - yaml_config_data = configparser.export( - 'yaml', indent=2, default_flow_style=False) - - with open(yaml_config_file, 'w') as buf: - buf.write(yaml_config_data) - - new_config = kaptan.Kaptan() - new_config_data = new_config.import_config(yaml_config_file).get() - self.assertDictEqual(sampleconfigdict, new_config_data) - - def test_scan_config(self): - configs = [] - - garbage_file = os.path.join(self.tmp_dir, 'config.psd') - with open(garbage_file, 'w') as buf: - buf.write('wat') - - if os.path.exists(self.tmp_dir): - for r, d, f in os.walk(self.tmp_dir): - for filela in ( - x for x in f if x.endswith(('.json', '.ini', 'yaml')) - ): - configs.append(os.path.join( - self.tmp_dir, filela)) - - files = 0 - if os.path.exists(os.path.join(self.tmp_dir, 'config.json')): - files += 1 - self.assertIn(os.path.join( - self.tmp_dir, 'config.json'), configs) - - if os.path.exists(os.path.join(self.tmp_dir, 'config.yaml')): - files += 1 - self.assertIn(os.path.join( - self.tmp_dir, 'config.yaml'), configs) - - if os.path.exists(os.path.join(self.tmp_dir, 'config.ini')): - files += 1 - self.assertIn(os.path.join(self.tmp_dir, 'config.ini'), configs) - - self.assertEqual(len(configs), files) - - -class ExpandTest(TestCase): - - """Assume configuration has been imported into a python dict correctly.""" - - before_config = { - 'session_name': 'sampleconfig', - 'start_directory': '~', - 'windows': [ - { - 'window_name': 'editor', - 'panes': [ - { - 'shell_command': [ - 'vim', - 'top' - ] - }, - { - 'shell_command': ['vim'], - }, - { - 'shell_command': 'cowsay "hey"' - } - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - } - ] - }, - { - 'start_directory': '/var/log', - 'options': {'automatic_rename': True, }, - 'panes': [ - { - 'shell_command': 'htop' - }, - 'vim', - ] - }, - { - 'start_directory': './', - 'panes': [ - 'pwd' - ] - }, - { - 'start_directory': './asdf/', - 'panes': [ - 'pwd' - ] - }, - { - 'start_directory': '../', - 'panes': [ - 'pwd' - ] - }, - { - 'panes': [ - 'top' - ] - } - ] - } - - after_config = { - 'session_name': 'sampleconfig', - 'start_directory': os.path.expanduser('~'), - 'windows': [ - { - 'window_name': 'editor', - 'panes': [ - { - 'shell_command': ['vim', 'top'], - }, - { - 'shell_command': ['vim'], - }, - { - 'shell_command': ['cowsay "hey"'] - }, - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - } - ] - }, - { - 'start_directory': '/var/log', - 'options': {'automatic_rename': True}, - 'panes': [ - {'shell_command': ['htop']}, - {'shell_command': ['vim']} - ] - }, - { - 'start_directory': os.path.normpath( - os.path.join(os.path.expanduser('~'), './') - ), - 'panes': [ - {'shell_command': ['pwd']} - ] - }, - { - 'start_directory': os.path.normpath( - os.path.join(os.path.expanduser('~'), './asdf') - ), - 'panes': [ - {'shell_command': ['pwd']} - ] - }, - { - 'start_directory': os.path.normpath( - os.path.join(os.path.expanduser('~'), '../') - ), - 'panes': [ - {'shell_command': ['pwd']} - ] - }, - - { - 'panes': [ - {'shell_command': ['top']} - ] - } - ] - } - - def test_config(self): - """Expand shell commands from string to list.""" - self.maxDiff = None - test_config = config.expand(self.before_config) - self.assertDictEqual(test_config, self.after_config) - - def test_no_window_name(self): - """Expand shell commands from string to list.""" - - unexpanded_yaml = """ - session_name: sampleconfig - start_directory: '~' - windows: - - window_name: focused window - layout: main-horizontal - focus: true - panes: - - shell_command: - - cd ~ - - shell_command: - - cd /usr - focus: true - - shell_command: - - cd ~ - - echo "moo" - - top - - window_name: window 2 - panes: - - shell_command: - - top - focus: true - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: window 3 - panes: - - shell_command: cd / - focus: true - - pane - - pane - """ - - expanded_yaml = """ - session_name: sampleconfig - start_directory: {HOME} - windows: - - window_name: focused window - layout: main-horizontal - focus: true - panes: - - shell_command: - - cd ~ - - shell_command: - - cd /usr - focus: true - - shell_command: - - cd ~ - - echo "moo" - - top - - window_name: window 2 - panes: - - shell_command: - - top - focus: true - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: window 3 - panes: - - shell_command: - - cd / - focus: true - - shell_command: [] - - shell_command: [] - """.format( - HOME=os.path.expanduser('~') - ) - - self.maxDiff = None - - unexpanded_dict = kaptan.Kaptan(handler='yaml'). \ - import_config(unexpanded_yaml).get() - - expanded_dict = kaptan.Kaptan(handler='yaml'). \ - import_config(expanded_yaml).get() - - self.assertDictEqual( - config.expand(unexpanded_dict), - expanded_dict - ) - - -class InlineTest(TestCase): - - """Tests for :meth:`config.inline()`.""" - - before_config = { - 'session_name': 'sampleconfig', - 'start_directory': '~', - 'windows': [ - { - 'shell_command': ['top'], - 'window_name': 'editor', - 'panes': [ - { - 'shell_command': ['vim'], - }, - { - 'shell_command': ['cowsay "hey"'] - }, - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - } - ] - }, - { - 'options': {'automatic_rename': True, }, - 'panes': [ - {'shell_command': ['htop']} - ] - } - ] - } - - after_config = { - 'session_name': 'sampleconfig', - 'start_directory': '~', - 'windows': [ - { - 'shell_command': 'top', - 'window_name': 'editor', - 'panes': [ - 'vim', - 'cowsay "hey"' - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'panes': [ - 'tail -F /var/log/syslog', - ] - }, - { - 'options': { - 'automatic_rename': True, - }, - 'panes': [ - 'htop' - ] - }, - - ] - } - - def test_config(self): - """:meth:`config.inline()` shell commands list to string.""" - - self.maxDiff = None - test_config = config.inline(self.before_config) - self.assertDictEqual(test_config, self.after_config) - - -class InheritanceTest(TestCase): - - """Test config inheritance for the nested 'start_command'.""" - - config_before = { - 'session_name': 'sampleconfig', - 'start_directory': '/', - 'windows': [ - { - 'window_name': 'editor', - 'start_directory': '~', - 'panes': [ - { - 'shell_command': ['vim'], - }, - { - 'shell_command': ['cowsay "hey"'] - }, - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - } - ] - }, - { - 'window_name': 'shufu', - 'panes': [ - { - 'shell_command': ['htop'], - } - ] - }, - { - 'options': { - 'automatic_rename': True, - }, - 'panes': [ - { - 'shell_command': ['htop'] - } - ] - } - ] - } - - config_after = { - 'session_name': 'sampleconfig', - 'start_directory': '/', - 'windows': [ - { - 'window_name': 'editor', - 'start_directory': '~', - 'panes': [ - { - 'shell_command': ['vim'], - }, { - 'shell_command': ['cowsay "hey"'], - }, - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - } - ] - }, - { - 'window_name': 'shufu', - 'panes': [ - { - 'shell_command': ['htop'], - } - ] - }, - { - 'options': {'automatic_rename': True, }, - 'panes': [ - { - 'shell_command': ['htop'], - } - ] - } - ] - } - - def test_start_directory(self): - config = self.config_before - - # if 'start_directory' in config: - # session_start_directory = config['start_directory'] - # else: - # session_start_directory = None - - # TODO: Look at verifying window_start_directory - # for windowconfitem in config['windows']: - # window_start_directory = None - # - # if 'start_directory' in windowconfitem: - # window_start_directory = windowconfitem['start_directory'] - # elif session_start_directory: - # window_start_directory = session_start_directory - # - # for paneconfitem in windowconfitem['panes']: - # if 'start_directory' in paneconfitem: - # pane_start_directory = paneconfitem['start_directory'] - # elif window_start_directory: - # paneconfitem['start_directory'] = window_start_directory - # elif session_start_directory: - # paneconfitem['start_directory'] = session_start_directory - - self.maxDiff = None - self.assertDictEqual(config, self.config_after) - - -class ShellCommandBeforeTest(TestCase): - - """Config inheritance for the nested 'start_command'.""" - - config_unexpanded = { # shell_command_before is string in some areas - 'session_name': 'sampleconfig', - 'start_directory': '/', - 'windows': [ - { - 'window_name': 'editor', - 'start_directory': '~', - 'shell_command_before': 'source .venv/bin/activate', - 'panes': [ - { - 'shell_command': ['vim'], - }, - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['cowsay "hey"'] - }, - ], - 'layout': 'main-verticle' - }, - { - 'shell_command_before': 'rbenv local 2.0.0-p0', - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - }, - { - } - ] - }, - { - 'window_name': 'shufu', - 'panes': [ - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['htop'], - } - ] - }, - { - 'options': {'automatic_rename': True, }, - 'panes': [ - {'shell_command': ['htop']} - ] - }, - { - 'panes': ['top'] - } - ] - } - - config_expanded = { # shell_command_before is string in some areas - 'session_name': 'sampleconfig', - 'start_directory': '/', - 'windows': [ - { - 'window_name': 'editor', - 'start_directory': os.path.expanduser('~'), - 'shell_command_before': ['source .venv/bin/activate'], - 'panes': [ - { - 'shell_command': ['vim'], - }, - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['cowsay "hey"'] - }, - ], - 'layout': 'main-verticle' - }, - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - }, - { - 'shell_command': [] - } - ] - }, - { - 'window_name': 'shufu', - 'panes': [ - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['htop'], - } - ] - }, - { - 'options': {'automatic_rename': True, }, - 'panes': [ - {'shell_command': ['htop']} - ] - }, - { - 'panes': [{ - 'shell_command': ['top'] - }] - }, - ] - } - - config_after = { # shell_command_before is string in some areas - 'session_name': 'sampleconfig', - 'start_directory': '/', - 'windows': [ - { - 'window_name': 'editor', - 'start_directory': os.path.expanduser('~'), - 'shell_command_before': ['source .venv/bin/activate'], - 'panes': [ - { - 'shell_command': ['source .venv/bin/activate', 'vim'], - }, - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': [ - 'source .venv/bin/activate', - 'rbenv local 2.0.0-p0', 'cowsay "hey"' - ] - }, - ], - 'layout': 'main-verticle' - }, - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'start_directory': '/', - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': [ - 'rbenv local 2.0.0-p0', - 'tail -F /var/log/syslog' - ], - }, - { - 'shell_command': ['rbenv local 2.0.0-p0'] - } - ] - }, - { - 'start_directory': '/', - 'window_name': 'shufu', - 'panes': [ - { - 'shell_command_before': ['rbenv local 2.0.0-p0'], - 'shell_command': ['rbenv local 2.0.0-p0', 'htop'], - } - ] - }, - { - 'start_directory': '/', - 'options': {'automatic_rename': True, }, - 'panes': [ - { - 'shell_command': ['htop'] - } - ] - }, - { - 'start_directory': '/', - 'panes': [ - { - 'shell_command': ['top'] - } - ] - } - ] - } - - def test_shell_command_before(self): - self.maxDiff = None - test_config = self.config_unexpanded - test_config = config.expand(test_config) - - self.assertDictEqual(test_config, self.config_expanded) - - test_config = config.trickle(test_config) - self.maxDiff = None - self.assertDictEqual(test_config, self.config_after) - - -class ShellCommandBeforeSession(TestCase): - - def test_in_session_scope(self): - - yaml_config = """ - shell_command_before: - - 'echo "hi"' - session_name: 'test' - windows: - - window_name: editor - panes: - - shell_command: - - vim - - :Ex - - pane - - cd /usr - - window_name: logging - panes: - - shell_command: - - - - shell_command: - - top - - emacs - """ - - yaml_final_config = """ - shell_command_before: - - 'echo "hi"' - session_name: 'test' - windows: - - window_name: editor - panes: - - shell_command: - - 'echo "hi"' - - vim - - :Ex - - shell_command: - - 'echo "hi"' - - shell_command: - - 'echo "hi"' - - cd /usr - - window_name: logging - panes: - - shell_command: - - 'echo "hi"' - - shell_command: - - 'echo "hi"' - - top - - emacs - """ - - self.maxDiff = None - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(yaml_config).get() - - config.validate_schema(sconfig) - - self.assertDictEqual(config.expand(sconfig), sconfig) - - self.assertDictEqual( - config.expand(config.trickle(sconfig)), - self.yaml_to_dict(yaml_final_config) - ) - - def yaml_to_dict(self, yaml): - return kaptan.Kaptan(handler='yaml').import_config(yaml).get() - - -class TrickleRelativeStartDirectory(TestCase): - - config_expanded = { # shell_command_before is string in some areas - 'session_name': 'sampleconfig', - 'start_directory': '/var', - 'windows': [ - { - 'window_name': 'editor', - 'start_directory': 'log', - 'panes': [ - { - 'shell_command': ['vim'], - }, - { - 'shell_command': ['cowsay "hey"'] - }, - ], - 'layout': 'main-verticle' - }, - { - 'window_name': 'logging', - 'start_directory': '~', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - }, - { - 'shell_command': [] - } - ] - }, - ] - } - - config_after = { # shell_command_before is string in some areas - 'session_name': 'sampleconfig', - 'start_directory': '/var', - 'windows': [ - { - 'window_name': 'editor', - 'start_directory': '/var/log', - 'panes': [ - { - 'shell_command': ['vim'], - }, - { - 'shell_command': [ - 'cowsay "hey"' - ] - }, - ], - 'layout': 'main-verticle' - }, - { - 'start_directory': '~', - 'window_name': 'logging', - 'panes': [ - { - 'shell_command': ['tail -F /var/log/syslog'], - }, - { - 'shell_command': [] - } - ] - }, - ] - } - - def test_shell_command_before(self): - - test_config = config.trickle(self.config_expanded) - self.assertDictEqual(test_config, self.config_after) - - -class ConfigBlankPanes(TestCase): - - yaml_config_file = os.path.join(example_dir, 'blank-panes.yaml') - - expanded_config = { - 'session_name': 'Blank pane test', - 'windows': [ - { - 'window_name': 'Blank pane test', - 'panes': [ - { - 'shell_command': [], - }, - { - 'shell_command': [], - }, - { - 'shell_command': [], - } - ] - }, - { - 'window_name': 'More blank panes', - 'panes': [ - { - 'shell_command': [], - }, - { - 'shell_command': [], - }, - { - 'shell_command': [], - } - ] - }, - { - 'window_name': 'Empty string (return)', - 'panes': [ - { - 'shell_command': [ - '' - ], - }, - { - 'shell_command': [ - '' - ], - }, - { - 'shell_command': [ - '' - ], - } - ] - }, - { - 'window_name': 'Blank with options', - 'panes': [ - { - 'shell_command': [], - 'focus': True, - }, - { - 'shell_command': [], - 'start_directory': '/tmp', - } - ] - } - ] - } - - def test_expands_blank(self): - """Expand blank config into full form. - - Handle ``NoneType`` and 'blank':: - - # nothing, None, 'blank' - 'panes': [ - None, - 'blank' - ] - - # should be blank - 'panes': [ - 'shell_command': [] - ] - - Blank strings:: - - panes: [ - '' - ] - - # should output to: - panes: - 'shell_command': [''] - - """ - - self.maxDiff = None - - test_config = kaptan.Kaptan().import_config( - self.yaml_config_file).get() - - self.assertDictEqual( - config.expand(test_config), - self.expanded_config - ) - - -class ConfigConsistency(TestCase): - - def test_no_session_name(self): - yaml_config = """ - - window_name: editor - panes: - shell_command: - - tail -F /var/log/syslog - start_directory: /var/log - - window_name: logging - automatic_rename: true - panes: - - shell_command: - - htop - """ - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(yaml_config).get() - - with self.assertRaisesRegexp( - exc.ConfigError, 'requires "session_name"' - ): - config.validate_schema(sconfig) - - def test_no_windows(self): - yaml_config = """ - session_name: test session - """ - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(yaml_config).get() - - with self.assertRaisesRegexp(exc.ConfigError, 'list of "windows"'): - config.validate_schema(sconfig) - - def test_no_window_name(self): - yaml_config = """ - session_name: test session - windows: - - window_name: editor - panes: - shell_command: - - tail -F /var/log/syslog - start_directory: /var/log - - automatic_rename: true - panes: - - shell_command: - - htop - """ - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(yaml_config).get() - - with self.assertRaisesRegexp(exc.ConfigError, 'missing "window_name"'): - config.validate_schema(sconfig) - - -class ConfigExpandEnvironmentVariables(TestCase, unittest.TestCase): - def test_replaces_start_directory(self): - env_key = "TESTHEY92" - env_value = "HEYO1" - yaml_config = """ - start_directory: {TEST_VAR}/test - shell_command_before: {TEST_VAR}/test2 - before_script: {TEST_VAR}/test3 - session_name: hi - {TEST_VAR} - windows: - - window_name: editor - panes: - - shell_command: - - tail -F /var/log/syslog - start_directory: /var/log - - window_name: logging @ {TEST_VAR} - automatic_rename: true - panes: - - shell_command: - - htop - """.format( - TEST_VAR="${%s}" % env_key - ) - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(yaml_config).get() - - with EnvironmentVarGuard() as env: - env.set(env_key, env_value) - sconfig = config.expand(sconfig) - self.assertEqual("%s/test" % env_value, sconfig['start_directory']) - self.assertIn( - "%s/test2" % env_value, sconfig['shell_command_before'] - ) - self.assertEqual("%s/test3" % env_value, sconfig['before_script']) - self.assertEqual("hi - %s" % env_value, sconfig['session_name']) - self.assertEqual( - "logging @ %s" % env_value, - sconfig['windows'][1]['window_name'] - ) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(ConfigBlankPanes)) - suite.addTest(unittest.makeSuite(ConfigConsistency)) - suite.addTest(unittest.makeSuite(ExpandTest)) - suite.addTest(unittest.makeSuite(ImportExportTest)) - suite.addTest(unittest.makeSuite(InlineTest)) - suite.addTest(unittest.makeSuite(ShellCommandBeforeTest)) - suite.addTest(unittest.makeSuite(ShellCommandBeforeSession)) - suite.addTest(unittest.makeSuite(TrickleRelativeStartDirectory)) - suite.addTest(unittest.makeSuite(ConfigExpandEnvironmentVariables)) - return suite diff --git a/tmuxp/testsuite/config_teamocil.py b/tmuxp/testsuite/config_teamocil.py deleted file mode 100644 index e38d26a6c7..0000000000 --- a/tmuxp/testsuite/config_teamocil.py +++ /dev/null @@ -1,742 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp teamocil configuration.. - -tmuxp.tests.config_teamocil -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import os -import unittest - -import kaptan - -from tmuxp import config -from tmuxp.testsuite.helpers import TestCase - -logger = logging.getLogger(__name__) -TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') - - -class TeamocilTest(TestCase): - - teamocil_yaml = """\ - windows: - - name: "sample-two-panes" - root: "~/Code/sample/www" - layout: even-horizontal - panes: - - cmd: ["pwd", "ls -la"] - - cmd: "rails server --port 3000" - """ - - teamocil_dict = { - 'windows': [{ - 'name': 'sample-two-panes', - 'root': '~/Code/sample/www', - 'layout': 'even-horizontal', - 'panes': [ - { - 'cmd': [ - 'pwd', - 'ls -la' - ] - }, - { - 'cmd': 'rails server --port 3000' - } - ] - }] - } - - tmuxp_dict = { - 'session_name': None, - 'windows': [ - { - 'window_name': 'sample-two-panes', - 'layout': 'even-horizontal', - 'start_directory': '~/Code/sample/www', - 'panes': [ - { - 'shell_command': [ - 'pwd', - 'ls -la' - ] - }, - { - 'shell_command': 'rails server --port 3000' - } - ] - } - ] - } - - def test_config_to_dict(self): - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.teamocil_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.teamocil_dict) - - self.assertDictEqual( - config.import_teamocil(self.teamocil_dict), - self.tmuxp_dict - ) - - config.validate_schema( - config.import_teamocil( - self.teamocil_dict - ) - ) - - -class Teamocil2Test(TestCase): - - teamocil_yaml = """\ - windows: - - name: "sample-four-panes" - root: "~/Code/sample/www" - layout: tiled - panes: - - cmd: "pwd" - - cmd: "pwd" - - cmd: "pwd" - - cmd: "pwd" - """ - - teamocil_dict = { - 'windows': [{ - 'name': 'sample-four-panes', - 'root': '~/Code/sample/www', - 'layout': 'tiled', - 'panes': [ - {'cmd': 'pwd'}, - {'cmd': 'pwd'}, - {'cmd': 'pwd'}, - {'cmd': 'pwd'}, - ] - }] - } - - tmuxp_dict = { - 'session_name': None, - 'windows': [ - { - 'window_name': 'sample-four-panes', - 'layout': 'tiled', - 'start_directory': '~/Code/sample/www', - 'panes': [ - { - 'shell_command': 'pwd' - }, - { - 'shell_command': 'pwd' - }, - { - 'shell_command': 'pwd' - }, - { - 'shell_command': 'pwd' - }, - ] - } - ] - } - - def test_config_to_dict(self): - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.teamocil_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.teamocil_dict) - - self.assertDictEqual( - config.import_teamocil(self.teamocil_dict), - self.tmuxp_dict - ) - - config.validate_schema( - config.import_teamocil( - self.teamocil_dict - ) - ) - - -class Teamocil3Test(TestCase): - - teamocil_yaml = """\ - windows: - - name: "my-first-window" - root: "~/Projects/foo-www" - layout: even-vertical - filters: - before: "rbenv local 2.0.0-p0" - after: "echo 'I am done initializing this pane.'" - panes: - - cmd: "git status" - - cmd: "bundle exec rails server --port 40" - focus: true - - cmd: - - "sudo service memcached start" - - "sudo service mongodb start" - """ - - teamocil_dict = { - 'windows': [{ - 'name': 'my-first-window', - 'root': '~/Projects/foo-www', - 'layout': 'even-vertical', - 'filters': { - 'before': 'rbenv local 2.0.0-p0', - 'after': 'echo \'I am done initializing this pane.\'' - }, - 'panes': [ - {'cmd': 'git status'}, - {'cmd': 'bundle exec rails server --port 40', - 'focus': True}, - {'cmd': [ - 'sudo service memcached start', - 'sudo service mongodb start', - ]} - ] - }] - } - - tmuxp_dict = { - 'session_name': None, - 'windows': [ - { - 'window_name': 'my-first-window', - 'layout': 'even-vertical', - 'start_directory': "~/Projects/foo-www", - 'shell_command_before': 'rbenv local 2.0.0-p0', - 'shell_command_after': ( - 'echo ' - '\'I am done initializing this pane.\'' - ), - 'panes': [ - { - 'shell_command': 'git status' - }, - { - 'shell_command': 'bundle exec rails server --port 40', - 'focus': True - }, - { - 'shell_command': [ - 'sudo service memcached start', - 'sudo service mongodb start' - ] - } - ] - } - - ] - } - - def test_config_to_dict(self): - self.maxDiff = None - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.teamocil_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.teamocil_dict) - - self.assertDictEqual( - config.import_teamocil(self.teamocil_dict), - self.tmuxp_dict - ) - - config.validate_schema( - config.import_teamocil( - self.teamocil_dict - ) - ) - - -class Teamocil4Test(TestCase): - - teamocil_yaml = """\ - windows: - - name: "erb-example" - root: <%= ENV['MY_PROJECT_ROOT'] %> - panes: - - cmd: "pwd" - """ - - teamocil_dict = { - 'windows': [{ - 'name': 'erb-example', - 'root': "<%= ENV['MY_PROJECT_ROOT'] %>", - 'panes': [ - {'cmd': 'pwd'} - ] - }] - } - - tmuxp_dict = { - 'session_name': None, - 'windows': [ - { - 'window_name': 'erb-example', - 'start_directory': "<%= ENV['MY_PROJECT_ROOT'] %>", - 'panes': [ - { - 'shell_command': 'pwd' - } - ] - } - ] - } - - def test_config_to_dict(self): - self.maxDiff = None - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.teamocil_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.teamocil_dict) - - self.assertDictEqual( - config.import_teamocil(self.teamocil_dict), - self.tmuxp_dict - ) - - config.validate_schema( - config.import_teamocil( - self.teamocil_dict - ) - ) - - -class TeamocilLayoutsTest(TestCase): - - """Import configurations from teamocil's . - - https://github.com/remiprev/teamocil/blob/master/spec/fixtures/layouts.yml - - LICENSE: https://github.com/remiprev/teamocil/blob/master/LICENSE - - """ - - teamocil_yaml = """\ - # Simple two windows layout - two-windows: - windows: - - name: "foo" - clear: true - root: "/foo" - layout: "tiled" - panes: - - cmd: "echo 'foo'" - - cmd: "echo 'foo again'" - - name: "bar" - root: "/bar" - splits: - - cmd: - - "echo 'bar'" - - "echo 'bar in an array'" - target: bottom-right - - cmd: "echo 'bar again'" - focus: true - width: 50 - - # Simple two windows layout with filters - two-windows-with-filters: - windows: - - name: "foo" - root: "/foo" - filters: - before: - - "echo first before filter" - - "echo second before filter" - after: - - "echo first after filter" - - "echo second after filter" - panes: - - cmd: "echo 'foo'" - - cmd: "echo 'foo again'" - width: 50 - - two-windows-with-custom-command-options: - windows: - - name: "foo" - cmd_separator: "\n" - with_env_var: false - clear: true - root: "/foo" - layout: "tiled" - panes: - - cmd: "echo 'foo'" - - cmd: "echo 'foo again'" - - name: "bar" - cmd_separator: " && " - with_env_var: true - root: "/bar" - splits: - - cmd: - - "echo 'bar'" - - "echo 'bar in an array'" - target: bottom-right - - cmd: "echo 'bar again'" - focus: true - width: 50 - - three-windows-within-a-session: - session: - name: "my awesome session" - windows: - - name: "first window" - panes: - - cmd: "echo 'foo'" - - name: "second window" - panes: - - cmd: "echo 'foo'" - - name: "third window" - panes: - - cmd: "echo 'foo'" - """ - - teamocil_dict = { - 'two-windows': { - 'windows': [ - { - 'name': 'foo', - 'clear': True, - 'root': '/foo', - 'layout': 'tiled', - 'panes': [ - { - 'cmd': "echo 'foo'" - }, - { - 'cmd': "echo 'foo again'" - } - ] - }, - { - 'name': 'bar', - 'root': '/bar', - 'splits': [ - { - 'cmd': [ - "echo 'bar'", - "echo 'bar in an array'" - ], - 'target': 'bottom-right' - }, - { - 'cmd': "echo 'bar again'", - 'focus': True, - 'width': 50 - } - ] - - } - ] - }, - - 'two-windows-with-filters': { - 'windows': [ - { - 'name': 'foo', - 'root': '/foo', - 'filters': - { - 'before': [ - 'echo first before filter', - 'echo second before filter' - ], - 'after': [ - 'echo first after filter', - 'echo second after filter', - ] - }, - 'panes': [ - { - 'cmd': "echo 'foo'" - }, - { - 'cmd': "echo 'foo again'", - 'width': 50 - } - ] - } - ] - }, - - 'two-windows-with-custom-command-options': { - 'windows': [ - { - 'name': 'foo', - 'cmd_separator': ' ', - 'with_env_var': False, - 'clear': True, - 'root': '/foo', - 'layout': 'tiled', - 'panes': [ - { - 'cmd': "echo 'foo'" - }, - { - 'cmd': "echo 'foo again'" - } - ] - }, { - 'name': 'bar', - 'cmd_separator': ' && ', - 'with_env_var': True, - 'root': '/bar', - 'splits': [ - { - 'cmd': [ - "echo 'bar'", - "echo 'bar in an array'" - ], - 'target': 'bottom-right' - }, - { - 'cmd': "echo 'bar again'", - 'focus': True, - 'width': 50 - } - ] - }] - }, - - 'three-windows-within-a-session': { - 'session': { - 'name': 'my awesome session', - 'windows': [ - { - 'name': 'first window', - 'panes': [ - { - 'cmd': "echo 'foo'" - } - ] - }, { - 'name': 'second window', - 'panes': [ - { - 'cmd': "echo 'foo'"} - ] - }, { - 'name': 'third window', - 'panes': [ - { - 'cmd': "echo 'foo'" - } - ] - } - ] - } - } - } - - two_windows = \ - { - 'session_name': None, - 'windows': [ - { - 'window_name': 'foo', - 'start_directory': '/foo', - 'clear': True, - 'layout': 'tiled', - 'panes': [ - { - 'shell_command': "echo 'foo'" - }, - { - 'shell_command': "echo 'foo again'" - } - ] - }, - { - 'window_name': 'bar', - 'start_directory': '/bar', - 'panes': [ - { - 'shell_command': [ - "echo 'bar'", - "echo 'bar in an array'" - ], - 'target': 'bottom-right' - }, - { - 'shell_command': "echo 'bar again'", - 'focus': True, - } - ] - } - ] - } - - two_windows_with_filters = \ - { - 'session_name': None, - 'windows': [ - { - 'window_name': 'foo', - 'start_directory': '/foo', - 'shell_command_before': [ - 'echo first before filter', - 'echo second before filter', - ], - 'shell_command_after': [ - 'echo first after filter', - 'echo second after filter', - ], - 'panes': [ - { - 'shell_command': "echo 'foo'" - }, - { - 'shell_command': "echo 'foo again'", - } - ] - } - ] - } - - two_windows_with_custom_command_options = \ - { - 'session_name': None, - 'windows': [ - { - 'window_name': 'foo', - 'start_directory': '/foo', - 'clear': True, - 'layout': 'tiled', - 'panes': [ - { - 'shell_command': "echo 'foo'", - }, - { - 'shell_command': "echo 'foo again'", - } - ] - }, - { - 'window_name': 'bar', - 'start_directory': '/bar', - 'panes': [ - { - 'shell_command': [ - "echo 'bar'", - "echo 'bar in an array'" - ], - 'target': 'bottom-right' - }, - { - 'shell_command': "echo 'bar again'", - 'focus': True, - } - ] - - } - ] - - } - - three_windows_within_a_session = { - 'session_name': 'my awesome session', - 'windows': [ - { - 'window_name': 'first window', - 'panes': [ - { - 'shell_command': "echo 'foo'" - }, - ] - }, - { - 'window_name': 'second window', - 'panes': [ - { - 'shell_command': "echo 'foo'" - }, - ] - }, - { - 'window_name': 'third window', - 'panes': [ - { - 'shell_command': "echo 'foo'" - }, - ] - }, - ] - } - - def test_config_to_dict(self): - self.maxDiff = None - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.teamocil_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.teamocil_dict) - - self.assertDictEqual( - config.import_teamocil( - self.teamocil_dict['two-windows'], - ), - self.two_windows - ) - - config.validate_schema( - config.import_teamocil( - self.teamocil_dict['two-windows'] - ) - ) - - self.assertDictEqual( - config.import_teamocil( - self.teamocil_dict['two-windows-with-filters'], - ), - self.two_windows_with_filters - ) - - config.validate_schema( - config.import_teamocil( - self.teamocil_dict['two-windows-with-filters'] - ) - ) - - self.assertDictEqual( - config.import_teamocil( - self.teamocil_dict['two-windows-with-custom-command-options'], - ), - self.two_windows_with_custom_command_options - ) - - config.validate_schema( - config.import_teamocil( - self.teamocil_dict['two-windows-with-custom-command-options'] - ) - ) - - self.assertDictEqual( - config.import_teamocil( - self.teamocil_dict['three-windows-within-a-session'], - ), - self.three_windows_within_a_session - ) - config.validate_schema( - config.import_teamocil( - self.teamocil_dict['three-windows-within-a-session'] - ) - ) - - """ this configuration contains multiple sessions in a single file. - tmuxp can split them into files, proceed? - """ - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TeamocilTest)) - suite.addTest(unittest.makeSuite(Teamocil2Test)) - suite.addTest(unittest.makeSuite(Teamocil3Test)) - suite.addTest(unittest.makeSuite(Teamocil4Test)) - suite.addTest(unittest.makeSuite(TeamocilLayoutsTest)) - return suite diff --git a/tmuxp/testsuite/config_tmuxinator.py b/tmuxp/testsuite/config_tmuxinator.py deleted file mode 100644 index 3dd59b1666..0000000000 --- a/tmuxp/testsuite/config_tmuxinator.py +++ /dev/null @@ -1,482 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp tmuxinator configuration. - -tmuxp.tests.config_tmuxinator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import os -import unittest - -import kaptan - -from tmuxp import config -from tmuxp.testsuite.helpers import TestCase - -logger = logging.getLogger(__name__) -TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') - - -class TmuxinatorTest(TestCase): - - tmuxinator_yaml = """\ - windows: - - editor: - layout: main-vertical - panes: - - vim - - guard - - server: bundle exec rails s - - logs: tail -f logs/development.log - """ - - tmuxinator_dict = { - 'windows': [ - { - 'editor': { - 'layout': 'main-vertical', - 'panes': [ - 'vim', - 'guard' - ] - } - }, - { - 'server': 'bundle exec rails s', - }, - { - 'logs': 'tail -f logs/development.log' - } - ] - } - - tmuxp_dict = { - 'session_name': None, - 'windows': [ - { - 'window_name': 'editor', - 'layout': 'main-vertical', - 'panes': [ - 'vim', - 'guard' - ] - }, - { - 'window_name': 'server', - 'panes': [ - 'bundle exec rails s' - ] - }, - { - 'window_name': 'logs', - 'panes': [ - 'tail -f logs/development.log' - ] - } - ] - } - - def test_config_to_dict(self): - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.tmuxinator_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.tmuxinator_dict) - - self.assertDictEqual(config.import_tmuxinator( - self.tmuxinator_dict), self.tmuxp_dict) - - -class TmuxinatorDeprecationsTest(TestCase): - - """Tmuxinator uses `tabs` instead of `windows` in older versions. - - https://github.com/aziz/tmuxinator/blob/master/lib/tmuxinator/project.rb#L18 - - https://github.com/aziz/tmuxinator/blob/master/spec/fixtures/sample.deprecations.yml - - LICENSE: https://github.com/aziz/tmuxinator/blob/master/LICENSE - - """ - - tmuxinator_yaml = """\ - project_name: sample - project_root: ~/test - socket_name: foo # Remove to use default socket - pre: sudo /etc/rc.d/mysqld start # Runs before everything - rbenv: 2.0.0-p247 - cli_args: -f ~/.tmux.mac.conf # Pass arguments to tmux - tabs: - - editor: - pre: - - echo "I get run in each pane, before each pane command!" - - - layout: main-vertical - panes: - - vim - - #empty, will just run plain bash - - top - - shell: git pull - - guard: - layout: tiled - pre: - - echo "I get run in each pane." - - echo "Before each pane command!" - panes: - - - - #empty, will just run plain bash - - - - database: bundle exec rails db - - server: bundle exec rails s - - logs: tail -f log/development.log - - console: bundle exec rails c - - capistrano: - - server: ssh user@example.com - """ - - tmuxinator_dict = { - 'project_name': 'sample', - 'project_root': '~/test', - 'socket_name': 'foo', - 'pre': 'sudo /etc/rc.d/mysqld start', - 'rbenv': '2.0.0-p247', - 'cli_args': '-f ~/.tmux.mac.conf', - 'tabs': [ - { - 'editor': { - 'pre': [ - 'echo "I get run in each pane, ' - 'before each pane command!"', - None - ], - 'layout': 'main-vertical', - 'panes': [ - 'vim', - None, - 'top' - ] - } - }, - {'shell': 'git pull', }, - { - 'guard': { - 'layout': 'tiled', - 'pre': [ - 'echo "I get run in each pane."', - 'echo "Before each pane command!"' - ], - 'panes': [ - None, - None, - None - ] - } - }, - {'database': 'bundle exec rails db'}, - {'server': 'bundle exec rails s'}, - {'logs': 'tail -f log/development.log'}, - {'console': 'bundle exec rails c'}, - {'capistrano': None}, - {'server': 'ssh user@example.com'} - ] - } - - tmuxp_dict = { - 'session_name': 'sample', - 'socket_name': 'foo', - 'config': '~/.tmux.mac.conf', - 'start_directory': '~/test', - 'shell_command_before': [ - 'sudo /etc/rc.d/mysqld start', - 'rbenv shell 2.0.0-p247' - ], - 'windows': [ - { - 'window_name': 'editor', - 'shell_command_before': [ - 'echo "I get run in each pane, before each pane command!"', - None - ], - 'layout': 'main-vertical', - 'panes': [ - 'vim', - None, - 'top' - ] - }, - { - 'window_name': 'shell', - 'panes': [ - 'git pull' - ] - }, - { - 'window_name': 'guard', - 'layout': 'tiled', - 'shell_command_before': [ - 'echo "I get run in each pane."', - 'echo "Before each pane command!"' - ], - 'panes': [ - None, - None, - None - ] - }, - { - 'window_name': 'database', - 'panes': [ - 'bundle exec rails db' - ] - }, - { - 'window_name': 'server', - 'panes': [ - 'bundle exec rails s' - ] - }, - { - 'window_name': 'logs', - 'panes': [ - 'tail -f log/development.log' - ] - }, - { - 'window_name': 'console', - 'panes': [ - 'bundle exec rails c' - ] - }, - { - 'window_name': 'capistrano', - 'panes': [ - None - ] - }, - { - 'window_name': 'server', - 'panes': [ - 'ssh user@example.com' - ] - } - ] - } - - def test_config_to_dict(self): - self.maxDiff = None - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.tmuxinator_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.tmuxinator_dict) - - self.assertDictEqual( - config.import_tmuxinator(self.tmuxinator_dict), self.tmuxp_dict - ) - - -class TmuxinatoriSampleTest(TestCase): - - """Test importing . - - https://github.com/aziz/tmuxinator/blob/master/spec/fixtures/sample.yml - - LICENSE: https://github.com/aziz/tmuxinator/blob/master/LICENSE - - """ - - tmuxinator_yaml = """\ - # ~/.tmuxinator/sample.yml - # you can make as many tabs as you wish... - - name: sample - root: ~/test - socket_name: foo # Remove to use default socket - pre: sudo /etc/rc.d/mysqld start # Runs before everything - pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane - tmux_options: -f ~/.tmux.mac.conf # Pass arguments to tmux - windows: - - editor: - pre: - - echo "I get run in each pane, before each pane command!" - - - layout: main-vertical - panes: - - vim - - #empty, will just run plain bash - - top - - shell: - - git pull - - git merge - - guard: - layout: tiled - pre: - - echo "I get run in each pane." - - echo "Before each pane command!" - panes: - - - - #empty, will just run plain bash - - - - database: bundle exec rails db - - server: bundle exec rails s - - logs: tail -f log/development.log - - console: bundle exec rails c - - capistrano: - - server: ssh user@example.com - """ - - tmuxinator_dict = { - 'name': 'sample', - 'root': '~/test', - 'socket_name': 'foo', - 'tmux_options': '-f ~/.tmux.mac.conf', - 'pre': 'sudo /etc/rc.d/mysqld start', - 'pre_window': 'rbenv shell 2.0.0-p247', - 'windows': [ - { - 'editor': { - 'pre': [ - 'echo "I get run in each pane, ' - 'before each pane command!"', - None - ], - 'layout': 'main-vertical', - 'panes': [ - 'vim', - None, - 'top' - ] - } - }, - { - 'shell': [ - 'git pull', - 'git merge' - ] - }, - { - 'guard': { - 'layout': 'tiled', - 'pre': [ - 'echo "I get run in each pane."', - 'echo "Before each pane command!"' - ], - 'panes': [ - None, - None, - None - ] - } - }, - {'database': 'bundle exec rails db'}, - {'server': 'bundle exec rails s'}, - {'logs': 'tail -f log/development.log'}, - {'console': 'bundle exec rails c'}, - {'capistrano': None}, - {'server': 'ssh user@example.com'} - ] - } - - tmuxp_dict = { - 'session_name': 'sample', - 'socket_name': 'foo', - 'config': '~/.tmux.mac.conf', - 'shell_command': 'sudo /etc/rc.d/mysqld start', - 'shell_command_before': [ - 'rbenv shell 2.0.0-p247' - ], - 'windows': [ - { - 'window_name': 'editor', - 'shell_command_before': [ - 'echo "I get run in each pane, before each pane command!"', - None - ], - 'layout': 'main-vertical', - 'panes': [ - 'vim', - None, - 'top' - ] - }, - { - 'window_name': 'shell', - 'panes': [ - 'git pull', - 'git merge' - ] - }, - { - 'window_name': 'guard', - 'layout': 'tiled', - 'shell_command_before': [ - 'echo "I get run in each pane."', - 'echo "Before each pane command!"' - ], - 'panes': [ - None, - None, - None - ] - }, - { - 'window_name': 'database', - 'panes': [ - 'bundle exec rails db' - ] - }, - { - 'window_name': 'server', - 'panes': [ - 'bundle exec rails s' - ] - }, - { - 'window_name': 'logs', - 'panes': [ - 'tail -f log/development.log' - ] - }, - { - 'window_name': 'console', - 'panes': [ - 'bundle exec rails c' - ] - }, - { - 'window_name': 'capistrano', - 'panes': [ - None - ] - }, - { - 'window_name': 'server', - 'panes': [ - 'ssh user@example.com' - ] - } - ] - } - - def test_config_to_dict(self): - self.maxDiff = None - configparser = kaptan.Kaptan(handler='yaml') - test_config = configparser.import_config(self.tmuxinator_yaml) - yaml_to_dict = test_config.get() - self.assertDictEqual(yaml_to_dict, self.tmuxinator_dict) - - self.assertDictEqual( - config.import_tmuxinator(self.tmuxinator_dict), - self.tmuxp_dict - ) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TmuxinatorTest)) - suite.addTest(unittest.makeSuite(TmuxinatorDeprecationsTest)) - suite.addTest(unittest.makeSuite(TmuxinatoriSampleTest)) - return suite diff --git a/tmuxp/testsuite/helpers.py b/tmuxp/testsuite/helpers.py deleted file mode 100644 index e43d6aa7b1..0000000000 --- a/tmuxp/testsuite/helpers.py +++ /dev/null @@ -1,367 +0,0 @@ -# -*- coding: utf-8 -*- -"""Helper methods for tmuxp unittests. - -_CallableContext, WhateverIO, decorator and stdouts are from the case project, -https://github.com/celery/case, license BSD 3-clause. -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import contextlib -import functools -import inspect -import io -import logging -import os -import sys -import tempfile -from contextlib import contextmanager - -from tmuxp import exc -from tmuxp.testsuite import t - -if sys.version_info < (2, 7): - import unittest2 as unittest -else: - import unittest - -logger = logging.getLogger(__name__) - -TEST_SESSION_PREFIX = 'test tmuxp_' - -namer = tempfile._RandomNameSequence() - - -def get_test_session_name(server, prefix=TEST_SESSION_PREFIX): - while True: - session_name = prefix + next(namer) - if not t.has_session(session_name): - break - return session_name - - -def get_test_window_name(session, prefix=TEST_SESSION_PREFIX): - while True: - window_name = prefix + next(namer) - if not session.findWhere(window_name=window_name): - break - return window_name - - -@contextlib.contextmanager -def temp_session(server, *args, **kwargs): - """Return a context manager with a temporary session. - - e.g.:: - - with temp_session(server) as session: - session.new_window(window_name='my window') - - The session will destroy itself upon closing with :meth:`Session. - kill_session()`. - - If no ``session_name`` is entered, :func:`get_test_session_name` will make - an unused session name. - - :args: Same arguments as :meth:`Server.new_session` - :yields: Temporary session - :rtype: :class:`Session` - """ - - if 'session_name' in kwargs: - session_name = kwargs.pop('session_name') - else: - session_name = get_test_session_name(server) - - session = server.new_session(session_name, *args, **kwargs) - - try: - yield session - finally: - if server.has_session(session_name): - session.kill_session() - return - - -@contextlib.contextmanager -def temp_window(session, *args, **kwargs): - """Return a context manager with a temporary window. - - e.g.:: - - with temp_window(session) as window: - my_pane = window.split_window() - - The window will destroy itself upon closing with :meth:`window. - kill_window()`. - - If no ``window_name`` is entered, :func:`get_test_window_name` will make - an unused window name. - - :args: Same arguments as :meth:`Session.new_window` - :yields: Temporary window - :rtype: :class:`Window` - """ - - if 'window_name' not in kwargs: - window_name = get_test_window_name(session) - else: - window_name = kwargs.pop('window_name') - - window = session.new_window(window_name, *args, **kwargs) - - # Get ``window_id`` before returning it, it may be killed within context. - window_id = window.get('window_id') - - try: - yield session - finally: - if session.findWhere(window_id=window_id): - window.kill_window() - return - - -class TestCase(unittest.TestCase): - - """Base TestClass so we don't have to try: unittest2 every module. """ - - @classmethod - def setUpClass(cls): - super(TestCase, cls).setUpClass() # for python 2.6 unittest2 - - -class TmuxTestCase(TestCase): - - """TmuxTestCase class, wraps the TestCase in a :class:`Session`.""" - - #: :class:`Session` object. - session = None - #: Session name for the TestCase. - TEST_SESSION_NAME = None - - def temp_session(self, session_name=None): - return temp_session(self.server, session_name) - - def setUp(self): - """Run bootstrap if :attr:`~.session` is not set.""" - - if not self.TEST_SESSION_NAME or not self.session: - self.bootstrap() - - def bootstrap(self): - """Return tuple of the session_name (generated) and :class:`Session`. - - Checks to verify if the user has a tmux client open. - - It will clean up and delete other sessions starting with the - :attr:`TEST_SESSION_PREFIX` ``tmuxp``. - - Since tmux closes when all sessions are deleted, the bootstrap will see - if there is no other client open aside from a tmuxp_ prefixed session - a dumby session will be made to prevent tmux from closing. - - """ - - session_name = 'tmuxp' - if not t.has_session(session_name): - t.cmd('new-session', '-d', '-s', session_name) - - # find current sessions prefixed with tmuxp - old_test_sessions = [ - s.get('session_name') for s in t._sessions - if s.get('session_name').startswith(TEST_SESSION_PREFIX) - ] - - TEST_SESSION_NAME = get_test_session_name(server=t) - - try: - session = t.new_session( - session_name=TEST_SESSION_NAME, - ) - except exc.TmuxpException as e: - raise e - - """ - Make sure that tmuxp can :ref:`test_builder_visually` and switches to - the newly created session for that testcase. - """ - try: - t.switch_client(session.get('session_id')) - pass - except exc.TmuxpException as e: - # t.attach_session(session.get('session_id')) - pass - - for old_test_session in old_test_sessions: - logger.debug( - 'Old test test session %s found. Killing it.' % - old_test_session - ) - t.kill_session(old_test_session) - assert TEST_SESSION_NAME == session.get('session_name') - assert TEST_SESSION_NAME != 'tmuxp' - - self.TEST_SESSION_NAME = TEST_SESSION_NAME - self.server = t - self.session = session - - -StringIO = io.StringIO -_SIO_write = StringIO.write -_SIO_init = StringIO.__init__ - - -def update_wrapper(wrapper, wrapped, *args, **kwargs): - wrapper = functools.update_wrapper(wrapper, wrapped, *args, **kwargs) - wrapper.__wrapped__ = wrapped - return wrapper - - -def wraps(wrapped, - assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): - return functools.partial(update_wrapper, wrapped=wrapped, - assigned=assigned, updated=updated) - - -class _CallableContext(object): - - def __init__(self, context, cargs, ckwargs, fun): - self.context = context - self.cargs = cargs - self.ckwargs = ckwargs - self.fun = fun - - def __call__(self, *args, **kwargs): - return self.fun(*args, **kwargs) - - def __enter__(self): - self.ctx = self.context(*self.cargs, **self.ckwargs) - return self.ctx.__enter__() - - def __exit__(self, *einfo): - if self.ctx: - return self.ctx.__exit__(*einfo) - - -def decorator(predicate): - context = contextmanager(predicate) - - @wraps(predicate) - def take_arguments(*pargs, **pkwargs): - - @wraps(predicate) - def decorator(cls): - if inspect.isclass(cls): - orig_setup = cls.setUp - orig_teardown = cls.tearDown - - @wraps(cls.setUp) - def around_setup(*args, **kwargs): - try: - contexts = args[0].__rb3dc_contexts__ - except AttributeError: - contexts = args[0].__rb3dc_contexts__ = [] - p = context(*pargs, **pkwargs) - p.__enter__() - contexts.append(p) - return orig_setup(*args, **kwargs) - around_setup.__wrapped__ = cls.setUp - cls.setUp = around_setup - - @wraps(cls.tearDown) - def around_teardown(*args, **kwargs): - try: - contexts = args[0].__rb3dc_contexts__ - except AttributeError: - pass - else: - for context in contexts: - context.__exit__(*sys.exc_info()) - orig_teardown(*args, **kwargs) - around_teardown.__wrapped__ = cls.tearDown - cls.tearDown = around_teardown - - return cls - else: - @wraps(cls) - def around_case(self, *args, **kwargs): - with context(*pargs, **pkwargs) as context_args: - context_args = context_args or () - if not isinstance(context_args, tuple): - context_args = (context_args,) - return cls(*(self,) + args + context_args, **kwargs) - return around_case - - if len(pargs) == 1 and callable(pargs[0]): - fun, pargs = pargs[0], () - return decorator(fun) - return _CallableContext(context, pargs, pkwargs, decorator) - assert take_arguments.__wrapped__ - return take_arguments - - -class WhateverIO(StringIO): - - def __init__(self, v=None, *a, **kw): - _SIO_init(self, v.decode() if isinstance(v, bytes) else v, *a, **kw) - - def write(self, data): - _SIO_write(self, data.decode() if isinstance(data, bytes) else data) - - -@decorator -def stdouts(): - """Override `sys.stdout` and `sys.stderr` with `StringIO` - instances. - Decorator example:: - @mock.stdouts - def test_foo(self, stdout, stderr): - something() - self.assertIn('foo', stdout.getvalue()) - Context example:: - with mock.stdouts() as (stdout, stderr): - something() - self.assertIn('foo', stdout.getvalue()) - """ - prev_out, prev_err = sys.stdout, sys.stderr - prev_rout, prev_rerr = sys.__stdout__, sys.__stderr__ - mystdout, mystderr = WhateverIO(), WhateverIO() - sys.stdout = sys.__stdout__ = mystdout - sys.stderr = sys.__stderr__ = mystderr - - try: - yield mystdout, mystderr - finally: - sys.stdout = prev_out - sys.stderr = prev_err - sys.__stdout__ = prev_rout - sys.__stderr__ = prev_rerr - - -@decorator -def mute(): - """Redirect `sys.stdout` and `sys.stderr` to /dev/null, silencent them. - Decorator example:: - @mute - def test_foo(self): - something() - Context example:: - with mute(): - something() - """ - prev_out, prev_err = sys.stdout, sys.stderr - prev_rout, prev_rerr = sys.__stdout__, sys.__stderr__ - devnull = open(os.devnull, 'w') - mystdout, mystderr = devnull, devnull - sys.stdout = sys.__stdout__ = mystdout - sys.stderr = sys.__stderr__ = mystderr - - try: - yield - finally: - sys.stdout = prev_out - sys.stderr = prev_err - sys.__stdout__ = prev_rout - sys.__stderr__ = prev_rerr diff --git a/tmuxp/testsuite/pane.py b/tmuxp/testsuite/pane.py deleted file mode 100644 index 8fca0c33f3..0000000000 --- a/tmuxp/testsuite/pane.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp Pane object. - -tmuxp.tests.pane -~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import unittest - -from tmuxp.testsuite.helpers import TmuxTestCase - -logger = logging.getLogger(__name__) - - -class ResizeTest(TmuxTestCase): - - def test_resize_pane(self): - """ Test Pane.resize_pane(). """ - - window = self.session.attached_window() - window.rename_window('test_resize_pane') - - pane1 = window.attached_pane() - pane1_height = pane1['pane_height'] - window.split_window() - - pane1.resize_pane(height=4) - self.assertNotEqual(pane1['pane_height'], pane1_height) - self.assertEqual(int(pane1['pane_height']), 4) - - pane1.resize_pane(height=3) - self.assertEqual(int(pane1['pane_height']), 3) - - def test_set_height(self): - window = self.session.new_window(window_name='test_set_height') - window.split_window() - pane1 = window.attached_pane() - pane1_height = pane1['pane_height'] - - pane1.set_height(2) - self.assertNotEqual(pane1['pane_height'], pane1_height) - self.assertEqual(int(pane1['pane_height']), 2) - - def test_set_width(self): - window = self.session.new_window(window_name='test_set_width') - window.split_window() - - window.select_layout('main-vertical') - pane1 = window.attached_pane() - pane1_width = pane1['pane_width'] - - pane1.set_width(10) - self.assertNotEqual(pane1['pane_width'], pane1_width) - self.assertEqual(int(pane1['pane_width']), 10) - - pane1.reset() - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(ResizeTest)) - return suite diff --git a/tmuxp/testsuite/server.py b/tmuxp/testsuite/server.py deleted file mode 100644 index f0fd57ae2b..0000000000 --- a/tmuxp/testsuite/server.py +++ /dev/null @@ -1,95 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp Server object. - -tmuxp.tests.server -~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import unittest - -from tmuxp import Server -from tmuxp.testsuite import t -from tmuxp.testsuite.helpers import TmuxTestCase - -logger = logging.getLogger(__name__) - - -class ServerTest(TmuxTestCase): - - def test_has_session(self): - self.assertTrue(t.has_session(self.TEST_SESSION_NAME)) - self.assertFalse(t.has_session('asdf2314324321')) - - def test_socket_name(self): - """ ``-L`` socket_name. - - ``-L`` socket_name file name of socket. which will be stored in - env TMUX_TMPDIR or /tmp if unset.) - - """ - myserver = Server(socket_name='test') - - self.assertEqual(myserver.socket_name, 'test') - - def test_socket_path(self): - """ ``-S`` socket_path (alternative path for server socket). """ - myserver = Server(socket_path='test') - - self.assertEqual(myserver.socket_path, 'test') - - def test_config(self): - """ ``-f`` file for tmux(1) configuration. """ - myserver = Server(config_file='test') - self.assertEqual(myserver.config_file, 'test') - - def test_256_colors(self): - myserver = Server(colors=256) - self.assertEqual(myserver.colors, 256) - - proc = myserver.cmd('list-servers') - - self.assertIn('-2', proc.cmd) - self.assertNotIn('-8', proc.cmd) - - def test_88_colors(self): - myserver = Server(colors=88) - self.assertEqual(myserver.colors, 88) - - proc = myserver.cmd('list-servers') - - self.assertIn('-8', proc.cmd) - self.assertNotIn('-2', proc.cmd) - - -class EnvironmentTest(TmuxTestCase): - - def test_show_environment(self): - """Server.show_environment() returns dict.""" - vars = self.server.show_environment() - self.assertIsInstance(vars, dict) - - def test_set_show_environment_single(self): - """Set environment then Server.show_environment(key).""" - self.server.set_environment('FOO', 'BAR') - self.assertEqual('BAR', self.server.show_environment('FOO')) - - self.server.set_environment('FOO', 'DAR') - self.assertEqual('DAR', self.server.show_environment('FOO')) - - self.assertEqual('DAR', self.server.show_environment()['FOO']) - - def test_show_environment_not_set(self): - """Unset environment variable returns None.""" - self.assertEqual(None, self.server.show_environment('BAR')) - - -def suite(): - _suite = unittest.TestSuite() - _suite.addTest(unittest.makeSuite(ServerTest)) - _suite.addTest(unittest.makeSuite(EnvironmentTest)) - return _suite diff --git a/tmuxp/testsuite/session.py b/tmuxp/testsuite/session.py deleted file mode 100644 index 1d5f3a3f5d..0000000000 --- a/tmuxp/testsuite/session.py +++ /dev/null @@ -1,188 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp Session object. - -tmuxp.tests.session -~~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import unittest - -from tmuxp import Pane, Session, Window -from tmuxp.testsuite import t -from tmuxp.testsuite.helpers import TEST_SESSION_PREFIX, TmuxTestCase, namer - -logger = logging.getLogger(__name__) - - -class SessionTest(TmuxTestCase): - - def test_has_session(self): - """Server.has_session returns True if has session_name exists.""" - self.assertTrue(t.has_session(self.TEST_SESSION_NAME)) - self.assertFalse(t.has_session('asdf2314324321')) - - def test_select_window(self): - """Session.select_window moves window.""" - # get the current window_base_index, since different user tmux config - # may start at 0 or 1, or whatever they want. - window_base_index = int( - self.session.attached_window().get('window_index') - ) - - self.session.new_window(window_name='test_window') - window_count = len(self.session._windows) - - self.assertGreaterEqual(window_count, 2) # 2 or more windows - - self.assertEqual(len(self.session._windows), window_count) - - # tmux selects a window, moves to it, shows it as attached_window - selected_window1 = self.session.select_window(window_base_index) - self.assertIsInstance(selected_window1, Window) - attached_window1 = self.session.attached_window() - - self.assertEqual(selected_window1, attached_window1) - self.assertEqual(selected_window1.__dict__, attached_window1.__dict__) - - # again: tmux selects a window, moves to it, shows it as - # attached_window - selected_window2 = self.session.select_window(window_base_index + 1) - self.assertIsInstance(selected_window2, Window) - attached_window2 = self.session.attached_window() - - self.assertEqual(selected_window2, attached_window2) - self.assertEqual(selected_window2.__dict__, attached_window2.__dict__) - - # assure these windows were really different - self.assertNotEqual(selected_window1, selected_window2) - self.assertNotEqual( - selected_window1.__dict__, selected_window2.__dict__) - - def test_select_window_returns_Window(self): - """Session.select_window returns Window object.""" - - window_count = len(self.session._windows) - self.assertEqual(len(self.session._windows), window_count) - window_base_index = int( - self.session.attached_window().get('window_index')) - - self.assertIsInstance(self.session.select_window( - window_base_index), Window) - - def test_attached_window(self): - """Session.attached_window() returns Window.""" - self.assertIsInstance(self.session.attached_window(), Window) - - def test_attached_pane(self): - """Session.attached_pane() returns Pane.""" - self.assertIsInstance(self.session.attached_pane(), Pane) - - def test_session_rename(self): - """Session.rename_session renames session.""" - test_name = 'testingdis_sessname' - self.session.rename_session(test_name) - self.assertEqual(self.session.get('session_name'), test_name) - self.session.rename_session(self.TEST_SESSION_NAME) - self.assertEqual( - self.session.get('session_name'), - self.TEST_SESSION_NAME - ) - - -class SessionNewTest(TmuxTestCase): - - def test_new_session(self): - """Server.new_session creates new session.""" - new_session_name = TEST_SESSION_PREFIX + next(namer) - new_session = t.new_session(session_name=new_session_name, detach=True) - - self.assertIsInstance(new_session, Session) - self.assertEqual(new_session.get('session_name'), new_session_name) - - -class Options(TmuxTestCase): - - def test_show_options(self): - """Session.show_options() returns dict.""" - - options = self.session.show_options() - self.assertIsInstance(options, dict) - - def test_set_show_options_single(self): - """Set option then Session.show_options(key).""" - - self.session.set_option('history-limit', 20) - self.assertEqual(20, self.session.show_options('history-limit')) - - self.session.set_option('history-limit', 40) - self.assertEqual(40, self.session.show_options('history-limit')) - - self.assertEqual(40, self.session.show_options()['history-limit']) - - def test_set_show_option(self): - """Set option then Session.show_option(key).""" - self.session.set_option('history-limit', 20) - self.assertEqual(20, self.session.show_option('history-limit')) - - self.session.set_option('history-limit', 40) - - self.assertEqual(40, self.session.show_option('history-limit')) - - def test_set_option_bad(self): - """Session.set_option raises ValueError for bad option key.""" - with self.assertRaises(ValueError): - self.session.set_option('afewewfew', 43) - - -class Environment(TmuxTestCase): - - def test_show_environment(self): - """Session.show_environment() returns dict.""" - - vars = self.session.show_environment() - self.assertIsInstance(vars, dict) - - def test_set_show_environment_single(self): - """Set environment then Session.show_environment(key).""" - - self.session.set_environment('FOO', 'BAR') - self.assertEqual('BAR', self.session.show_environment('FOO')) - - self.session.set_environment('FOO', 'DAR') - self.assertEqual('DAR', self.session.show_environment('FOO')) - - self.assertEqual('DAR', self.session.show_environment()['FOO']) - - def test_show_environment_not_set(self): - """Not set environment variable returns None.""" - self.assertEqual(None, self.session.show_environment('BAR')) - - def test_remove_environment(self): - """Remove environment variable.""" - self.assertEqual(None, self.session.show_environment('BAM')) - self.session.set_environment('BAM', 'OK') - self.assertEqual('OK', self.session.show_environment('BAM')) - self.session.remove_environment('BAM') - self.assertEqual(None, self.session.show_environment('BAM')) - - def test_unset_environment(self): - """Unset environment variable.""" - self.assertEqual(None, self.session.show_environment('BAM')) - self.session.set_environment('BAM', 'OK') - self.assertEqual('OK', self.session.show_environment('BAM')) - self.session.unset_environment('BAM') - self.assertEqual(None, self.session.show_environment('BAM')) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Options)) - suite.addTest(unittest.makeSuite(Environment)) - suite.addTest(unittest.makeSuite(SessionNewTest)) - suite.addTest(unittest.makeSuite(SessionTest)) - return suite diff --git a/tmuxp/testsuite/test_utils.py b/tmuxp/testsuite/test_utils.py deleted file mode 100644 index 2e80c4236e..0000000000 --- a/tmuxp/testsuite/test_utils.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for tmuxp testsuite's helper and utility functions.""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -from tmuxp.testsuite.helpers import (TmuxTestCase, get_test_session_name, - temp_session, unittest) - - -class TempSession(TmuxTestCase): - - def test_kills_session(self): - server = self.server - session_name = get_test_session_name(server=server) - - with temp_session( - server=server, session_name=session_name - ): - result = server.has_session(session_name) - self.assertTrue(result) - - self.assertFalse(server.has_session(session_name)) - - def test_if_session_killed_before(self): - """Handles situation where session already closed within context""" - - server = self.server - session_name = get_test_session_name(server=server) - - with temp_session(server=server, session_name=session_name): - - # an error or an exception within a temp_session kills the session - server.kill_session(session_name) - - result = server.has_session(session_name) - self.assertFalse(result) - - # really dead? - self.assertFalse(server.has_session(session_name)) - - def test_if_session_name_works(self): - """should allow custom ``session_name``.""" - pass - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TempSession)) - return suite diff --git a/tmuxp/testsuite/tmuxobject.py b/tmuxp/testsuite/tmuxobject.py deleted file mode 100644 index 2d35d9440b..0000000000 --- a/tmuxp/testsuite/tmuxobject.py +++ /dev/null @@ -1,208 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp TmuxRelationalObject and TmuxMappingObject. - -tmuxp.tests.tmuxobject -~~~~~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import unittest - -from tmuxp import Pane, Session, Window -from tmuxp.testsuite import t -from tmuxp.testsuite.helpers import TEST_SESSION_PREFIX, TmuxTestCase, namer - -logger = logging.getLogger(__name__) - - -class TmuxObjectTest(TmuxTestCase): - - """Test the :class:`TmuxRelationalObject` base class object.""" - - def test_findWhere(self): - """Test that findWhere() retrieves single matching object.""" - self.maxDiff = None - # server.findWhere - for session in t.sessions: - session_id = session.get('session_id') - - self.assertEqual(t.findWhere({'session_id': session_id}), session) - self.assertIsInstance( - t.findWhere({ - 'session_id': session_id - }), Session - ) - - # session.findWhere - for window in session.windows: - window_id = window.get('window_id') - - self.assertEqual( - session.findWhere({'window_id': window_id}), window - ) - self.assertIsInstance( - session.findWhere({'window_id': window_id}), Window - ) - - # window.findWhere - for pane in window.panes: - pane_id = pane.get('pane_id') - - self.assertEqual(window.findWhere( - {'pane_id': pane_id}), pane) - self.assertIsInstance(window.findWhere( - {'pane_id': pane_id}), Pane) - - def test_findWhere_None(self): - """.findWhere returns None if no results found.""" - - while True: - nonexistant_session = TEST_SESSION_PREFIX + next(namer) - - if not t.has_session(nonexistant_session): - break - - self.assertIsNone(t.findWhere({ - 'session_name': nonexistant_session - })) - - def test_findWhere_multiple_attrs(self): - """.findWhere returns objects with multiple attributes.""" - - for session in t.sessions: - session_id = session.get('session_id') - session_name = session.get('session_name') - find_where = t.findWhere({ - 'session_id': session_id, - 'session_name': session_name - }) - - self.assertEqual(find_where, session) - self.assertIsInstance(find_where, Session) - - # session.findWhere - for window in session.windows: - window_id = window.get('window_id') - window_index = window.get('window_index') - - find_where = session.findWhere({ - 'window_id': window_id, - 'window_index': window_index - }) - - self.assertEqual(find_where, window) - self.assertIsInstance(find_where, Window) - - # window.findWhere - for pane in window.panes: - pane_id = pane.get('pane_id') - pane_tty = pane.get('pane_tty') - - find_where = window.findWhere({ - 'pane_id': pane_id, - 'pane_tty': pane_tty - }) - - self.assertEqual(find_where, pane) - self.assertIsInstance(find_where, Pane) - - def test_where(self): - """Test self.where() returns matching objects.""" - - window = self.session.attached_window() - window.split_window() # create second pane - - for session in t.sessions: - session_id = session.get('session_id') - session_name = session.get('session_name') - where = t.where({ - 'session_id': session_id, - 'session_name': session_name - }) - - self.assertEqual(len(where), 1) - self.assertIsInstance(where, list) - self.assertEqual(where[0], session) - self.assertIsInstance(where[0], Session) - - # session.where - for window in session.windows: - window_id = window.get('window_id') - window_index = window.get('window_index') - - where = session.where({ - 'window_id': window_id, - 'window_index': window_index - }) - - self.assertEqual(len(where), 1) - self.assertIsInstance(where, list) - self.assertEqual(where[0], window) - self.assertIsInstance(where[0], Window) - - # window.where - for pane in window.panes: - pane_id = pane.get('pane_id') - pane_tty = pane.get('pane_tty') - - where = window.where({ - 'pane_id': pane_id, - 'pane_tty': pane_tty - }) - - self.assertEqual(len(where), 1) - self.assertIsInstance(where, list) - self.assertEqual(where[0], pane) - self.assertIsInstance(where[0], Pane) - - def test_getById(self): - """Test self.getById() retrieves child object.""" - - window = self.session.attached_window() - - window.split_window() # create second pane - - for session in t.sessions: - session_id = session.get('session_id') - get_by_id = t.getById(session_id) - - self.assertEqual(get_by_id, session) - self.assertIsInstance(get_by_id, Session) - self.assertIsNone(t.getById( - '$' + next(namer) - )) - - # session.getById - for window in session.windows: - window_id = window.get('window_id') - - get_by_id = session.getById(window_id) - - self.assertEqual(get_by_id, window) - self.assertIsInstance(get_by_id, Window) - - self.assertIsNone(session.getById( - '@' + next(namer) - )) - - # window.getById - for pane in window.panes: - pane_id = pane.get('pane_id') - - get_by_id = window.getById(pane_id) - - self.assertEqual(get_by_id, pane) - self.assertIsInstance(get_by_id, Pane) - self.assertIsNone(window.getById( - '%' + next(namer) - )) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TmuxObjectTest)) - return suite diff --git a/tmuxp/testsuite/util.py b/tmuxp/testsuite/util.py deleted file mode 100644 index b8d57975e9..0000000000 --- a/tmuxp/testsuite/util.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for utility functions in tmux. - -tmuxp.tests.util -~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import os -import unittest - -from tmuxp import exc -from tmuxp.exc import BeforeLoadScriptError, BeforeLoadScriptNotExists -from tmuxp.testsuite.helpers import TestCase, TmuxTestCase, stdouts -from tmuxp.util import has_required_tmux_version, run_before_script - -logger = logging.getLogger(__name__) - -current_dir = os.path.realpath(os.path.dirname(__file__)) -fixtures_dir = os.path.realpath(os.path.join(current_dir, 'fixtures')) - - -class EnvironmentVarGuard(object): - - """Class to help protect the environment variable properly. Can be used as - a context manager. - Vendorize to fix issue with Anaconda Python 2 not - including test module, see #121. - """ - - def __init__(self): - self._environ = os.environ - self._unset = set() - self._reset = dict() - - def set(self, envvar, value): - if envvar not in self._environ: - self._unset.add(envvar) - else: - self._reset[envvar] = self._environ[envvar] - self._environ[envvar] = value - - def unset(self, envvar): - if envvar in self._environ: - self._reset[envvar] = self._environ[envvar] - del self._environ[envvar] - - def __enter__(self): - return self - - def __exit__(self, *ignore_exc): - for envvar, value in self._reset.items(): - self._environ[envvar] = value - for unset in self._unset: - del self._environ[unset] - - -class TmuxVersionTest(TmuxTestCase): - - """Test the :meth:`has_required_tmux_version`.""" - - def test_no_arg_uses_tmux_version(self): - result = has_required_tmux_version() - self.assertRegexpMatches(result, r'[0-9]\.[0-9]') - - def test_ignores_letter_versions(self): - """Ignore letters such as 1.8b. - - See ticket https://github.com/tony/tmuxp/issues/55. - - In version 0.1.7 this is adjusted to use LooseVersion, in order to - allow letters. - - """ - result = has_required_tmux_version('1.9a') - self.assertRegexpMatches(result, r'[0-9]\.[0-9]') - - result = has_required_tmux_version('1.8a') - self.assertEqual(result, r'1.8') - - def test_error_version_less_1_7(self): - with self.assertRaisesRegexp( - exc.TmuxpException, 'tmuxp only supports' - ): - has_required_tmux_version('1.7') - - with self.assertRaisesRegexp( - exc.TmuxpException, 'tmuxp only supports' - ): - has_required_tmux_version('1.6a') - - has_required_tmux_version('1.9a') - - -class RunBeforeScript(TestCase): - - def test_raise_BeforeLoadScriptNotExists_if_not_exists(self): - script_file = os.path.join(fixtures_dir, 'script_noexists.sh') - - with self.assertRaises(BeforeLoadScriptNotExists): - run_before_script(script_file) - - with self.assertRaises(OSError): - run_before_script(script_file) - - def test_raise_BeforeLoadScriptError_if_retcode(self): - script_file = os.path.join(fixtures_dir, 'script_failed.sh') - - with self.assertRaises(BeforeLoadScriptError): - run_before_script(script_file) - - @stdouts - def test_return_stdout_if_ok(self, stdout, stderr): - script_file = os.path.join(fixtures_dir, 'script_complete.sh') - - run_before_script(script_file) - self.assertIn('hello', stdout.getvalue()) - - -class BeforeLoadScriptErrorTestCase(TestCase): - - def test_returncode(self): - script_file = os.path.join(fixtures_dir, 'script_failed.sh') - - with self.assertRaisesRegexp(exc.BeforeLoadScriptError, "113"): - run_before_script(script_file) - - def test_returns_stderr_messages(self): - script_file = os.path.join(fixtures_dir, 'script_failed.sh') - - with self.assertRaisesRegexp( - exc.BeforeLoadScriptError, "failed with returncode" - ): - run_before_script(script_file) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(BeforeLoadScriptErrorTestCase)) - suite.addTest(unittest.makeSuite(RunBeforeScript)) - suite.addTest(unittest.makeSuite(TmuxVersionTest)) - return suite diff --git a/tmuxp/testsuite/window.py b/tmuxp/testsuite/window.py deleted file mode 100644 index eabc00b477..0000000000 --- a/tmuxp/testsuite/window.py +++ /dev/null @@ -1,229 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp Window object. - -tmuxp.tests.window -~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import unittest - -from tmuxp import Pane, Server, Window -from tmuxp.testsuite.helpers import TmuxTestCase - -logger = logging.getLogger(__name__) - - -class SelectTest(TmuxTestCase): - - def test_select_window(self): - window_count = len(self.session._windows) - # to do, get option for base-index from tmux - # for now hoever, let's get the index from the first window. - self.assertEqual(window_count, 1) - - window_base_index = int( - self.session.attached_window().get('window_index')) - - window = self.session.new_window(window_name='testing 3') - - # self.assertEqual(2, - # int(self.session.attached_window().get('window_index'))) - self.assertEqual(int(window_base_index) + 1, int( - window.get('window_index'))) - - self.session.select_window(window_base_index) - self.assertEqual(window_base_index, int( - self.session.attached_window().get('window_index'))) - - self.session.select_window('testing 3') - self.assertEqual(int(window_base_index) + 1, int( - self.session.attached_window().get('window_index'))) - - self.assertEqual(len(self.session._windows), 2) - - -class NewTest(TmuxTestCase): - - def test_zfresh_window_data(self): - - pane_base_index = int( - self.session.attached_window().show_window_option( - 'pane-base-index', g=True - ) - ) - - self.assertEqual(len(self.session.windows), 1) - - self.assertEqual(len(self.session.attached_window().panes), 1) - current_windows = len(self.session._windows) - self.assertNotEqual('@0', self.session.get('session_id')) - self.assertEqual(current_windows, 1) - - self.assertEqual(len(self.session.attached_window().panes), 1) - self.assertIsInstance(self.session.server, Server) - # len(self.session.attached_window().panes)) - - self.assertEqual(1, len(self.session.windows)) - self.assertEqual(len(self.session.attached_window().panes), 1) - for w in self.session.windows: - self.assertIsInstance(w, Window) - window = self.session.attached_window() - self.assertIsInstance(window, Window) - self.assertEqual(len(self.session.attached_window().panes), 1) - window.split_window() - self.session.attached_window().select_pane(pane_base_index) - self.session.attached_pane().send_keys('cd /srv/www/flaskr') - self.session.attached_window().select_pane(pane_base_index + 1) - self.session.attached_pane().send_keys('source .venv/bin/activate') - self.session.new_window(window_name='second') - current_windows += 1 - self.assertEqual(current_windows, len(self.session._windows)) - self.session.new_window(window_name='hey') - current_windows += 1 - self.assertEqual(current_windows, len(self.session._windows)) - - self.session.select_window(1) - self.session.kill_window(target_window='hey') - current_windows -= 1 - self.assertEqual(current_windows, len(self.session._windows)) - - -class NewTest2(TmuxTestCase): - - def test_newest_pane_data(self): - window = self.session.new_window(window_name='test', attach=True) - self.assertIsInstance(window, Window) - self.assertEqual(1, len(window.panes)) - window.split_window(attach=True) - - self.assertEqual(2, len(window.panes)) - # note: the below used to accept -h, removing because split_window now - # has attach as its only argument now - window.split_window(attach=True) - self.assertEqual(3, len(window.panes)) - - -class NewTest3(TmuxTestCase): - - def test_attached_pane(self): - """Window.attached_window() returns active Pane.""" - - window = self.session.attached_window() # current window - self.assertIsInstance(window.attached_pane(), Pane) - - -class NewTest4(TmuxTestCase): - - def test_split_window(self): - """Window.split_window() splits window, returns new Pane.""" - window_name = 'test split window' - window = self.session.new_window(window_name=window_name, attach=True) - pane = window.split_window() - self.assertEqual(2, len(window.panes)) - self.assertIsInstance(pane, Pane) - - -class RenameTest(TmuxTestCase): - - window_name_before = 'test' - window_name_after = 'ha ha ha fjewlkjflwef' - - def test_window_rename(self): - """Window.rename_window().""" - self.session.set_option('automatic-rename', 'off') - window = self.session.new_window( - window_name=self.window_name_before, attach=True) - - self.assertEqual(window, self.session.attached_window()) - self.assertEqual(window.get('window_name'), self.window_name_before) - - window.rename_window(self.window_name_after) - - window = self.session.attached_window() - - self.assertEqual(window.get('window_name'), self.window_name_after) - - window = self.session.attached_window() - - self.assertEqual(window.get('window_name'), self.window_name_after) - - -class RenameSpacesTest(RenameTest): - window_name_after = 'hello \\ wazzup 0' - - -class KillWindow(TmuxTestCase): - - def test_kill_window(self): - self.session.new_window() - # create a second window to not kick out the client. - # there is another way to do this via options too. - - w = self.session.attached_window() - - w.get('window_id') - - w.kill_window() - with self.assertRaises(IndexError): - w.get('window_id') - - -class Options(TmuxTestCase): - - def test_show_window_options(self): - """Window.show_window_options() returns dict.""" - window = self.session.new_window(window_name='test_window') - - options = window.show_window_options() - self.assertIsInstance(options, dict) - - def test_set_show_window_options(self): - """Set option then Window.show_window_options(key).""" - window = self.session.new_window(window_name='test_window') - - window.set_window_option('main-pane-height', 20) - self.assertEqual(20, window.show_window_options('main-pane-height')) - - window.set_window_option('main-pane-height', 40) - self.assertEqual(40, window.show_window_options('main-pane-height')) - - self.assertEqual(40, window.show_window_options()['main-pane-height']) - - def test_show_window_option(self): - """Set option then Window.show_window_option(key).""" - window = self.session.new_window(window_name='test_window') - - window.set_window_option('main-pane-height', 20) - self.assertEqual(20, window.show_window_option('main-pane-height')) - - window.set_window_option('main-pane-height', 40) - self.assertEqual(40, window.show_window_option('main-pane-height')) - - self.assertEqual(40, window.show_window_option('main-pane-height')) - - def test_set_window_option_bad(self): - """Window.set_window_option raises ValueError for bad option key.""" - - window = self.session.new_window(window_name='test_window') - - with self.assertRaises(ValueError): - window.set_window_option('afewewfew', 43) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(KillWindow)) - suite.addTest(unittest.makeSuite(NewTest)) - suite.addTest(unittest.makeSuite(NewTest2)) - suite.addTest(unittest.makeSuite(NewTest3)) - suite.addTest(unittest.makeSuite(NewTest4)) - suite.addTest(unittest.makeSuite(Options)) - suite.addTest(unittest.makeSuite(RenameTest)) - suite.addTest(unittest.makeSuite(RenameSpacesTest)) - suite.addTest(unittest.makeSuite(SelectTest)) - return suite diff --git a/tmuxp/testsuite/workspacebuilder.py b/tmuxp/testsuite/workspacebuilder.py deleted file mode 100644 index 11ee31ea6f..0000000000 --- a/tmuxp/testsuite/workspacebuilder.py +++ /dev/null @@ -1,1002 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp workspacebuilder. - -tmuxp.tests.workspacebuilder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import os -import tempfile -import time -import unittest - -import kaptan - -from tmuxp import Window, config, exc -from tmuxp._compat import text_type -from tmuxp.testsuite.helpers import TmuxTestCase, mute -from tmuxp.workspacebuilder import WorkspaceBuilder - -logger = logging.getLogger(__name__) - -current_dir = os.path.realpath(os.path.dirname(__file__)) -example_dir = os.path.realpath( - os.path.join(current_dir, '..', '..', 'examples') -) -fixtures_dir = os.path.realpath(os.path.join(current_dir, 'fixtures')) - - -class TwoPaneTest(TmuxTestCase): - - yaml_config = """ - session_name: sampleconfig - start_directory: '~' - windows: - - layout: main-vertical - panes: - - shell_command: - - vim - - shell_command: - - echo "hey" - window_name: editor - - panes: - - shell_command: - - tail | echo 'hi' - window_name: logging - - window_name: test - panes: - - shell_command: - - htop - """ - - def test_split_windows(self): - s = self.session - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - - builder = WorkspaceBuilder(sconf=sconfig) - - window_count = len(self.session._windows) # current window count - self.assertEqual(len(s._windows), window_count) - for w, wconf in builder.iter_create_windows(s): - for p in builder.iter_create_panes(w, wconf): - p = p - self.assertEqual(len(s._windows), window_count) - self.assertIsInstance(w, Window) - - self.assertEqual(len(s._windows), window_count) - window_count += 1 - - -class ThreePaneTest(TmuxTestCase): - - yaml_config = """ - session_name: sampleconfig - start_directory: '~' - windows: - - window_name: test - layout: main-horizontal - panes: - - shell_command: - - vim - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - """ - - def test_split_windows(self): - s = self.session - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - - builder = WorkspaceBuilder(sconf=sconfig) - - window_count = len(self.session._windows) # current window count - self.assertEqual(len(s._windows), window_count) - for w, wconf in builder.iter_create_windows(s): - for p in builder.iter_create_panes(w, wconf): - p = p - self.assertEqual(len(s._windows), window_count) - self.assertIsInstance(w, Window) - - self.assertEqual(len(s._windows), window_count) - window_count += 1 - w.set_window_option('main-pane-height', 50) - w.select_layout(wconf['layout']) - - -class FocusAndPaneIndexTest(TmuxTestCase): - - yaml_config = """ - session_name: sampleconfig - start_directory: '~' - windows: - - window_name: focused window - layout: main-horizontal - focus: true - panes: - - shell_command: - - cd ~ - - shell_command: - - cd /usr - focus: true - - shell_command: - - cd ~ - - echo "moo" - - top - - window_name: window 2 - panes: - - shell_command: - - top - focus: true - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: window 3 - panes: - - shell_command: cd / - focus: true - - pane - - pane - """ - - def test_focus_pane_index(self): - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - builder.build(session=self.session) - - self.assertEqual( - self.session.attached_window().get('window_name'), - 'focused window' - ) - - pane_base_index = int( - self.session.attached_window().show_window_option( - 'pane-base-index', g=True - ) - ) - - if not pane_base_index: - pane_base_index = 0 - else: - pane_base_index = int(pane_base_index) - - # get the pane index for each pane - pane_base_indexes = [] - for pane in self.session.attached_window().panes: - pane_base_indexes.append(int(pane.get('pane_index'))) - - pane_indexes_should_be = [pane_base_index + x for x in range(0, 3)] - self.assertListEqual(pane_indexes_should_be, pane_base_indexes) - - w = self.session.attached_window() - - self.assertNotEqual(w.get('window_name'), 'man') - - pane_path = '/usr' - for i in range(20): - p = w.attached_pane() - p.server._update_panes() - if p.get('pane_current_path') == pane_path: - break - time.sleep(.4) - - self.assertEqual(p.get('pane_current_path'), pane_path) - - proc = self.session.cmd('show-option', '-gv', 'base-index') - base_index = int(proc.stdout[0]) - self.session.server._update_windows() - - window3 = self.session.findWhere({'window_index': str(base_index + 2)}) - self.assertIsInstance(window3, Window) - - p = None - pane_path = '/' - for i in range(10): - p = window3.attached_pane() - p.server._update_panes() - if p.get('pane_current_path') == pane_path: - break - time.sleep(.4) - - self.assertEqual(p.get('pane_current_path'), pane_path) - - -class SuppressHistoryTest(TmuxTestCase): - yaml_config = """ - session_name: sampleconfig - start_directory: '~' - suppress_history: false - windows: - - window_name: inHistory - panes: - - echo inHistory - - window_name: isMissing - suppress_history: true - panes: - - echo isMissing - """ - - def test_suppress_history(self): - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - builder.build(session=self.session) - - inHistoryPane = self.session.findWhere( - {'window_name': 'inHistory'}).attached_pane() - isMissingPane = self.session.findWhere( - {'window_name': 'isMissing'}).attached_pane() - - def assertHistory(cmd, hist): - return 'inHistory' in cmd and cmd == hist - - def assertIsMissing(cmd, hist): - return 'isMissing' in cmd and cmd != hist - - for p, assertCase in [ - (inHistoryPane, assertHistory,), (isMissingPane, assertIsMissing,) - ]: - correct = False - p.window.select_window() - p.select_pane() - - # Print the last-in-history command in the pane - self.session.cmd('send-keys', ' fc -ln -1') - self.session.cmd('send-keys', 'Enter') - - for i in range(10): - time.sleep(0.1) - - # Get the contents of the pane - self.session.cmd('capture-pane') - captured_pane = self.session.cmd('show-buffer') - self.session.cmd('delete-buffer') - - # Parse the sent and last-in-history commands - sent_cmd = captured_pane.stdout[0].strip() - history_cmd = captured_pane.stdout[-2].strip() - - if assertCase(sent_cmd, history_cmd): - correct = True - break - self.assertTrue(correct, "Unknown sent command: [%s]" % sent_cmd) - - -class WindowOptions(TmuxTestCase): - - yaml_config = """ - session_name: test window options - start_directory: '~' - windows: - - layout: main-horizontal - options: - main-pane-height: 5 - panes: - - pane - - pane - - pane - window_name: editor - """ - - def test_window_options(self): - s = self.session - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - sconfig = config.expand(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - window_count = len(self.session._windows) # current window count - self.assertEqual(len(s._windows), window_count) - for w, wconf in builder.iter_create_windows(s): - for p in builder.iter_create_panes(w, wconf): - p = p - self.assertEqual(len(s._windows), window_count) - self.assertIsInstance(w, Window) - self.assertEqual(w.show_window_option('main-pane-height'), 5) - - self.assertEqual(len(s._windows), window_count) - window_count += 1 - w.select_layout(wconf['layout']) - - def test_window_shell(self): - yaml_config = """ - session_name: test window options - start_directory: '~' - windows: - - layout: main-horizontal - options: - main-pane-height: 5 - panes: - - pane - - pane - - pane - window_name: editor - window_shell: top - """ - s = self.session - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(yaml_config).get() - sconfig = config.expand(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - for w, wconf in builder.iter_create_windows(s): - if 'window_shell' in wconf: - self.assertEqual(wconf['window_shell'], text_type('top')) - for i in range(10): - self.session.server._update_windows() - if w['window_name'] != 'top': - break - time.sleep(.2) - - self.assertNotEqual(w.get('window_name'), text_type('top')) - - -class EnvironmentVariables(TmuxTestCase): - - yaml_config = """ - session_name: test env vars - start_directory: '~' - environment: - FOO: BAR - PATH: /tmp - windows: - - layout: main-horizontal - panes: - - pane - window_name: editor - """ - - def test_environment_variables(self): - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - sconfig = config.expand(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - builder.build(self.session) - - self.assertEqual('BAR', self.session.show_environment('FOO')) - self.assertEqual('/tmp', self.session.show_environment('PATH')) - - -class WindowAutomaticRename(TmuxTestCase): - - yaml_config = """ - session_name: test window options - start_directory: '~' - windows: - - layout: main-horizontal - options: - automatic-rename: on - panes: - - shell_command: - - top - start_directory: '~' - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - """ - - def test_automatic_rename_option(self): - """With option automatic-rename: on.""" - s = self.session - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - - builder = WorkspaceBuilder(sconf=sconfig) - - window_count = len(self.session._windows) # current window count - self.assertEqual(len(s._windows), window_count) - for w, wconf in builder.iter_create_windows(s): - for p in builder.iter_create_panes(w, wconf): - p = p - self.assertEqual(len(s._windows), window_count) - self.assertIsInstance(w, Window) - self.assertEqual(w.show_window_option('automatic-rename'), 'on') - - self.assertEqual(len(s._windows), window_count) - - window_count += 1 - w.select_layout(wconf['layout']) - - self.assertNotEqual(s.get('session_name'), 'tmuxp') - w = s.windows[0] - - for i in range(10): - self.session.server._update_windows() - if w.get('window_name') != 'top': - break - time.sleep(.2) - - self.assertNotEqual(w.get('window_name'), 'top') - - pane_base_index = w.show_window_option('pane-base-index', g=True) - w.select_pane(pane_base_index) - - for i in range(10): - self.session.server._update_windows() - if w.get('window_name') == 'top': - break - time.sleep(.3) - - self.assertEqual(w.get('window_name'), text_type('top')) - - w.select_pane('-D') - for i in range(10): - self.session.server._update_windows() - if w['window_name'] != 'top': - break - time.sleep(.2) - - self.assertNotEqual(w.get('window_name'), text_type('top')) - - -class BlankPaneTest(TmuxTestCase): - - """:todo: Verify blank panes of various types build into workspaces.""" - - yaml_config_file = os.path.join(example_dir, 'blank-panes.yaml') - - def test_blank_pane_count(self): - - test_config = kaptan.Kaptan().import_config( - self.yaml_config_file).get() - test_config = config.expand(test_config) - builder = WorkspaceBuilder(sconf=test_config) - builder.build(session=self.session) - - self.assertEqual(self.session, builder.session) - - window1 = self.session.findWhere({'window_name': 'Blank pane test'}) - self.assertEqual(len(window1._panes), 3) - - window2 = self.session.findWhere({'window_name': 'More blank panes'}) - self.assertEqual(len(window2._panes), 3) - - window3 = self.session.findWhere( - {'window_name': 'Empty string (return)'} - ) - self.assertEqual(len(window3._panes), 3) - - window4 = self.session.findWhere({'window_name': 'Blank with options'}) - self.assertEqual(len(window4._panes), 2) - - -class StartDirectoryTest(TmuxTestCase): - yaml_config = """ - session_name: sampleconfig - start_directory: '/usr' - windows: - - window_name: supposed to be /usr/bin - window_index: 1 - start_directory: /usr/bin - layout: main-horizontal - options: - main-pane-height: 50 - panes: - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: support to be /dev - window_index: 2 - start_directory: /dev - layout: main-horizontal - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: cwd containing a space - window_index: 3 - start_directory: {TEST_DIR} - layout: main-horizontal - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: testsa3 - window_index: 4 - layout: main-horizontal - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo3" - - window_name: cwd relative to start_directory since no rel dir entered - window_index: 5 - layout: main-horizontal - start_directory: ./ - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo3" - """ - - def setUp(self): - super(StartDirectoryTest, self).setUp() - - self.tempdir = tempfile.gettempdir() - self.test_dir = os.path.join(self.tempdir, 'foo bar') - - if not os.path.exists(self.test_dir): - os.mkdir(self.test_dir) - self._temp_dir_created = True - else: - self._temp_dir_created = False - - def tearDown(self): - super(StartDirectoryTest, self).tearDown() - if self._temp_dir_created: - os.rmdir(self.test_dir) - - def test_start_directory(self): - - test_config = self.yaml_config.format( - TMP_DIR=self.tempdir, - TEST_DIR=self.test_dir - ) - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(test_config).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - builder.build(session=self.session) - - assert(self.session == builder.session) - dirs = [ - '/usr/bin', '/dev', self.test_dir, - '/usr', - '/usr' - ] - - for path, window in zip(dirs, self.session.windows): - for p in window.panes: - for i in range(60): - p.server._update_panes() - pane_path = p.get('pane_current_path') - if pane_path is None: - pass - elif ( - path in pane_path or - pane_path == path - ): - result = ( - path == pane_path or - path in pane_path - ) - break - time.sleep(.2) - - # handle case with OS X adding /private/ to /tmp/ paths - self.assertTrue(result) - - -class StartDirectoryRelativeTest(TmuxTestCase): - """Same as above test, but with relative start directory, mimicing - loading it from a location of project file. Like:: - - $ tmuxp load ~/workspace/myproject/.tmuxp.yaml - - instead of:: - - $ cd ~/workspace/myproject/.tmuxp.yaml - $ tmuxp load . - - """ - - yaml_config = """ - session_name: sampleconfig - start_directory: ./ - windows: - - window_name: supposed to be /usr/bin - start_directory: '/usr/bin' - options: - main-pane-height: 50 - panes: - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: support to be /dev - start_directory: '/dev' - layout: main-horizontal - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: cwd containing a space - start_directory: {TEST_DIR} - layout: main-horizontal - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo" - - window_name: inherit start_directory which is rel to config file - layout: main-horizontal - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo3" - - window_name: cwd relative to config file - layout: main-horizontal - start_directory: ./ - panes: - - shell_command: - - pwd - - shell_command: - - echo "hey" - - shell_command: - - echo "moo3" - """ - - def setUp(self): - super(StartDirectoryRelativeTest, self).setUp() - - self.tempdir = tempfile.gettempdir() - - self.test_dir = os.path.join(self.tempdir, 'foo bar') - self.config_dir = os.path.join(self.tempdir, 'testRelConfigDir') - - if ( - not os.path.exists(self.test_dir) or - not os.path.exists(self.config_dir) - ): - os.mkdir(self.test_dir) - os.mkdir(self.config_dir) - self._temp_dir_created = True - else: - self._temp_dir_created = False - - assert(os.path.exists(self.config_dir)) - assert(os.path.exists(self.test_dir)) - - def tearDown(self): - super(StartDirectoryRelativeTest, self).tearDown() - if self._temp_dir_created: - os.rmdir(self.test_dir) - os.rmdir(self.config_dir) - - def test_start_directory(self): - - test_config = self.yaml_config.format( - TEST_DIR=self.test_dir, - ) - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(test_config).get() - # the second argument of os.getcwd() mimics the behavior - # the CLI loader will do, but it passes in the config file's location. - sconfig = config.expand(sconfig, self.config_dir) - - sconfig = config.trickle(sconfig) - - assert(os.path.exists(self.config_dir)) - assert(os.path.exists(self.test_dir)) - builder = WorkspaceBuilder(sconf=sconfig) - builder.build(session=self.session) - - assert(self.session == builder.session) - - dirs = [ - '/usr/bin', - '/dev', - self.test_dir, - self.config_dir, - self.config_dir, - ] - - for path, window in zip(dirs, self.session.windows): - for p in window.panes: - for i in range(60): - p.server._update_panes() - # Handle case where directories resolve to /private/ in OSX - pane_path = p.get('pane_current_path') - if pane_path is None: - pass - elif ( - path in pane_path or - pane_path == path - ): - result = ( - path == pane_path or - path in pane_path - ) - - break - time.sleep(.2) - - self.assertTrue(result) - - -class PaneOrderingTest(TmuxTestCase): - - """Pane ordering based on position in config and ``pane_index``. - - Regression test for https://github.com/tony/tmuxp/issues/15. - - """ - - yaml_config = """ - session_name: sampleconfig - start_directory: {HOME} - windows: - - options: - - automatic_rename: on - layout: tiled - panes: - - cd /usr/bin - - cd /usr - - cd /usr/sbin - - cd {HOME} - """.format( - HOME=os.path.realpath(os.path.expanduser('~')) - ) - - def test_pane_order(self): - - # test order of `panes` (and pane_index) above aganist pane_dirs - pane_paths = [ - '/usr/bin', - '/usr', - '/usr/sbin', - os.path.realpath(os.path.expanduser('~')) - ] - - s = self.session - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - window_count = len(self.session._windows) # current window count - self.assertEqual(len(s._windows), window_count) - for w, wconf in builder.iter_create_windows(s): - for p in builder.iter_create_panes(w, wconf): - p = p - self.assertEqual(len(s._windows), window_count) - - self.assertIsInstance(w, Window) - - self.assertEqual(len(s._windows), window_count) - window_count += 1 - - for w in self.session.windows: - pane_base_index = w.show_window_option('pane-base-index', g=True) - for p_index, p in enumerate(w.list_panes(), start=pane_base_index): - self.assertEqual(int(p_index), int(p.get('pane_index'))) - - # pane-base-index start at base-index, pane_paths always start - # at 0 since python list. - pane_path = pane_paths[p_index - pane_base_index] - - for i in range(60): - p.server._update_panes() - if p.get('pane_current_path') == pane_path: - break - time.sleep(.2) - - self.assertEqual(p.get('pane_current_path'), pane_path) - - -class WindowIndexTest(TmuxTestCase): - yaml_config = """ - session_name: sampleconfig - windows: - - window_name: zero - panes: - - echo 'zero' - - window_name: five - panes: - - echo 'five' - window_index: 5 - - window_name: one - panes: - - echo 'one' - """ - - def test_window_index(self): - proc = self.session.cmd('show-option', '-gv', 'base-index') - base_index = int(proc.stdout[0]) - name_index_map = { - 'zero': 0 + base_index, - 'one': 1 + base_index, - 'five': 5, - } - - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - for window, wconf in builder.iter_create_windows(self.session): - expected_index = name_index_map[window['window_name']] - self.assertEqual(int(window['window_index']), expected_index) - - -class BeforeLoadScript(TmuxTestCase): - config = 'HI' - config_script_not_exists = """ - session_name: sampleconfig - before_script: {script_not_exists} - windows: - - panes: - - pane - """ - - config_script_fails = """ - session_name: sampleconfig - before_script: {script_failed} - windows: - - panes: - - pane - """ - - config_script_completes = """ - session_name: sampleconfig - before_script: {script_complete} - windows: - - panes: - - pane - """ - - @mute() - def test_throw_error_if_retcode_error(self): - sconfig = kaptan.Kaptan(handler='yaml') - yaml = self.config_script_fails.format( - fixtures_dir=fixtures_dir, - script_failed=os.path.join(fixtures_dir, 'script_failed.sh') - ) - - sconfig = sconfig.import_config(yaml).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - with self.temp_session() as sess: - session_name = sess.get('session_name') - - with self.assertRaises(exc.BeforeLoadScriptError): - builder.build(session=sess) - - result = self.server.has_session(session_name) - self.assertFalse( - result, - msg="Kills session if before_script exits with errcode" - ) - - @mute() - def test_throw_error_if_file_not_exists(self): - sconfig = kaptan.Kaptan(handler='yaml') - yaml = self.config_script_not_exists.format( - fixtures_dir=fixtures_dir, - script_not_exists=os.path.join( - fixtures_dir, 'script_not_exists.sh' - ) - ) - sconfig = sconfig.import_config(yaml).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - with self.temp_session() as sess: - session_name = sess.get('session_name') - temp_session_exists = self.server.has_session( - sess.get('session_name') - ) - self.assertTrue(temp_session_exists) - with self.assertRaisesRegexp( - (exc.BeforeLoadScriptNotExists, OSError), - 'No such file or directory' - ): - builder.build(session=sess) - result = self.server.has_session(session_name) - self.assertFalse( - result, - msg="Kills session if before_script doesn't exist" - ) - - @mute() - def test_true_if_test_passes(self): - assert( - os.path.exists(os.path.join(fixtures_dir, 'script_complete.sh')) - ) - sconfig = kaptan.Kaptan(handler='yaml') - yaml = self.config_script_completes.format( - fixtures_dir=fixtures_dir, - script_complete=os.path.join(fixtures_dir, 'script_complete.sh') - ) - - sconfig = sconfig.import_config(yaml).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - with self.temp_session(): - builder.build(session=self.session) - - @mute() - def test_true_if_test_passes_with_args(self): - assert( - os.path.exists(os.path.join(fixtures_dir, 'script_complete.sh')) - ) - sconfig = kaptan.Kaptan(handler='yaml') - yaml = self.config_script_completes.format( - fixtures_dir=fixtures_dir, - script_complete=os.path.join( - fixtures_dir, 'script_complete.sh' - ) + ' -v' - ) - - sconfig = sconfig.import_config(yaml).get() - sconfig = config.expand(sconfig) - sconfig = config.trickle(sconfig) - - builder = WorkspaceBuilder(sconf=sconfig) - - with self.temp_session(): - builder.build(session=self.session) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(BeforeLoadScript)) - suite.addTest(unittest.makeSuite(BlankPaneTest)) - suite.addTest(unittest.makeSuite(FocusAndPaneIndexTest)) - suite.addTest(unittest.makeSuite(PaneOrderingTest)) - suite.addTest(unittest.makeSuite(StartDirectoryTest)) - suite.addTest(unittest.makeSuite(StartDirectoryRelativeTest)) - suite.addTest(unittest.makeSuite(ThreePaneTest)) - suite.addTest(unittest.makeSuite(TwoPaneTest)) - suite.addTest(unittest.makeSuite(WindowAutomaticRename)) - suite.addTest(unittest.makeSuite(WindowIndexTest)) - suite.addTest(unittest.makeSuite(WindowOptions)) - suite.addTest(unittest.makeSuite(SuppressHistoryTest)) - suite.addTest(unittest.makeSuite(EnvironmentVariables)) - return suite diff --git a/tmuxp/testsuite/workspacefreezer.py b/tmuxp/testsuite/workspacefreezer.py deleted file mode 100644 index 883b245626..0000000000 --- a/tmuxp/testsuite/workspacefreezer.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test for tmuxp workspacefreezer. - -tmuxp.tests.workspacefreezer -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -""" - -from __future__ import (absolute_import, division, print_function, - unicode_literals, with_statement) - -import logging -import os -import time -import unittest - -import kaptan - -from tmuxp import config -from tmuxp.testsuite.helpers import TmuxTestCase -from tmuxp.workspacebuilder import WorkspaceBuilder, freeze - -logger = logging.getLogger(__name__) - -current_dir = os.path.abspath(os.path.dirname(__file__)) -example_dir = os.path.abspath(os.path.join(current_dir, '..', '..')) - - -class FreezeTest(TmuxTestCase): - - yaml_config = """ - session_name: sampleconfig - start_directory: '~' - windows: - - layout: main-vertical - panes: - - shell_command: - - vim - start_directory: '~' - - shell_command: - - echo "hey" - - cd ../ - window_name: editor - - panes: - - shell_command: - - pane - start_directory: /usr/bin - window_name: logging - - window_name: test - panes: - - shell_command: - - top - """ - - def test_focus(self): - # assure the built yaml config has focus - pass - - def test_freeze_config(self): - sconfig = kaptan.Kaptan(handler='yaml') - sconfig = sconfig.import_config(self.yaml_config).get() - - builder = WorkspaceBuilder(sconf=sconfig) - builder.build(session=self.session) - assert(self.session == builder.session) - - time.sleep(.50) - - session = self.session - sconf = freeze(session) - - config.validate_schema(sconf) - - sconf = config.inline(sconf) - - kaptanconf = kaptan.Kaptan() - kaptanconf = kaptanconf.import_config(sconf) - kaptanconf.export( - 'json', - indent=2 - ) - kaptanconf.export( - 'yaml', - indent=2, - default_flow_style=False, - safe=True - ) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(FreezeTest)) - return suite diff --git a/tox.ini b/tox.ini index 7465ab6b63..17b4394b17 100644 --- a/tox.ini +++ b/tox.ini @@ -4,8 +4,4 @@ envlist = py26, py27, py33 # released in a stable version [testenv] -commands = python run-tests.py [] - -[testenv:py26] -deps= - unittest2 +commands = make test []