#!/usr/bin/env python # License: GPL v3 Copyright: 2026, Kovid Goyal from unittest.mock import patch from kitty.fast_data_types import LEFT_EDGE, Region from kitty.tab_bar import TabBar, TabBarData from . import BaseTest def region(left: int, top: int, right: int, bottom: int) -> Region: return Region((left, top, right, bottom, right - left, bottom - top)) class DummyBoss: class mappings: current_keyboard_mode_name = '' def tab_for_id(self, tab_id: int) -> None: return None class TestTabBar(BaseTest): def test_vertical_tab_bar_hit_testing(self) -> None: self.set_options({ 'tab_bar_edge': LEFT_EDGE, 'tab_bar_style': 'separator', 'tab_title_template': '{title}', }) central = region(120, 0, 400, 160) tab_bar = region(0, 0, 120, 160) geometries: list[tuple[int, int, int, int]] = [] boss = DummyBoss() with ( patch('kitty.tab_bar.cell_size_for_window', return_value=(10, 20)), patch('kitty.tab_bar.viewport_for_window', return_value=(central, tab_bar, 400, 160, 10, 20)), patch('kitty.tab_bar.set_tab_bar_render_data', side_effect=lambda *args: geometries.append(args[2:6])), patch('kitty.tab_bar.get_boss', return_value=boss), ): tb = TabBar(1) tb.layout() tb.update(( TabBarData(title='one', tab_id=1, is_active=True), TabBarData(title='two', tab_id=2), TabBarData(title='three', tab_id=3), )) self.assertTrue(tb.is_vertical) self.ae(geometries[-1], (0, 0, 120, 160)) self.ae(tb.drag_axis_coordinate(5, 35), 35) self.ae(tb.tab_id_at(5, 10), 1) self.ae(tb.tab_id_at(110, 35), 1) self.ae(tb.tab_id_at(60, 55), 2) self.ae(tb.tab_id_at(60, 95), 3) self.ae(tb.tab_id_at(60, 135), 0) self.ae(tb.tab_id_at(180, 10), 0) def test_vertical_tab_bar_alignment(self) -> None: self.set_options({ 'tab_bar_align': 'end', 'tab_bar_edge': LEFT_EDGE, 'tab_bar_style': 'separator', 'tab_title_template': '{title}', }) central = region(120, 0, 400, 160) tab_bar = region(0, 0, 120, 160) boss = DummyBoss() with ( patch('kitty.tab_bar.cell_size_for_window', return_value=(10, 20)), patch('kitty.tab_bar.viewport_for_window', return_value=(central, tab_bar, 400, 160, 10, 20)), patch('kitty.tab_bar.set_tab_bar_render_data'), patch('kitty.tab_bar.get_boss', return_value=boss), ): tb = TabBar(1) tb.layout() tb.update(( TabBarData(title='one', tab_id=1, is_active=True), TabBarData(title='two', tab_id=2), )) self.ae(tb.tab_extents[0].y, (4, 5)) self.ae(tb.tab_extents[1].y, (6, 7)) self.ae(tb.tab_id_at(5, 10), 0) self.ae(tb.tab_id_at(5, 110), 1) self.ae(tb.tab_id_at(5, 150), 2)