87 lines
4.3 KiB
Python
87 lines
4.3 KiB
Python
"""Check Impact widget restoration in the four original AnimateDiff tutorial PNGs.
|
|
|
|
Set IMPACT_TUTORIALS_DIR to ComfyUI-extension-tutorials. This checks native
|
|
PNG import and JSON export/reload in both restoration modes, without inference.
|
|
Missing external nodes are recorded; the Impact nodes under test must be real.
|
|
"""
|
|
import hashlib
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import tempfile
|
|
|
|
from PIL import Image
|
|
|
|
from e2e_ui import browser_session, options
|
|
from test_e2e_widget_catalog import WIDGETS, export_workflow, full_zoom, setting, show_node, widget_state
|
|
|
|
|
|
WORKFLOWS = ["cinemagraph", "detailer-for-animatediff", "MakeTileSEGS_upscale_AnimateDiff",
|
|
"MakeTileSEGS_upscale_AnimateDiff_ControlNet"]
|
|
TYPES = {"SEGSDetailerForAnimateDiff", "DetailerForEachPipeForAnimateDiff", "SEGSPaste",
|
|
"MaskToSEGS", "ImpactSimpleDetectorSEGS_for_AD", "ImpactMakeTileSEGS",
|
|
"ImpactControlNetApplySEGS", "PreviewDetailerHookProvider"}
|
|
|
|
|
|
def check_widgets(ui, expected):
|
|
full_zoom(ui)
|
|
for node in expected:
|
|
show_node(ui, node["id"])
|
|
actual = widget_state(ui, node["id"])
|
|
assert json.dumps(actual, sort_keys=True) == json.dumps(node, sort_keys=True), (actual, node)
|
|
|
|
|
|
def main():
|
|
args = options(__doc__)
|
|
tutorials = Path(os.environ.get("IMPACT_TUTORIALS_DIR",
|
|
Path(__file__).resolve().parents[4] / "ComfyUI-extension-tutorials"))
|
|
catalog = {node["type"]: node["widgets"] for node in json.loads(WIDGETS.read_text())["nodes"]}
|
|
artifacts = args.artifacts or Path(tempfile.mkdtemp(prefix="impact-animatediff-tutorials-"))
|
|
for name in WORKFLOWS:
|
|
path = tutorials / "ComfyUI-Impact-Pack/workflow" / f"{name}.png"
|
|
with Image.open(path) as image:
|
|
workflow = json.loads(image.info["workflow"])
|
|
expected = []
|
|
for node in workflow["nodes"]:
|
|
if node["type"] not in TYPES:
|
|
continue
|
|
# Names/order and defaults come from the unchanged trusted catalog;
|
|
# saved values come from the original PNG, never the current runtime.
|
|
widgets = [dict(widget) for widget in catalog[node["type"]]]
|
|
saved = node["widgets_values"]
|
|
assert len(saved) <= len(widgets)
|
|
for widget, value in zip(widgets, saved):
|
|
widget["value"] = value
|
|
expected.append(dict(id=str(node["id"]), type=node["type"], widgets=widgets))
|
|
assert any(node["type"] in {"SEGSDetailerForAnimateDiff", "DetailerForEachPipeForAnimateDiff"} for node in expected)
|
|
for restore_by_name in (False, True):
|
|
label = f"{name}-{'named' if restore_by_name else 'positional'}"
|
|
args.artifacts = artifacts / label
|
|
result_path = args.artifacts / "result.json"
|
|
result_path.unlink(missing_ok=True)
|
|
with browser_session(args) as ui:
|
|
ui.page.keyboard.press("Escape")
|
|
setting(ui, "Restore widget values", "Comfy.Workflow.NamedValuesRestore", restore_by_name)
|
|
ui.new_workflow()
|
|
ui.load_workflow(path, len(workflow["nodes"]), check_node_errors=False)
|
|
check_widgets(ui, expected)
|
|
missing = ui.app.evaluate("""app => app.graph._nodes.filter(node =>
|
|
!LiteGraph.registered_node_types[node.type]).map(node => node.type)""")
|
|
assert not TYPES.intersection(missing)
|
|
# Export through the native UI; no hand-built workflow JSON.
|
|
exported = args.artifacts / "exported.json"
|
|
export_workflow(ui, exported)
|
|
ui.new_workflow()
|
|
ui.load_workflow(exported, len(workflow["nodes"]), check_node_errors=False)
|
|
check_widgets(ui, expected)
|
|
report = dict(source=str(path), sha256=hashlib.sha256(path.read_bytes()).hexdigest(),
|
|
restore_by_name=restore_by_name, widgets=expected, missing_external_nodes=missing,
|
|
png_import=True, native_export_reload=True, inference=False)
|
|
# Session exit also checks browser errors and trace/close failures.
|
|
result_path.write_text(json.dumps(report, indent=2) + "\n")
|
|
print(f"PASS: {label}, {len(expected)} Impact nodes, original PNG and native JSON reload", flush=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|