128 lines
3.4 KiB
Python
128 lines
3.4 KiB
Python
import contextlib
|
|
import shlex
|
|
import sys
|
|
|
|
import pytest
|
|
from hecate import Runner
|
|
from hecate.hecate import AbnormalExit
|
|
|
|
import babi
|
|
|
|
|
|
class PrintsErrorRunner(Runner):
|
|
def await_exit(self, *args, **kwargs):
|
|
try:
|
|
return super().await_exit(*args, **kwargs)
|
|
except AbnormalExit: # pragma: no cover
|
|
print('=' * 79, flush=True)
|
|
print(self.screenshot(), end='', flush=True)
|
|
print('=' * 79, flush=True)
|
|
raise
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def run(*args, color=True, **kwargs):
|
|
cmd = (sys.executable, '-mcoverage', 'run', '-m', 'babi', *args)
|
|
quoted = ' '.join(shlex.quote(p) for p in cmd)
|
|
term = 'screen-256color' if color else 'screen'
|
|
cmd = ('bash', '-c', f'export TERM={term}; exec {quoted}')
|
|
with PrintsErrorRunner(*cmd, **kwargs) as h:
|
|
h.await_text(babi.VERSION_STR)
|
|
yield h
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def and_exit(h):
|
|
try:
|
|
yield
|
|
finally:
|
|
h.press('C-x')
|
|
h.await_exit()
|
|
|
|
|
|
def await_text_missing(h, text):
|
|
"""largely based on await_text"""
|
|
for _ in h.poll_until_timeout():
|
|
screen = h.screenshot()
|
|
munged = screen.replace('\n', '')
|
|
if text not in munged: # pragma: no branch
|
|
return
|
|
raise AssertionError(f'Timeout while waiting for text {text!r} to appear')
|
|
|
|
|
|
def get_size(h):
|
|
cmd = ('display', '-t0', '-p', '#{pane_width}\t#{pane_height}')
|
|
w, h = h.tmux.execute_command(*cmd).split()
|
|
return int(w), int(h)
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def resize(h, width, height):
|
|
current_w, current_h = get_size(h)
|
|
|
|
panes = 0
|
|
|
|
hsplit_w = current_w - width - 1
|
|
if hsplit_w > 0: # pragma: no branch # TODO
|
|
cmd = ('split-window', '-ht0', '-l', hsplit_w, 'sleep', 'infinity')
|
|
h.tmux.execute_command(*cmd)
|
|
panes += 1
|
|
|
|
vsplit_h = current_h - height - 1
|
|
if vsplit_h > 0: # pragma: no branch # TODO
|
|
cmd = ('split-window', '-vt0', '-l', vsplit_h, 'sleep', 'infinity')
|
|
h.tmux.execute_command(*cmd)
|
|
panes += 1
|
|
|
|
assert get_size(h) == (width, height)
|
|
try:
|
|
yield
|
|
finally:
|
|
for _ in range(panes):
|
|
h.tmux.execute_command('kill-pane', '-t1')
|
|
|
|
|
|
@pytest.mark.parametrize('color', (True, False))
|
|
def test_color_test(color):
|
|
with run('--color-test', color=color) as h, and_exit(h):
|
|
h.await_text('* 1* 2')
|
|
|
|
|
|
def test_can_start_without_color():
|
|
with run(color=False) as h, and_exit(h):
|
|
pass
|
|
|
|
|
|
def test_window_bounds(tmpdir):
|
|
f = tmpdir.join('f.txt')
|
|
f.write(f'{"x" * 40}\n' * 40)
|
|
|
|
with run(str(f), width=30, height=30) as h, and_exit(h):
|
|
h.await_text('x' * 30)
|
|
# make sure we don't go off the top left of the screen
|
|
h.press('LEFT')
|
|
h.press('UP')
|
|
# make sure we don't go off the bottom of the screen
|
|
for i in range(32):
|
|
h.press('RIGHT')
|
|
h.press('DOWN')
|
|
|
|
|
|
def test_status_clearing_behaviour():
|
|
with run() as h, and_exit(h):
|
|
h.press('C-j')
|
|
h.await_text('unknown key')
|
|
for i in range(24):
|
|
h.press('LEFT')
|
|
h.await_text('unknown key')
|
|
h.press('LEFT')
|
|
await_text_missing(h, 'unknown key')
|
|
|
|
|
|
def test_reacts_to_resize():
|
|
with run() as h, and_exit(h):
|
|
first_line = h.screenshot().splitlines()[0]
|
|
with resize(h, 40, 20):
|
|
# the first line should be different after resize
|
|
await_text_missing(h, first_line)
|