afv-library/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_invocation_target.py
2026-06-12 10:55:46 +00:00

146 lines
5.2 KiB
Python

"""Tests for resolve_invocation_target.resolve_target_id never raises,
and `resolve_or_unresolved` records unknown prefixes + invalid shapes into
`_unresolved[]` so the wave orchestrator can keep running when Salesforce
ships a new NGA target type.
"""
from __future__ import annotations
import unittest
from . import _bootstrap # noqa: F401
import resolve_invocation_target as rit # type: ignore
# A valid-shape Salesforce Id is 15 or 18 alphanumeric chars. Prefixes below
# are chosen to avoid collision with _PREFIX_MAP so they exercise the
# "unknown prefix" path.
_APEX_ID_15 = "01p0000000ABC12"
_APEX_ID_18 = "01p0000000ABC12AAA"
_FLOW_DEF_ID_15 = "3000000000XYZ99"
_FLOW_VER_ID_15 = "3010000000XYZ99"
_PROMPT_ID_15 = "0hf0000000QRS77"
_UNKNOWN_PREFIX_ID_15 = "0aN000000000XYZ"
class KnownPrefixTests(unittest.TestCase):
def test_apex_prefix(self):
self.assertEqual(rit.resolve_target_id(_APEX_ID_15), ("apex", "tooling_soql"))
def test_flow_definition_prefix(self):
self.assertEqual(
rit.resolve_target_id(_FLOW_DEF_ID_15),
("flow_definition", "tooling_soql"),
)
def test_flow_version_prefix(self):
self.assertEqual(
rit.resolve_target_id(_FLOW_VER_ID_15),
("flow_version", "tooling_soql"),
)
def test_prompt_template_prefix(self):
self.assertEqual(
rit.resolve_target_id(_PROMPT_ID_15),
("prompt_template", "retrieve_required"),
)
def test_eighteen_char_id_works(self):
self.assertEqual(
rit.resolve_target_id(_APEX_ID_18),
("apex", "tooling_soql"),
)
class UnknownPrefixTests(unittest.TestCase):
def test_resolve_target_id_never_raises(self):
# Unknown prefix → ("unknown", "skip"), no exception.
self.assertEqual(
rit.resolve_target_id(_UNKNOWN_PREFIX_ID_15),
("unknown", "skip"),
)
def test_resolve_or_unresolved_records_unknown_prefix(self):
unresolved: list[dict] = []
result = rit.resolve_or_unresolved(_UNKNOWN_PREFIX_ID_15, unresolved)
self.assertEqual(result, ("unknown", "skip"))
self.assertEqual(len(unresolved), 1)
entry = unresolved[0]
self.assertEqual(entry["id"], _UNKNOWN_PREFIX_ID_15)
self.assertEqual(entry["reason"], "unknown-id-prefix:0aN")
def test_known_prefix_does_not_touch_unresolved(self):
unresolved: list[dict] = []
result = rit.resolve_or_unresolved(_APEX_ID_15, unresolved)
self.assertEqual(result, ("apex", "tooling_soql"))
self.assertEqual(unresolved, [])
class InvalidShapeTests(unittest.TestCase):
def test_empty_string(self):
unresolved: list[dict] = []
result = rit.resolve_or_unresolved("", unresolved)
self.assertEqual(result, ("unknown", "skip"))
self.assertEqual(len(unresolved), 1)
self.assertEqual(unresolved[0]["reason"], "invalid-id-format")
self.assertEqual(unresolved[0]["id"], "")
def test_none_coerced_via_str(self):
unresolved: list[dict] = []
result = rit.resolve_or_unresolved(None, unresolved)
self.assertEqual(result, ("unknown", "skip"))
self.assertEqual(len(unresolved), 1)
self.assertEqual(unresolved[0]["reason"], "invalid-id-format")
self.assertEqual(unresolved[0]["id"], "None")
def test_wrong_length_is_invalid(self):
# A 10-char id-like string is not 15 or 18 — invalid shape, not
# an unknown prefix.
unresolved: list[dict] = []
rit.resolve_or_unresolved("01pABC1234", unresolved)
self.assertEqual(len(unresolved), 1)
self.assertEqual(unresolved[0]["reason"], "invalid-id-format")
def test_bad_chars_rejected(self):
# 15-char length but contains punctuation — not an Id shape.
unresolved: list[dict] = []
rit.resolve_or_unresolved("01p!!!!!!!!!!99", unresolved)
self.assertEqual(len(unresolved), 1)
self.assertEqual(unresolved[0]["reason"], "invalid-id-format")
def test_short_string_is_invalid(self):
unresolved: list[dict] = []
rit.resolve_or_unresolved("ab", unresolved)
self.assertEqual(len(unresolved), 1)
self.assertEqual(unresolved[0]["reason"], "invalid-id-format")
class RegisteredPrefixesTests(unittest.TestCase):
def test_exact_membership(self):
self.assertEqual(
rit.REGISTERED_PREFIXES,
frozenset({"01p", "300", "301", "0hf"}),
)
def test_is_frozenset(self):
"""Immutable so callers can't accidentally corrupt the table."""
self.assertIsInstance(rit.REGISTERED_PREFIXES, frozenset)
class ResolveTargetIdRobustnessTests(unittest.TestCase):
"""`resolve_target_id` is the lower-level helper — it must also never
raise, even on garbage input."""
def test_none_input(self):
self.assertEqual(rit.resolve_target_id(None), ("unknown", "skip")) # type: ignore[arg-type]
def test_empty_string(self):
self.assertEqual(rit.resolve_target_id(""), ("unknown", "skip"))
def test_too_short(self):
self.assertEqual(rit.resolve_target_id("ab"), ("unknown", "skip"))
if __name__ == "__main__":
unittest.main()