Files
ComfyAssets-ComfyUI_PromptM…/tests/test_pair_output_roles.py
Vito caa9649f32 feat: reuse positive and negative prompt combinations (#195)
* feat(db): add pair schema and stage restore migrations for #193

* feat(database): persist reusable ordered prompt pairs (#193)

* feat(api): expose reusable pairs and atomic metadata enrichment (#193)

* feat(metadata): resolve canonical prompt pairs with bounded provenance (#193)

* feat(scan): enrich image pairs without guessing or duplicate links (#193)

* fix(database): preserve pair tags during global maintenance (#193)

* feat(tracking): enrich live image pairs and cancel scans safely (#193)

* feat(nodes): encode paired prompts and count cached recipe runs (#193)

* fix(database): validate restored pair ownership and provenance (#193)

* feat(admin): report pair scan outcomes and cancellation (#193)

* feat(ui): add paired prompt editor and explicit recipe library for #193

* fix(autocomplete): include reusable pair metadata vocabulary (#193)

* fix(pairs): honor recent sorting and conservative scan outcomes (#193)

* fix(ui): protect paired draft saves and clarify negative variants (#193)

* fix(metadata): preserve bounded paired execution evidence (#193)

* fix(tracking): follow actual pair output roles and prefer execution evidence (#193)

* docs(pairs): document live validation and retain renderer screenshots (#193)

* test(api): inject disposable databases before API startup (#194)

* test(api): canonicalize portable temporary gallery roots (#194)

* docs(ui): prototype branching negative variant history (#193)

* docs(ui): show selected negative beneath positive in timeline concept (#193)

* docs: retain approved timeline for later gallery redesign (#193)

* test(db): close restore fixture connections before cleanup (#194)

* test(db): reuse existing handle guards in all pair fixtures (#194)

* chore: clarify rollback test and intentional exception handling (#193)
2026-10-17 08:00:42 -07:00

84 lines
3.0 KiB
Python

"""Actual sampler wires determine which component counts as its positive text."""
import unittest
from utils.hashing import generate_prompt_hash
from utils.usage_tracking import queued_prompt_runs, queued_pair_runs
def paired_graph(positive_slot=0, negative_slot=1):
return {
"1": {
"class_type": "PromptManagerPair",
"inputs": {"text": "cat", "negative_text": "blur"},
},
"2": {
"class_type": "KSampler",
"inputs": {
"model": ["3", 0],
"positive": ["1", positive_slot],
"negative": ["1", negative_slot],
},
},
}
class TestPairOutputRoles(unittest.TestCase):
def test_swapped_conditioning_counts_actual_positive_component_only(self):
graph = paired_graph(1, 0)
self.assertEqual(
queued_prompt_runs(graph), [(generate_prompt_hash("blur"), "blur")]
)
self.assertEqual(queued_pair_runs(graph), [])
def test_negative_string_encoded_as_positive_counts_actual_string_component(self):
graph = paired_graph()
graph["4"] = {"class_type": "CLIPTextEncode", "inputs": {"text": ["1", 3]}}
graph["2"]["inputs"]["positive"] = ["4", 0]
self.assertEqual(
queued_prompt_runs(graph), [(generate_prompt_hash("blur"), "blur")]
)
self.assertEqual(queued_pair_runs(graph), [])
def test_two_sampler_positive_roles_count_each_component_once(self):
graph = paired_graph()
graph["5"] = {
"class_type": "KSampler",
"inputs": {"model": ["3", 0], "positive": ["1", 1], "negative": ["1", 0]},
}
self.assertEqual(
{text for _, text in queued_prompt_runs(graph)}, {"cat", "blur"}
)
class TestPairRoleExecution(unittest.TestCase):
def setUp(self):
from tests.test_prompt_pair_node import TestPromptPairNode
TestPromptPairNode.setUp(self)
def test_new_swapped_component_consumes_its_queued_pending_use(self):
self.node.pending_first_use.add(generate_prompt_hash("blur"))
self.node.encode_prompt(
self.clip, "cat", "blur", prompt=paired_graph(1, 0), unique_id="1"
)
pair = self.db.list_prompt_pairs()["pairs"][0]
self.assertEqual(
self.db.get_prompt_by_id(pair["negative_prompt_id"])["run_count"], 1
)
self.assertEqual(
self.db.get_prompt_by_id(pair["positive_prompt_id"])["run_count"], 0
)
self.assertEqual(pair["run_count"], 0)
def test_unknown_negative_link_used_as_positive_counts_at_execution(self):
graph = paired_graph(1, 0)
graph["1"]["inputs"]["negative_text"] = ["8", 0]
graph["8"] = {"class_type": "UnknownBatch", "inputs": {}}
self.node.encode_prompt(self.clip, "cat", "blur", prompt=graph, unique_id="1")
pair = self.db.list_prompt_pairs()["pairs"][0]
self.assertEqual(
self.db.get_prompt_by_id(pair["negative_prompt_id"])["run_count"], 1
)
self.assertEqual(pair["run_count"], 0)