Files
Taremin 26e910b4f1 chore(test): ComfyUIの複数バージョン自動検証基盤の導入とテスト安定化
テスト時に指定された複数のComfyUIバージョンを自動ダウンロードし、最適な仮想環境を構築した上でテストを実行する仕組みを導入。また、Playwright同期APIに起因するデッドロックやキャッシュ汚染によるテストのハングアップ問題を解消。

- 設定ファイルで複数バージョンの定義をサポート
- 該当するComfyUIおよびEmbeddable Pythonを自動取得するdownloaderモジュールを追加
- pytest_generate_testsによりバージョン別のテストを動的にパラメータ化
- min_comfy_versionマーカーによるバージョン制限テストの条件付きスキップをサポート
- Windows環境でのゾンビプロセス防止のためtaskkillによる強制終了処理を追加
- バージョン切り替え時のブラウザキャッシュ汚染を防ぐためキャッシュを無効化
- Playwright同期APIのダイアログ処理をJavaScript側でのモック化へ移行しデッドロックを回避
- 設定画面でのCSVトグル描画有無によるテストアプローチの動的切り替えを実装
- リサイズ操作のsteps指定など各種タイミング競合とタイムアウト処理を強化
2026-07-13 21:13:11 +09:00

153 lines
6.6 KiB
Python

import pytest
import time
import os
from pathlib import Path
from playwright.sync_api import Page, expect
def test_settings_sync_between_editors(page: Page, comfyui_server, wait_for_comfyui, wmp_helpers):
page.on("console", lambda msg: print(f"BROWSER CONSOLE: {msg.type}: {msg.text}"))
page.set_viewport_size({"width": 1920, "height": 1080})
wmp_helpers.load_comfyui(page, comfyui_server, wait_for_comfyui)
wmp_helpers.wait_for_graph_clear(page)
page.evaluate(f"""() => {{
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
const types = Object.keys(window.LiteGraph.registered_node_types);
const nodeType = types.find(t => t.includes('WebuiMonacoPromptMultiText') || t.includes('MultiText'));
const node1 = window.LiteGraph.createNode(nodeType);
node1.pos = [100, 300];
app.graph.add(node1);
const node2 = window.LiteGraph.createNode(nodeType);
node2.pos = [700, 300];
app.graph.add(node2);
app.canvas.centerOnNode(node1);
}}""")
page.wait_for_function("() => app.graph && app.graph._nodes.length >= 2")
wmp_helpers.wait_for_editor(page)
font_sizes = page.evaluate("""() => {
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
const nodes = app.graph._nodes.filter(n => n.type && n.type.includes('MultiText'));
return nodes.map((n, i) => {
if (n.multitext_widget && n.multitext_widget.editorInstance) {
return n.multitext_widget.editorInstance.getSettings().fontSize;
}
return null;
});
}""")
assert font_sizes[0] == font_sizes[1], "Both editors should start with the same font size."
wmp_helpers.open_settings(page)
wmp_helpers.switch_settings_category(page, "WebuiMonacoPrompt")
wmp_helpers.set_comfy_setting(page, 'WebuiMonacoPrompt.FontSize', 18)
page.wait_for_function("""() => {
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
const nodes = app.graph._nodes.filter(n => n.type && n.type.includes('MultiText'));
return nodes.every(n => n.multitext_widget && n.multitext_widget.editorInstance && n.multitext_widget.editorInstance.getSettings().fontSize === 18);
}""")
new_font_sizes = page.evaluate("""() => {
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
const nodes = app.graph._nodes.filter(n => n.type && n.type.includes('MultiText'));
return nodes.map(n => n.multitext_widget.editorInstance.getSettings().fontSize);
}""")
assert new_font_sizes[0] == 18 and new_font_sizes[1] == 18, "Both editors should reflect the new font size."
def test_dynamic_csv_toggle_sync(page: Page, comfyui_server, wait_for_comfyui, wmp_helpers):
page.set_viewport_size({"width": 1920, "height": 1080})
wmp_helpers.load_comfyui(page, comfyui_server, wait_for_comfyui)
wmp_helpers.wait_for_graph_clear(page)
page.evaluate(f"""() => {{
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
const types = Object.keys(window.LiteGraph.registered_node_types);
const nodeType = types.find(t => t.includes('WebuiMonacoPromptMultiText') || t.includes('MultiText'));
const node1 = window.LiteGraph.createNode(nodeType);
node1.pos = [100, 300];
app.graph.add(node1);
app.canvas.centerOnNode(node1);
}}""")
wmp_helpers.wait_for_editor(page)
extension_path = os.environ.get("COMFYUI_EXTENSION_PATH", os.getcwd())
csv_dir = Path(extension_path) / "csv"
csv_dir.mkdir(exist_ok=True)
test_csv_path = csv_dir / "test_dynamic.csv"
try:
if test_csv_path.exists():
test_csv_path.unlink()
wmp_helpers.load_comfyui(page, comfyui_server, wait_for_comfyui)
wmp_helpers.wait_for_graph_clear(page)
page.evaluate(f"""() => {{
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
const types = Object.keys(window.LiteGraph.registered_node_types);
const nodeType = types.find(t => t.includes('WebuiMonacoPromptMultiText') || t.includes('MultiText'));
const node1 = window.LiteGraph.createNode(nodeType);
node1.pos = [100, 300];
app.graph.add(node1);
app.canvas.centerOnNode(node1);
}}""")
wmp_helpers.wait_for_editor(page)
content = "test_tag_1,100\\ntest_tag_2,50\\n"
with open(test_csv_path, "w", encoding="utf-8") as f:
f.write(content)
refresh_btn = page.locator("button:has-text('Refresh')")
if refresh_btn.is_visible():
refresh_btn.click()
else:
page.evaluate("""() => {
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
if (app.refreshComboInNodes) {
app.refreshComboInNodes();
} else if (app.extensionManager && app.extensionManager.refreshComboInNodes) {
app.extensionManager.refreshComboInNodes();
}
}""")
# Wait dynamically instead of fixed timeout to avoid flakiness
try:
page.wait_for_function("""() => {
const findApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp;
const app = findApp();
const nodes = app.graph._nodes.filter(n => n.type && n.type.includes('MultiText'));
if (nodes.length === 0) return false;
const editor = nodes[0].multitext_widget.editorInstance;
if (!editor) return false;
const val = editor.getContext(editor.createContextKey("csv.test_dynamic"));
return val !== undefined && val !== null;
}""")
except Exception:
pytest.fail("Dynamic CSV was not detected or added to the local context by refresh within timeout")
finally:
if test_csv_path.exists():
try:
test_csv_path.unlink()
except Exception as e:
print(f"Failed to cleanup {test_csv_path}: {e}")