fix: 任务执行前检查 Android 设备连接 (#84)
This commit is contained in:
@@ -12,6 +12,7 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
from src.android_device_service import AndroidDeviceSearchError
|
||||
from src.pdd_ui import PDDTaskPage
|
||||
from src.admin_gateway import AdminGatewayError, AdminTask, SubmissionReceipt
|
||||
from src.pdd_ui_event import (
|
||||
@@ -238,8 +239,14 @@ class PDDTaskPageEventTest(unittest.TestCase):
|
||||
self.temp_directory = tempfile.TemporaryDirectory()
|
||||
self.db_path = Path(self.temp_directory.name) / "client.db"
|
||||
self.repository = TaskRepository(self.db_path)
|
||||
self.device_checker_patch = patch(
|
||||
"src.pdd_ui_event.AndroidDeviceService.require_connected",
|
||||
autospec=True,
|
||||
)
|
||||
self.device_checker_patch.start()
|
||||
|
||||
def tearDown(self):
|
||||
self.device_checker_patch.stop()
|
||||
self.temp_directory.cleanup()
|
||||
|
||||
def _add_task(
|
||||
@@ -481,6 +488,97 @@ class PDDTaskPageEventTest(unittest.TestCase):
|
||||
events.shutdown()
|
||||
page.deleteLater()
|
||||
|
||||
def test_disconnected_device_stops_auto_fetch_before_claim(self):
|
||||
page = PDDTaskPage()
|
||||
gateway = RecordingClaimGateway(collect_admin_task())
|
||||
checker_threads = []
|
||||
|
||||
def disconnected(_serial):
|
||||
checker_threads.append(threading.get_ident())
|
||||
raise AndroidDeviceSearchError("USB Android 设备 USB-001 未连接")
|
||||
|
||||
events = PDDTaskPageEvent(
|
||||
page,
|
||||
self.repository,
|
||||
claim_gateway=gateway,
|
||||
settings_repository=self._saved_settings(),
|
||||
collect_service_factory=fake_collect_factory,
|
||||
device_connection_checker=disconnected,
|
||||
)
|
||||
page.autoFetchRequested.emit()
|
||||
|
||||
self.assertTrue(wait_until(self.app, lambda: not events._claim_busy))
|
||||
self.assertEqual(gateway.calls, [])
|
||||
self.assertEqual(self.repository.count_tasks(), 0)
|
||||
self.assertEqual(len(checker_threads), 1)
|
||||
self.assertNotEqual(checker_threads[0], threading.get_ident())
|
||||
self.assertIn("Android 设备不可用", page.statusLabel.text())
|
||||
self.assertIsNotNone(events._device_feedback)
|
||||
events.shutdown()
|
||||
page.deleteLater()
|
||||
|
||||
def test_disconnected_rerun_keeps_existing_task_unchanged(self):
|
||||
self._add_task(1)
|
||||
first = self.repository.start_collect_run("PDD-001", "USB-001")
|
||||
event = self.repository.save_collect_result(
|
||||
"PDD-001", first.attempt_id, FakeCollectResult().to_pdd_data()
|
||||
)
|
||||
self.repository.mark_outbox_sent(event.id)
|
||||
before = self.repository.get_task("PDD-001")
|
||||
before_run = self.repository.latest_task_run("PDD-001")
|
||||
page = PDDTaskPage()
|
||||
def disconnected(_serial):
|
||||
raise AndroidDeviceSearchError(
|
||||
"USB Android 设备 USB-001 未连接"
|
||||
)
|
||||
|
||||
events = PDDTaskPageEvent(
|
||||
page,
|
||||
self.repository,
|
||||
claim_gateway=RecordingClaimGateway(),
|
||||
settings_repository=self._saved_settings(),
|
||||
collect_service_factory=fake_collect_factory,
|
||||
device_connection_checker=disconnected,
|
||||
)
|
||||
|
||||
with patch("src.pdd_ui_event.MessageBox") as message_box:
|
||||
message_box.return_value.exec.return_value = True
|
||||
page.rerunRequested.emit("PDD-001")
|
||||
self.assertTrue(wait_until(self.app, lambda: not events._claim_busy))
|
||||
|
||||
after = self.repository.get_task("PDD-001")
|
||||
after_run = self.repository.latest_task_run("PDD-001")
|
||||
self.assertEqual(after.status, TaskStatus.SUCCEEDED)
|
||||
self.assertEqual(after.pdd_data, before.pdd_data)
|
||||
self.assertEqual(after_run.attempt_id, before_run.attempt_id)
|
||||
self.assertIn("重新采集未开始", page.statusLabel.text())
|
||||
events.shutdown()
|
||||
page.deleteLater()
|
||||
|
||||
def test_device_feedback_opens_settings_closes_and_does_not_stack(self):
|
||||
page = PDDTaskPage()
|
||||
events = PDDTaskPageEvent(page, self.repository)
|
||||
opened = []
|
||||
page.openSettingsRequested.connect(lambda: opened.append(True))
|
||||
|
||||
events._show_device_unavailable("第一条")
|
||||
first = events._device_feedback
|
||||
events._show_device_unavailable("第二条")
|
||||
second = events._device_feedback
|
||||
self.assertIsNot(first, second)
|
||||
buttons = {
|
||||
button.text(): button
|
||||
for button in second.findChildren(type(page.rerunButton))
|
||||
}
|
||||
self.assertIn("打开设置", buttons)
|
||||
self.assertIn("关闭提示", buttons)
|
||||
buttons["打开设置"].click()
|
||||
self.app.processEvents()
|
||||
self.assertEqual(opened, [True])
|
||||
self.assertIsNone(events._device_feedback)
|
||||
events.shutdown()
|
||||
page.deleteLater()
|
||||
|
||||
def test_query_failure_shows_readable_error(self):
|
||||
page = PDDTaskPage()
|
||||
events = PDDTaskPageEvent(page, BrokenRepository())
|
||||
@@ -587,6 +685,9 @@ class PDDTaskPageEventTest(unittest.TestCase):
|
||||
create_u2_purchase_adapter,
|
||||
)
|
||||
self.assertEqual(window.pddTaskPage.taskModel.data_row_count(), 0)
|
||||
window.pddTaskPage.openSettingsRequested.emit()
|
||||
self.app.processEvents()
|
||||
self.assertIs(window.stackedWidget.currentWidget(), window.settingsPage)
|
||||
window.close()
|
||||
window.deleteLater()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user