Refresh label-filter hook catalog after removing SEGS input
Recreate the hook through Chrome node search and native Export, preserving every expected widget name, order and value. Cover fresh and legacy hook execution with both native restoration modes. Validation: all 16 catalog E2E tests passed on the identical source tree; native Export also normalizes MaskRectArea height from 356 to 358.
This commit is contained in:
@@ -183,6 +183,16 @@ Two direct-creation cases also check that label-filter presets start at `all`,
|
||||
append a selected label to the text field, and retain both values after export
|
||||
and reload.
|
||||
|
||||
The label-filter hook execution cases connect the hook to Preview as Text and
|
||||
click Run before and after native export/reload, in both widget restoration
|
||||
modes. They cover freshly created nodes without a `segs` input and the native
|
||||
`label-filter-hook-legacy.json` fixture exported before PR #1218, which retains
|
||||
the obsolete unconnected input. The selected preset, label text, widget order,
|
||||
and positional saved values must survive loading while hook creation succeeds.
|
||||
The all-node catalog replaces that legacy node through Chrome deletion, node
|
||||
search, and native Export; its widget snapshot changes only the replacement
|
||||
node's ID and record position, preserving every expected widget name and value.
|
||||
|
||||
Branching tests connect Inversed Switch through three distinct image operations
|
||||
back into Switch, including both legacy names. Selection changes through the UI
|
||||
must produce the expected pixels and final output, including after reimport.
|
||||
|
||||
@@ -207,6 +207,8 @@ def test_catalog_contains_every_registered_node():
|
||||
for widget in node["widgets"]:
|
||||
assert set(widget) == {"name", "value"}
|
||||
assert isinstance(widget["name"], str)
|
||||
label_hook = next(node for node in workflow["nodes"] if node["type"] == "SEGSLabelFilterDetailerHookProvider")
|
||||
assert label_hook["inputs"] == [], "Recreate the label-filter hook to remove its obsolete SEGS input"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -253,6 +255,52 @@ def test_label_preset_initial_value_and_selection(ui, node_type):
|
||||
assert_catalog(browser, [before])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("restore_by_name", [False, True], ids=["positional", "named"])
|
||||
@pytest.mark.parametrize("legacy", [False, True], ids=["fresh", "legacy-segs-input"])
|
||||
def test_label_filter_hook_executes_after_native_load(ui, restore_by_name, legacy):
|
||||
browser, args = ui
|
||||
node_type = "SEGSLabelFilterDetailerHookProvider"
|
||||
expected_widgets = [{"name": "preset", "value": "person"},
|
||||
{"name": "labels", "value": "person, dog"}]
|
||||
setting(browser, "Restore widget values", "Comfy.Workflow.NamedValuesRestore", restore_by_name)
|
||||
browser.new_workflow()
|
||||
if legacy:
|
||||
browser.load_workflow(ROOT / "tests/workflows/label-filter-hook-legacy.json", 2)
|
||||
node_id = browser.app.evaluate("""(app, type) =>
|
||||
String(app.graph._nodes.find(node => node.type === type).id)
|
||||
""", node_type)
|
||||
else:
|
||||
full_zoom(browser)
|
||||
definitions = node_definitions(browser)
|
||||
node_id = browser.add_node(definitions[node_type]["display_name"], node_type, 250, 180)
|
||||
browser.choose(node_type, "preset", "person")
|
||||
browser.page.get_by_placeholder(
|
||||
"List the types of segments to be allowed, separated by commas", exact=True
|
||||
).fill("person, dog")
|
||||
assert "segs" not in browser.app.evaluate("""(app, id) =>
|
||||
app.graph.getNodeById(id).inputs.map(input => input.name)
|
||||
""", node_id)
|
||||
browser.add_node("Preview as Text", "PreviewAny", 850, 180)
|
||||
browser.connect(node_type, "PreviewAny")
|
||||
|
||||
path = args.artifacts / "label-filter-hook.json"
|
||||
for reloaded in (False, True):
|
||||
if reloaded:
|
||||
browser.new_workflow()
|
||||
browser.load_workflow(path, 2)
|
||||
full_zoom(browser)
|
||||
show_node(browser, node_id)
|
||||
assert widget_state(browser, node_id)["widgets"] == expected_widgets
|
||||
entry = browser.run()
|
||||
text = next(output["text"] for output in entry["outputs"].values() if "text" in output)
|
||||
assert len(text) == 1 and "SEGSLabelFilterDetailerHook object" in text[0]
|
||||
if not reloaded:
|
||||
export_workflow(browser, path)
|
||||
saved = next(node for node in json.loads(path.read_text())["nodes"] if node["type"] == node_type)
|
||||
assert saved["widgets_values"] == ["person", "person, dog"]
|
||||
assert saved["widgets_values_named"] == {"preset": "person", "labels": "person, dog"}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mutation", [
|
||||
"this.widgets[0].name = 'guide_size_broken';",
|
||||
"[this.widgets[0], this.widgets[2]] = [this.widgets[2], this.widgets[0]];",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1710,20 +1710,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "58",
|
||||
"type": "SEGSLabelFilterDetailerHookProvider",
|
||||
"widgets": [
|
||||
{
|
||||
"name": "preset",
|
||||
"value": "all"
|
||||
},
|
||||
{
|
||||
"name": "labels",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "59",
|
||||
"type": "VariationNoiseDetailerHookProvider",
|
||||
@@ -3969,6 +3955,20 @@
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "198",
|
||||
"type": "SEGSLabelFilterDetailerHookProvider",
|
||||
"widgets": [
|
||||
{
|
||||
"name": "preset",
|
||||
"value": "all"
|
||||
},
|
||||
{
|
||||
"name": "labels",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"id": "16e4d8a1-d7cc-4dfa-a95e-bb8f5f5b21c9",
|
||||
"revision": 0,
|
||||
"last_node_id": 2,
|
||||
"last_link_id": 1,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "SEGSLabelFilterDetailerHookProvider",
|
||||
"pos": [
|
||||
-277.1111111111111,
|
||||
135.55555555555554
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
200
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "segs",
|
||||
"type": "SEGS",
|
||||
"link": null
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "DETAILER_HOOK",
|
||||
"type": "DETAILER_HOOK",
|
||||
"links": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SEGSLabelFilterDetailerHookProvider"
|
||||
},
|
||||
"widgets_values": [
|
||||
"person",
|
||||
"person, dog"
|
||||
],
|
||||
"widgets_values_named": {
|
||||
"preset": "person",
|
||||
"labels": "person, dog"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewAny",
|
||||
"pos": [
|
||||
417.8888888888889,
|
||||
135.55555555555554
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
122
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "source",
|
||||
"type": "*",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewAny"
|
||||
},
|
||||
"widgets_values": [],
|
||||
"widgets_values_named": {}
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"DETAILER_HOOK"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1,
|
||||
"offset": [
|
||||
327.1111111111111,
|
||||
54.44444444444446
|
||||
]
|
||||
},
|
||||
"frontendVersion": "1.57.6"
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
Reference in New Issue
Block a user