282 lines
12 KiB
Python
282 lines
12 KiB
Python
import os
|
||
import sys
|
||
import unittest
|
||
|
||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||
sys.path.insert(0, os.path.dirname(__file__))
|
||
|
||
from _helpers import TempDirMixin
|
||
|
||
from app import accounts, appconfig, image_studio, image_studio_images
|
||
from app import gui
|
||
|
||
if gui.QT_IMPORT_ERROR is not None:
|
||
raise unittest.SkipTest("PySide6 未安装")
|
||
|
||
from PySide6.QtGui import QImage
|
||
from PySide6.QtWidgets import QApplication, QLabel, QPushButton
|
||
|
||
from app.gui.tabs.product_suite import ProductSuiteTab, SuiteResultCard
|
||
|
||
|
||
class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
|
||
@classmethod
|
||
def setUpClass(cls):
|
||
cls.app = QApplication.instance() or QApplication([])
|
||
|
||
def tearDown(self):
|
||
for widget in QApplication.topLevelWidgets():
|
||
widget.close()
|
||
widget.deleteLater()
|
||
self.app.processEvents()
|
||
|
||
def _config(self, temp_dir):
|
||
return {
|
||
"chrome_path": "chrome.exe",
|
||
"user_data_root": os.path.join(temp_dir, "chrome_user_data_dir"),
|
||
"image_dir": os.path.join(temp_dir, "images"),
|
||
"db_path": os.path.join(temp_dir, "cmshopee.db"),
|
||
"debug_port_range": [9222, 9260],
|
||
"config_path": os.path.join(temp_dir, "config.json"),
|
||
"cmhub_config_path": os.path.join(temp_dir, "cmhub.json"),
|
||
}
|
||
|
||
def _write_image(self, path):
|
||
image = QImage(40, 30, QImage.Format_RGB32)
|
||
image.fill(0xFF336699)
|
||
self.assertTrue(image.save(path))
|
||
|
||
def test_tab_builds_suite_controls_without_old_detail_workspace(self):
|
||
with self.make_temp_dir() as temp_dir:
|
||
config = self._config(temp_dir)
|
||
accounts.create_account("主店", "alias-a", debug_port=9222, config=config)
|
||
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
|
||
self.addCleanup(tab.close)
|
||
tab.resize(1180, 760)
|
||
tab.show()
|
||
self.app.processEvents()
|
||
|
||
self.assertEqual("productSuiteTab", tab.objectName())
|
||
self.assertEqual(1, tab.task_tabs.count())
|
||
self.assertEqual("套图任务 1", tab.task_tabs.tabText(0))
|
||
self.assertEqual("alias-a", tab.account_combo.currentData())
|
||
self.assertEqual("Shopee", tab.platform_combo.currentData())
|
||
self.assertEqual("中国台湾", tab.country_combo.currentData())
|
||
self.assertEqual("繁体中文", tab.language_combo.currentData())
|
||
self.assertEqual("1:1", tab.ratio_combo.currentData())
|
||
self.assertEqual("Shopee", tab.platform_combo.currentText())
|
||
self.assertEqual("中国台湾", tab.country_combo.currentText())
|
||
self.assertEqual("繁体中文", tab.language_combo.currentText())
|
||
self.assertEqual("1:1", tab.ratio_combo.currentText())
|
||
self.assertEqual("平台", tab.platform_label.text())
|
||
self.assertEqual("站点", tab.country_label.text())
|
||
self.assertEqual("语言", tab.language_label.text())
|
||
self.assertEqual("比例", tab.ratio_label.text())
|
||
for column, combo in enumerate(
|
||
(
|
||
tab.platform_combo,
|
||
tab.country_combo,
|
||
tab.language_combo,
|
||
tab.ratio_combo,
|
||
)
|
||
):
|
||
self.assertIs(combo, tab.settings_grid.itemAtPosition(1, column).widget())
|
||
self.assertEqual(
|
||
1,
|
||
len(
|
||
{
|
||
tab.platform_combo.width(),
|
||
tab.country_combo.width(),
|
||
tab.language_combo.width(),
|
||
tab.ratio_combo.width(),
|
||
}
|
||
),
|
||
)
|
||
self.assertLessEqual(tab.task_tabs.maximumHeight(), 36)
|
||
self.assertEqual(120, tab.account_combo.minimumWidth())
|
||
self.assertEqual(160, tab.account_combo.maximumWidth())
|
||
self.assertGreaterEqual(tab.item_id_edit.minimumWidth(), 120)
|
||
self.assertLessEqual(tab.item_id_edit.maximumWidth(), 140)
|
||
self.assertLess(
|
||
tab.context_bar_layout.indexOf(tab.history_button),
|
||
tab.context_bar_layout.indexOf(tab.account_combo),
|
||
)
|
||
self.assertLess(
|
||
tab.context_bar_layout.indexOf(tab.open_folder_button),
|
||
tab.context_bar_layout.indexOf(tab.account_combo),
|
||
)
|
||
self.assertLess(
|
||
tab.context_bar_layout.indexOf(tab.add_images_button),
|
||
tab.context_bar_layout.indexOf(tab.account_combo),
|
||
)
|
||
self.assertEqual(-1, tab.results_toolbar_layout.indexOf(tab.history_button))
|
||
self.assertEqual(-1, tab.results_toolbar_layout.indexOf(tab.open_folder_button))
|
||
self.assertEqual("打开结果文件夹", tab.open_folder_button.text())
|
||
self.assertEqual("合计 5 张", tab.category_total_label.text())
|
||
self.assertEqual("生成套图(5)", tab.generate_button.text())
|
||
|
||
visible_text = " ".join(
|
||
[widget.text() for widget in tab.findChildren(QLabel)]
|
||
+ [widget.text() for widget in tab.findChildren(QPushButton)]
|
||
)
|
||
self.assertNotIn("详情图", visible_text)
|
||
self.assertNotIn("AI工场", visible_text)
|
||
self.assertIn("白底图", visible_text)
|
||
self.assertIn("场景图", visible_text)
|
||
self.assertIn("卖点图", visible_text)
|
||
|
||
tab.add_custom_category()
|
||
self.assertFalse(tab.custom_category_edit.isHidden())
|
||
tab.custom_category_edit.setText("尺寸图")
|
||
tab._commit_custom_category()
|
||
self.assertTrue(tab.custom_category_edit.isHidden())
|
||
self.assertIn("尺寸图", tab._displayed_state.settings["categories"])
|
||
self.assertEqual("尺寸图", tab._displayed_state.active_category)
|
||
|
||
self.assert_removed(temp_dir)
|
||
|
||
def test_recent_dropdown_settings_restore_after_restart_and_project_wins(self):
|
||
with self.make_temp_dir() as temp_dir:
|
||
config_path = os.path.join(temp_dir, "config.json")
|
||
config = appconfig.save_config(self._config(temp_dir), path=config_path)
|
||
account = accounts.create_account(
|
||
"主店",
|
||
"alias-a",
|
||
debug_port=9222,
|
||
config=config,
|
||
)
|
||
project = image_studio.create_or_get_project(
|
||
account,
|
||
item_id="51100639510",
|
||
path=config["db_path"],
|
||
)
|
||
project_settings = image_studio.project_suite_settings(project)
|
||
project_settings["ratio"] = "4:3"
|
||
image_studio.update_project_suite_settings(
|
||
project.id,
|
||
project_settings,
|
||
path=config["db_path"],
|
||
)
|
||
|
||
first = ProductSuiteTab(
|
||
config=config,
|
||
config_path=config_path,
|
||
db_path=config["db_path"],
|
||
)
|
||
first.ratio_combo.setCurrentIndex(first.ratio_combo.findData("16:9"))
|
||
self.assertEqual(
|
||
"16:9",
|
||
appconfig.product_suite_last_settings(
|
||
appconfig.load_config(config_path)
|
||
)["ratio"],
|
||
)
|
||
first.close()
|
||
first.deleteLater()
|
||
self.app.processEvents()
|
||
|
||
reloaded = appconfig.load_config(config_path)
|
||
second = ProductSuiteTab(
|
||
config=reloaded,
|
||
config_path=config_path,
|
||
db_path=reloaded["db_path"],
|
||
)
|
||
self.addCleanup(second.close)
|
||
self.assertEqual("16:9", second.ratio_combo.currentData())
|
||
|
||
state = second._displayed_state
|
||
state.account_alias = "alias-a"
|
||
state.item_id = "51100639510"
|
||
second._bind_project(state, load_existing=True)
|
||
|
||
self.assertEqual("4:3", second.ratio_combo.currentData())
|
||
self.assertEqual("4:3", state.settings["ratio"])
|
||
|
||
self.assert_removed(temp_dir)
|
||
|
||
def test_task_tabs_keep_independent_prompt_and_settings(self):
|
||
with self.make_temp_dir() as temp_dir:
|
||
config = self._config(temp_dir)
|
||
accounts.create_account("主店", "alias-a", debug_port=9222, config=config)
|
||
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
|
||
self.addCleanup(tab.close)
|
||
|
||
tab.prompt_edit.setPlainText("任务一卖点")
|
||
first_state = tab._displayed_state
|
||
tab.ratio_combo.setCurrentIndex(tab.ratio_combo.findData("3:4"))
|
||
second_state = tab.add_task(inherit=True)
|
||
|
||
self.assertEqual(2, tab.task_tabs.count())
|
||
self.assertEqual("任务一卖点", second_state.prompt)
|
||
self.assertEqual("3:4", second_state.settings["ratio"])
|
||
tab.prompt_edit.setPlainText("任务二卖点")
|
||
tab.ratio_combo.setCurrentIndex(tab.ratio_combo.findData("16:9"))
|
||
tab.task_tabs.setCurrentIndex(0)
|
||
|
||
self.assertIs(first_state, tab._displayed_state)
|
||
self.assertEqual("任务一卖点", tab.prompt_edit.toPlainText())
|
||
self.assertEqual("3:4", tab.ratio_combo.currentData())
|
||
|
||
self.assert_removed(temp_dir)
|
||
|
||
def test_project_settings_and_result_history_use_existing_backend(self):
|
||
with self.make_temp_dir() as temp_dir:
|
||
config = self._config(temp_dir)
|
||
account = accounts.create_account("主店", "alias-a", debug_port=9222, config=config)
|
||
project = image_studio.create_or_get_project(
|
||
account,
|
||
item_id="51100639510",
|
||
path=config["db_path"],
|
||
)
|
||
source_path = os.path.join(temp_dir, "source.png")
|
||
self._write_image(source_path)
|
||
source = image_studio_images.import_original_files(
|
||
project.id,
|
||
[source_path],
|
||
path=config["db_path"],
|
||
config=config,
|
||
)["assets"][0]
|
||
job = image_studio.create_job(
|
||
project.id,
|
||
source_asset_id=source.id,
|
||
job_type="场景图",
|
||
prompt="场景卖点",
|
||
path=config["db_path"],
|
||
)
|
||
image_studio.update_job_status(
|
||
job.id,
|
||
"failed",
|
||
error="上游超时 https://example.invalid/private",
|
||
path=config["db_path"],
|
||
)
|
||
|
||
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
|
||
self.addCleanup(tab.close)
|
||
state = tab._displayed_state
|
||
state.account_alias = "alias-a"
|
||
state.item_id = "51100639510"
|
||
state.project_id = project.id
|
||
state.current_job_ids = [job.id]
|
||
tab._load_state(state)
|
||
|
||
self.assertEqual([source.id], tab.original_list.asset_ids())
|
||
self.assertEqual("共 1 张 · 成功 0 张", tab.result_summary_label.text())
|
||
cards = tab.findChildren(SuiteResultCard)
|
||
self.assertEqual(1, len(cards))
|
||
self.assertNotIn(
|
||
"https://",
|
||
" ".join(label.text() for label in cards[0].findChildren(QLabel)),
|
||
)
|
||
|
||
state.settings["ratio"] = "4:3"
|
||
state.prompt = "持久化卖点"
|
||
tab._persist_state(state)
|
||
stored = image_studio.get_project(project.id, path=config["db_path"])
|
||
self.assertEqual("持久化卖点", stored.draft_prompt)
|
||
self.assertEqual("4:3", image_studio.project_suite_settings(stored)["ratio"])
|
||
|
||
self.assert_removed(temp_dir)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|