T-577 封面画廊重置图片

This commit is contained in:
chengma
2026-07-09 18:15:14 +08:00
parent d8472c988a
commit 90a054a14d
8 changed files with 135 additions and 287 deletions
+64 -97
View File
@@ -2800,7 +2800,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_cover_gallery_regenerate_cancel_has_no_side_effect(self):
def test_cover_gallery_reset_image_clears_pointer_without_worker_or_confirmation(self):
with self.make_temp_dir() as temp_dir:
cfg, account, task, canonical = self._cover_gallery_task(temp_dir)
dialog = CoverGalleryDialog(
@@ -2808,131 +2808,119 @@ class GuiTests(TempDirMixin, unittest.TestCase):
cfg["image_dir"],
cfg["db_path"],
account=account,
config=cfg,
prompt_values={"title": "标题", "cover": "封面"},
)
self.addCleanup(dialog.close)
message_box, _ = self.make_fake_message_box("取消")
message_box, boxes = self.make_fake_message_box("取消")
FakeGenerateWorker.instances.clear()
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box), \
mock.patch("app.gui.tabs.generate.GenerateWorker", FakeGenerateWorker):
self.assertFalse(dialog.regenerate_cover())
self.assertTrue(dialog.reset_cover_image())
self.assertEqual(canonical, db.get_task(task.id, path=cfg["db_path"]).new_cover_path)
self.assertTrue(os.path.exists(canonical))
updated = db.get_task(task.id, path=cfg["db_path"])
self.assertEqual("新标题", updated.new_title)
self.assertIsNone(updated.new_cover_path)
self.assertEqual("generated", updated.stage)
self.assertEqual("success", updated.status)
self.assertFalse(os.path.exists(canonical))
self.assertIsNone(dialog.current_path)
self.assertIsNone(dialog.selected_path)
self.assertFalse(dialog.save_button.isEnabled())
self.assertFalse(dialog._has_unsaved_selection())
self.assertTrue(dialog.candidates)
self.assertIn("已重置图片", dialog.status_label.text())
self.assertEqual([], boxes)
self.assertEqual([], FakeGenerateWorker.instances)
self.assert_removed(temp_dir)
def test_cover_gallery_regenerate_uses_fresh_task_and_forces_cover_generation(self):
def test_cover_gallery_reset_image_committed_cancel_does_not_write_db(self):
with self.make_temp_dir() as temp_dir:
cfg, account, task, canonical = self._cover_gallery_task(temp_dir, generate_cover=False)
fake_thread = FakeThread()
running_states = []
cfg, account, task, canonical = self._cover_gallery_task(temp_dir)
db.set_applied(task.id, True, path=cfg["db_path"])
task = db.get_task(task.id, path=cfg["db_path"])
dialog = CoverGalleryDialog(
task,
cfg["image_dir"],
cfg["db_path"],
account=account,
config=cfg,
prompt_values={"title": "标题提示", "cover": "封面提示 {新标题}"},
regenerate_running_callback=running_states.append,
)
self.addCleanup(dialog.close)
message_box, _ = self.make_fake_message_box("重新生成")
FakeGenerateWorker.instances.clear()
message_box, boxes = self.make_fake_message_box("取消")
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box), \
mock.patch("app.gui.tabs.generate.GenerateWorker", FakeGenerateWorker), \
mock.patch("app.gui.tabs.generate.run_worker", return_value=fake_thread):
self.assertTrue(dialog.regenerate_cover())
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box):
self.assertFalse(dialog.reset_cover_image())
self.assertTrue(fake_thread.started)
self.assertEqual([True], running_states)
worker = FakeGenerateWorker.instances[0]
self.assertIsNone(worker.tasks[0].new_cover_path)
self.assertEqual("新标题", worker.tasks[0].new_title)
self.assertTrue(worker.config["ai"]["generate_cover"])
self.assertFalse(appconfig.ai_config(cfg).get("generate_cover", False))
self.assertFalse(os.path.exists(canonical))
self.assertTrue(any(path.endswith(".jpg") for path in dialog.candidates))
self.assertIn("开始重新生成商品", dialog.status_label.text())
updated = db.get_task(task.id, path=cfg["db_path"])
self.assertEqual(canonical, updated.new_cover_path)
self.assertEqual("applied", updated.stage)
self.assertEqual(1, updated.committed)
self.assertTrue(os.path.exists(canonical))
self.assertIn("本地重置不会回滚蝦皮", boxes[0].text)
self.assert_removed(temp_dir)
def test_cover_gallery_regenerate_success_refreshes_candidates_and_current_selection(self):
def test_cover_gallery_reset_image_committed_confirm_clears_pointer(self):
with self.make_temp_dir() as temp_dir:
cfg, account, task, canonical = self._cover_gallery_task(temp_dir)
fake_thread = FakeThread()
db.set_applied(task.id, True, path=cfg["db_path"])
task = db.get_task(task.id, path=cfg["db_path"])
refreshed = []
dialog = CoverGalleryDialog(
task,
cfg["image_dir"],
cfg["db_path"],
account=account,
config=cfg,
prompt_values={"title": "标题", "cover": "封面"},
regenerate_running_callback=lambda running: None,
gallery_updated_callback=lambda task: refreshed.append(task.id),
)
self.addCleanup(dialog.close)
message_box, _ = self.make_fake_message_box("重新生成")
FakeGenerateWorker.instances.clear()
message_box, boxes = self.make_fake_message_box("确认重置")
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box), \
mock.patch("app.gui.tabs.generate.GenerateWorker", FakeGenerateWorker), \
mock.patch("app.gui.tabs.generate.run_worker", return_value=fake_thread):
self.assertTrue(dialog.regenerate_cover())
worker = FakeGenerateWorker.instances[0]
self.write_test_image(canonical)
db.set_generated(task.id, "新标题", canonical, path=cfg["db_path"])
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box):
self.assertTrue(dialog.reset_cover_image())
worker.finished.emit({"ok": True, "cover_done": 1, "failed": 0})
self.assertEqual(canonical, db.get_task(task.id, path=cfg["db_path"]).new_cover_path)
self.assertEqual(canonical, dialog.selected_path)
self.assertTrue(dialog.candidate_buttons[canonical].isChecked())
self.assertEqual("封面重新生成完成", dialog.status_label.text())
updated = db.get_task(task.id, path=cfg["db_path"])
self.assertIsNone(updated.new_cover_path)
self.assertEqual("generated", updated.stage)
self.assertEqual(1, updated.committed)
self.assertIn("再次提交线上", boxes[0].text)
self.assertIn(task.id, refreshed)
self.assert_removed(temp_dir)
def test_cover_gallery_regenerate_failure_keeps_archived_candidate_selectable(self):
def test_cover_gallery_reset_image_keeps_archive_selectable_for_restore(self):
with self.make_temp_dir() as temp_dir:
cfg, account, task, canonical = self._cover_gallery_task(temp_dir)
fake_thread = FakeThread()
cfg, account, tasks, canonicals, _archives = self._cover_gallery_task_set(temp_dir, count=2)
dialog = CoverGalleryDialog(
task,
tasks[0],
cfg["image_dir"],
cfg["db_path"],
account=account,
config=cfg,
prompt_values={"title": "标题", "cover": "封面"},
visible_tasks=tasks,
task_index=0,
account_by_alias={"alias-a": account},
)
self.addCleanup(dialog.close)
message_box, _ = self.make_fake_message_box("重新生成")
FakeGenerateWorker.instances.clear()
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box), \
mock.patch("app.gui.tabs.generate.GenerateWorker", FakeGenerateWorker), \
mock.patch("app.gui.tabs.generate.run_worker", return_value=fake_thread):
self.assertTrue(dialog.regenerate_cover())
worker = FakeGenerateWorker.instances[0]
worker.log.emit("[失败] 商品 51100639510 图片生成失败:测试失败")
worker.finished.emit({"ok": False, "cover_done": 0, "failed": 1})
self.assertFalse(os.path.exists(canonical))
self.assertIsNone(db.get_task(task.id, path=cfg["db_path"]).new_cover_path)
self.assertTrue(dialog.reset_cover_image())
self.assertTrue(dialog.candidates)
archived = dialog.candidates[0]
self.assertIsNone(db.get_task(tasks[0].id, path=cfg["db_path"]).new_cover_path)
message_box, boxes = self.make_fake_message_box("取消")
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box):
self.assertTrue(dialog.switch_task(1))
self.assertEqual([], boxes)
self.assertEqual(tasks[1].id, dialog.task.id)
self.assertTrue(dialog.switch_task(-1))
dialog.candidate_buttons[archived].setChecked(True)
self.assertTrue(dialog.save_selection())
self.assertEqual(os.path.abspath(archived), db.get_task(task.id, path=cfg["db_path"]).new_cover_path)
self.assertEqual(os.path.abspath(archived), db.get_task(tasks[0].id, path=cfg["db_path"]).new_cover_path)
self.assert_removed(temp_dir)
def test_cover_gallery_regenerate_archive_failure_does_not_start_worker(self):
def test_cover_gallery_reset_image_archive_failure_keeps_db_pointer(self):
with self.make_temp_dir() as temp_dir:
cfg, account, task, canonical = self._cover_gallery_task(temp_dir)
dialog = CoverGalleryDialog(
@@ -2940,17 +2928,15 @@ class GuiTests(TempDirMixin, unittest.TestCase):
cfg["image_dir"],
cfg["db_path"],
account=account,
config=cfg,
prompt_values={"title": "标题", "cover": "封面"},
)
self.addCleanup(dialog.close)
message_box, boxes = self.make_fake_message_box("重新生成")
message_box, boxes = self.make_fake_message_box("取消")
FakeGenerateWorker.instances.clear()
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box), \
mock.patch("app.db.os.rename", side_effect=PermissionError), \
mock.patch("app.gui.tabs.generate.GenerateWorker", FakeGenerateWorker):
self.assertFalse(dialog.regenerate_cover())
self.assertFalse(dialog.reset_cover_image())
self.assertTrue(os.path.exists(canonical))
self.assertEqual(canonical, db.get_task(task.id, path=cfg["db_path"]).new_cover_path)
@@ -2959,7 +2945,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_cover_gallery_regenerate_disabled_while_bulk_generation_runs(self):
def test_cover_gallery_reset_image_disabled_while_bulk_generation_runs(self):
with self.make_temp_dir() as temp_dir:
cfg, account, task, canonical = self._cover_gallery_task(temp_dir)
dialog = CoverGalleryDialog(
@@ -2967,36 +2953,17 @@ class GuiTests(TempDirMixin, unittest.TestCase):
cfg["image_dir"],
cfg["db_path"],
account=account,
config=cfg,
prompt_values={"title": "标题", "cover": "封面"},
bulk_running_checker=lambda: True,
)
self.addCleanup(dialog.close)
self.assertFalse(dialog.regenerate_button.isEnabled())
self.assertIn("批量生成正在运行", dialog.regenerate_button.toolTip())
self.assertFalse(dialog.regenerate_cover())
self.assertFalse(dialog.reset_cover_button.isEnabled())
self.assertIn("AI 生成正在进行", dialog.reset_cover_button.toolTip())
self.assertFalse(dialog.reset_cover_image())
self.assertEqual(canonical, db.get_task(task.id, path=cfg["db_path"]).new_cover_path)
self.assert_removed(temp_dir)
def test_generate_tab_blocks_batch_generate_while_gallery_regenerates(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
statuses = []
tab = GenerateTab(config=cfg, status_callback=statuses.append)
self.addCleanup(tab.close)
tab._set_cover_gallery_regenerate_running(True)
tab.start_generate()
self.assertFalse(tab.generate_button.isEnabled())
self.assertIn("封面画廊正在重新生成", statuses[-1])
tab._set_cover_gallery_regenerate_running(False)
self.assertTrue(tab.generate_button.isEnabled())
self.assert_removed(temp_dir)
def test_generate_tab_allows_editing_generated_title_locally(self):
with self.make_temp_dir() as temp_dir: