Files
cthulhu/tests/test_braille_presenter.py

1225 lines
44 KiB
Python

# Unit tests for braille_presenter.py methods.
#
# Copyright 2025-2026 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
# pylint: disable=wrong-import-position
# pylint: disable=import-outside-toplevel
# pylint: disable=protected-access
# pylint: disable=too-many-public-methods
# pylint: disable=too-many-lines
"""Unit tests for braille_presenter.py methods."""
from __future__ import annotations
import unittest.mock
from typing import TYPE_CHECKING
import gi
gi.require_version("Gtk", "3.0")
import pytest
if TYPE_CHECKING:
from unittest.mock import MagicMock
from cthulhu_test_context import CthulhuTestContext
@pytest.mark.unit
class TestBraillePresenter:
"""Test BraillePresenter methods."""
def _setup_dependencies(self, test_context: CthulhuTestContext) -> dict[str, MagicMock]:
"""Set up mocks for braille_presenter dependencies."""
additional_modules = ["cthulhu.braille", "cthulhu.braille_monitor", "cthulhu.cthulhu_platform"]
essential_modules = test_context.setup_shared_dependencies(additional_modules)
platform_mock = essential_modules["cthulhu.cthulhu_platform"]
platform_mock.tablesdir = "/usr/share/liblouis/tables"
from cthulhu import gsettings_registry
registry = gsettings_registry.get_registry()
registry.clear_runtime_values()
test_context.patch(
"cthulhu.braille_presenter.BraillePresenter._get_table_files",
return_value=[
"en-us-g1.ctb",
"en-us-g2.ctb",
"en-us-comp8.ctb",
"fr-bfu-g2.ctb",
"de-g2.ctb",
],
)
return essential_modules
def test_get_braille_is_enabled(self, test_context: CthulhuTestContext):
"""Test getting braille enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_braille_is_enabled() is True
presenter.set_braille_is_enabled(False)
assert presenter.get_braille_is_enabled() is False
def test_set_braille_is_enabled(self, test_context: CthulhuTestContext):
"""Test setting braille enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_braille_is_enabled(True)
assert result is True
assert presenter.get_braille_is_enabled() is True
result = presenter.set_braille_is_enabled(False)
assert result is True
assert presenter.get_braille_is_enabled() is False
def test_get_contraction_table(self, test_context: CthulhuTestContext):
"""Test getting contraction table."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_contraction_table() == ""
presenter.set_contraction_table("en-us-g2")
assert presenter.get_contraction_table() == "en-us-g2"
def test_get_available_contraction_tables(self, test_context: CthulhuTestContext):
"""Test getting available contraction tables."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
tables = presenter.get_available_contraction_tables()
expected = ["en-us-g1", "en-us-g2", "en-us-comp8", "fr-bfu-g2", "de-g2"]
assert tables == expected
def test_set_contraction_table_valid(self, test_context: CthulhuTestContext):
"""Test setting valid contraction table."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_contraction_table("en-us-g2")
assert result is True
assert presenter.get_contraction_table_path() == "/usr/share/liblouis/tables/en-us-g2.ctb"
result = presenter.set_contraction_table("en-us-g1.ctb")
assert result is True
assert presenter.get_contraction_table_path() == "/usr/share/liblouis/tables/en-us-g1.ctb"
def test_set_contraction_table_invalid(self, test_context: CthulhuTestContext):
"""Test setting invalid contraction table."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_contraction_table("nonexistent")
assert result is False
result = presenter.set_contraction_table("nonexistent.ctb")
assert result is False
def test_set_contraction_table_empty_string(self, test_context: CthulhuTestContext):
"""Test setting empty contraction table returns False."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_contraction_table("")
assert result is False
def test_get_indicator_styles(self, test_context: CthulhuTestContext):
"""Test getting indicator styles."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_selector_indicator() == "dots78"
assert presenter.get_link_indicator() == "dots78"
assert presenter.get_text_attributes_indicator() == "none"
presenter.set_link_indicator("dot7")
assert presenter.get_link_indicator() == "dot7"
def test_set_indicator_styles(self, test_context: CthulhuTestContext):
"""Test setting indicator styles."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_selector_indicator("dots78")
assert result is True
assert presenter.get_selector_indicator() == "dots78"
result = presenter.set_link_indicator("dot8")
assert result is True
assert presenter.get_link_indicator() == "dot8"
result = presenter.set_text_attributes_indicator("none")
assert result is True
assert presenter.get_text_attributes_indicator() == "none"
result = presenter.set_selector_indicator("invalid")
assert result is False
result = presenter.set_link_indicator("invalid")
assert result is False
result = presenter.set_text_attributes_indicator("invalid")
assert result is False
def test_end_of_line_indicator(self, test_context: CthulhuTestContext):
"""Test end of line indicator settings."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_end_of_line_indicator_is_enabled() is True
result = presenter.set_end_of_line_indicator_is_enabled(False)
assert result is True
assert presenter.get_end_of_line_indicator_is_enabled() is False
result = presenter.set_end_of_line_indicator_is_enabled(True)
assert result is True
assert presenter.get_end_of_line_indicator_is_enabled() is True
def test_use_braille(self, test_context: CthulhuTestContext):
"""Test use_braille method."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
presenter.set_monitor_is_enabled(False)
assert presenter.use_braille() is True
presenter.set_braille_is_enabled(False)
presenter.set_monitor_is_enabled(True)
assert presenter.use_braille() is True
presenter.set_monitor_is_enabled(False)
assert presenter.use_braille() is False
def test_use_verbose_braille(self, test_context: CthulhuTestContext):
"""Test use_verbose_braille method."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.use_verbose_braille() is True
presenter.set_verbosity_level("brief")
assert presenter.use_verbose_braille() is False
def test_get_verbosity_level(self, test_context: CthulhuTestContext):
"""Test getting verbosity level."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_verbosity_level() == "verbose"
presenter.set_verbosity_level("brief")
assert presenter.get_verbosity_level() == "brief"
def test_set_verbosity_level(self, test_context: CthulhuTestContext):
"""Test setting verbosity level."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_verbosity_level("brief")
assert result is True
assert presenter.get_verbosity_level() == "brief"
result = presenter.set_verbosity_level("verbose")
assert result is True
assert presenter.get_verbosity_level() == "verbose"
result = presenter.set_verbosity_level("invalid")
assert result is False
def test_use_full_rolenames(self, test_context: CthulhuTestContext):
"""Test use_full_rolenames method."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.use_full_rolenames() is True
presenter.set_rolename_style("brief")
assert presenter.use_full_rolenames() is False
def test_get_rolename_style(self, test_context: CthulhuTestContext):
"""Test getting rolename style."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_rolename_style() == "verbose"
presenter.set_rolename_style("brief")
assert presenter.get_rolename_style() == "brief"
def test_set_rolename_style(self, test_context: CthulhuTestContext):
"""Test setting rolename style."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_rolename_style("brief")
assert result is True
assert presenter.get_rolename_style() == "brief"
result = presenter.set_rolename_style("verbose")
assert result is True
assert presenter.get_rolename_style() == "verbose"
result = presenter.set_rolename_style("invalid")
assert result is False
def test_get_display_ancestors(self, test_context: CthulhuTestContext):
"""Test getting display ancestors setting."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_display_ancestors() is True
presenter.set_display_ancestors(False)
assert presenter.get_display_ancestors() is False
def test_set_display_ancestors(self, test_context: CthulhuTestContext):
"""Test setting display ancestors."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_display_ancestors(True)
assert result is True
assert presenter.get_display_ancestors() is True
result = presenter.set_display_ancestors(False)
assert result is True
assert presenter.get_display_ancestors() is False
def test_get_contracted_braille_is_enabled(self, test_context: CthulhuTestContext):
"""Test getting contracted braille enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_contracted_braille_is_enabled() is False
presenter.set_contracted_braille_is_enabled(True)
assert presenter.get_contracted_braille_is_enabled() is True
def test_set_contracted_braille_is_enabled(self, test_context: CthulhuTestContext):
"""Test setting contracted braille enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_contracted_braille_is_enabled(True)
assert result is True
assert presenter.get_contracted_braille_is_enabled() is True
result = presenter.set_contracted_braille_is_enabled(False)
assert result is True
assert presenter.get_contracted_braille_is_enabled() is False
def test_get_computer_braille_at_cursor_is_enabled(self, test_context: CthulhuTestContext):
"""Test getting computer braille at cursor enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_computer_braille_at_cursor_is_enabled() is True
presenter.set_computer_braille_at_cursor_is_enabled(False)
assert presenter.get_computer_braille_at_cursor_is_enabled() is False
def test_set_computer_braille_at_cursor_is_enabled(self, test_context: CthulhuTestContext):
"""Test setting computer braille at cursor enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_computer_braille_at_cursor_is_enabled(True)
assert result is True
assert presenter.get_computer_braille_at_cursor_is_enabled() is True
result = presenter.set_computer_braille_at_cursor_is_enabled(False)
assert result is True
assert presenter.get_computer_braille_at_cursor_is_enabled() is False
def test_get_word_wrap_is_enabled(self, test_context: CthulhuTestContext):
"""Test getting word wrap enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_word_wrap_is_enabled() is False
presenter.set_word_wrap_is_enabled(True)
assert presenter.get_word_wrap_is_enabled() is True
def test_set_word_wrap_is_enabled(self, test_context: CthulhuTestContext):
"""Test setting word wrap enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_word_wrap_is_enabled(True)
assert result is True
assert presenter.get_word_wrap_is_enabled() is True
result = presenter.set_word_wrap_is_enabled(False)
assert result is True
assert presenter.get_word_wrap_is_enabled() is False
def test_get_flash_messages_are_enabled(self, test_context: CthulhuTestContext):
"""Test getting flash messages enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_flash_messages_are_enabled() is True
presenter.set_flash_messages_are_enabled(False)
assert presenter.get_flash_messages_are_enabled() is False
def test_set_flash_messages_are_enabled(self, test_context: CthulhuTestContext):
"""Test setting flash messages enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_flash_messages_are_enabled(True)
assert result is True
assert presenter.get_flash_messages_are_enabled() is True
result = presenter.set_flash_messages_are_enabled(False)
assert result is True
assert presenter.get_flash_messages_are_enabled() is False
def test_get_flashtime_from_settings(self, test_context: CthulhuTestContext):
"""Test getting flashtime from settings."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
presenter.set_flash_messages_are_persistent(True)
assert presenter.get_flashtime_from_settings() == -1
presenter.set_flash_messages_are_persistent(False)
presenter.set_flash_message_duration(3000)
assert presenter.get_flashtime_from_settings() == 3000
def test_get_flash_message_duration(self, test_context: CthulhuTestContext):
"""Test getting flash message duration."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_flash_message_duration() == 5000
def test_set_flash_message_duration(self, test_context: CthulhuTestContext):
"""Test setting flash message duration."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_flash_message_duration(4000)
assert result is True
assert presenter.get_flash_message_duration() == 4000
def test_get_flash_messages_are_persistent(self, test_context: CthulhuTestContext):
"""Test getting flash messages persistent status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_flash_messages_are_persistent() is False
presenter.set_flash_messages_are_persistent(True)
assert presenter.get_flash_messages_are_persistent() is True
def test_set_flash_messages_are_persistent(self, test_context: CthulhuTestContext):
"""Test setting flash messages persistent status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_flash_messages_are_persistent(True)
assert result is True
assert presenter.get_flash_messages_are_persistent() is True
result = presenter.set_flash_messages_are_persistent(False)
assert result is True
assert presenter.get_flash_messages_are_persistent() is False
def test_get_flash_messages_are_detailed(self, test_context: CthulhuTestContext):
"""Test getting flash messages detailed status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_flash_messages_are_detailed() is True
presenter.set_flash_messages_are_detailed(False)
assert presenter.get_flash_messages_are_detailed() is False
def test_set_flash_messages_are_detailed(self, test_context: CthulhuTestContext):
"""Test setting flash messages detailed status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_flash_messages_are_detailed(True)
assert result is True
assert presenter.get_flash_messages_are_detailed() is True
result = presenter.set_flash_messages_are_detailed(False)
assert result is True
assert presenter.get_flash_messages_are_detailed() is False
def test_get_verbosity_is_detailed(self, test_context: CthulhuTestContext):
"""Test _get_verbosity_is_detailed returns correct boolean."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter._get_verbosity_is_detailed() is True
presenter.set_verbosity_level("brief")
assert presenter._get_verbosity_is_detailed() is False
def test_set_verbosity_is_detailed(self, test_context: CthulhuTestContext):
"""Test _set_verbosity_is_detailed sets verbosity level from boolean."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter._set_verbosity_is_detailed(True)
assert result is True
assert presenter.get_verbosity_level() == "verbose"
result = presenter._set_verbosity_is_detailed(False)
assert result is True
assert presenter.get_verbosity_level() == "brief"
def test_get_eol_enabled(self, test_context: CthulhuTestContext):
"""Test get_end_of_line_indicator_is_enabled returns default then setter value."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_end_of_line_indicator_is_enabled() is True
presenter.set_end_of_line_indicator_is_enabled(False)
assert presenter.get_end_of_line_indicator_is_enabled() is False
def test_set_eol_enabled(self, test_context: CthulhuTestContext):
"""Test set_end_of_line_indicator_is_enabled sets end-of-line-indicator."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_end_of_line_indicator_is_enabled(True)
assert result is True
assert presenter.get_end_of_line_indicator_is_enabled() is True
result = presenter.set_end_of_line_indicator_is_enabled(False)
assert result is True
assert presenter.get_end_of_line_indicator_is_enabled() is False
def test_get_use_abbreviated_rolenames(self, test_context: CthulhuTestContext):
"""Test _get_use_abbreviated_rolenames returns True when brief style."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter._get_use_abbreviated_rolenames() is False
presenter.set_rolename_style("brief")
assert presenter._get_use_abbreviated_rolenames() is True
def test_set_use_abbreviated_rolenames(self, test_context: CthulhuTestContext):
"""Test _set_use_abbreviated_rolenames sets rolename style from boolean."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter._set_use_abbreviated_rolenames(True)
assert result is True
assert presenter.get_rolename_style() == "brief"
result = presenter._set_use_abbreviated_rolenames(False)
assert result is True
assert presenter.get_rolename_style() == "verbose"
def test_get_flash_duration_seconds(self, test_context: CthulhuTestContext):
"""Test _get_flash_duration_seconds converts milliseconds to seconds."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter._get_flash_duration_seconds() == 5
presenter.set_flash_message_duration(2500)
assert presenter._get_flash_duration_seconds() == 2
presenter.set_flash_message_duration(1000)
assert presenter._get_flash_duration_seconds() == 1
def test_set_flash_duration_seconds(self, test_context: CthulhuTestContext):
"""Test _set_flash_duration_seconds converts seconds to milliseconds."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
presenter._set_flash_duration_seconds(5)
assert presenter.get_flash_message_duration() == 5000
presenter._set_flash_duration_seconds(1)
assert presenter.get_flash_message_duration() == 1000
presenter._set_flash_duration_seconds(10)
assert presenter.get_flash_message_duration() == 10000
def test_get_present_mnemonics(self, test_context: CthulhuTestContext):
"""Test getting present mnemonics setting."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter.get_present_mnemonics() is True
presenter.set_present_mnemonics(False)
assert presenter.get_present_mnemonics() is False
def test_set_present_mnemonics(self, test_context: CthulhuTestContext):
"""Test setting present mnemonics."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_present_mnemonics(True)
assert result is True
assert presenter.get_present_mnemonics() is True
result = presenter.set_present_mnemonics(False)
assert result is True
assert presenter.get_present_mnemonics() is False
def test_get_set_monitor_is_enabled(self, test_context: CthulhuTestContext):
"""Test getting and setting braille monitor enabled status."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
result = presenter.set_monitor_is_enabled(True)
assert result is True
assert presenter.get_monitor_is_enabled() is True
result = presenter.set_monitor_is_enabled(False)
assert result is True
assert presenter.get_monitor_is_enabled() is False
def test_set_braille_monitor_disabled_destroys_monitor(self, test_context: CthulhuTestContext):
"""Test explicitly disabling braille monitor destroys the monitor widget."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
mock_monitor = test_context.Mock()
presenter._monitor = mock_monitor
presenter.set_monitor_is_enabled(False)
mock_monitor.destroy.assert_called_once()
assert presenter._monitor is None
def test_init_braille_registers_monitor_callback(self, test_context: CthulhuTestContext):
"""Test init_braille registers the monitor callback with braille."""
essential_modules = self._setup_dependencies(test_context)
braille_mock = essential_modules["cthulhu.braille"]
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
presenter.init_braille()
braille_mock.set_monitor_callback.assert_called_once_with(presenter.update_monitor)
def test_update_monitor_creates_when_enabled(self, test_context: CthulhuTestContext):
"""Test update_monitor creates monitor on demand when enabled."""
essential_modules = self._setup_dependencies(test_context)
braille_monitor_mock = essential_modules["cthulhu.braille_monitor"]
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
presenter.set_monitor_is_enabled(True)
presenter.set_monitor_cell_count(40)
mock_monitor = test_context.Mock()
braille_monitor_mock.BrailleMonitor.return_value = mock_monitor
presenter.update_monitor(1, "hello", None, 40)
braille_monitor_mock.BrailleMonitor.assert_called_once_with(
40,
on_close=unittest.mock.ANY,
foreground=unittest.mock.ANY,
background=unittest.mock.ANY,
)
mock_monitor.show_all.assert_called_once()
mock_monitor.write_text.assert_called_once_with(1, "hello", None)
def test_update_monitor_uses_cell_count_setting(self, test_context: CthulhuTestContext):
"""Test update_monitor uses the configured cell count instead of display size."""
essential_modules = self._setup_dependencies(test_context)
braille_monitor_mock = essential_modules["cthulhu.braille_monitor"]
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
presenter.set_monitor_is_enabled(True)
presenter.set_monitor_cell_count(20)
mock_monitor = test_context.Mock()
braille_monitor_mock.BrailleMonitor.return_value = mock_monitor
presenter.update_monitor(1, "hello", None, 40)
braille_monitor_mock.BrailleMonitor.assert_called_once_with(
20,
on_close=unittest.mock.ANY,
foreground=unittest.mock.ANY,
background=unittest.mock.ANY,
)
def test_update_monitor_skips_when_disabled(self, test_context: CthulhuTestContext):
"""Test update_monitor skips update when disabled without destroying."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
presenter.set_monitor_is_enabled(False)
mock_monitor = test_context.Mock()
presenter._monitor = mock_monitor
presenter.update_monitor(1, "hello", None, 40)
mock_monitor.write_text.assert_not_called()
assert presenter._monitor is mock_monitor
def test_destroy_monitor(self, test_context: CthulhuTestContext):
"""Test destroy_monitor destroys existing monitor."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
mock_monitor = test_context.Mock()
presenter._monitor = mock_monitor
presenter.destroy_monitor()
mock_monitor.destroy.assert_called_once()
assert presenter._monitor is None
def test_destroy_monitor_no_op_when_none(self, test_context: CthulhuTestContext):
"""Test destroy_monitor does nothing when no monitor exists."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
assert presenter._monitor is None
presenter.destroy_monitor()
assert presenter._monitor is None
def test_shutdown_braille_does_not_destroy_monitor(self, test_context: CthulhuTestContext):
"""Test shutdown_braille does not destroy the monitor."""
essential_modules = self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
mock_monitor = test_context.Mock()
presenter._monitor = mock_monitor
presenter.shutdown_braille()
mock_monitor.destroy.assert_not_called()
assert presenter._monitor is mock_monitor
essential_modules["cthulhu.braille"].shutdown.assert_called_once()
def test_set_braille_disabled_keeps_monitor(self, test_context: CthulhuTestContext):
"""Test disabling braille does not destroy the monitor."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import get_presenter
presenter = get_presenter()
mock_monitor = test_context.Mock()
presenter._monitor = mock_monitor
presenter.set_braille_is_enabled(False)
mock_monitor.destroy.assert_not_called()
assert presenter._monitor is mock_monitor
@pytest.mark.unit
class TestBraillePreferencesGridUI:
"""Test Braille preferences grid UI creation."""
# pylint: disable-next=too-many-statements
def _setup_dependencies(self, test_context: CthulhuTestContext) -> dict[str, MagicMock]:
"""Set up mocks for braille_presenter GUI dependencies."""
additional_modules = ["cthulhu.braille", "cthulhu.braille_monitor", "cthulhu.cthulhu_platform"]
essential_modules = test_context.setup_shared_dependencies(additional_modules)
platform_mock = essential_modules["cthulhu.cthulhu_platform"]
platform_mock.tablesdir = "/usr/share/liblouis/tables"
from cthulhu import gsettings_registry
registry = gsettings_registry.get_registry()
registry.clear_runtime_values()
test_context.patch(
"cthulhu.braille_presenter.BraillePresenter._get_table_files",
return_value=[
"en-us-g1.ctb",
"en-us-g2.ctb",
],
)
guilabels_mock = essential_modules["cthulhu.guilabels"]
guilabels_mock.OBJECT_PRESENTATION_IS_DETAILED = "Detailed"
guilabels_mock.BRAILLE_SHOW_CONTEXT = "Show context"
guilabels_mock.BRAILLE_ABBREVIATED_ROLE_NAMES = "Abbreviated role names"
guilabels_mock.PRESENT_OBJECT_MNEMONICS = "Present mnemonics"
guilabels_mock.VERBOSITY = "Verbosity"
guilabels_mock.BRAILLE_ENABLE_CONTRACTED_BRAILLE = "Enable contracted braille"
guilabels_mock.BRAILLE_COMPUTER_BRAILLE_AT_CURSOR = "Expand word at cursor"
guilabels_mock.BRAILLE_ENABLE_END_OF_LINE_SYMBOL = "End of line symbol"
guilabels_mock.BRAILLE_ENABLE_WORD_WRAP = "Enable word wrap"
guilabels_mock.BRAILLE_CONTRACTION_TABLE = "Contraction table"
guilabels_mock.BRAILLE_HYPERLINK_INDICATOR = "Hyperlink indicator"
guilabels_mock.BRAILLE_DOT_NONE = "None"
guilabels_mock.BRAILLE_DOT_7 = "Dot 7"
guilabels_mock.BRAILLE_DOT_8 = "Dot 8"
guilabels_mock.BRAILLE_DOT_7_8 = "Dots 7 and 8"
guilabels_mock.BRAILLE_INDICATORS = "Indicators"
guilabels_mock.BRAILLE_SELECTION_INDICATOR = "Selection indicator"
guilabels_mock.BRAILLE_TEXT_ATTRIBUTES_INDICATOR = "Text attributes indicator"
guilabels_mock.BRAILLE_DISPLAY_SETTINGS = "Display Settings"
guilabels_mock.BRAILLE_MESSAGES_ARE_PERSISTENT = "Messages are persistent"
guilabels_mock.BRAILLE_ENABLE_FLASH_MESSAGES = "Enable flash messages"
guilabels_mock.BRAILLE_MESSAGES_ARE_DETAILED = "Messages are detailed"
guilabels_mock.BRAILLE_DURATION_SECS = "Duration (secs)"
guilabels_mock.BRAILLE_FLASH_MESSAGES = "Flash Messages"
guilabels_mock.GENERAL_BRAILLE_UPDATES = "Braille updates"
guilabels_mock.GENERAL_FREQUENCY_SECS = "Frequency (secs)"
guilabels_mock.GENERAL_APPLIES_TO = "Applies to"
guilabels_mock.PROGRESS_BAR_ALL = "All"
guilabels_mock.PROGRESS_BAR_APPLICATION = "Application"
guilabels_mock.PROGRESS_BAR_WINDOW = "Window"
guilabels_mock.PROGRESS_BARS = "Progress Bars"
guilabels_mock.BRAILLE = "Braille"
guilabels_mock.BRAILLE_MONITOR = "On-screen braille"
guilabels_mock.ON_SCREEN_DISPLAY = "On-Screen Display"
guilabels_mock.BRAILLE_MONITOR_CELL_COUNT = "Cell count"
guilabels_mock.BRAILLE_MONITOR_SHOW_DOTS = "Show braille dot patterns"
guilabels_mock.BRAILLE_MONITOR_FOREGROUND = "Text color"
guilabels_mock.BRAILLE_MONITOR_BACKGROUND = "Background color"
guilabels_mock.BRAILLE_MONITOR_INFO = "On-screen braille info"
return essential_modules
def test_braille_verbosity_grid_creates_widgets(self, test_context: CthulhuTestContext) -> None:
"""Test BrailleVerbosityPreferencesGrid creates correct widgets."""
from gi.repository import Gtk
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BraillePresenter,
BrailleVerbosityPreferencesGrid,
)
presenter = BraillePresenter()
grid = BrailleVerbosityPreferencesGrid(presenter)
assert isinstance(grid, Gtk.Grid)
assert len(grid._widgets) == 4
def test_braille_display_settings_grid_creates_widgets(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test BrailleDisplaySettingsPreferencesGrid creates correct widgets."""
from gi.repository import Gtk
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BrailleDisplaySettingsPreferencesGrid,
BraillePresenter,
)
presenter = BraillePresenter()
grid = BrailleDisplaySettingsPreferencesGrid(presenter)
assert isinstance(grid, Gtk.Grid)
assert len(grid._widgets) == 8
def test_braille_display_settings_grid_has_contracted_control(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test BrailleDisplaySettingsPreferencesGrid has contracted control."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BrailleDisplaySettingsPreferencesGrid,
BraillePresenter,
)
presenter = BraillePresenter()
grid = BrailleDisplaySettingsPreferencesGrid(presenter)
contracted_switch = grid.get_widget(2)
assert contracted_switch is not None
computer_braille_at_cursor_switch = grid.get_widget(3)
assert computer_braille_at_cursor_switch is not None
contraction_table_combo = grid.get_widget(4)
assert contraction_table_combo is not None
def test_braille_flash_messages_grid_creates_widgets(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test BrailleFlashMessagesPreferencesGrid creates correct widgets."""
from gi.repository import Gtk
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BrailleFlashMessagesPreferencesGrid,
BraillePresenter,
)
presenter = BraillePresenter()
grid = BrailleFlashMessagesPreferencesGrid(presenter)
assert isinstance(grid, Gtk.Grid)
assert len(grid._widgets) == 4
def test_braille_flash_messages_grid_has_persistent_control(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test BrailleFlashMessagesPreferencesGrid has persistent control."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BrailleFlashMessagesPreferencesGrid,
BraillePresenter,
)
presenter = BraillePresenter()
grid = BrailleFlashMessagesPreferencesGrid(presenter)
persistent_switch = grid.get_widget(2)
assert persistent_switch is not None
duration_spinbutton = grid.get_widget(3)
assert duration_spinbutton is not None
def test_braille_progress_bars_grid_creates_widgets(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test BrailleProgressBarsPreferencesGrid creates correct widgets."""
from gi.repository import Gtk
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BraillePresenter,
BrailleProgressBarsPreferencesGrid,
)
presenter = BraillePresenter()
grid = BrailleProgressBarsPreferencesGrid(presenter)
assert isinstance(grid, Gtk.Grid)
assert len(grid._widgets) == 3
def test_braille_preferences_grid_creates_multi_page_stack(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test BraillePreferencesGrid creates multi-page stack."""
from gi.repository import Gtk
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import BraillePreferencesGrid, BraillePresenter
presenter = BraillePresenter()
grid = BraillePreferencesGrid(presenter)
assert isinstance(grid, Gtk.Grid)
assert grid._verbosity_grid is not None
assert grid._display_settings_grid is not None
assert grid._flash_messages_grid is not None
assert grid._progress_bars_grid is not None
def test_braille_preferences_grid_save_settings(self, test_context: CthulhuTestContext) -> None:
"""Test BraillePreferencesGrid save_settings returns combined dict."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import BraillePreferencesGrid, BraillePresenter
presenter = BraillePresenter()
grid = BraillePreferencesGrid(presenter)
result = grid.save_settings()
assert isinstance(result, dict)
assert "verbosity-level" in result
assert "end-of-line-indicator" in result
assert "flash-messages" in result
assert "braille-progress-bar-updates" in result
def test_braille_preferences_grid_title_callback(self, test_context: CthulhuTestContext) -> None:
"""Test BraillePreferencesGrid stores title change callback."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import BraillePreferencesGrid, BraillePresenter
presenter = BraillePresenter()
callback_calls: list[str] = []
def title_callback(title: str) -> None:
callback_calls.append(title)
grid = BraillePreferencesGrid(presenter, title_change_callback=title_callback)
assert grid._title_change_callback is title_callback
def test_verbosity_grid_switch_reflects_initial_value(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test verbosity grid switch shows correct initial value."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BraillePresenter,
BrailleVerbosityPreferencesGrid,
)
presenter = BraillePresenter()
presenter.set_verbosity_level("verbose")
grid = BrailleVerbosityPreferencesGrid(presenter)
detailed_switch = grid.get_widget(0)
assert detailed_switch is not None
assert detailed_switch.get_active() is True
def test_verbosity_grid_switch_toggle_updates_setting(
self,
test_context: CthulhuTestContext,
) -> None:
"""Test toggling verbosity switch updates the setting."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BraillePresenter,
BrailleVerbosityPreferencesGrid,
)
presenter = BraillePresenter()
presenter.set_verbosity_level("brief")
grid = BrailleVerbosityPreferencesGrid(presenter)
detailed_switch = grid.get_widget(0)
assert detailed_switch is not None
assert detailed_switch.get_active() is False
grid._initializing = False
detailed_switch.set_active(True)
result = grid.save_settings()
assert result["verbosity-level"] == "verbose"
def test_flash_messages_duration_initial_value(self, test_context: CthulhuTestContext) -> None:
"""Test flash duration spinbutton shows correct initial value."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BrailleFlashMessagesPreferencesGrid,
BraillePresenter,
)
presenter = BraillePresenter()
presenter.set_flash_message_duration(3000)
grid = BrailleFlashMessagesPreferencesGrid(presenter)
duration_spinbutton = grid.get_widget(3)
assert duration_spinbutton is not None
assert duration_spinbutton.get_value() == 3
def test_display_settings_combobox_initial_value(self, test_context: CthulhuTestContext) -> None:
"""Test indicator combobox shows correct initial selection."""
self._setup_dependencies(test_context)
from cthulhu.braille_presenter import (
BrailleDisplaySettingsPreferencesGrid,
BraillePresenter,
)
presenter = BraillePresenter()
presenter.set_link_indicator("dot7")
grid = BrailleDisplaySettingsPreferencesGrid(presenter)
link_combo = grid.get_widget(5)
assert link_combo is not None
assert link_combo.get_active() == 1