mirror of
https://github.com/happycola233/tchMaterial-parser.git
synced 2026-10-18 06:20:38 +08:00
68ed43735c
- 展示每项任务的状态、进度、大小和速度,支持搜索与筛选 - 集中展示下载和解析错误,支持复制详情、停止任务、失败重试和打开目录 - 使用主线程定时刷新界面,保留本次运行的任务记录 - 完善停止与退出时的临时文件清理,防止重试覆盖已有文件 - 将 PDF 书签写入失败纳入任务错误处理 - 适配浅色、深色及高 DPI,优化表头与空状态样式 - 更新使用说明,补充下载流程和界面交互测试 close #96
107 lines
4.1 KiB
Python
107 lines
4.1 KiB
Python
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from src.tchmaterial_parser.network import REQUEST_TIMEOUT
|
|
from src.tchmaterial_parser.ui import download_panel
|
|
|
|
|
|
class RecordingWidget:
|
|
def __init__(self) -> None:
|
|
self.configs: list[dict] = []
|
|
|
|
def config(self, **kwargs: dict) -> None:
|
|
self.configs.append(kwargs)
|
|
|
|
|
|
class FakeResponse:
|
|
def __init__(self, status_code: int) -> None:
|
|
self.ok = status_code < 400
|
|
self.status_code = status_code
|
|
|
|
def close(self) -> None:
|
|
pass
|
|
|
|
|
|
class TimeoutRecordingSession:
|
|
def __init__(self) -> None:
|
|
self.timeouts: list[tuple | None] = []
|
|
|
|
def get(self, url: str, **kwargs: dict) -> FakeResponse:
|
|
self.timeouts.append(kwargs.get("timeout"))
|
|
return FakeResponse(200)
|
|
|
|
|
|
class DownloadProgressTest(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
# 让 ui_call 直接同步执行,便于断言标签与进度条的实际更新内容
|
|
previous_call = download_panel.ui_call
|
|
self.addCleanup(setattr, download_panel, "ui_call", previous_call)
|
|
download_panel.ui_call = lambda func, *args, **kwargs: func(*args, **kwargs)
|
|
|
|
previous_states = download_panel.download_states
|
|
self.addCleanup(setattr, download_panel, "download_states", previous_states)
|
|
download_panel.download_states = []
|
|
|
|
self.label = RecordingWidget()
|
|
self.bar = RecordingWidget()
|
|
for name, widget in (("progress_label", self.label), ("download_progress_bar", self.bar)):
|
|
widget_patch = patch.object(download_panel, name, widget, create=True)
|
|
widget_patch.start()
|
|
self.addCleanup(widget_patch.stop)
|
|
|
|
def latest_label_text(self) -> str:
|
|
return self.label.configs[-1]["text"]
|
|
|
|
def test_summary_counts_finished_tasks_instead_of_mixing_file_sizes(self) -> None:
|
|
download_panel.download_states = [
|
|
{"downloaded_size": 50, "total_size": 100, "finished": True, "failed_reason": None},
|
|
{"downloaded_size": 50, "total_size": 100, "finished": False, "failed_reason": None},
|
|
]
|
|
|
|
download_panel.refresh_download_progress()
|
|
|
|
self.assertIn("已结束 1/2", self.latest_label_text())
|
|
self.assertIn("已完成 1", self.latest_label_text())
|
|
self.assertEqual(self.bar.configs[-1], {"value": 50.0})
|
|
|
|
def test_shows_finished_count_without_total_size(self) -> None:
|
|
download_panel.download_states = [
|
|
{"downloaded_size": 0, "total_size": 0, "finished": True, "failed_reason": None},
|
|
{"downloaded_size": 0, "total_size": 0, "finished": False, "failed_reason": None},
|
|
]
|
|
|
|
download_panel.refresh_download_progress()
|
|
|
|
self.assertIn("已结束 1/2", self.latest_label_text())
|
|
self.assertEqual(self.bar.configs[-1], {"value": 50.0})
|
|
|
|
def test_counts_failed_downloads(self) -> None:
|
|
download_panel.download_states = [
|
|
{"downloaded_size": 0, "total_size": 0, "finished": True, "failed_reason": "服务器返回 HTTP 状态码 403"},
|
|
{"downloaded_size": 0, "total_size": 0, "finished": False, "failed_reason": None},
|
|
]
|
|
|
|
download_panel.refresh_download_progress()
|
|
|
|
self.assertIn("下载失败 1", self.latest_label_text())
|
|
self.assertNotIn("已完成", self.latest_label_text())
|
|
|
|
def test_private_download_requests_carry_timeout(self) -> None:
|
|
fake_session = TimeoutRecordingSession()
|
|
previous_session = download_panel.session
|
|
self.addCleanup(setattr, download_panel, "session", previous_session)
|
|
download_panel.session = fake_session
|
|
previous_interval = download_panel._MIN_REQUEST_INTERVAL
|
|
self.addCleanup(setattr, download_panel, "_MIN_REQUEST_INTERVAL", previous_interval)
|
|
download_panel._MIN_REQUEST_INTERVAL = 0
|
|
|
|
response, _attempted_urls = download_panel.request_download("https://r1-ndr-private.ykt.cbern.com.cn/edu_product/esp/assets/test.pkg/book.pdf")
|
|
|
|
self.assertTrue(response.ok)
|
|
self.assertTrue(fake_session.timeouts)
|
|
self.assertTrue(all(timeout == REQUEST_TIMEOUT for timeout in fake_session.timeouts))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|