Add node runtime contract smoke
This commit is contained in:
@@ -5998,6 +5998,69 @@ def smoke_formatter_metadata_fixtures() -> None:
|
||||
_expect("coworking lounge" in caption_text, "Generated training caption lost scene metadata")
|
||||
|
||||
|
||||
def _expect_comfy_input_spec(node_name: str, group: str, input_name: str, spec: Any) -> None:
|
||||
_expect(isinstance(input_name, str) and input_name, f"{node_name}.{group} has invalid input name {input_name!r}")
|
||||
if group == "hidden":
|
||||
_expect(
|
||||
isinstance(spec, (str, tuple)),
|
||||
f"{node_name}.{input_name} hidden input should be a ComfyUI hidden token or tuple",
|
||||
)
|
||||
return
|
||||
|
||||
_expect(isinstance(spec, tuple) and spec, f"{node_name}.{input_name} visible input has invalid spec")
|
||||
type_spec = spec[0]
|
||||
_expect(
|
||||
isinstance(type_spec, str) or isinstance(type_spec, list),
|
||||
f"{node_name}.{input_name} input type should be a socket type or choices list",
|
||||
)
|
||||
if isinstance(type_spec, list):
|
||||
_expect(type_spec, f"{node_name}.{input_name} choice list should not be empty")
|
||||
_expect(len(spec) >= 2 and isinstance(spec[1], dict), f"{node_name}.{input_name} visible input options should be a dict")
|
||||
_expect("tooltip" in spec[1], f"{node_name}.{input_name} visible input is missing tooltip")
|
||||
|
||||
|
||||
def smoke_node_runtime_contracts() -> None:
|
||||
node_names = sorted(sxcp_nodes.NODE_CLASS_MAPPINGS)
|
||||
_expect(node_names, "Node registry is empty")
|
||||
_expect(
|
||||
set(sxcp_nodes.NODE_CLASS_MAPPINGS) == set(sxcp_nodes.NODE_DISPLAY_NAME_MAPPINGS),
|
||||
"Node class and display registries are out of sync",
|
||||
)
|
||||
_expect(len(node_names) >= 50, "Node registry unexpectedly small")
|
||||
|
||||
for node_name in node_names:
|
||||
node_class = sxcp_nodes.NODE_CLASS_MAPPINGS[node_name]
|
||||
display_name = sxcp_nodes.NODE_DISPLAY_NAME_MAPPINGS.get(node_name)
|
||||
_expect(isinstance(display_name, str) and display_name, f"{node_name} has no display name")
|
||||
|
||||
input_types = node_class.INPUT_TYPES()
|
||||
_expect(isinstance(input_types, dict), f"{node_name}.INPUT_TYPES should return a dict")
|
||||
_expect("required" in input_types, f"{node_name}.INPUT_TYPES lost required group")
|
||||
for group, inputs in input_types.items():
|
||||
_expect(group in {"required", "optional", "hidden"}, f"{node_name}.INPUT_TYPES has unknown group {group!r}")
|
||||
_expect(isinstance(inputs, dict), f"{node_name}.{group} inputs should be a dict")
|
||||
for input_name, spec in inputs.items():
|
||||
_expect_comfy_input_spec(node_name, group, input_name, spec)
|
||||
|
||||
return_types = getattr(node_class, "RETURN_TYPES", None)
|
||||
_expect(isinstance(return_types, tuple) and return_types, f"{node_name}.RETURN_TYPES should be a non-empty tuple")
|
||||
for output_type in return_types:
|
||||
_expect(isinstance(output_type, str) and output_type, f"{node_name}.RETURN_TYPES contains an invalid output type")
|
||||
|
||||
return_names = getattr(node_class, "RETURN_NAMES", None)
|
||||
if return_names is not None:
|
||||
_expect(isinstance(return_names, tuple), f"{node_name}.RETURN_NAMES should be a tuple when present")
|
||||
_expect(len(return_names) == len(return_types), f"{node_name}.RETURN_NAMES length does not match RETURN_TYPES")
|
||||
for output_name in return_names:
|
||||
_expect(isinstance(output_name, str) and output_name, f"{node_name}.RETURN_NAMES contains an invalid name")
|
||||
|
||||
function_name = getattr(node_class, "FUNCTION", None)
|
||||
_expect(isinstance(function_name, str) and function_name, f"{node_name}.FUNCTION should name the executor method")
|
||||
_expect(callable(getattr(node_class(), function_name, None)), f"{node_name}.FUNCTION target is not callable")
|
||||
category = getattr(node_class, "CATEGORY", None)
|
||||
_expect(isinstance(category, str) and category, f"{node_name}.CATEGORY should be a non-empty string")
|
||||
|
||||
|
||||
def smoke_node_utility_registration() -> None:
|
||||
required_nodes = [
|
||||
"SxCPGlobalSeed",
|
||||
@@ -7100,6 +7163,7 @@ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
|
||||
("fallback_role_graph_routes", smoke_fallback_role_graph_routes),
|
||||
("expression_disabled", smoke_no_expression_fallback),
|
||||
("formatter_metadata_fixtures", smoke_formatter_metadata_fixtures),
|
||||
("node_runtime_contracts", smoke_node_runtime_contracts),
|
||||
("node_utility_registration", smoke_node_utility_registration),
|
||||
("server_route_payload_policy", smoke_server_route_payload_policy),
|
||||
("seed_config_policy", smoke_seed_config_policy),
|
||||
|
||||
Reference in New Issue
Block a user