Critical security fixes ----------------------- - Sandbox Jinja2 in template_render + prompt_template_render (was RCE via shared workflows) - Drop user home dir from filesystem allow-list (was arbitrary delete/overwrite) - Confine save_image_with_manifest + sanitize filename basename - SSRF block on http_get/http_post/notify_webhook (catches 169.254.169.254 metadata) - Case-insensitive path confinement on Windows Critical correctness/perf ------------------------- - halftone_dots: O(N^2) -> O(cells*36); was freezing worker on 1024+ images - Preserve latent dict keys (noise_mask, batch_index) in latent_math/noise/upscale - Preserve alpha channel in invert + threshold_binary on RGBA inputs - Force odd kernel in mask_erode/mask_dilate to prevent H+1 shape mismatch - Snap aspect_ratio_pick output to multiples of 8 (was crashing SD UNet) Theme engine (JS) ----------------- - Hoist window.matchMedia() out of per-frame hot path -> recovers 200 FPS from 25 - Wrap-once draw method to stop stomping other extensions wrappers - nodeRemoved hook + WeakMap groups + in-place canvas reuse -> three memory leaks closed - Wire thickness now uses connections_width (the wrap was a no-op vs LiteGraph) - onGroupAdded auto-themes new groups; budget change triggers redraw - Gradient caching in synthwave/glassmorphic New ops (10) ------------ - json_path (programming): dotted/bracketed path extract - latent_nan_guard, latent_pad_crop (mask_latent) - mask_from_depth, mask_invert (mask_latent) - color_match_histogram, image_composite_over (image_pro/value) - frequency_separation (image_pro/style) - pad_to_multiple (image_pro/spatial) - save_images_zip (io_workflow) - llm_enhance_prompt via Ollama / LM Studio / llama.cpp (prompt) Theme UX -------- - Right-click "Theme..." submenu on every node (including vanilla ComfyUI nodes) - Auto-contrast title text (WCAG AA-based flip) Tests: 373 Python + 33 JS = 406 passing (added 33 new tests for security + features). Full review notes in CHANGELOG.md.
69 lines
2.0 KiB
Python
69 lines
2.0 KiB
Python
"""End-to-end integration tests for PromptNode."""
|
|
|
|
import importlib.util
|
|
import pathlib
|
|
|
|
import pytest
|
|
|
|
PACKAGE_ROOT = pathlib.Path(__file__).resolve().parent.parent.parent
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def pkg():
|
|
spec = importlib.util.spec_from_file_location(
|
|
"megapack_pkg",
|
|
PACKAGE_ROOT / "__init__.py",
|
|
)
|
|
mod = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(mod)
|
|
return mod
|
|
|
|
|
|
def test_prompt_node_registered(pkg):
|
|
assert "UtilMegaPack_Prompt" in pkg.NODE_CLASS_MAPPINGS
|
|
assert pkg.NODE_DISPLAY_NAME_MAPPINGS["UtilMegaPack_Prompt"] == "Prompt"
|
|
|
|
|
|
def test_prompt_node_has_four_outputs(pkg):
|
|
NodeCls = pkg.NODE_CLASS_MAPPINGS["UtilMegaPack_Prompt"]
|
|
assert NodeCls.RETURN_TYPES == ("STRING", "STRING", "LIST", "INT")
|
|
assert NodeCls.RETURN_NAMES == ("prompt", "negative", "all_prompts", "token_count")
|
|
|
|
|
|
def test_prompt_node_lists_ops(pkg):
|
|
NodeCls = pkg.NODE_CLASS_MAPPINGS["UtilMegaPack_Prompt"]
|
|
schema = NodeCls.INPUT_TYPES()
|
|
options, _ = schema["required"]["mode"]
|
|
# Lower bound — new ops are additive, exact equality was a brittle assertion.
|
|
assert len(options) >= 9, f"expected >=9 ops, got {len(options)}"
|
|
|
|
|
|
def test_prompt_node_smoke_one_per_op_type(pkg):
|
|
NodeCls = pkg.NODE_CLASS_MAPPINGS["UtilMegaPack_Prompt"]
|
|
node = NodeCls()
|
|
|
|
# batch
|
|
assert node.process(
|
|
mode="prompt_batch_pick", theme="(use pack default)",
|
|
prompts="a\nb\nc", index=0,
|
|
)[0] == "a"
|
|
|
|
# mix
|
|
assert node.process(
|
|
mode="prompt_mix", theme="(use pack default)",
|
|
a="cat", weight_a=1.0, b="dog", weight_b=1.0,
|
|
)[0] == "(cat:1.00) (dog:1.00)"
|
|
|
|
# negative auto build
|
|
out = node.process(
|
|
mode="negative_auto_build", theme="(use pack default)",
|
|
positive="x", preset="realistic",
|
|
)
|
|
assert "blurry" in out[1]
|
|
|
|
# token count
|
|
assert node.process(
|
|
mode="token_count", theme="(use pack default)",
|
|
text="hello world",
|
|
)[3] == 2
|