zapretgui/tests/test_table_accessibility.py
2026-06-14 02:00:46 +03:00

366 lines
14 KiB
Python

from __future__ import annotations
import os
from types import SimpleNamespace
import unittest
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QLabel, QTableWidget, QWidget
from qfluentwidgets import PushButton
class TableAccessibilityTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls._app = QApplication.instance() or QApplication([])
def _add_strategy_scan_result_row(self, table: QTableWidget) -> None:
from blockcheck.ui.strategy_scan_page_results_workflow import add_strategy_result_row
class _Feature:
def build_result_presentation(self, _result, *, scan_cursor: int):
self.scan_cursor = scan_cursor
return SimpleNamespace(
number_text="1",
strategy_name="TLS fake",
strategy_tooltip="Подмена TLS",
status_text="OK",
status_tone="success",
status_tooltip="Стратегия сработала",
time_text="120 ms",
can_apply=True,
stored_row={"strategy": "TLS fake"},
)
add_strategy_result_row(
blockcheck_feature=_Feature(),
table=table,
result=SimpleNamespace(strategy_args="--lua-desync=fake", strategy_name="TLS fake"),
scan_cursor=0,
tr_fn=lambda _key, default: default,
push_button_cls=PushButton,
on_apply_strategy=lambda _args, _name: None,
)
def test_strategy_scan_result_row_has_screen_reader_text(self) -> None:
table = QTableWidget(0, 5)
self._add_strategy_scan_result_row(table)
expected = "Строка 1. Стратегия TLS fake, статус OK, время 120 ms. Доступно действие: применить."
self.assertEqual(table.item(0, 1).data(Qt.ItemDataRole.AccessibleTextRole), expected)
self.assertEqual(table.item(0, 2).data(Qt.ItemDataRole.AccessibleTextRole), expected)
self.assertEqual(table.item(0, 3).data(Qt.ItemDataRole.AccessibleTextRole), expected)
self.assertEqual(table.cellWidget(0, 4).accessibleName(), "Применить стратегию TLS fake")
def test_strategy_scan_table_reports_current_row_to_screen_reader(self) -> None:
table = QTableWidget(0, 5)
self._add_strategy_scan_result_row(table)
row_text = table.item(0, 1).data(Qt.ItemDataRole.AccessibleTextRole)
table.setCurrentCell(0, 2)
self.assertEqual(table.property("screenReaderStateText"), row_text)
def test_updater_server_row_has_screen_reader_text(self) -> None:
from updater.ui.table_view import render_server_row
table = QTableWidget(1, 4)
render_server_row(
table,
row=0,
server_name="server-1",
status={"status": "online", "response_time": 0.12, "stable_version": "1.2.3", "dev_version": "1.2.4"},
channel="stable",
language="ru",
accent_hex="#52c477",
)
text = table.item(0, 1).data(Qt.ItemDataRole.AccessibleTextRole)
self.assertIn("Сервер server-1", text)
self.assertIn("статус Онлайн", text)
def test_updater_servers_table_reports_current_row_to_screen_reader(self) -> None:
from updater.ui.table_view import render_server_row
table = QTableWidget(1, 4)
render_server_row(
table,
row=0,
server_name="server-1",
status={"status": "online", "response_time": 0.12, "stable_version": "1.2.3", "dev_version": "1.2.4"},
channel="stable",
language="ru",
accent_hex="#52c477",
)
row_text = table.item(0, 0).data(Qt.ItemDataRole.AccessibleTextRole)
table.setCurrentCell(0, 1)
self.assertEqual(table.property("screenReaderStateText"), row_text)
def test_updater_servers_table_reset_restores_empty_screen_reader_state(self) -> None:
from updater.ui.main_build import build_servers_table_widget
from updater.ui.table_view import render_server_row, reset_server_rows
class _TableState:
def __init__(self) -> None:
self.reset_called = False
def reset(self) -> None:
self.reset_called = True
table = build_servers_table_widget(tr_fn=lambda _key, default: default)
table.setRowCount(1)
render_server_row(
table,
row=0,
server_name="server-1",
status={"status": "online", "response_time": 0.12, "stable_version": "1.2.3", "dev_version": "1.2.4"},
channel="stable",
language="ru",
accent_hex="#52c477",
)
table.setCurrentCell(0, 1)
table_state = _TableState()
reset_server_rows(table, table_state=table_state)
self.assertTrue(table_state.reset_called)
self.assertEqual(table.rowCount(), 0)
self.assertEqual(table.accessibleName(), "Серверы обновлений: строки пока не загружены")
self.assertEqual(
table.property("screenReaderStateText"),
"Серверы обновлений: строки пока не загружены",
)
def test_updater_servers_table_has_screen_reader_name(self) -> None:
from updater.ui.main_build import build_servers_table_widget
table = build_servers_table_widget(tr_fn=lambda _key, default: default)
self.assertEqual(table.accessibleName(), "Серверы обновлений: строки пока не загружены")
self.assertEqual(
table.property("screenReaderStateText"),
"Серверы обновлений: строки пока не загружены",
)
self.assertIn("статус и версии", table.accessibleDescription())
def test_updater_active_server_legend_has_screen_reader_text(self) -> None:
from updater.ui.main_build import build_servers_header_widgets
parent = QWidget()
self.addCleanup(parent.deleteLater)
widgets = build_servers_header_widgets(
tr_fn=lambda _key, default: default,
parent=parent,
on_about_clicked=lambda: None,
)
expected = "Легенда серверов обновлений: активный сервер"
self.assertEqual(widgets.legend_active_label.accessibleName(), expected)
self.assertEqual(
widgets.legend_active_label.property("screenReaderStateText"),
expected,
)
def test_updater_server_headers_have_screen_reader_text(self) -> None:
from updater.ui.main_build import build_servers_header_widgets
parent = QWidget()
self.addCleanup(parent.deleteLater)
widgets = build_servers_header_widgets(
tr_fn=lambda _key, default: default,
parent=parent,
on_about_clicked=lambda: None,
)
self.assertEqual(widgets.page_title_label.accessibleName(), "Страница: Серверы")
self.assertEqual(widgets.servers_title_label.accessibleName(), "Раздел: Серверы обновлений")
def test_blockcheck_result_tables_have_screen_reader_names(self) -> None:
from blockcheck.ui.sections_build import build_results_section
widgets = build_results_section(
tr_fn=lambda _key, default: default,
settings_card_cls=_FakeSettingsCard,
strong_body_label_cls=QLabel,
table_widget_cls=QTableWidget,
)
self.assertEqual(
widgets.results_table.accessibleName(),
"Результаты BlockCheck по доменам: пока нет результатов",
)
self.assertIn("HTTP, TLS, DNS, DPI", widgets.results_table.accessibleDescription())
self.assertEqual(
widgets.results_table.property("screenReaderStateText"),
"Результаты BlockCheck по доменам: пока нет результатов",
)
self.assertEqual(
widgets.tcp_table.accessibleName(),
"Результаты TCP 16-20KB: пока нет результатов",
)
self.assertIn("ASN, провайдер", widgets.tcp_table.accessibleDescription())
self.assertEqual(
widgets.tcp_table.property("screenReaderStateText"),
"Результаты TCP 16-20KB: пока нет результатов",
)
def test_blockcheck_tcp_result_row_has_screen_reader_text(self) -> None:
from blockcheck.models import SingleTestResult, TargetResult, TestStatus, TestType
from blockcheck.ui.page_results_workflow import update_tcp_result_table
table = QTableWidget(0, 5)
target = TargetResult(
name="YouTube",
value="youtube.com",
tests=[
SingleTestResult(
target_name="youtube.com",
test_type=TestType.TCP_16_20,
status=TestStatus.FAIL,
error_code="TCP_16_20",
detail="Блокировка после 16 KB",
raw_data={
"target_id": "youtube.com",
"asn": "12345",
"provider": "Example ISP",
"bytes_received": 20480,
},
)
],
)
update_tcp_result_table(target_result=target, tcp_table=table, tcp_section_label=None)
text = table.item(0, 3).data(Qt.ItemDataRole.AccessibleTextRole)
self.assertIn("TCP youtube.com", text)
self.assertIn("AS12345", text)
self.assertIn("Example ISP", text)
self.assertIn("статус DETECTED", text)
def test_blockcheck_tcp_result_table_reports_current_row_to_screen_reader(self) -> None:
from blockcheck.models import SingleTestResult, TargetResult, TestStatus, TestType
from blockcheck.ui.page_results_workflow import update_tcp_result_table
table = QTableWidget(0, 5)
target = TargetResult(
name="YouTube",
value="youtube.com",
tests=[
SingleTestResult(
target_name="youtube.com",
test_type=TestType.TCP_16_20,
status=TestStatus.FAIL,
error_code="TCP_16_20",
detail="Блокировка после 16 KB",
raw_data={
"target_id": "youtube.com",
"asn": "12345",
"provider": "Example ISP",
"bytes_received": 20480,
},
)
],
)
update_tcp_result_table(target_result=target, tcp_table=table, tcp_section_label=None)
row_text = table.item(0, 3).data(Qt.ItemDataRole.AccessibleTextRole)
table.setCurrentCell(0, 4)
self.assertEqual(table.property("screenReaderStateText"), row_text)
def test_blockcheck_target_result_row_has_screen_reader_text(self) -> None:
from blockcheck.models import DPIClassification, SingleTestResult, TargetResult, TestStatus, TestType
from blockcheck.ui.page_results_workflow import update_target_result_table
table = QTableWidget(0, 8)
tcp_table = QTableWidget(0, 5)
target = TargetResult(
name="YouTube",
value="youtube.com",
classification=DPIClassification.HTTP_INJECT,
tests=[
SingleTestResult(
target_name="youtube.com",
test_type=TestType.HTTP,
status=TestStatus.FAIL,
error_code="HTTP_INJECT",
detail="Провайдер подменил HTTP-ответ",
)
],
)
update_target_result_table(
target_result=target,
table=table,
tcp_table=tcp_table,
tcp_section_label=None,
)
text = table.item(0, 0).data(Qt.ItemDataRole.AccessibleTextRole)
self.assertIsNotNone(text)
self.assertIn("YouTube", text)
self.assertIn("HTTP HTTP_INJECT", text)
self.assertIn("DPI HTTP инъекция", text)
self.assertIn("Провайдер подменил HTTP-ответ", text)
self.assertEqual(table.item(0, 1).data(Qt.ItemDataRole.AccessibleTextRole), text)
self.assertEqual(table.item(0, 5).data(Qt.ItemDataRole.AccessibleTextRole), text)
self.assertEqual(table.item(0, 7).data(Qt.ItemDataRole.AccessibleTextRole), text)
def test_blockcheck_target_result_table_reports_current_row_to_screen_reader(self) -> None:
from blockcheck.models import DPIClassification, SingleTestResult, TargetResult, TestStatus, TestType
from blockcheck.ui.page_results_workflow import update_target_result_table
table = QTableWidget(0, 8)
tcp_table = QTableWidget(0, 5)
target = TargetResult(
name="YouTube",
value="youtube.com",
classification=DPIClassification.HTTP_INJECT,
tests=[
SingleTestResult(
target_name="youtube.com",
test_type=TestType.HTTP,
status=TestStatus.FAIL,
error_code="HTTP_INJECT",
detail="Провайдер подменил HTTP-ответ",
)
],
)
update_target_result_table(
target_result=target,
table=table,
tcp_table=tcp_table,
tcp_section_label=None,
)
row_text = table.item(0, 0).data(Qt.ItemDataRole.AccessibleTextRole)
table.setCurrentCell(0, 7)
self.assertEqual(table.property("screenReaderStateText"), row_text)
class _FakeSettingsCard:
def __init__(self, title: str) -> None:
self.title = str(title)
self.widgets = []
def add_widget(self, widget) -> None:
self.widgets.append(widget)
if __name__ == "__main__":
unittest.main()