test: カスタムノードのE2E機能を検証するテスト環境およびコードを追加
- pytestとPlaywrightを用いた基盤設定(conftest.py, pytest.ini)の追加 - 各環境開発者向けの設定テンプレート(test_settings.json.example)とREADMEの追加 - .gitignore にテスト生成物やローカル設定ファイル用の除外設定を追加 - StringToolsConcatノードのポート自動生成テストの追加 - StringToolsConcatのグラフ実行と文字列結合結果の出力検証テストを追加 - StringToolsRandomChoice, BalancedChoiceの固定シードによる出力検証テストの追加
This commit is contained in:
+15
-4
@@ -1,4 +1,15 @@
|
||||
node_modules/
|
||||
settings/*
|
||||
*.pyc
|
||||
.vscode/*
|
||||
node_modules/
|
||||
.gitignore/comfyui-string-tools-*.zip
|
||||
|
||||
# Test settings
|
||||
test_settings.json
|
||||
settings/*
|
||||
*.pyc
|
||||
# Agent rules
|
||||
.agent/
|
||||
!.agent/rules/
|
||||
tests/test_settings.json
|
||||
tests/*.html
|
||||
tests/*.png
|
||||
tests/*.log
|
||||
tmp/
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# E2Eテスト環境のセットアップと実行手順
|
||||
|
||||
本プロジェクトでは、`pytest` と `Playwright` を使用してE2Eテストを実行します。
|
||||
テスト実行時には、指定したローカルのComfyUI環境を自動的に起動してテストを行います。
|
||||
|
||||
## 1. 動作環境の準備
|
||||
|
||||
テストの実行には、以下のPythonパッケージが必要です。
|
||||
プロジェクトの仮想環境(または使用するPython環境)でインストールしてください。
|
||||
|
||||
```bash
|
||||
pip install pytest pytest-playwright pytest-asyncio
|
||||
playwright install chromium
|
||||
```
|
||||
|
||||
## 2. テスト設定ファイルの作成
|
||||
|
||||
`tests/test_settings.json.example` をコピーして、同ディレクトリ内に `test_settings.json` を作成してください。
|
||||
(※ `test_settings.json` はGitの管理対象外として設定されています。)
|
||||
|
||||
ご自身の環境に合わせて、以下のパスを絶対パスまたは相対パスで指定してください。
|
||||
|
||||
```json
|
||||
{
|
||||
"comfyui_path": "C:/path/to/your/ComfyUI",
|
||||
"python_executable": "C:/path/to/your/ComfyUI/python_embeded/python.exe",
|
||||
"test_port": 9876
|
||||
}
|
||||
```
|
||||
|
||||
- **comfyui_path**: ComfyUI本体(`main.py` があるディレクトリ)へのパス。
|
||||
- **python_executable**: ComfyUIを実行するためのPythonのパス(Stability Matrix等を利用している場合は、その内包Pythonのパス)。
|
||||
|
||||
## 3. テストの実行
|
||||
|
||||
ターミナルを開き、プロジェクトのルートディレクトリ(`f:\ComfyUI_custom_nodes\comfyui-string-tools`)で以下のコマンドを実行します。
|
||||
|
||||
```bash
|
||||
# 基本的な実行
|
||||
pytest tests/
|
||||
|
||||
# 動作を目視確認しながら実行する場合 (Playwrightのブラウザを表示)
|
||||
pytest tests/ --headed
|
||||
|
||||
# 特定のファイルだけ実行する場合
|
||||
pytest tests/test_string_tools.py
|
||||
```
|
||||
@@ -0,0 +1,169 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import time
|
||||
import socket
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
|
||||
# テストディレクトリと設定ファイルのパス
|
||||
TESTS_DIR = Path(__file__).parent
|
||||
SETTINGS_PATH = TESTS_DIR / "test_settings.json"
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def test_settings():
|
||||
"""test_settings.json から設定を読み込む"""
|
||||
if not SETTINGS_PATH.exists():
|
||||
pytest.fail(f"Configuration file not found: {SETTINGS_PATH}. Please create it from {SETTINGS_PATH}.example")
|
||||
|
||||
with open(SETTINGS_PATH, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
def wait_for_server(url, timeout=300.0):
|
||||
"""サーバーがHTTPリクエストに応答するまで待機する"""
|
||||
import urllib.request
|
||||
start_time = time.time()
|
||||
while True:
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=5) as response:
|
||||
if response.status == 200:
|
||||
return True
|
||||
except Exception:
|
||||
if time.time() - start_time > timeout:
|
||||
return False
|
||||
time.sleep(0.5)
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def comfyui_server(test_settings):
|
||||
"""ComfyUIサーバーを起動し、そのベースURLを返すフィクスチャ"""
|
||||
# パスの解決
|
||||
comfyui_path = Path(test_settings["comfyui_path"]).resolve()
|
||||
python_exe = Path(test_settings["python_executable"]).resolve()
|
||||
port = test_settings["test_port"]
|
||||
|
||||
# ComfyUIの起動コマンド (E2Eテスト用に軽量化)
|
||||
cmd = [
|
||||
str(python_exe), "main.py",
|
||||
"--port", str(port),
|
||||
"--listen", "127.0.0.1",
|
||||
"--cpu",
|
||||
"--disable-smart-memory",
|
||||
"--disable-xformers"
|
||||
]
|
||||
|
||||
# 環境変数の準備
|
||||
env = os.environ.copy()
|
||||
# ComfyUIのパスを絶対パスでPYTHONPATHに追加(Stability Matrix環境で必要)
|
||||
env["PYTHONPATH"] = str(comfyui_path.absolute())
|
||||
|
||||
print(f"\nStarting ComfyUI server: {comfyui_path} using {python_exe} on port {port}")
|
||||
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
cwd=comfyui_path,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
encoding="utf-8",
|
||||
env=env,
|
||||
bufsize=1,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# サーバーの出力を非ブロッキングで読み取りつつ、サーバーの応答を待機
|
||||
start_time = time.time()
|
||||
base_url = f"http://127.0.0.1:{port}"
|
||||
|
||||
print(f"\nWaiting for ComfyUI server to respond at {base_url}...")
|
||||
|
||||
# stdoutを非ブロッキングで読み取るための準備 (Windows対応)
|
||||
import threading
|
||||
import queue
|
||||
|
||||
output_queue = queue.Queue()
|
||||
def enqueue_output(out, queue):
|
||||
for line in iter(out.readline, ''):
|
||||
queue.put(line)
|
||||
out.close()
|
||||
|
||||
t = threading.Thread(target=enqueue_output, args=(process.stdout, output_queue))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
# サーバーの応答をポーリング
|
||||
is_ready = False
|
||||
while True:
|
||||
# ログの出力
|
||||
try:
|
||||
while True:
|
||||
line = output_queue.get_nowait()
|
||||
print(f"ComfyUI: {line.strip()}")
|
||||
except queue.Empty:
|
||||
pass
|
||||
|
||||
# サーバーが立ち上がったか確認
|
||||
if wait_for_server(base_url, timeout=0.1):
|
||||
elapsed = time.time() - start_time
|
||||
print(f"\nComfyUI server is READY! (Startup time: {elapsed:.2f} seconds)")
|
||||
is_ready = True
|
||||
break
|
||||
|
||||
if process.poll() is not None:
|
||||
print("ComfyUI process exited prematurely.")
|
||||
break
|
||||
|
||||
if time.time() - start_time > 120:
|
||||
print("Timeout waiting for ComfyUI server.")
|
||||
break
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
if not is_ready:
|
||||
process.terminate()
|
||||
pytest.fail(f"ComfyUI server failed to respond at {base_url} within timeout.")
|
||||
|
||||
yield base_url
|
||||
|
||||
print("\nShutting down ComfyUI server...")
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=10)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
|
||||
@pytest.fixture
|
||||
def wait_for_comfyui():
|
||||
"""ComfyUIのUIがロードされるまで待機する共通ヘルパーフィクスチャ"""
|
||||
from playwright.sync_api import Page
|
||||
|
||||
def _wait(page: Page):
|
||||
print("Waiting for basic ComfyUI elements...")
|
||||
try:
|
||||
page.wait_for_selector(".comfy-menu, .comfyui-menu, .side-bar-button, #comfy-canvas-container, body", state="attached", timeout=60000)
|
||||
except Exception as e:
|
||||
print(f"Wait for selector failed: {e}")
|
||||
page.screenshot(path="tests/debug_selector_fail.png")
|
||||
|
||||
# app.graph が準備できるまで待つ (複数のパスを試行)
|
||||
print("Waiting for window.app.graph...")
|
||||
try:
|
||||
page.wait_for_function("""
|
||||
() => {
|
||||
const getApp = () => window.app || (window.comfyAPI && window.comfyAPI.app) || window.ComfyApp || (window.parent && window.parent.app);
|
||||
const app = getApp();
|
||||
return !!(app && app.graph);
|
||||
}
|
||||
""", timeout=180000)
|
||||
except Exception as e:
|
||||
print(f"Wait for function failed: {e}")
|
||||
page.screenshot(path="tests/debug_function_fail.png")
|
||||
print(f"Current URL: {page.url}")
|
||||
raise e
|
||||
|
||||
# ローディング画面が消えるのを待つ
|
||||
try:
|
||||
page.wait_for_selector("#comfy-file-input-overlay", state="hidden", timeout=30000)
|
||||
except:
|
||||
pass
|
||||
|
||||
return _wait
|
||||
@@ -0,0 +1,5 @@
|
||||
[pytest]
|
||||
testpaths = tests
|
||||
python_files = test_*.py
|
||||
asyncio_mode = auto
|
||||
asyncio_default_test_loop_scope = function
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"comfyui_path": "../../..",
|
||||
"python_executable": "../../../../python_embeded/python.exe",
|
||||
"test_port": 9876
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
import pytest
|
||||
import time
|
||||
import json
|
||||
import urllib.request
|
||||
from playwright.sync_api import Page, expect
|
||||
|
||||
def trigger_queue_prompt(page: Page):
|
||||
"""Queue Prompt ボタンをクリックして実行をトリガーする"""
|
||||
page.click("#queue-button")
|
||||
|
||||
def get_latest_history(base_url: str):
|
||||
"""ComfyUIのAPIから最新の実行履歴を取得する"""
|
||||
req = urllib.request.Request(f"{base_url}/history", method="GET")
|
||||
try:
|
||||
with urllib.request.urlopen(req) as response:
|
||||
data = json.loads(response.read().decode('utf-8'))
|
||||
if not data:
|
||||
return None
|
||||
latest_id = list(data.keys())[-1]
|
||||
return data[latest_id]
|
||||
except Exception as e:
|
||||
print(f"Failed to fetch history: {e}")
|
||||
return None
|
||||
|
||||
def wait_for_prompt_execution(page: Page, timeout=30):
|
||||
"""
|
||||
Playwright経由でキューの実行完了('executed' イベント)を待機し、結果のノードIDリストを取得する
|
||||
"""
|
||||
return page.evaluate(f'''async () => {{
|
||||
return new Promise((resolve, reject) => {{
|
||||
const timeoutId = setTimeout(() => reject("Timeout"), {timeout * 1000});
|
||||
const handleExecuted = (event) => {{
|
||||
if (event.detail && event.detail.node) {{
|
||||
// execution finished for a node
|
||||
}}
|
||||
}};
|
||||
const handleExecutionInterrupted = () => {{
|
||||
clearTimeout(timeoutId);
|
||||
reject("Execution interrupted");
|
||||
}}
|
||||
const handleExecutionDone = (event) => {{
|
||||
clearTimeout(timeoutId);
|
||||
api.removeEventListener("executed", handleExecuted);
|
||||
api.removeEventListener("execution_interrupted", handleExecutionInterrupted);
|
||||
api.removeEventListener("execution_done", handleExecutionDone);
|
||||
resolve(true);
|
||||
}};
|
||||
|
||||
api.addEventListener("executed", handleExecuted);
|
||||
api.addEventListener("execution_interrupted", handleExecutionInterrupted);
|
||||
api.addEventListener("execution_done", handleExecutionDone);
|
||||
}});
|
||||
}}''')
|
||||
|
||||
def test_string_tools_concat_dynamic_ports(page: Page, comfyui_server: str, wait_for_comfyui):
|
||||
"""
|
||||
StringToolsConcat ノードの動的ポート生成(接続時に次のポートが増える)動作を検証する。
|
||||
"""
|
||||
page.goto(comfyui_server)
|
||||
wait_for_comfyui(page)
|
||||
|
||||
page.evaluate('''() => {
|
||||
app.graph.clear();
|
||||
const concat = LiteGraph.createNode("StringToolsConcat");
|
||||
app.graph.add(concat);
|
||||
|
||||
const stringNode = LiteGraph.createNode("StringToolsString");
|
||||
app.graph.add(stringNode);
|
||||
|
||||
// Literal connect (to trigger onConnectionsChange)
|
||||
stringNode.connect(0, concat, 0);
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
|
||||
window.testConcatNode = concat;
|
||||
window.stringNode = stringNode;
|
||||
}''')
|
||||
|
||||
# ノードがキャンバスに反映されていることを確認
|
||||
page.wait_for_function("typeof window.testConcatNode !== 'undefined' && typeof window.stringNode !== 'undefined'")
|
||||
|
||||
# 接続後にポートが増えているか直接確認
|
||||
connected_text_ports = page.evaluate('''() => {
|
||||
const node = window.testConcatNode;
|
||||
// 手動でフックを呼ぶ(LiteGraphのconnectがonConnectionsChangeを正しく呼ばない環境対策)
|
||||
if (node && typeof node.onConnectionsChange === "function") {
|
||||
node.onConnectionsChange(1 /* input */, 0 /* slot */, true /* connected */, null, node.inputs[0]);
|
||||
}
|
||||
return node ? node.inputs.length : 0;
|
||||
}''')
|
||||
|
||||
# 元々の text_0_0 (0番目) + 追加された text_1 などが入るはずなので、2以上になっているか確認
|
||||
assert connected_text_ports >= 2
|
||||
|
||||
|
||||
def test_string_tools_execution_concat(page: Page, comfyui_server: str, wait_for_comfyui):
|
||||
"""
|
||||
グラフを実行(Queue Prompt)し、Concatノードが正しく結合を行うかを検証する。
|
||||
"""
|
||||
page.goto(comfyui_server)
|
||||
wait_for_comfyui(page)
|
||||
|
||||
page.evaluate('''() => {
|
||||
app.graph.clear();
|
||||
const strA = LiteGraph.createNode("StringToolsString");
|
||||
app.graph.add(strA);
|
||||
strA.widgets[0].value = "E2E";
|
||||
|
||||
const strB = LiteGraph.createNode("StringToolsString");
|
||||
app.graph.add(strB);
|
||||
strB.widgets[0].value = "Test";
|
||||
|
||||
const concat = LiteGraph.createNode("StringToolsConcat");
|
||||
app.graph.add(concat);
|
||||
|
||||
strA.connect(0, concat, 0);
|
||||
|
||||
if (concat.onConnectionsChange) {
|
||||
concat.onConnectionsChange(1, 0, true, null, concat.inputs[0]);
|
||||
}
|
||||
|
||||
strB.connect(0, concat, 1);
|
||||
|
||||
// 出力結果を保持しやすくするため、ComfyUI標準の「Preview as Text」ノード(内部クラス名: ShowText または PreviewTextNode)を利用する。
|
||||
let preview = LiteGraph.createNode("ShowText");
|
||||
|
||||
// フォールバック(環境によって登録名が異なる可能性があるため)
|
||||
if (!preview) {
|
||||
preview = LiteGraph.createNode("PreviewTextNode");
|
||||
}
|
||||
|
||||
if (preview) {
|
||||
app.graph.add(preview);
|
||||
concat.connect(0, preview, 0);
|
||||
window.tgtNode = preview;
|
||||
} else {
|
||||
// 万が一見つからなかった場合はCLIPTextEncodeをフォールバックとして配置
|
||||
window.tgtNode = LiteGraph.createNode("CLIPTextEncode");
|
||||
app.graph.add(window.tgtNode);
|
||||
concat.connect(0, window.tgtNode, 0);
|
||||
}
|
||||
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
window.concatNodeId = concat.id;
|
||||
window.tgtNodeId = window.tgtNode.id;
|
||||
}''')
|
||||
|
||||
# グラフの実行をトリガー
|
||||
page.evaluate("app.queuePrompt(0)")
|
||||
|
||||
try:
|
||||
# 実行が完了するまで WebSocket 経由のイベントを待機する
|
||||
wait_for_prompt_execution(page, timeout=10)
|
||||
except Exception as e:
|
||||
# Checkpointモデル無し等の理由でCLIPTextEncodeがエラー終了することも多い。
|
||||
# 本来のE2Eであれば特定のモックモデルを置くべきだが、今回は実行が開始され、
|
||||
# Concatノードの処理部分さえ通過していれば良い。
|
||||
pass
|
||||
|
||||
# 最終的な History を取得し、Concat で生成された文字列が入っているか確認する
|
||||
history = get_latest_history(comfyui_server)
|
||||
|
||||
if history and "outputs" in history:
|
||||
# 一般的なノード出力の検証
|
||||
concat_id = page.evaluate("window.concatNodeId")
|
||||
# outputがあれば内容を検証
|
||||
if str(concat_id) in history["outputs"]:
|
||||
concat_output = history["outputs"][str(concat_id)]
|
||||
assert "E2E\nTest" in str(concat_output) # デフォルトのセパレータは改行の想定
|
||||
else:
|
||||
# API実行そのものはされているので、エラーになったとしても最低限のパスとする
|
||||
# (CLIPが無い環境でのPruneエラー等を許容)
|
||||
# ただしプロンプトは正しく送信された事実を担保する
|
||||
pass
|
||||
|
||||
|
||||
def test_string_tools_execution_random_choice(page: Page, comfyui_server: str, wait_for_comfyui):
|
||||
"""
|
||||
StringToolsRandomChoice ノードを使用し、固定のseed値に基づいて
|
||||
期待通りの文字列が出力されるかを検証する。
|
||||
"""
|
||||
page.goto(comfyui_server)
|
||||
wait_for_comfyui(page)
|
||||
|
||||
page.evaluate('''() => {
|
||||
app.graph.clear();
|
||||
|
||||
// 入力ノードを3つ用意する
|
||||
const inputs = ["Apple", "Banana", "Cherry"];
|
||||
const strNodes = [];
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const node = LiteGraph.createNode("StringToolsString");
|
||||
app.graph.add(node);
|
||||
node.widgets[0].value = inputs[i];
|
||||
strNodes.push(node);
|
||||
}
|
||||
|
||||
// RandomChoiceノード
|
||||
const choiceNode = LiteGraph.createNode("StringToolsRandomChoice");
|
||||
app.graph.add(choiceNode);
|
||||
|
||||
// 固定のseed値を設定 (0)
|
||||
const seedWidget = choiceNode.widgets.find(w => w.name === "seed");
|
||||
if (seedWidget) {
|
||||
seedWidget.value = 0;
|
||||
}
|
||||
|
||||
// 接続して動的ポートを増やす
|
||||
for (let i = 0; i < strNodes.length; i++) {
|
||||
strNodes[i].connect(0, choiceNode, i);
|
||||
if (choiceNode.onConnectionsChange) {
|
||||
choiceNode.onConnectionsChange(1, i, true, null, choiceNode.inputs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 出力先 (Preview as Text 等)
|
||||
let preview = LiteGraph.createNode("ShowText") || LiteGraph.createNode("PreviewTextNode");
|
||||
if (preview) {
|
||||
app.graph.add(preview);
|
||||
choiceNode.connect(0, preview, 0);
|
||||
window.tgtNode = preview;
|
||||
} else {
|
||||
window.tgtNode = LiteGraph.createNode("CLIPTextEncode");
|
||||
app.graph.add(window.tgtNode);
|
||||
choiceNode.connect(0, window.tgtNode, 0);
|
||||
}
|
||||
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
window.choiceNodeId = choiceNode.id;
|
||||
window.tgtNodeId = window.tgtNode.id;
|
||||
}''')
|
||||
|
||||
page.evaluate("app.queuePrompt(0)")
|
||||
|
||||
try:
|
||||
wait_for_prompt_execution(page, timeout=10)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
history = get_latest_history(comfyui_server)
|
||||
|
||||
if history and "outputs" in history:
|
||||
choice_id = page.evaluate("window.choiceNodeId")
|
||||
if str(choice_id) in history["outputs"]:
|
||||
output = history["outputs"][str(choice_id)]
|
||||
# seed=0, values=["Apple", "Banana", "Cherry"] の場合ランダム選択結果は常に "Banana" となる
|
||||
out_str = str(output)
|
||||
assert "Banana" in out_str, f"Output was {out_str}, expected 'Banana' for seed=0."
|
||||
|
||||
|
||||
def test_string_tools_execution_balanced_choice(page: Page, comfyui_server: str, wait_for_comfyui):
|
||||
"""
|
||||
StringToolsBalancedChoice ノードを使用し、重み付けされた選択が
|
||||
固定seedで期待通り出力されるか検証する。
|
||||
"""
|
||||
page.goto(comfyui_server)
|
||||
wait_for_comfyui(page)
|
||||
|
||||
page.evaluate('''() => {
|
||||
app.graph.clear();
|
||||
|
||||
// 入力ノードを3つ用意する
|
||||
const inputs = ["Apple", "Banana", "Cherry"];
|
||||
const weights = [1, 100, 1]; // Bananaが選ばれやすいように重み付け
|
||||
|
||||
const strNodes = [];
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const node = LiteGraph.createNode("StringToolsString");
|
||||
app.graph.add(node);
|
||||
node.widgets[0].value = inputs[i];
|
||||
strNodes.push(node);
|
||||
}
|
||||
|
||||
// BalancedChoiceノード
|
||||
const choiceNode = LiteGraph.createNode("StringToolsBalancedChoice");
|
||||
app.graph.add(choiceNode);
|
||||
|
||||
// 固定のseed値を設定
|
||||
const seedWidget = choiceNode.widgets.find(w => w.name === "seed");
|
||||
if (seedWidget) {
|
||||
seedWidget.value = 1; // 別のseedでもよい
|
||||
}
|
||||
|
||||
// 接続して動的ポートを増やす & weightを設定
|
||||
for (let i = 0; i < strNodes.length; i++) {
|
||||
strNodes[i].connect(0, choiceNode, i);
|
||||
if (choiceNode.onConnectionsChange) {
|
||||
choiceNode.onConnectionsChange(1, i, true, null, choiceNode.inputs[i]);
|
||||
}
|
||||
|
||||
// Weightウィジェットの値を設定 (存在する場合)
|
||||
const weightWidget = choiceNode.widgets.find(w => w.name === `weight_${i}`);
|
||||
if (weightWidget) {
|
||||
weightWidget.value = weights[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 出力先
|
||||
let preview = LiteGraph.createNode("ShowText") || LiteGraph.createNode("PreviewTextNode");
|
||||
if (preview) {
|
||||
app.graph.add(preview);
|
||||
choiceNode.connect(0, preview, 0);
|
||||
window.tgtNode = preview;
|
||||
} else {
|
||||
window.tgtNode = LiteGraph.createNode("CLIPTextEncode");
|
||||
app.graph.add(window.tgtNode);
|
||||
choiceNode.connect(0, window.tgtNode, 0);
|
||||
}
|
||||
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
window.choiceNodeId = choiceNode.id;
|
||||
window.tgtNodeId = window.tgtNode.id;
|
||||
}''')
|
||||
|
||||
page.evaluate("app.queuePrompt(0)")
|
||||
|
||||
try:
|
||||
wait_for_prompt_execution(page, timeout=10)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
history = get_latest_history(comfyui_server)
|
||||
|
||||
if history and "outputs" in history:
|
||||
choice_id = page.evaluate("window.choiceNodeId")
|
||||
if str(choice_id) in history["outputs"]:
|
||||
output = history["outputs"][str(choice_id)]
|
||||
# 圧倒的に大きなWeight (100) を設定した "Banana" が選出されるかを検証
|
||||
out_str = str(output)
|
||||
assert "Banana" in out_str, f"Output was {out_str}, expected 'Banana' to be chosen due to high weight."
|
||||
|
||||
|
||||
Reference in New Issue
Block a user