mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-07-31 04:01:24 +08:00
146 lines
5.2 KiB
Python
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()
|