T-576 增加生成和更新内容模式
This commit is contained in:
+53
-35
@@ -19,7 +19,7 @@ if gui.QT_IMPORT_ERROR is not None:
|
||||
|
||||
from PySide6.QtCore import QItemSelectionModel, QRect
|
||||
from PySide6.QtGui import QImage, QKeyEvent, QTextCursor
|
||||
from PySide6.QtWidgets import QApplication, QCheckBox, QLineEdit, QPlainTextEdit, QProgressBar, QTableView
|
||||
from PySide6.QtWidgets import QApplication, QComboBox, QLineEdit, QPlainTextEdit, QProgressBar, QTableView
|
||||
|
||||
from app.gui import (
|
||||
AccountDialog,
|
||||
@@ -850,6 +850,8 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
)
|
||||
self.assertFalse(tab.allow_real_submit_checkbox.isChecked())
|
||||
self.assertFalse(tab.allow_cover_update_checkbox.isChecked())
|
||||
self.assertTrue(tab.allow_cover_update_checkbox.isHidden())
|
||||
self.assertEqual(-1, tab.shopee_update_form_layout.indexOf(tab.allow_cover_update_checkbox))
|
||||
self.assertEqual(1, tab.max_items_per_run_spin.value())
|
||||
self.assertFalse(tab.close_success_tab_checkbox.isChecked())
|
||||
self.assertFalse(tab.parallel_accounts_checkbox.isChecked())
|
||||
@@ -866,12 +868,8 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
tab.shopee_update_form_layout,
|
||||
tab.parallel_accounts_group,
|
||||
)
|
||||
cover_row, cover_col, _row_span, _col_span = widget_position(
|
||||
tab.shopee_update_form_layout,
|
||||
tab.allow_cover_update_checkbox,
|
||||
)
|
||||
self.assertEqual(cover_row, group_row)
|
||||
self.assertGreater(group_col, cover_col)
|
||||
self.assertGreaterEqual(group_row, 0)
|
||||
self.assertGreaterEqual(group_col, 0)
|
||||
self.assertEqual(4, group_col_span)
|
||||
|
||||
group_widgets = [
|
||||
@@ -1153,7 +1151,6 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
tab.debug_port_end_spin.setValue(9350)
|
||||
tab.cdp_ready_timeout_spin.setValue(45)
|
||||
tab.allow_real_submit_checkbox.setChecked(True)
|
||||
tab.allow_cover_update_checkbox.setChecked(True)
|
||||
tab.max_items_per_run_spin.setValue(2)
|
||||
tab.close_success_tab_checkbox.setChecked(True)
|
||||
tab.parallel_accounts_checkbox.setChecked(True)
|
||||
@@ -1183,7 +1180,8 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
{
|
||||
"test_item_id": "51100639510",
|
||||
"allow_real_submit": True,
|
||||
"allow_cover_update": True,
|
||||
"allow_cover_update": False,
|
||||
"update_mode": "title",
|
||||
"max_items_per_run": 2,
|
||||
"close_success_tab": True,
|
||||
"dry_run": False,
|
||||
@@ -1235,7 +1233,6 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
apply_tab = window.tabs.widget(TAB_TITLES.index("③ 更新蝦皮"))
|
||||
|
||||
settings_tab.allow_real_submit_checkbox.setChecked(True)
|
||||
settings_tab.allow_cover_update_checkbox.setChecked(True)
|
||||
settings_tab.max_items_per_run_spin.setValue(3)
|
||||
settings_tab.close_success_tab_checkbox.setChecked(True)
|
||||
settings_tab.parallel_accounts_checkbox.setChecked(True)
|
||||
@@ -1247,7 +1244,8 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
safety_cfg = apply_tab._shopee_update_config()
|
||||
self.assertEqual("123456789", safety_cfg["test_item_id"])
|
||||
self.assertTrue(safety_cfg["allow_real_submit"])
|
||||
self.assertTrue(safety_cfg["allow_cover_update"])
|
||||
self.assertFalse(safety_cfg["allow_cover_update"])
|
||||
self.assertEqual("title", safety_cfg["update_mode"])
|
||||
self.assertEqual(3, safety_cfg["max_items_per_run"])
|
||||
self.assertTrue(safety_cfg["close_success_tab"])
|
||||
self.assertFalse(safety_cfg["dry_run"])
|
||||
@@ -1826,7 +1824,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertIsInstance(tab.title_prompt_edit, QPlainTextEdit)
|
||||
self.assertIsInstance(tab.cover_prompt_edit, QPlainTextEdit)
|
||||
self.assertIsInstance(tab.task_table, QTableView)
|
||||
self.assertIsInstance(tab.generate_cover_checkbox, QCheckBox)
|
||||
self.assertIsInstance(tab.generate_mode_combo, QComboBox)
|
||||
self.assertEqual("标题提示词", tab.title_prompt_edit.placeholderText())
|
||||
self.assertEqual("封面提示词", tab.cover_prompt_edit.placeholderText())
|
||||
self.assertEqual("保存标题提示词", tab.save_title_button.text())
|
||||
@@ -1834,8 +1832,11 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual("开始生成", tab.generate_button.text())
|
||||
self.assertEqual("停止", tab.stop_generate_button.text())
|
||||
self.assertEqual("重置生成结果", tab.reset_generate_button.text())
|
||||
self.assertEqual("生成封面图片(成本较高)", tab.generate_cover_checkbox.text())
|
||||
self.assertFalse(tab.generate_cover_checkbox.isChecked())
|
||||
self.assertEqual(
|
||||
["只生成标题", "只生成封面", "生成标题和封面"],
|
||||
[tab.generate_mode_combo.itemText(index) for index in range(tab.generate_mode_combo.count())],
|
||||
)
|
||||
self.assertEqual("title", tab.generate_mode_combo.currentData())
|
||||
self.assertFalse(tab.stop_generate_button.isEnabled())
|
||||
self.assertEqual("进度:标题0/0 · 图片0/0 · 失败0", tab.progress_label.text())
|
||||
self.assertIsInstance(tab.title_progress_bar, QProgressBar)
|
||||
@@ -2179,7 +2180,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_generate_tab_persists_generate_cover_toggle(self):
|
||||
def test_generate_tab_persists_generate_mode_selection(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
statuses = []
|
||||
@@ -2187,16 +2188,18 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.addCleanup(tab.close)
|
||||
|
||||
self.assertFalse(appconfig.ai_config(cfg)["generate_cover"])
|
||||
tab.generate_cover_checkbox.setChecked(True)
|
||||
tab.generate_mode_combo.setCurrentIndex(tab.generate_mode_combo.findData("cover"))
|
||||
|
||||
saved = appconfig.load_config(cfg["config_path"])
|
||||
self.assertTrue(saved["ai"]["generate_cover"])
|
||||
self.assertEqual("cover", saved["ai"]["generate_mode"])
|
||||
self.assertTrue(cfg["ai"]["generate_cover"])
|
||||
self.assertIn("会同时生成封面图片", statuses[-1])
|
||||
self.assertEqual("cover", cfg["ai"]["generate_mode"])
|
||||
self.assertIn("只生成封面", statuses[-1])
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_generate_tab_refreshes_to_generate_filter_when_cover_toggle_changes(self):
|
||||
def test_generate_tab_refreshes_to_generate_filter_when_mode_changes_to_cover(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
@@ -2224,7 +2227,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
tab.status_filter.setCurrentIndex(tab.status_filter.findData("to_generate"))
|
||||
self.assertEqual(0, tab.model.rowCount())
|
||||
|
||||
tab.generate_cover_checkbox.setChecked(True)
|
||||
tab.generate_mode_combo.setCurrentIndex(tab.generate_mode_combo.findData("cover"))
|
||||
|
||||
self.assertEqual(1, tab.model.rowCount())
|
||||
self.assertEqual("51100639510", tab.model.task_at(0).item_id)
|
||||
@@ -3788,7 +3791,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual(0, progress[-1]["cover_total"])
|
||||
self.assertEqual(1, progress[-1]["generated_done"])
|
||||
joined_logs = "\n".join(logs)
|
||||
self.assertIn("本轮仅生成标题,不生成图片", joined_logs)
|
||||
self.assertIn("本轮生成内容:只生成标题", joined_logs)
|
||||
self.assertIn("已保存,仅生成标题", joined_logs)
|
||||
self.assertIn("[完成] AI 生成完成:标题1/1,图片0/0,失败0", joined_logs)
|
||||
run_log = db.list_run_logs(limit=1, run_type="generate", path=cfg["db_path"])[0]
|
||||
@@ -3803,6 +3806,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
cfg = self.make_config(temp_dir)
|
||||
cfg["ai"] = appconfig.ai_config(cfg)
|
||||
cfg["ai"]["backend"] = "direct"
|
||||
cfg["ai"]["generate_mode"] = "cover"
|
||||
cfg["ai"]["generate_cover"] = True
|
||||
accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
batch_id = db.create_batch(["input.xlsx"], path=cfg["db_path"])
|
||||
@@ -3860,7 +3864,8 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual(0, progress[-1]["title_total"])
|
||||
self.assertEqual(1, progress[-1]["cover_total"])
|
||||
joined_logs = "\n".join(logs)
|
||||
self.assertIn("[开始] 本轮生成 1 条:标题0,图片1", joined_logs)
|
||||
self.assertIn("本轮生成内容:只生成封面", joined_logs)
|
||||
self.assertIn("标题0,图片1", joined_logs)
|
||||
self.assertIn("已有标题,跳过生文", joined_logs)
|
||||
self.assertIn("[完成] AI 生成完成:标题0/0,图片1/1,失败0", joined_logs)
|
||||
|
||||
@@ -3944,7 +3949,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertTrue(fake_thread.started)
|
||||
self.assertNotIn("上一轮失败日志", text)
|
||||
self.assertIn("本轮AI生成开始:任务 1 条", text)
|
||||
self.assertIn("生成封面:否", text)
|
||||
self.assertIn("生成内容:只生成标题", text)
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
@@ -3952,6 +3957,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
cfg["ai"] = appconfig.ai_config(cfg)
|
||||
cfg["ai"]["generate_mode"] = "cover"
|
||||
cfg["ai"]["generate_cover"] = True
|
||||
accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
batch_id = db.create_batch(["input.xlsx"], path=cfg["db_path"])
|
||||
@@ -3999,7 +4005,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual("图片 0/1", tab.cover_progress_label.text())
|
||||
text = tab.run_log_view.toPlainText()
|
||||
self.assertIn("本轮AI生成开始:任务 1 条", text)
|
||||
self.assertIn("生成封面:是", text)
|
||||
self.assertIn("生成内容:只生成封面", text)
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
@@ -4145,6 +4151,11 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual(["店铺", "商品ID", "新标题", "新封面", "阶段", "结果"], tab.model.HEADERS)
|
||||
self.assertEqual("检查本轮更新", tab.preview_update_button.text())
|
||||
self.assertEqual("开始更新", tab.start_update_button.text())
|
||||
self.assertIsInstance(tab.update_mode_combo, QComboBox)
|
||||
self.assertEqual(
|
||||
["只更新标题", "只更新封面", "更新标题和封面"],
|
||||
[tab.update_mode_combo.itemText(index) for index in range(tab.update_mode_combo.count())],
|
||||
)
|
||||
self.assertEqual("applyItemFilter", tab.item_filter.objectName())
|
||||
self.assertEqual("停止", tab.stop_update_button.text())
|
||||
self.assertEqual("重置更新状态", tab.reset_update_button.text())
|
||||
@@ -4293,6 +4304,8 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertIn("任务数:1", message)
|
||||
self.assertIn("预计批次:1", message)
|
||||
self.assertIn("提交线上", message)
|
||||
self.assertIn("更新内容:更新标题和封面", message)
|
||||
self.assertIn("本轮将更新线上封面", message)
|
||||
self.assertIn("状态:已生成", message)
|
||||
self.assertIn("商品ID:51100639510", message)
|
||||
self.assertNotIn("测试商品ID", message)
|
||||
@@ -4360,9 +4373,10 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertFalse(tab.apply_worker.dry_run)
|
||||
self.assertFalse(tab.apply_worker.parallel_accounts)
|
||||
self.assertEqual(1, tab.apply_worker.batch_size)
|
||||
self.assertEqual("title_cover", tab.apply_worker.update_mode)
|
||||
log_text = tab.run_log_view.toPlainText()
|
||||
self.assertNotIn("上一轮更新失败", log_text)
|
||||
self.assertIn("本轮更新开始:任务 1 条,每批 1 条", log_text)
|
||||
self.assertIn("本轮更新开始:任务 1 条,更新内容:更新标题和封面,每批 1 条", log_text)
|
||||
self.assertFalse(tab.preview_update_button.isEnabled())
|
||||
self.assertFalse(tab.start_update_button.isEnabled())
|
||||
self.assertTrue(tab.stop_update_button.isEnabled())
|
||||
@@ -4440,7 +4454,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual(2, tab.apply_worker.max_parallel_accounts)
|
||||
log_text = tab.run_log_view.toPlainText()
|
||||
self.assertNotIn("上一轮检查失败", log_text)
|
||||
self.assertIn("本轮检查开始:任务 1 条,每批 1 条", log_text)
|
||||
self.assertIn("本轮检查开始:任务 1 条,更新内容:只更新标题,每批 1 条", log_text)
|
||||
self.assertEqual("开始检查本轮更新:1 条", statuses[-1])
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
@@ -4486,7 +4500,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_apply_tab_blocks_cover_update_when_cover_switch_is_off(self):
|
||||
def test_apply_tab_blocks_cover_update_when_cover_is_missing_for_selected_mode(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
self.allow_shopee_update(cfg, allow_cover=False)
|
||||
@@ -4508,18 +4522,22 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
)
|
||||
task = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])[0]
|
||||
db.set_collected(task.id, "旧标题", "old.jpg", path=cfg["db_path"])
|
||||
db.set_generated(task.id, "新标题", "new.jpg", path=cfg["db_path"])
|
||||
db.set_generated(task.id, "新标题", None, path=cfg["db_path"])
|
||||
tab = ApplyTab(config=cfg)
|
||||
self.addCleanup(tab.close)
|
||||
tab.update_mode_combo.setCurrentIndex(tab.update_mode_combo.findData("cover"))
|
||||
|
||||
with mock.patch.object(tab, "_show_update_safety_error") as safety_error, \
|
||||
with mock.patch("app.gui.QMessageBox.warning") as warning, \
|
||||
mock.patch("app.gui.QMessageBox.question") as question, \
|
||||
mock.patch("app.gui.run_worker") as run_worker:
|
||||
tab.start_update()
|
||||
|
||||
message = safety_error.call_args[0][0]
|
||||
self.assertIn("允许更新封面", message)
|
||||
self.assertIn("⑤设置", message)
|
||||
warning.assert_called_once()
|
||||
self.assertEqual("更新内容未生成", warning.call_args[0][1])
|
||||
message = warning.call_args[0][2]
|
||||
self.assertIn("缺少新封面", message)
|
||||
self.assertIn("只更新封面", message)
|
||||
self.assertIn("51100639510", message)
|
||||
question.assert_not_called()
|
||||
run_worker.assert_not_called()
|
||||
|
||||
@@ -4621,7 +4639,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
progress = []
|
||||
rows = []
|
||||
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True):
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True, update_mode=None):
|
||||
applied_aliases.append(account.alias)
|
||||
close_flags.append(close_success_tab)
|
||||
foreground_flags.append(bring_to_front)
|
||||
@@ -4725,7 +4743,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
tasks = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])
|
||||
foreground_flags = []
|
||||
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True):
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True, update_mode=None):
|
||||
foreground_flags.append(bring_to_front)
|
||||
return {"committed": True, "error": None}
|
||||
|
||||
@@ -4850,7 +4868,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
thread_names = set()
|
||||
foreground_by_alias = {}
|
||||
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True):
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True, update_mode=None):
|
||||
thread_names.add(threading.current_thread().name)
|
||||
foreground_by_alias[account.alias] = bring_to_front
|
||||
started[account.alias].set()
|
||||
@@ -6716,7 +6734,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
task = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])[0]
|
||||
diagnostic_log_dir = os.path.join(temp_dir, "logs")
|
||||
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True):
|
||||
def fake_apply(account, task, close_success_tab=False, on_step=None, bring_to_front=True, update_mode=None):
|
||||
on_step({"step": "open_product", "result": "start"})
|
||||
on_step({"step": "replace_cover", "result": "failed", "detail": "token=SECRET"})
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user