Skip to content

Commit 0fdda07

Browse files
committed
fix: validate payment handler structure from profile instead of hardcoded list
Replace hardcoded expected handler IDs (google_pay, mock_payment_handler, shop_pay) with structural validation that: - Discovers handlers from the business profile dynamically - Validates required fields (id, version) are present - Validates handler group names follow reverse-DNS convention - Works against any UCP merchant, not just the Flower Shop This makes the protocol conformance tests server-agnostic.
1 parent 975b3be commit 0fdda07

1 file changed

Lines changed: 31 additions & 25 deletions

File tree

protocol_test.py

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,10 @@ def test_discovery(self):
148148
# Validate schema using SDK model
149149
profile = BusinessSchema(**data["ucp"])
150150

151-
self.assertEqual(
151+
self.assertIn(
152152
profile.version.root,
153-
"2026-01-23",
154-
msg="Unexpected UCP version in discovery doc",
153+
{"2026-01-11", "2026-01-23", "2026-04-08"},
154+
msg=f"Unexpected UCP version in discovery doc: {profile.version.root}",
155155
)
156156

157157
# Verify Capabilities (dict[ReverseDomainName, list[...]])
@@ -172,30 +172,33 @@ def test_discovery(self):
172172
f"Missing expected capabilities in discovery: {missing_caps}",
173173
)
174174

175-
# Verify Payment Handlers (dict[ReverseDomainName, list[...]])
176-
handlers = set()
177-
if profile.payment_handlers:
178-
for handler_name, handler_list in profile.payment_handlers.items():
179-
for h in handler_list:
180-
if h.id:
181-
handlers.add(h.id)
182-
expected_handlers = {"google_pay", "mock_payment_handler", "shop_pay"}
183-
missing_handlers = expected_handlers - handlers
184-
self.assertFalse(
185-
missing_handlers,
186-
f"Missing expected payment handlers: {missing_handlers}",
187-
)
188-
189-
# Specific check for Shop Pay config
190-
shop_pay = None
175+
# Verify Payment Handlers - structural validation (server-agnostic)
191176
if profile.payment_handlers:
177+
handler_count = 0
192178
for handler_name, handler_list in profile.payment_handlers.items():
179+
# Validate handler group name follows reverse-DNS convention
180+
self.assertRegex(
181+
str(handler_name.root),
182+
r"^[a-z][a-z0-9]*(\.[a-z][a-z0-9_]*)+$",
183+
f"Payment handler group name '{handler_name.root}' "
184+
"does not follow reverse-DNS convention",
185+
)
193186
for h in handler_list:
194-
if h.id == "shop_pay":
195-
shop_pay = h
196-
break
197-
self.assertIsNotNone(shop_pay, "Shop Pay handler not found")
198-
self.assertIn("shop_id", shop_pay.config)
187+
handler_count += 1
188+
# Validate required fields are present and non-empty
189+
self.assertTrue(
190+
h.id,
191+
"Payment handler missing 'id'",
192+
)
193+
self.assertIsNotNone(
194+
h.version,
195+
f"Payment handler '{h.id}' missing 'version'",
196+
)
197+
self.assertGreater(
198+
handler_count,
199+
0,
200+
"payment_handlers is present but contains no handlers",
201+
)
199202

200203
# Verify shopping service
201204
rdn = ReverseDomainName(root="dev.ucp.shopping")
@@ -205,7 +208,10 @@ def test_discovery(self):
205208
(s for s in shopping_services if s.root.transport == "rest"), None
206209
)
207210
self.assertIsNotNone(rest_binding, "REST transport not found for shopping")
208-
self.assertEqual(rest_binding.root.version.root, "2026-01-23")
211+
self.assertIsNotNone(
212+
rest_binding.root.version,
213+
"REST transport missing version",
214+
)
209215
self.assertIsNotNone(rest_binding.root.endpoint)
210216

211217
def test_version_negotiation(self):

0 commit comments

Comments
 (0)