418 lines
19 KiB
Python
418 lines
19 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
|
|
|
from PyQt6.QtCore import QEvent, Qt
|
|
from PyQt6.QtGui import QIcon, QKeyEvent
|
|
from PyQt6.QtWidgets import QApplication, QWidget
|
|
from qfluentwidgets import (
|
|
CaptionLabel,
|
|
IndeterminateProgressBar,
|
|
PrimaryPushButton,
|
|
PushButton,
|
|
PushSettingCard,
|
|
StrongBodyLabel,
|
|
)
|
|
|
|
|
|
class _ButtonTarget:
|
|
def __init__(self) -> None:
|
|
self._text = ""
|
|
self._accessible_name = ""
|
|
self._accessible_description = ""
|
|
self._properties = {}
|
|
self.fixed_width = None
|
|
|
|
def text(self) -> str:
|
|
return self._text
|
|
|
|
def setText(self, text: str) -> None: # noqa: N802
|
|
self._text = str(text)
|
|
|
|
def accessibleName(self) -> str: # noqa: N802
|
|
return self._accessible_name
|
|
|
|
def setAccessibleName(self, text: str) -> None: # noqa: N802
|
|
self._accessible_name = str(text)
|
|
|
|
def accessibleDescription(self) -> str: # noqa: N802
|
|
return self._accessible_description
|
|
|
|
def setAccessibleDescription(self, text: str) -> None: # noqa: N802
|
|
self._accessible_description = str(text)
|
|
|
|
def setIcon(self, _icon) -> None: # noqa: N802
|
|
pass
|
|
|
|
def setMinimumWidth(self, _width: int) -> None: # noqa: N802
|
|
pass
|
|
|
|
def setFixedWidth(self, width: int) -> None: # noqa: N802
|
|
self.fixed_width = int(width)
|
|
|
|
def property(self, name: str) -> object: # noqa: A003
|
|
return self._properties.get(name)
|
|
|
|
def setProperty(self, name: str, value: object) -> None: # noqa: N802
|
|
self._properties[name] = value
|
|
|
|
|
|
class _TitleLabel:
|
|
def __init__(self) -> None:
|
|
self.text = ""
|
|
|
|
def setText(self, text: str) -> None: # noqa: N802
|
|
self.text = str(text)
|
|
|
|
|
|
class _CardTarget:
|
|
def __init__(self) -> None:
|
|
self.titleLabel = _TitleLabel()
|
|
self.button = _ButtonTarget()
|
|
|
|
def setTitle(self, text: str) -> None: # noqa: N802
|
|
self.title = str(text)
|
|
|
|
def setContent(self, text: str) -> None: # noqa: N802
|
|
self.content = str(text)
|
|
|
|
|
|
class _SignalTarget:
|
|
def __init__(self) -> None:
|
|
self.callback = None
|
|
|
|
def connect(self, callback) -> None:
|
|
self.callback = callback
|
|
|
|
|
|
class _PushSettingCardTarget(_CardTarget):
|
|
def __init__(self, button_text, _icon, title_text, content_text, _parent=None) -> None:
|
|
super().__init__()
|
|
self.button.setText(button_text)
|
|
self.title = str(title_text)
|
|
self.content = str(content_text or "")
|
|
self.clicked = _SignalTarget()
|
|
|
|
def setProperty(self, _name: str, _value: object) -> None: # noqa: N802
|
|
pass
|
|
|
|
|
|
class _ToggleTarget:
|
|
def set_texts(self, _title: str, _description: str) -> None:
|
|
pass
|
|
|
|
|
|
def _language_refresh_kwargs() -> dict[str, object]:
|
|
kwargs = {
|
|
"language": "ru",
|
|
"program_settings_card": _CardTarget(),
|
|
"auto_dpi_toggle": _ToggleTarget(),
|
|
"gui_autostart_toggle": _ToggleTarget(),
|
|
"tray_close_mode_combo": _ToggleTarget(),
|
|
"defender_toggle": _ToggleTarget(),
|
|
"max_block_toggle": _ToggleTarget(),
|
|
"state_media_block_toggle": _ToggleTarget(),
|
|
"test_card": _CardTarget(),
|
|
"internet_cleanup_card": _CardTarget(),
|
|
"folder_card": _CardTarget(),
|
|
"docs_card": _CardTarget(),
|
|
"additional_settings_card": _CardTarget(),
|
|
"additional_settings_notice": _TitleLabel(),
|
|
"discord_restart_toggle": _ToggleTarget(),
|
|
"wssize_toggle": _ToggleTarget(),
|
|
"debug_log_toggle": _ToggleTarget(),
|
|
}
|
|
for key in ("test_card", "internet_cleanup_card", "folder_card", "docs_card"):
|
|
kwargs[key].button.setProperty("controlIconTextGap", True)
|
|
return kwargs
|
|
|
|
|
|
class ControlAccessibilityTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls) -> None:
|
|
cls._app = QApplication.instance() or QApplication([])
|
|
|
|
def test_management_buttons_have_screen_reader_names_and_descriptions(self) -> None:
|
|
from presets.ui.control.shared_builders import build_mode_management_section_common
|
|
|
|
_card, start_btn, stop_btn, stop_exit_btn, progress, loading = build_mode_management_section_common(
|
|
tr_fn=lambda _key, default: default,
|
|
caption_label_cls=CaptionLabel,
|
|
indeterminate_progress_bar_cls=IndeterminateProgressBar,
|
|
big_action_button_cls=PrimaryPushButton,
|
|
stop_button_cls=PushButton,
|
|
start_key="start",
|
|
start_default="Запустить Zapret",
|
|
stop_key="stop",
|
|
stop_default="Остановить winws.exe",
|
|
stop_exit_key="stop_exit",
|
|
stop_exit_default="Остановить и закрыть",
|
|
on_start=lambda: None,
|
|
on_stop=lambda: None,
|
|
on_stop_and_exit=lambda: None,
|
|
parent=QWidget(),
|
|
)
|
|
|
|
self.assertEqual(start_btn.accessibleName(), "Запустить Zapret")
|
|
self.assertEqual(start_btn.property("screenReaderStateText"), "Запустить Zapret")
|
|
self.assertIn("Запускает", start_btn.accessibleDescription())
|
|
self.assertEqual(stop_btn.accessibleName(), "Остановить winws.exe")
|
|
self.assertEqual(stop_btn.property("screenReaderStateText"), "Остановить winws.exe")
|
|
self.assertIn("Останавливает", stop_btn.accessibleDescription())
|
|
self.assertEqual(stop_exit_btn.accessibleName(), "Остановить и закрыть")
|
|
self.assertEqual(stop_exit_btn.property("screenReaderStateText"), "Остановить и закрыть")
|
|
self.assertIn("закрывает программу", stop_exit_btn.accessibleDescription())
|
|
self.assertEqual(progress.accessibleName(), "Ход запуска Zapret: не выполняется")
|
|
self.assertEqual(progress.property("screenReaderStateText"), "Ход запуска Zapret: не выполняется")
|
|
self.assertIn("Показывает", progress.accessibleDescription())
|
|
self.assertEqual(loading.accessibleName(), "Статус запуска Zapret: нет активного запуска")
|
|
self.assertEqual(loading.property("screenReaderStateText"), "Статус запуска Zapret: нет активного запуска")
|
|
|
|
def test_status_dot_has_initial_screen_reader_state(self) -> None:
|
|
from presets.ui.control.shared_builders import build_mode_status_section_common
|
|
|
|
_card, status_dot, _title, _desc = build_mode_status_section_common(
|
|
tr_fn=lambda _key, default: default,
|
|
strong_body_label_cls=StrongBodyLabel,
|
|
caption_label_cls=CaptionLabel,
|
|
checking_key="checking",
|
|
checking_default="Проверка состояния",
|
|
detecting_key="detecting",
|
|
detecting_default="Определяем текущий статус",
|
|
)
|
|
|
|
self.assertEqual(status_dot.accessibleName(), "Индикатор состояния Zapret: состояние пока не загружено")
|
|
self.assertEqual(
|
|
status_dot.property("screenReaderStateText"),
|
|
"Индикатор состояния Zapret: состояние пока не загружено",
|
|
)
|
|
|
|
def test_status_section_has_initial_screen_reader_text(self) -> None:
|
|
from presets.ui.control.shared_builders import build_mode_status_section_common
|
|
|
|
status_card, _status_dot, status_title, status_desc = build_mode_status_section_common(
|
|
tr_fn=lambda _key, default: default,
|
|
strong_body_label_cls=StrongBodyLabel,
|
|
caption_label_cls=CaptionLabel,
|
|
checking_key="checking",
|
|
checking_default="Проверка состояния",
|
|
detecting_key="detecting",
|
|
detecting_default="Определяем текущий статус",
|
|
)
|
|
|
|
self.assertEqual(status_card.accessibleName(), "Проверка состояния: Определяем текущий статус")
|
|
self.assertEqual(
|
|
status_card.property("screenReaderStateText"),
|
|
"Проверка состояния: Определяем текущий статус",
|
|
)
|
|
self.assertEqual(status_title.accessibleName(), "Статус Zapret: Проверка состояния")
|
|
self.assertEqual(status_desc.accessibleName(), "Описание состояния Zapret: Определяем текущий статус")
|
|
|
|
def test_last_status_message_dot_has_initial_screen_reader_state(self) -> None:
|
|
from presets.ui.control.shared_builders import build_last_status_message_card_common
|
|
|
|
widgets = build_last_status_message_card_common(
|
|
tr_fn=lambda _key, default: default,
|
|
strong_body_label_cls=StrongBodyLabel,
|
|
caption_label_cls=CaptionLabel,
|
|
)
|
|
|
|
self.assertEqual(widgets.dot.accessibleName(), "Индикатор последнего сообщения: пока нет новых сообщений")
|
|
self.assertEqual(
|
|
widgets.dot.property("screenReaderStateText"),
|
|
"Индикатор последнего сообщения: пока нет новых сообщений",
|
|
)
|
|
|
|
def test_last_status_message_card_has_initial_screen_reader_text(self) -> None:
|
|
from presets.ui.control.shared_builders import build_last_status_message_card_common
|
|
|
|
widgets = build_last_status_message_card_common(
|
|
tr_fn=lambda _key, default: default,
|
|
strong_body_label_cls=StrongBodyLabel,
|
|
caption_label_cls=CaptionLabel,
|
|
)
|
|
|
|
self.assertEqual(widgets.card.accessibleName(), "Последнее сообщение: Пока нет новых сообщений")
|
|
self.assertEqual(
|
|
widgets.card.property("screenReaderStateText"),
|
|
"Последнее сообщение: Пока нет новых сообщений",
|
|
)
|
|
self.assertEqual(widgets.title_label.accessibleName(), "Раздел статуса Zapret: Последнее сообщение")
|
|
self.assertEqual(widgets.message_label.accessibleName(), "Последнее сообщение Zapret: Пока нет новых сообщений")
|
|
|
|
def test_stop_button_loads_square_stop_icon_after_first_paint(self) -> None:
|
|
from presets.ui.control.shared_builders import build_mode_management_section_common
|
|
|
|
scheduled: list[tuple[int, object]] = []
|
|
with patch(
|
|
"presets.ui.control.shared_builders.get_themed_qta_icon",
|
|
return_value=QIcon(),
|
|
) as get_icon, patch(
|
|
"presets.ui.control.shared_builders.QTimer.singleShot",
|
|
side_effect=lambda delay_ms, callback: scheduled.append((delay_ms, callback)),
|
|
):
|
|
build_mode_management_section_common(
|
|
tr_fn=lambda _key, default: default,
|
|
caption_label_cls=CaptionLabel,
|
|
indeterminate_progress_bar_cls=IndeterminateProgressBar,
|
|
big_action_button_cls=PrimaryPushButton,
|
|
stop_button_cls=PushButton,
|
|
start_key="start",
|
|
start_default="Запустить Zapret",
|
|
stop_key="stop",
|
|
stop_default="Остановить winws.exe",
|
|
stop_exit_key="stop_exit",
|
|
stop_exit_default="Остановить и закрыть",
|
|
on_start=lambda: None,
|
|
on_stop=lambda: None,
|
|
on_stop_and_exit=lambda: None,
|
|
parent=QWidget(),
|
|
)
|
|
|
|
get_icon.assert_not_called()
|
|
self.assertEqual(len(scheduled), 1)
|
|
self.assertGreaterEqual(scheduled[0][0], 200)
|
|
scheduled[0][1]()
|
|
get_icon.assert_called_once_with("fa5s.stop")
|
|
|
|
def test_push_setting_card_button_has_specific_screen_reader_name(self) -> None:
|
|
from presets.ui.control.shared_builders import ACTION_CARD_BUTTON_WIDTH, build_push_setting_card_common
|
|
|
|
card = build_push_setting_card_common(
|
|
push_setting_card_cls=_PushSettingCardTarget,
|
|
button_text="Открыть",
|
|
icon=QIcon(),
|
|
title_text="Тест соединения",
|
|
content_text="Проверить доступность сети и состояние обхода",
|
|
on_click=lambda: None,
|
|
)
|
|
|
|
self.assertEqual(card.button.accessibleName(), "Открыть тест соединения")
|
|
self.assertEqual(card.button.text(), " Открыть")
|
|
self.assertEqual(card.button.fixed_width, ACTION_CARD_BUTTON_WIDTH)
|
|
self.assertIn("Проверить доступность сети", card.button.accessibleDescription())
|
|
self.assertEqual(card.button.property("screenReaderStateText"), "Открыть тест соединения")
|
|
|
|
def test_push_setting_card_itself_works_from_keyboard(self) -> None:
|
|
from presets.ui.control.shared_builders import build_push_setting_card_common
|
|
|
|
opened: list[bool] = []
|
|
card = build_push_setting_card_common(
|
|
push_setting_card_cls=PushSettingCard,
|
|
button_text="Открыть",
|
|
icon=QIcon(),
|
|
title_text="Тест соединения",
|
|
content_text="Проверить доступность сети и состояние обхода",
|
|
on_click=lambda: opened.append(True),
|
|
)
|
|
|
|
self.assertEqual(card.accessibleName(), "Открыть тест соединения")
|
|
self.assertEqual(card.property("screenReaderStateText"), "Открыть тест соединения")
|
|
self.assertIn("Проверить доступность сети", card.accessibleDescription())
|
|
self.assertEqual(card.focusPolicy(), Qt.FocusPolicy.StrongFocus)
|
|
|
|
card.keyPressEvent(
|
|
QKeyEvent(
|
|
QEvent.Type.KeyPress,
|
|
Qt.Key.Key_Return,
|
|
Qt.KeyboardModifier.NoModifier,
|
|
)
|
|
)
|
|
|
|
self.assertEqual(opened, [True])
|
|
|
|
def test_winws1_language_refresh_updates_control_button_screen_reader_names(self) -> None:
|
|
from presets.ui.control.zapret1.runtime_helpers import apply_winws1_pages_language
|
|
|
|
start_btn = _ButtonTarget()
|
|
stop_btn = _ButtonTarget()
|
|
stop_exit_btn = _ButtonTarget()
|
|
|
|
apply_winws1_pages_language(
|
|
**_language_refresh_kwargs(),
|
|
start_btn=start_btn,
|
|
stop_winws_btn=stop_btn,
|
|
stop_and_exit_btn=stop_exit_btn,
|
|
refresh_preset_name=lambda: None,
|
|
get_current_dpi_runtime_state=lambda: ("stopped", ""),
|
|
update_status=lambda _phase, _last_error: None,
|
|
)
|
|
|
|
self.assertEqual(start_btn.accessibleName(), "Запустить Zapret")
|
|
self.assertEqual(stop_btn.accessibleName(), "Остановить winws.exe")
|
|
self.assertEqual(stop_exit_btn.accessibleName(), "Остановить и закрыть")
|
|
|
|
def test_winws1_language_refresh_updates_extra_action_button_screen_reader_names(self) -> None:
|
|
from presets.ui.control.zapret1.runtime_helpers import apply_winws1_pages_language
|
|
|
|
kwargs = _language_refresh_kwargs()
|
|
apply_winws1_pages_language(
|
|
**kwargs,
|
|
start_btn=_ButtonTarget(),
|
|
stop_winws_btn=_ButtonTarget(),
|
|
stop_and_exit_btn=_ButtonTarget(),
|
|
refresh_preset_name=lambda: None,
|
|
get_current_dpi_runtime_state=lambda: ("stopped", ""),
|
|
update_status=lambda _phase, _last_error: None,
|
|
)
|
|
|
|
self.assertEqual(kwargs["test_card"].button.accessibleName(), "Открыть тест соединения")
|
|
self.assertEqual(kwargs["internet_cleanup_card"].button.accessibleName(), "Сбросить сеть Windows")
|
|
self.assertEqual(kwargs["folder_card"].button.accessibleName(), "Открыть папку программы")
|
|
self.assertEqual(kwargs["docs_card"].button.accessibleName(), "Открыть документацию")
|
|
self.assertEqual(kwargs["test_card"].button.text(), " Открыть")
|
|
self.assertEqual(kwargs["internet_cleanup_card"].button.text(), " Сбросить")
|
|
self.assertEqual(kwargs["folder_card"].button.text(), " Открыть")
|
|
self.assertEqual(kwargs["docs_card"].button.text(), " Открыть")
|
|
self.assertEqual(kwargs["test_card"].button.property("screenReaderStateText"), "Открыть тест соединения")
|
|
self.assertEqual(kwargs["internet_cleanup_card"].button.property("screenReaderStateText"), "Сбросить сеть Windows")
|
|
self.assertEqual(kwargs["folder_card"].button.property("screenReaderStateText"), "Открыть папку программы")
|
|
self.assertEqual(kwargs["docs_card"].button.property("screenReaderStateText"), "Открыть документацию")
|
|
|
|
def test_winws2_language_refresh_updates_control_button_screen_reader_names(self) -> None:
|
|
from presets.ui.control.zapret2.runtime_helpers import apply_profile_language
|
|
|
|
start_btn = _ButtonTarget()
|
|
stop_exit_btn = _ButtonTarget()
|
|
|
|
apply_profile_language(
|
|
**_language_refresh_kwargs(),
|
|
start_btn=start_btn,
|
|
stop_and_exit_btn=stop_exit_btn,
|
|
update_stop_button_text=lambda: None,
|
|
)
|
|
|
|
self.assertEqual(start_btn.accessibleName(), "Запустить Zapret")
|
|
self.assertEqual(stop_exit_btn.accessibleName(), "Остановить и закрыть программу")
|
|
|
|
def test_winws2_language_refresh_updates_extra_action_button_screen_reader_names(self) -> None:
|
|
from presets.ui.control.zapret2.runtime_helpers import apply_profile_language
|
|
|
|
kwargs = _language_refresh_kwargs()
|
|
apply_profile_language(
|
|
**kwargs,
|
|
start_btn=_ButtonTarget(),
|
|
stop_and_exit_btn=_ButtonTarget(),
|
|
update_stop_button_text=lambda: None,
|
|
)
|
|
|
|
self.assertEqual(kwargs["test_card"].button.accessibleName(), "Открыть тест соединения")
|
|
self.assertEqual(kwargs["internet_cleanup_card"].button.accessibleName(), "Сбросить сеть Windows")
|
|
self.assertEqual(kwargs["folder_card"].button.accessibleName(), "Открыть папку программы")
|
|
self.assertEqual(kwargs["docs_card"].button.accessibleName(), "Открыть документацию")
|
|
self.assertEqual(kwargs["test_card"].button.text(), " Открыть")
|
|
self.assertEqual(kwargs["internet_cleanup_card"].button.text(), " Сбросить")
|
|
self.assertEqual(kwargs["folder_card"].button.text(), " Открыть")
|
|
self.assertEqual(kwargs["docs_card"].button.text(), " Открыть")
|
|
self.assertEqual(kwargs["test_card"].button.property("screenReaderStateText"), "Открыть тест соединения")
|
|
self.assertEqual(kwargs["internet_cleanup_card"].button.property("screenReaderStateText"), "Сбросить сеть Windows")
|
|
self.assertEqual(kwargs["folder_card"].button.property("screenReaderStateText"), "Открыть папку программы")
|
|
self.assertEqual(kwargs["docs_card"].button.property("screenReaderStateText"), "Открыть документацию")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|