T-567 增加封面候选画廊
This commit is contained in:
+203
-2
@@ -12,13 +12,13 @@ sys.path.insert(0, os.path.dirname(__file__))
|
||||
from _helpers import TempDirMixin
|
||||
|
||||
from app import gui
|
||||
from app import accounts, ai, appconfig, db, prompts, update_check
|
||||
from app import accounts, ai, appconfig, db, image_paths, prompts, update_check
|
||||
|
||||
if gui.QT_IMPORT_ERROR is not None:
|
||||
raise unittest.SkipTest("PySide6 未安装")
|
||||
|
||||
from PySide6.QtCore import QItemSelectionModel, QRect
|
||||
from PySide6.QtGui import QTextCursor
|
||||
from PySide6.QtGui import QImage, QTextCursor
|
||||
from PySide6.QtWidgets import QApplication, QCheckBox, QLineEdit, QPlainTextEdit, QProgressBar, QTableView
|
||||
|
||||
from app.gui import (
|
||||
@@ -39,6 +39,7 @@ from app.gui import (
|
||||
TAB_TITLES,
|
||||
WriteBackWorker,
|
||||
)
|
||||
from app.gui.tabs.generate import CoverGalleryDialog, OriginalImageDialog
|
||||
from app.gui.main_window import _fit_and_center_window
|
||||
|
||||
|
||||
@@ -81,6 +82,13 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
}
|
||||
return cfg
|
||||
|
||||
def write_test_image(self, path, width=32, height=32):
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
image = QImage(width, height, QImage.Format_RGB32)
|
||||
image.fill(0xFF336699)
|
||||
self.assertTrue(image.save(path))
|
||||
return path
|
||||
|
||||
def assert_foreground(self, model, row, column, color):
|
||||
value = model.data(model.index(row, column), gui.Qt.ForegroundRole)
|
||||
self.assertIsNotNone(value)
|
||||
@@ -2068,6 +2076,199 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_cover_gallery_lists_candidates_and_selects_current_cover(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
account = accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
db.init_db(cfg["db_path"])
|
||||
batch_id = db.create_batch(["input.xlsx"], path=cfg["db_path"])
|
||||
db.insert_tasks(
|
||||
batch_id,
|
||||
[
|
||||
{
|
||||
"source_file_abs": os.path.join(temp_dir, "input.xlsx"),
|
||||
"source_sheet": "商品",
|
||||
"source_row": 2,
|
||||
"account_name": "Excel主店",
|
||||
"alias": "alias-a",
|
||||
"item_id": "51100639510",
|
||||
}
|
||||
],
|
||||
path=cfg["db_path"],
|
||||
)
|
||||
task = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])[0]
|
||||
old_cover = self.write_test_image(os.path.join(temp_dir, "old.jpg"))
|
||||
canonical = image_paths.task_image_path(cfg["image_dir"], task, account, "new")
|
||||
prefix = os.path.splitext(canonical)[0]
|
||||
archive_newer = self.write_test_image(f"{prefix}_20260709101000.jpg")
|
||||
archive_older = self.write_test_image(f"{prefix}_20260709094800.jpg")
|
||||
old_candidate = f"{prefix.replace('_new', '_old')}.jpg"
|
||||
self.write_test_image(canonical)
|
||||
self.write_test_image(old_candidate)
|
||||
db.set_collected(task.id, "旧标题", old_cover, path=cfg["db_path"])
|
||||
db.set_generated(task.id, "新标题", canonical, 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)
|
||||
self.addCleanup(dialog.close)
|
||||
|
||||
self.assertEqual([canonical, archive_newer, archive_older], dialog.candidates)
|
||||
self.assertTrue(dialog.candidate_buttons[canonical].isChecked())
|
||||
self.assertEqual(canonical, dialog.selected_path)
|
||||
self.assertNotIn(old_candidate, dialog.candidates)
|
||||
renamed_archive = archive_newer.replace(".jpg", "_renamed.jpg")
|
||||
os.rename(archive_newer, renamed_archive)
|
||||
self.assertTrue(os.path.exists(renamed_archive))
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_cover_gallery_save_switches_current_cover(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
account = accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
db.init_db(cfg["db_path"])
|
||||
batch_id = db.create_batch(["input.xlsx"], path=cfg["db_path"])
|
||||
db.insert_tasks(
|
||||
batch_id,
|
||||
[
|
||||
{
|
||||
"source_file_abs": os.path.join(temp_dir, "input.xlsx"),
|
||||
"source_sheet": "商品",
|
||||
"source_row": 2,
|
||||
"account_name": "Excel主店",
|
||||
"alias": "alias-a",
|
||||
"item_id": "51100639510",
|
||||
}
|
||||
],
|
||||
path=cfg["db_path"],
|
||||
)
|
||||
task = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])[0]
|
||||
canonical = image_paths.task_image_path(cfg["image_dir"], task, account, "new")
|
||||
selected = self.write_test_image(os.path.splitext(canonical)[0] + "_20260709101000.jpg")
|
||||
self.write_test_image(canonical)
|
||||
db.set_generated(task.id, "新标题", canonical, 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)
|
||||
self.addCleanup(dialog.close)
|
||||
|
||||
dialog.candidate_buttons[selected].setChecked(True)
|
||||
self.assertTrue(dialog.save_selection())
|
||||
|
||||
updated = db.get_task(task.id, path=cfg["db_path"])
|
||||
self.assertEqual(os.path.abspath(selected), updated.new_cover_path)
|
||||
self.assertEqual("generated", updated.stage)
|
||||
self.assertEqual("pending", updated.status)
|
||||
self.assertTrue(dialog.changed)
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_cover_gallery_committed_cancel_does_not_write_db(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
account = accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
db.init_db(cfg["db_path"])
|
||||
batch_id = db.create_batch(["input.xlsx"], path=cfg["db_path"])
|
||||
db.insert_tasks(
|
||||
batch_id,
|
||||
[
|
||||
{
|
||||
"source_file_abs": os.path.join(temp_dir, "input.xlsx"),
|
||||
"source_sheet": "商品",
|
||||
"source_row": 2,
|
||||
"account_name": "Excel主店",
|
||||
"alias": "alias-a",
|
||||
"item_id": "51100639510",
|
||||
}
|
||||
],
|
||||
path=cfg["db_path"],
|
||||
)
|
||||
task = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])[0]
|
||||
canonical = image_paths.task_image_path(cfg["image_dir"], task, account, "new")
|
||||
selected = self.write_test_image(os.path.splitext(canonical)[0] + "_20260709101000.jpg")
|
||||
self.write_test_image(canonical)
|
||||
db.set_generated(task.id, "新标题", canonical, path=cfg["db_path"])
|
||||
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)
|
||||
self.addCleanup(dialog.close)
|
||||
|
||||
dialog.candidate_buttons[selected].setChecked(True)
|
||||
message_box, boxes = self.make_fake_message_box("取消")
|
||||
with mock.patch("app.gui.tabs.generate.QMessageBox", message_box):
|
||||
self.assertFalse(dialog.save_selection())
|
||||
|
||||
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.assertIn("重复更新会再次提交线上", boxes[0].text)
|
||||
self.assertFalse(dialog.changed)
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_cover_gallery_handles_missing_current_and_empty_candidates(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
account = accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
db.init_db(cfg["db_path"])
|
||||
batch_id = db.create_batch(["input.xlsx"], path=cfg["db_path"])
|
||||
db.insert_tasks(
|
||||
batch_id,
|
||||
[
|
||||
{
|
||||
"source_file_abs": os.path.join(temp_dir, "input.xlsx"),
|
||||
"source_sheet": "商品",
|
||||
"source_row": 2,
|
||||
"account_name": "Excel主店",
|
||||
"alias": "alias-a",
|
||||
"item_id": "51100639510",
|
||||
},
|
||||
{
|
||||
"source_file_abs": os.path.join(temp_dir, "input.xlsx"),
|
||||
"source_sheet": "商品",
|
||||
"source_row": 3,
|
||||
"account_name": "Excel主店",
|
||||
"alias": "alias-a",
|
||||
"item_id": "51100639511",
|
||||
},
|
||||
],
|
||||
path=cfg["db_path"],
|
||||
)
|
||||
first, second = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])
|
||||
missing_current = os.path.join(temp_dir, "missing.jpg")
|
||||
db.set_generated(first.id, "新标题A", missing_current, path=cfg["db_path"])
|
||||
first_candidate = image_paths.task_image_path(cfg["image_dir"], first, account, "new")
|
||||
self.write_test_image(first_candidate)
|
||||
first = db.get_task(first.id, path=cfg["db_path"])
|
||||
|
||||
missing_dialog = CoverGalleryDialog(first, cfg["image_dir"], cfg["db_path"], account=account)
|
||||
self.addCleanup(missing_dialog.close)
|
||||
self.assertIsNone(missing_dialog.selected_path)
|
||||
self.assertFalse(missing_dialog.save_button.isEnabled())
|
||||
self.assertIn("当前生效封面文件不存在", missing_dialog.status_label.text())
|
||||
|
||||
db.set_generated(second.id, "新标题B", os.path.join(temp_dir, "none.jpg"), path=cfg["db_path"])
|
||||
second = db.get_task(second.id, path=cfg["db_path"])
|
||||
empty_dialog = CoverGalleryDialog(second, cfg["image_dir"], cfg["db_path"], account=account)
|
||||
self.addCleanup(empty_dialog.close)
|
||||
self.assertEqual([], empty_dialog.candidates)
|
||||
self.assertFalse(empty_dialog.save_button.isEnabled())
|
||||
self.assertIn("暂无生成封面图片", empty_dialog.status_label.text())
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_original_image_dialog_title_contains_resolution(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
image_path = self.write_test_image(os.path.join(temp_dir, "cover.jpg"), width=64, height=32)
|
||||
|
||||
dialog = OriginalImageDialog(image_path)
|
||||
self.addCleanup(dialog.close)
|
||||
|
||||
self.assertIn("cover.jpg", dialog.windowTitle())
|
||||
self.assertIn("64x32", dialog.windowTitle())
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
|
||||
def test_generate_tab_allows_editing_generated_title_locally(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
|
||||
Reference in New Issue
Block a user