Files
templates/python/tests/test_console.py

78 lines
9.2 KiB
Python
Raw 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.
"""Проверки общей консоли на настоящем Qt без физического устройства.""" # Проверяем сохранность истории, фильтры и очистку при асинхронном обновлении.
import os # Виртуальная платформа выбирается до импорта Qt.
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") # Тесты не открывают окна на рабочем столе.
import pytest # Фикстура даёт каждому сценарию независимую консоль.
from set_devices.qt_ports.console import ConsoleView, QApplication # Используем реальный порт templates, а не имитацию обработчиков.
@pytest.fixture # Создаём отдельный журнал для проверки независимости состояний.
def console(): # Ссылка на приложение удерживается до завершения сценария.
app = QApplication.instance() or QApplication([]) # Qt требует приложение перед созданием виджетов.
view = ConsoleView(limit=3, payloads=True) # Малый предел проверяет вытеснение без большого массива данных.
yield view # Сценарий управляет настоящими сигналами флажков и кнопок.
view.panel.deleteLater() # Удаляется контейнер вместе с редактором и таймером.
app.processEvents() # Отложенное удаление доставляется до следующего сценария.
def test_pause_keeps_bounded_history_and_clear_cannot_resurrect(console): # Очистка на паузе должна удалять также невидимые данные.
console.appendPlainText("первая") # Первая запись сразу видна на экране.
console.pause.setChecked(True) # Замораживаем только представление.
for index in range(5): console.appendPlainText("строка %d" % index) # На паузе поступает больше данных, чем помещается в истории.
assert console.toPlainText() == "первая" and len(console.records) == 3 # Экран заморожен, память ограничена.
console.pause.setChecked(False) # Возобновление показывает последние сохранённые строки.
assert console.toPlainText().splitlines() == ["строка 2", "строка 3", "строка 4"] # Вытеснённые записи больше не появляются.
console.appendPlainText("ожидает таймер") # Полный буфер ставит пакетное обновление в очередь.
assert console.timer.isActive() # Проверяем именно очистку при ожидающем обновлении.
console.pause.setChecked(True) # Очистка должна работать и при замороженном экране.
console.clear_button.click() # Пользователь удаляет весь журнал через общую панель.
console.pause.setChecked(False) # Возобновление не должно вернуть старые данные.
assert not console.records and not console.toPlainText() and not console.timer.isActive() # Документ, история и очередь согласованы.
def test_filters_restore_hidden_rows_and_preserve_service_errors(console): # Фильтры направлений не должны скрывать ошибки без метки TX/RX.
console.appendPlainText("[12:00:00] TX команда") # Начальная метка после времени определяет направление.
console.appendPlainText("12:00:01.123 RX ответ") # Поддерживаем существующий формат временных меток SETGUI.
console.appendPlainText("#ERR RX timeout") # Слово RX внутри ошибки не делает её принятым пакетом.
console.show_rx.setChecked(False) # Скрываем только входящие пакеты.
console.show_tx.setChecked(False) # Оба направления можно выключить одновременно.
assert console.toPlainText() == "#ERR RX timeout" # Служебная ошибка остаётся доступной оператору.
console.search.setText("ОТВЕТ") # Регистр запроса не должен влиять на поиск.
console.show_rx.setChecked(True) # Входящие данные восстанавливаются из сохранённой истории.
assert console.toPlainText() == "12:00:01.123 RX ответ" # Поиск применяется к той же записи без повторного приёма.
console.search.clear() # Снимаем текстовый фильтр.
assert len(console.records) == 3 # Фильтры не удаляют события.
def test_payload_and_utf8_export_use_visible_snapshot(console, tmp_path): # Сохранение и копирование соответствуют выбранному представлению.
console.append_message("RX пакет <текст>", direction="RX", payload=b"A\x00\xff") # Payload содержит печатный, управляющий и не-ASCII байты.
console.display.setCurrentText("HEX + ASCII") # Выбираем совместное представление байтов.
assert console.toPlainText() == "RX пакет <текст> · 41 00 FF | A.." # Непечатные байты заменяются точками без потери HEX.
path = tmp_path / "журнал.txt" # Проверяем кириллицу в имени и содержимом файла.
console.save_to(path) # Экспорт выполняется без диалога, сохраняя тот же код записи.
assert path.read_text(encoding="utf-8") == console.toPlainText() # UTF-8 сохраняет фактически видимый текст.
console.copy_visible() # Кнопка копирует весь показанный журнал.
assert QApplication.clipboard().text() == console.toPlainText() # Буфер обмена совпадает с экспортом.
def test_multiline_html_and_snapshot_obey_limit(console): # Предел относится к строкам, а не к числу вызовов записи.
console.appendPlainText("0\n1\n2\n3\n4") # Один пакет расшифровки превышает лимит документа и истории.
console.refresh() # Применяем запланированное пакетное обновление.
assert console.toPlainText() == "2\n3\n4" # Старые строки не возвращаются при смене фильтра.
console.setPlainText("снимок") # Потребитель может передать результат повторного разбора кадров целиком.
console.appendHtml('<span style="color:#ff0000">&lt;ошибка&gt;</span>') # Проверяем совместимость прежнего цветного API SETGUI.
console.search.setText("ошибка") # Поиск должен работать по тексту без тегов разметки.
assert console.toPlainText() == "<ошибка>" # Спецсимволы устройства остаются обычным текстом.
console.search.clear() # Возвращаем обе записи с исходным оформлением.
assert console.toPlainText() == "снимок\n<ошибка>" # Фильтр не теряет предыдущий снимок истории.
def test_clear_notifies_external_owner_once(console): # Владелец может очистить свой буфер и повторно вызвать clear без рекурсии.
external = ["старый кадр"] # Имитируем отдельную историю протокольных кадров приложения.
def clear_owner(): # Обработчик очищает внешний источник повторного форматирования.
external.clear() # Старые кадры не вернутся после смены парсера.
console.clear() # Повторный программный вызов не должен снова эмитировать пользовательский сигнал.
console.userCleared.connect(clear_owner) # Подключаем тот же контракт, что консоли платы и TX/RX SETGUI.
console.appendPlainText("строка") # До очистки журнал содержит данные.
console.clear_button.click() # Нажимаем настоящую кнопку Qt.
assert not external and not console.toPlainText() # Обе истории очищены одним действием.