zapretgui/tests/test_strategy_scan_widgets.py

159 lines
7.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Панель хода и итога подбора, плитки, переключатели и тексты итога."""
from __future__ import annotations
import os
import unittest
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from PyQt6.QtWidgets import QApplication
from blockcheck.scan_models import StrategyScanReport
from blockcheck.strategy_scan_page_plans import build_panel_outcome
from blockcheck.ui.fun_texts import phrases, strategy_phrases, technique_kind
from blockcheck.ui.strategy_scan_widgets import ChoiceRadios, ChoiceTiles, ScanProgressPanel
class ChoiceTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.app = QApplication.instance() or QApplication([])
def test_tiles_behave_like_a_combo(self) -> None:
tiles = ChoiceTiles()
self.addCleanup(tiles.deleteLater)
changes = []
tiles.currentIndexChanged.connect(changes.append)
tiles.addItem("Сайты", userData="tcp_https")
tiles.addItem("Игры", userData="udp_games")
self.assertEqual(tiles.currentData(), "tcp_https")
self.assertEqual(tiles.findData("udp_games"), 1)
tiles.tiles()[1].click()
self.assertEqual(tiles.currentIndex(), 1)
self.assertEqual(changes[-1], 1)
self.assertTrue(tiles.tiles()[1].is_selected())
self.assertFalse(tiles.tiles()[0].is_selected())
tiles.setItemText(1, "Онлайн-игры")
self.assertEqual(tiles.currentText(), "Онлайн-игры")
def test_radios_behave_like_a_combo(self) -> None:
radios = ChoiceRadios()
self.addCleanup(radios.deleteLater)
for text, value in (("Быстро", "quick"), ("Тщательно", "standard")):
radios.addItem(text, userData=value)
radios.buttons()[1].setChecked(True)
self.assertEqual(radios.currentData(), "standard")
radios.setCurrentIndex(0)
self.assertTrue(radios.buttons()[0].isChecked())
class PanelTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.app = QApplication.instance() or QApplication([])
def test_panel_walks_through_states(self) -> None:
panel = ScanProgressPanel()
self.addCleanup(panel.deleteLater)
self.assertEqual(panel.state, "idle")
self.assertFalse(panel.steps.isVisibleTo(panel))
panel.show_running("discord.com")
self.assertEqual(panel.state, "running")
self.assertTrue(panel.steps.isVisibleTo(panel))
panel.set_step("network", "done", "Интернет есть")
self.assertEqual(panel.steps.status("network"), "done")
panel.note_found(1)
self.assertEqual(panel.found_badge.value(), 1)
requested = []
panel.apply_best_clicked.connect(lambda: requested.append(True))
panel.show_outcome(kind="found", title="Ура!", detail="…", best_text="Лучшая — «X»")
self.assertTrue(panel._actions_host.isVisibleTo(panel))
self.assertFalse(panel.found_badge.isVisibleTo(panel))
panel.apply_best_btn.click()
self.assertEqual(requested, [True])
panel.show_outcome(kind="address_block", title="Тут стратегии бессильны", detail="порт 443")
self.assertFalse(panel._actions_host.isVisibleTo(panel))
self.assertEqual(panel.mascot.mood(), "alarm")
self.assertEqual(panel.property("screenReaderStateText"), "Подбор стратегии: Тут стратегии бессильны")
class OutcomeTests(unittest.TestCase):
def _report(self, **fields):
base = dict(target="discord.com", total_tested=30, total_available=463)
base.update(fields)
return StrategyScanReport(**base)
def test_found_picks_fastest_and_celebrates(self) -> None:
rows = [
{"success": False, "name": "a"},
{"success": True, "name": "slow", "time_ms": 300.0},
{"success": True, "name": "fast", "time_ms": 90.0},
]
outcome = build_panel_outcome(self._report(), rows)
self.assertEqual(outcome.kind, "found")
self.assertEqual(outcome.best_index, 2)
self.assertIn("fast", outcome.best_text)
self.assertIn("2 надёжные стратегии", outcome.title)
self.assertTrue(outcome.celebrate)
def test_single_found_uses_singular(self) -> None:
outcome = build_panel_outcome(self._report(), [{"success": True, "name": "x", "time_ms": 1.0}])
self.assertIn("Нашлась 1 надёжная стратегия", outcome.title)
def test_stops_keep_the_precise_reason(self) -> None:
outcome = build_panel_outcome(
self._report(cancelled=True, stop_kind="address_block", fatal_error="порт 443 закрыт, порт 80 открыт"),
[],
)
self.assertEqual(outcome.kind, "address_block")
self.assertEqual(outcome.detail, "порт 443 закрыт, порт 80 открыт")
self.assertEqual(outcome.title, "Тут стратегии бессильны")
def test_plural_forms(self) -> None:
rows = [{"success": True, "name": f"s{i}", "time_ms": float(i + 1)} for i in range(24)]
self.assertIn("Нашлось 24 надёжные стратегии", build_panel_outcome(self._report(), rows).title)
rows = [{"success": True, "name": f"s{i}", "time_ms": float(i + 1)} for i in range(21)]
self.assertIn("Нашлась 21 надёжная стратегия", build_panel_outcome(self._report(), rows).title)
rows = [{"success": True, "name": f"s{i}", "time_ms": float(i + 1)} for i in range(12)]
self.assertIn("Нашлось 12 надёжных стратегий", build_panel_outcome(self._report(), rows).title)
def test_forced_scan_does_not_celebrate_or_offer_apply(self) -> None:
rows = [{"success": True, "name": "x", "time_ms": 10.0}]
outcome = build_panel_outcome(self._report(baseline_accessible=True), rows)
self.assertEqual(outcome.kind, "open")
self.assertFalse(outcome.celebrate)
self.assertEqual(outcome.best_text, "")
self.assertIn("ни при чём", outcome.title)
def test_switching_back_to_sites_drops_stun_target(self) -> None:
from blockcheck.strategy_scan_page_plans import build_protocol_ui_plan
plan = build_protocol_ui_plan(scan_protocol="tcp_https", current_value="stun.cloudflare.com:3478")
self.assertEqual(plan.normalized_target, "discord.com")
kept = build_protocol_ui_plan(scan_protocol="tcp_https", current_value="youtube.com")
self.assertEqual(kept.normalized_target, "youtube.com")
def test_open_without_bypass_and_not_found(self) -> None:
self.assertEqual(build_panel_outcome(self._report(total_tested=0, baseline_accessible=True), []).kind, "open")
not_found = build_panel_outcome(self._report(), [{"success": False}])
self.assertEqual(not_found.kind, "not_found")
self.assertIn("30 из 463", not_found.detail)
class FunTextsTests(unittest.TestCase):
def test_technique_phrases(self) -> None:
self.assertEqual(technique_kind("--lua-desync=multisplit:pos=1"), "split")
self.assertEqual(technique_kind("--lua-desync=fake\n--lua-desync=multidisorder"), "disorder")
self.assertEqual(technique_kind("--lua-desync=hostfakesplit:x"), "hostfake")
self.assertEqual(technique_kind("--lua-desync=wssize"), "scan_generic")
self.assertIn(phrases("split")[0], strategy_phrases("--lua-desync=multisplit"))
self.assertTrue(phrases("dns", "en"))
self.assertTrue(all(isinstance(item, str) and item for item in phrases("blockcheck")))
if __name__ == "__main__":
unittest.main()