blob: 099eaa8f88431dafe03a0ef5d51b00995ababe3f [file]
# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Tests for pw_console.console_app"""
import logging
import unittest
from unittest.mock import MagicMock
from prompt_toolkit.application import create_app_session
from prompt_toolkit.output import ColorDepth
# inclusive-language: ignore
from prompt_toolkit.output import DummyOutput as FakeOutput
from pw_console.console_app import ConsoleApp
from pw_console.console_prefs import ConsolePrefs
from pw_console.window_list import _WINDOW_HEIGHT_ADJUST, DisplayMode
from pw_console.window_manager import Direction, _WINDOW_SPLIT_ADJUST
def _create_console_app(logger_count=2):
prefs = ConsolePrefs(
project_file=False, project_user_file=False, user_file=False
)
prefs.code_theme = 'default'
console_app = ConsoleApp(color_depth=ColorDepth.DEPTH_8_BIT, prefs=prefs)
console_app.focus_on_container = MagicMock()
console_app.application.layout.focus = MagicMock()
loggers = {}
for i in range(logger_count):
loggers['Log{}'.format(i)] = [logging.getLogger('test_log{}'.format(i))]
for window_title, logger_instances in loggers.items():
console_app.add_log_handler(window_title, logger_instances)
return console_app
_WINDOW_MANAGER_WIDTH = 80
_WINDOW_MANAGER_HEIGHT = 30
_DEFAULT_WINDOW_WIDTH = 10
_DEFAULT_WINDOW_HEIGHT = 10
def _window_list_widths(window_manager):
window_manager.update_window_manager_size(
_WINDOW_MANAGER_WIDTH, _WINDOW_MANAGER_HEIGHT
)
return [
window_list.width.preferred
for window_list in window_manager.window_lists
]
def _window_list_heights(window_manager):
window_manager.update_window_manager_size(
_WINDOW_MANAGER_WIDTH, _WINDOW_MANAGER_HEIGHT
)
return [
window_list.height.preferred
for window_list in window_manager.window_lists
]
def _window_pane_widths(window_manager, window_list_index=0):
window_manager.update_window_manager_size(
_WINDOW_MANAGER_WIDTH, _WINDOW_MANAGER_HEIGHT
)
return [
pane.width.preferred
for pane in window_manager.window_lists[window_list_index].active_panes
]
def _window_pane_heights(window_manager, window_list_index=0):
window_manager.update_window_manager_size(
_WINDOW_MANAGER_WIDTH, _WINDOW_MANAGER_HEIGHT
)
return [
pane.height.preferred
for pane in window_manager.window_lists[window_list_index].active_panes
]
def _window_pane_counts(window_manager):
return [
len(window_list.active_panes)
for window_list in window_manager.window_lists
]
def window_pane_titles(window_manager):
return [
[
pane.pane_title() + ' - ' + pane.pane_subtitle()
for pane in window_list.active_panes
]
for window_list in window_manager.window_lists
]
def target_window_pane(console_app, window_manager, pane_index: int):
# Bypass prompt_toolkit has_focus()
# pylint: disable=protected-access
window_manager._get_active_window_list_and_pane = MagicMock( # type: ignore
return_value=(
window_manager.window_lists[0],
window_manager.window_lists[0].active_panes[pane_index],
)
)
# pylint: enable=protected-access
window_list = console_app.window_manager.first_window_list()
window_list.get_current_active_pane = MagicMock( # type: ignore
return_value=window_list.active_panes[pane_index]
)
def target_list_and_pane(window_manager, list_index, pane_index):
window_list = window_manager.window_lists[list_index]
pane = window_list.active_panes[pane_index]
# If the pane is in focus it will be visible.
pane.show_pane = True
# Bypass prompt_toolkit has_focus()
# pylint: disable=protected-access
window_manager._get_active_window_list_and_pane = MagicMock( # type: ignore
return_value=(
window_manager.window_lists[list_index],
window_manager.window_lists[list_index].active_panes[pane_index],
)
)
# pylint: enable=protected-access
class TestWindowManager(unittest.TestCase):
"""Tests for window management functions."""
maxDiff = None
def test_find_window_list_and_pane(self) -> None:
"""Test getting the window list for a given pane."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=3)
window_manager = console_app.window_manager
self.assertEqual([4], _window_pane_counts(window_manager))
# Move 2 windows to the right into their own splits
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_to_next_group()
# 3 splits, first split has 2 windows
self.assertEqual([2, 1, 1], _window_pane_counts(window_manager))
# Move the first window in the first split left
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_prev_group()
# 4 splits, each with their own window
self.assertEqual([1, 1, 1, 1], _window_pane_counts(window_manager))
# Move the first window to the right
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
# 3 splits, first split has 2 windows
self.assertEqual([2, 1, 1], _window_pane_counts(window_manager))
target_pane = window_manager.window_lists[2].active_panes[0]
(
result_window_list,
result_pane_index,
) = window_manager.find_window_list_and_pane_index(target_pane)
self.assertEqual(
(result_window_list, result_pane_index),
(window_manager.window_lists[2], 0),
)
window_manager.remove_pane(target_pane)
self.assertEqual([2, 1], _window_pane_counts(window_manager))
def test_window_list_moving_and_resizing(self) -> None:
"""Test window split movement resizing."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=3)
window_manager = console_app.window_manager
target_list_and_pane(window_manager, 0, 0)
# Should have one window list split of size 50.
self.assertEqual(
_window_list_widths(window_manager),
[_WINDOW_MANAGER_WIDTH],
)
# Move one pane to the right, creating a new window_list split.
window_manager.move_pane_to_next_group()
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 2),
int(_WINDOW_MANAGER_WIDTH / 2),
],
)
# Move another pane to the right twice, creating a third
# window_list split.
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
# Above window pane is at a new location
target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_to_next_group()
# Should have 3 splits now
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 3),
int(_WINDOW_MANAGER_WIDTH / 3),
int(_WINDOW_MANAGER_WIDTH / 3),
],
)
# Total of 4 active panes
self.assertEqual(len(list(window_manager.active_panes())), 4)
# Target the middle split
target_list_and_pane(window_manager, 1, 0)
# Shrink the middle split twice
window_manager.shrink_split()
window_manager.shrink_split()
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 3),
int(_WINDOW_MANAGER_WIDTH / 3) - (2 * _WINDOW_SPLIT_ADJUST),
int(_WINDOW_MANAGER_WIDTH / 3) + (2 * _WINDOW_SPLIT_ADJUST),
],
)
# Target the first split
target_list_and_pane(window_manager, 0, 0)
window_manager.reset_split_sizes()
# Shrink the first split twice
window_manager.shrink_split()
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 3) - (1 * _WINDOW_SPLIT_ADJUST),
int(_WINDOW_MANAGER_WIDTH / 3) + (1 * _WINDOW_SPLIT_ADJUST),
int(_WINDOW_MANAGER_WIDTH / 3),
],
)
# Target the third (last) split
target_list_and_pane(window_manager, 2, 0)
window_manager.reset_split_sizes()
# Shrink the third split once
window_manager.shrink_split()
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 3),
int(_WINDOW_MANAGER_WIDTH / 3) + (1 * _WINDOW_SPLIT_ADJUST),
int(_WINDOW_MANAGER_WIDTH / 3) - (1 * _WINDOW_SPLIT_ADJUST),
],
)
window_manager.reset_split_sizes()
# Enlarge the third split a few times.
window_manager.enlarge_split()
window_manager.enlarge_split()
window_manager.enlarge_split()
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 3),
int(_WINDOW_MANAGER_WIDTH / 3) - (3 * _WINDOW_SPLIT_ADJUST),
int(_WINDOW_MANAGER_WIDTH / 3) + (3 * _WINDOW_SPLIT_ADJUST),
],
)
# Target the middle split
target_list_and_pane(window_manager, 1, 0)
# Move the middle window pane left
window_manager.move_pane_to_prev_group()
# This is called on the next render pass
window_manager.rebalance_window_list_sizes()
# Middle split should be removed
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 2) - (3 * _WINDOW_SPLIT_ADJUST),
# This split is removed
int(_WINDOW_MANAGER_WIDTH / 2) + (2 * _WINDOW_SPLIT_ADJUST),
],
)
# Revert sizes to default
window_manager.reset_split_sizes()
self.assertEqual(
_window_list_widths(window_manager),
[
int(_WINDOW_MANAGER_WIDTH / 2),
int(_WINDOW_MANAGER_WIDTH / 2),
],
)
def test_get_pane_titles(self) -> None:
"""Test window resizing."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=3)
window_manager = console_app.window_manager
list_pane_titles = [
# Remove mouse click handler partials in tup[2]
[(tup[0], tup[1]) for tup in window_list.get_pane_titles()]
for window_list in window_manager.window_lists
]
self.assertEqual(
list_pane_titles[0],
[
('', ' '),
('class:window-tab-inactive', ' Log2 test_log2 '),
('', ' '),
('class:window-tab-inactive', ' Log1 test_log1 '),
('', ' '),
('class:window-tab-inactive', ' Log0 test_log0 '),
('', ' '),
('class:window-tab-inactive', ' Python Repl '),
('', ' '),
],
)
def test_window_pane_movement_resizing(self) -> None:
"""Test window resizing."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=3)
window_manager = console_app.window_manager
# 4 panes, 3 for the loggers and 1 for the repl.
self.assertEqual(
len(window_manager.first_window_list().active_panes), 4
)
# Target the first window pane
target_window_pane(console_app, window_manager, 0)
# Shrink the first pane
window_manager.shrink_pane()
self.assertEqual(
_window_pane_heights(window_manager),
[
_DEFAULT_WINDOW_HEIGHT - (1 * _WINDOW_HEIGHT_ADJUST),
_DEFAULT_WINDOW_HEIGHT + (1 * _WINDOW_HEIGHT_ADJUST),
_DEFAULT_WINDOW_HEIGHT,
_DEFAULT_WINDOW_HEIGHT,
],
)
# Reset pane sizes
window_manager.window_lists[0].current_window_list_height = (
4 * _DEFAULT_WINDOW_HEIGHT
)
window_manager.reset_pane_sizes()
self.assertEqual(
_window_pane_heights(window_manager),
[
_DEFAULT_WINDOW_HEIGHT,
_DEFAULT_WINDOW_HEIGHT,
_DEFAULT_WINDOW_HEIGHT,
_DEFAULT_WINDOW_HEIGHT,
],
)
# Shrink last pane
target_window_pane(console_app, window_manager, 3)
window_manager.shrink_pane()
self.assertEqual(
_window_pane_heights(window_manager),
[
_DEFAULT_WINDOW_HEIGHT,
_DEFAULT_WINDOW_HEIGHT,
_DEFAULT_WINDOW_HEIGHT + (1 * _WINDOW_HEIGHT_ADJUST),
_DEFAULT_WINDOW_HEIGHT - (1 * _WINDOW_HEIGHT_ADJUST),
],
)
# Enlarge second pane
target_window_pane(console_app, window_manager, 1)
window_manager.reset_pane_sizes()
window_manager.enlarge_pane()
window_manager.enlarge_pane()
self.assertEqual(
_window_pane_heights(window_manager),
[
_DEFAULT_WINDOW_HEIGHT,
_DEFAULT_WINDOW_HEIGHT + (2 * _WINDOW_HEIGHT_ADJUST),
_DEFAULT_WINDOW_HEIGHT - (2 * _WINDOW_HEIGHT_ADJUST),
_DEFAULT_WINDOW_HEIGHT,
],
)
# Check window pane ordering
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log2 - test_log2',
'Log1 - test_log1',
'Log0 - test_log0',
'Python Repl - ',
],
],
)
# Switch to Tabbed view mode
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
target_window_pane(console_app, window_manager, 0)
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 0
)
window_manager.move_pane_down()
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 1
)
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log1 - test_log1',
'Log2 - test_log2',
'Log0 - test_log0',
'Python Repl - ',
],
],
)
target_window_pane(console_app, window_manager, 2)
window_manager.move_pane_up()
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 1
)
target_window_pane(console_app, window_manager, 1)
window_manager.move_pane_up()
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 0
)
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log0 - test_log0',
'Log1 - test_log1',
'Log2 - test_log2',
'Python Repl - ',
],
],
)
target_window_pane(console_app, window_manager, 0)
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 0
)
window_manager.move_pane_up()
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 0
)
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log0 - test_log0',
'Log1 - test_log1',
'Log2 - test_log2',
'Python Repl - ',
],
],
)
target_window_pane(console_app, window_manager, 2)
window_manager.move_pane_down()
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 3
)
window_manager.move_pane_down()
self.assertEqual(
window_manager.window_lists[0].focused_pane_index, 3
)
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log0 - test_log0',
'Log1 - test_log1',
'Python Repl - ',
'Log2 - test_log2',
],
],
)
def test_window_pane_movement_with_tabs(self) -> None:
"""Test window resizing."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
# 5 panes, 4 for the loggers and 1 for the repl.
self.assertEqual(
len(window_manager.first_window_list().active_panes), 5
)
def wm_state() -> list[str]:
return repr(window_manager).split('\n')
# pylint: disable=line-too-long
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=True)',
],
)
# Switch to tabbed mode.
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
# WindowList 0 is now tabbed, focus_pane_index is 0, and only Log3
# should be visible.
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=False)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=False)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
# Focus Log3
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_prev_group()
# WindowList 0 should now be just Log3, rest of the windows in WindowList 1
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=False)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
# Focus Log3 since moving it would now put that in focus
target_list_and_pane(window_manager, 0, 0)
# Switch list 0 to tabbed mode.
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
# WindowList 0 should now be TABBED with focus on 0
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=False)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
# Switch to Log1
window_manager.window_lists[1].switch_to_tab(1)
# WindowList 1 focused_pane_index should be 1 and only Log1 visible
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:1)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=False)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
# Focus Log1 since switch_to_tab would put that in focus.
target_list_and_pane(window_manager, 1, 1)
window_manager.move_pane_to_next_group()
# WindowList 2 should contain Log1, WindowList 1 should be focused on index 1.
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:1)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=False)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=False)',
'WindowList 2: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
],
)
# Focus Log1 since move_pane_to_next_group would put that in focus.
target_list_and_pane(window_manager, 2, 0)
# Switch to python repl tab.
window_manager.window_lists[1].switch_to_tab(2)
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:2)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=False)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=True)',
'WindowList 2: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
],
)
# Focus Python Repl since switch_to_tab would put that in focus.
target_list_and_pane(window_manager, 1, 2)
window_manager.move_pane_to_next_group()
# WindowList 1 now only has 2 tabs with #0 in focus, Python Repl is
# in WindowList 2
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
'WindowList 2: mode:DisplayMode.STACK focused_pane_index:None)',
' ReplPane(pane_title="Python Repl", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
],
)
# pylint: enable=line-too-long
def test_directional_window_focus_vertical_tabbed(self) -> None:
"""
Test directional focus with a tabbed vertical split.
Test Cases:
Vertical group split:
* Tabbed
* Left
* Focus the left tab if there is one.
* If at the leftmost tab, should focus the left group
if there is one, otherwise no-op.
* Right
* Focus right tab if there is one.
* If at rightmost tab, should focus the right group if
there is one, otherwise no-op.
* Up
* no-op
* Down
* no-op
"""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
# 5 panes, 4 for the loggers and 1 for the repl.
self.assertEqual(
len(window_manager.first_window_list().active_panes), 5
)
def wm_state() -> list[str]:
return repr(window_manager).split('\n')
# pylint: disable=line-too-long
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=True)',
],
)
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=False)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=False)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
# Move 2 windows left and switch to tabbed.
# Left window should have 2 tabs, right should have 3.
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_prev_group()
target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_to_prev_group()
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=False)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
# This is the first tab, so focus left should no-op.
target_list_and_pane(window_manager, 0, 0)
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_not_called()
# Focus right should move to the next tab.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
target_list_and_pane(window_manager, 0, 1)
# This is the last tab in this group, so focus right should focus the right group.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[1].active_panes[0]
)
target_list_and_pane(window_manager, 1, 0)
# This is the first tab in this group, so focus left should focus the left group.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
# Move to Python repl.
window_manager.window_lists[1].switch_to_tab(2)
target_list_and_pane(window_manager, 1, 2)
# This is the last tab in the last group, so focus right should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
console_app.focus_on_container.assert_not_called()
# Focus Up should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.UP)
console_app.focus_on_container.assert_not_called()
# Focus Down should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.DOWN)
console_app.focus_on_container.assert_not_called()
def test_directional_window_focus_vertical_stacked(self):
"""
Test directional focus with a stacked vertical split.
Test Cases:
Vertical group split:
* Stacked
* Left
* Focus the left group if there is one.
* If at leftmost group, no-op.
* Right
* Focus the right group if there is one.
* If at rightmost group, no-op.
* Up
* Focus the upper pane if there is one.
* If at first pane, no-op.
* Down
* Focus the below pane if there is one.
* If at last pane, no-op.
"""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
# 5 panes, 4 for the loggers and 1 for the repl.
self.assertEqual(
len(window_manager.first_window_list().active_panes), 5
)
def wm_state() -> list[str]:
return repr(window_manager).split('\n')
# pylint: disable=line-too-long
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=True)',
],
)
# Move 2 windows left.
# Left window should have 2 panes, right should have 3.
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_prev_group()
target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_to_prev_group()
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=True)',
],
)
target_list_and_pane(window_manager, 0, 0)
# Focus right should focus the right group.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[1].active_panes[0]
)
target_list_and_pane(window_manager, 1, 0)
# If currently focused on the rightmost group, focus right should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
console_app.focus_on_container.assert_not_called()
# Focus left should focus the left group.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[0]
)
target_list_and_pane(window_manager, 0, 0)
# If currently focused on the leftmost group, focus left should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_not_called()
# If currently focused on the first pane, focus up should no-op.
console_app.application.layout.focus.reset_mock()
window_manager.focus_pane_direction(Direction.UP)
console_app.application.layout.focus.assert_not_called()
# Focus down should move down one pane.
console_app.application.layout.focus.reset_mock()
window_manager.focus_pane_direction(Direction.DOWN)
console_app.application.layout.focus.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
target_list_and_pane(window_manager, 0, 1)
# If currently focused on the last pane, focus down should no-op.
console_app.application.layout.focus.reset_mock()
window_manager.focus_pane_direction(Direction.DOWN)
console_app.application.layout.focus.assert_not_called()
# Focus up should move up one pane.
console_app.application.layout.focus.reset_mock()
window_manager.focus_pane_direction(Direction.UP)
console_app.application.layout.focus.assert_called_once_with(
window_manager.window_lists[0].active_panes[0]
)
def test_directional_window_focus_horizontal_tabbed(self):
"""
Test directional focus with a horizontal tabbed split.
Horizontal Group Split:
* Tabbed
* Left
* Focus the left tab if there is one.
* If at the leftmost tab, no-op.
* Right
* Focus the right tab if there is one.
* If at the rightmost tab, no-op.
* Up
* Focus the upper group if there is one.
* If at the first group, no-op.
* Should focus the upper group if there is one.
* Down
* Focus the below group if there is one.
* If at the last group, no-op.
"""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
window_manager.vertical_window_list_splitting = MagicMock(
return_value=False
)
self.assertFalse(window_manager.vertical_window_list_splitting())
# 5 panes, 4 for the loggers and 1 for the repl.
self.assertEqual(
len(window_manager.first_window_list().active_panes), 5
)
def wm_state() -> list[str]:
return repr(window_manager).split('\n')
# pylint: disable=line-too-long
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=True)',
],
)
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=False)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=False)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
# Move 2 windows left and switch to tabbed.
# Left window should have 2 tabs, right should have 3.
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_prev_group()
target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_to_prev_group()
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=False)',
'WindowList 1: mode:DisplayMode.TABBED focused_pane_index:0)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=False)',
' ReplPane(pane_title="Python Repl", visible=False)',
],
)
target_list_and_pane(window_manager, 0, 0)
# There is no left group, and the leftmost tab is visible, so focus left should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_not_called()
target_list_and_pane(window_manager, 0, 0)
# Focus right should focus the next tab.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
target_list_and_pane(window_manager, 0, 1)
# There is no right group, and the rightmost tab is visible, so focus right should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
console_app.focus_on_container.assert_not_called()
target_list_and_pane(window_manager, 0, 1)
# Focus left should focus the previous tab.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[0]
)
target_list_and_pane(window_manager, 0, 0)
# This is the first group, so focus up should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.UP)
console_app.focus_on_container.assert_not_called()
target_list_and_pane(window_manager, 0, 0)
# Focus down should focus the below group.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.DOWN)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[1].active_panes[0]
)
target_list_and_pane(window_manager, 1, 0)
# There is no left group, and the leftmost tab is visible, so focus left should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_not_called()
target_list_and_pane(window_manager, 1, 0)
def test_directional_window_focus_horizontal_stacked(self):
"""
Test directional focus with a horizontal stacked split.
Horizontal Group Split:
* Stacked
* Left
* no-op
* Right
* no-op
* Up
* Focus the upper pane if there is one.
* If at the top pane, focus upper group if there is
one.
* If at top group, no-op.
* Down
* Focus the below pane if there is one.
* If at the bottom pane, focus below group if there is
one.
* If at bottom group, no-op.
"""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
window_manager.vertical_window_list_splitting = MagicMock(
return_value=False
)
self.assertFalse(window_manager.vertical_window_list_splitting())
# 5 panes, 4 for the loggers and 1 for the repl.
self.assertEqual(
len(window_manager.first_window_list().active_panes), 5
)
def wm_state() -> list[str]:
return repr(window_manager).split('\n')
# pylint: disable=line-too-long
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=True)',
],
)
# Move 2 windows left.
# Left window should have 2 panes, right should have 3.
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_prev_group()
target_list_and_pane(window_manager, 1, 0)
window_manager.move_pane_to_prev_group()
self.assertEqual(
wm_state(),
[
'WindowList 0: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log2", pane_subtitle="test_log2", visible=True)',
' LogPane(pane_title="Log3", pane_subtitle="test_log3", visible=True)',
'WindowList 1: mode:DisplayMode.STACK focused_pane_index:None)',
' LogPane(pane_title="Log1", pane_subtitle="test_log1", visible=True)',
' LogPane(pane_title="Log0", pane_subtitle="test_log0", visible=True)',
' ReplPane(pane_title="Python Repl", visible=True)',
],
)
target_list_and_pane(window_manager, 0, 0)
# In a horizontal stacked split, left and right should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.RIGHT)
window_manager.focus_pane_direction(Direction.LEFT)
console_app.focus_on_container.assert_not_called()
# This is the first pane, so focus up should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.UP)
console_app.focus_on_container.assert_not_called()
# Focus down should move down one pane.
console_app.application.layout.focus.reset_mock()
window_manager.focus_pane_direction(Direction.DOWN)
console_app.application.layout.focus.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
target_list_and_pane(window_manager, 0, 1)
# Focus down should move down to the next group.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.DOWN)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[1].active_panes[0]
)
target_list_and_pane(window_manager, 1, 0)
# Focus up should move up to the next group.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.UP)
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
target_list_and_pane(window_manager, 0, 1)
# Focus up should move up one pane.
console_app.application.layout.focus.reset_mock()
window_manager.focus_pane_direction(Direction.UP)
console_app.application.layout.focus.assert_called_once_with(
window_manager.window_lists[0].active_panes[0]
)
target_list_and_pane(window_manager, 1, 2)
# This is the last pane, so focus down should no-op.
console_app.focus_on_container.reset_mock()
window_manager.focus_pane_direction(Direction.DOWN)
console_app.focus_on_container.assert_not_called()
def test_focus_next_and_previous_pane(self) -> None:
"""Test switching focus to next and previous window panes."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
window_manager.window_lists[0].set_display_mode(DisplayMode.STACK)
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log3 - test_log3',
'Log2 - test_log2',
'Log1 - test_log1',
'Log0 - test_log0',
'Python Repl - ',
],
],
)
# Scenario: Move between panes with a single stacked window list.
# Set the first pane in focus.
target_list_and_pane(window_manager, 0, 0)
# Switch focus to the next pane
window_manager.focus_next_pane()
# Pane index 1 should now be focused.
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
console_app.focus_on_container.reset_mock()
# Set the first pane in focus.
target_list_and_pane(window_manager, 0, 0)
# Switch focus to the previous pane
window_manager.focus_previous_pane()
# Previous pane should wrap around to the last pane in the first
# window_list.
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[-1]
)
console_app.focus_on_container.reset_mock()
# Set the last pane in focus.
target_list_and_pane(window_manager, 0, 4)
# Switch focus to the next pane
window_manager.focus_next_pane()
# Next pane should wrap around to the first pane in the first
# window_list.
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[0]
)
console_app.focus_on_container.reset_mock()
# Scenario: Move between panes with a single tabbed window list.
# Switch to Tabbed view mode
window_manager.window_lists[0].set_display_mode(DisplayMode.TABBED)
# The set_display_mode call above will call focus_on_container once.
console_app.focus_on_container.reset_mock()
# Setup the switch_to_tab mock
window_manager.window_lists[0].switch_to_tab = MagicMock(
wraps=window_manager.window_lists[0].switch_to_tab
)
# Set the first pane/tab in focus.
target_list_and_pane(window_manager, 0, 0)
# Switch focus to the next pane/tab
window_manager.focus_next_pane()
# Check switch_to_tab is called
window_manager.window_lists[
0
].switch_to_tab.assert_called_once_with(1)
# And that focus_on_container is called only once
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
console_app.focus_on_container.reset_mock()
window_manager.window_lists[0].switch_to_tab.reset_mock()
# Set the last pane/tab in focus.
target_list_and_pane(window_manager, 0, 4)
# Switch focus to the next pane/tab
window_manager.focus_next_pane()
# Check switch_to_tab is called
window_manager.window_lists[
0
].switch_to_tab.assert_called_once_with(0)
# And that focus_on_container is called only once
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[0]
)
console_app.focus_on_container.reset_mock()
window_manager.window_lists[0].switch_to_tab.reset_mock()
# Set the first pane/tab in focus.
target_list_and_pane(window_manager, 0, 0)
# Switch focus to the prev pane/tab
window_manager.focus_previous_pane()
# Check switch_to_tab is called
window_manager.window_lists[
0
].switch_to_tab.assert_called_once_with(4)
# And that focus_on_container is called only once
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[4]
)
console_app.focus_on_container.reset_mock()
window_manager.window_lists[0].switch_to_tab.reset_mock()
# Scenario: Move between multiple window lists with mixed stacked
# and tabbed view modes.
# Setup: Move two panes to the right into their own stacked
# window_list.
target_list_and_pane(window_manager, 0, 4)
window_manager.move_pane_to_next_group()
target_list_and_pane(window_manager, 0, 3)
window_manager.move_pane_to_next_group()
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log3 - test_log3',
'Log2 - test_log2',
'Log1 - test_log1',
],
[
'Log0 - test_log0',
'Python Repl - ',
],
],
)
# Setup the switch_to_tab mock on the second window_list
window_manager.window_lists[1].switch_to_tab = MagicMock(
wraps=window_manager.window_lists[1].switch_to_tab
)
# Set Log1 in focus
target_list_and_pane(window_manager, 0, 2)
console_app.focus_on_container.reset_mock()
window_manager.focus_next_pane()
# Log0 should now have focus
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[1].active_panes[0]
)
# Set Log0 in focus
target_list_and_pane(window_manager, 1, 0)
# Reset mock
console_app.focus_on_container.reset_mock()
window_manager.window_lists[0].switch_to_tab.reset_mock()
window_manager.focus_previous_pane()
# Log1 should now have focus
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[2]
)
# The first window list is in tabbed mode so switch_to_tab should be
# called once.
window_manager.window_lists[
0
].switch_to_tab.assert_called_once_with(2)
# Reset
console_app.focus_on_container.reset_mock()
window_manager.window_lists[0].switch_to_tab.reset_mock()
# Set Python Repl in focus
target_list_and_pane(window_manager, 1, 1)
window_manager.focus_next_pane()
# Log3 should now have focus
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[0]
)
window_manager.window_lists[
0
].switch_to_tab.assert_called_once_with(0)
# Reset
window_manager.window_lists[0].switch_to_tab.reset_mock()
console_app.focus_on_container.reset_mock()
# Set Log3 in focus
target_list_and_pane(window_manager, 0, 0)
window_manager.focus_next_pane()
# Log2 should now have focus
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[0].active_panes[1]
)
window_manager.window_lists[
0
].switch_to_tab.assert_called_once_with(1)
# Reset
window_manager.window_lists[0].switch_to_tab.reset_mock()
console_app.focus_on_container.reset_mock()
# Set Python Repl in focus
target_list_and_pane(window_manager, 1, 1)
window_manager.focus_previous_pane()
# Log0 should now have focus
console_app.focus_on_container.assert_called_once_with(
window_manager.window_lists[1].active_panes[0]
)
# The second window list is in stacked mode so switch_to_tab should
# not be called.
window_manager.window_lists[1].switch_to_tab.assert_not_called()
# Reset
window_manager.window_lists[1].switch_to_tab.reset_mock()
console_app.focus_on_container.reset_mock()
def test_resize_vertical_splits(self) -> None:
"""Test resizing window splits."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
# Required before moving windows
window_manager.update_window_manager_size(
_WINDOW_MANAGER_WIDTH, _WINDOW_MANAGER_HEIGHT
)
window_manager.create_root_container()
# Vertical split by default
self.assertTrue(window_manager.vertical_window_list_splitting())
# Move windows to create 3 splits
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
target_list_and_pane(window_manager, 1, 1)
window_manager.move_pane_to_next_group()
# Check windows are where expected
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log1 - test_log1',
'Log0 - test_log0',
'Python Repl - ',
],
[
'Log2 - test_log2',
],
[
'Log3 - test_log3',
],
],
)
# Check initial split widths
widths = [
int(_WINDOW_MANAGER_WIDTH / 3),
int(_WINDOW_MANAGER_WIDTH / 3),
int(_WINDOW_MANAGER_WIDTH / 3),
]
self.assertEqual(_window_list_widths(window_manager), widths)
# Decrease size of first split
window_manager.adjust_split_size(window_manager.window_lists[0], -4)
widths = [
widths[0] - (4 * _WINDOW_SPLIT_ADJUST),
widths[1] + (4 * _WINDOW_SPLIT_ADJUST),
widths[2],
]
self.assertEqual(_window_list_widths(window_manager), widths)
# Increase size of last split
widths = [
widths[0],
widths[1] - (4 * _WINDOW_SPLIT_ADJUST),
widths[2] + (4 * _WINDOW_SPLIT_ADJUST),
]
window_manager.adjust_split_size(window_manager.window_lists[2], 4)
self.assertEqual(_window_list_widths(window_manager), widths)
# Check heights are all the same
window_manager.rebalance_window_list_sizes()
heights = [
int(_WINDOW_MANAGER_HEIGHT),
int(_WINDOW_MANAGER_HEIGHT),
int(_WINDOW_MANAGER_HEIGHT),
]
self.assertEqual(_window_list_heights(window_manager), heights)
def test_resize_horizontal_splits(self) -> None:
"""Test resizing window splits."""
with create_app_session(output=FakeOutput()):
console_app = _create_console_app(logger_count=4)
window_manager = console_app.window_manager
# We want horizontal window splits
window_manager.vertical_window_list_splitting = MagicMock(
return_value=False
)
self.assertFalse(window_manager.vertical_window_list_splitting())
# Required before moving windows
window_manager.update_window_manager_size(
_WINDOW_MANAGER_WIDTH, _WINDOW_MANAGER_HEIGHT
)
window_manager.create_root_container()
# Move windows to create 3 splits
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
target_list_and_pane(window_manager, 0, 0)
window_manager.move_pane_to_next_group()
target_list_and_pane(window_manager, 1, 1)
window_manager.move_pane_to_next_group()
# Check windows are where expected
self.assertEqual(
window_pane_titles(window_manager),
[
[
'Log1 - test_log1',
'Log0 - test_log0',
'Python Repl - ',
],
[
'Log2 - test_log2',
],
[
'Log3 - test_log3',
],
],
)
# Check initial split widths
heights = [
int(_WINDOW_MANAGER_HEIGHT / 3),
int(_WINDOW_MANAGER_HEIGHT / 3),
int(_WINDOW_MANAGER_HEIGHT / 3),
]
self.assertEqual(_window_list_heights(window_manager), heights)
# Decrease size of first split
window_manager.adjust_split_size(window_manager.window_lists[0], -4)
heights = [
heights[0] - (4 * _WINDOW_SPLIT_ADJUST),
heights[1] + (4 * _WINDOW_SPLIT_ADJUST),
heights[2],
]
self.assertEqual(_window_list_heights(window_manager), heights)
# Increase size of last split
heights = [
heights[0],
heights[1] - (4 * _WINDOW_SPLIT_ADJUST),
heights[2] + (4 * _WINDOW_SPLIT_ADJUST),
]
window_manager.adjust_split_size(window_manager.window_lists[2], 4)
self.assertEqual(_window_list_heights(window_manager), heights)
# Check widths are all the same
window_manager.rebalance_window_list_sizes()
widths = [
int(_WINDOW_MANAGER_WIDTH),
int(_WINDOW_MANAGER_WIDTH),
int(_WINDOW_MANAGER_WIDTH),
]
self.assertEqual(_window_list_widths(window_manager), widths)
if __name__ == '__main__':
unittest.main()