Playwright full-flow: assert payment actually settles + exercise the KYC route#108
Merged
Conversation
…UI scaffolding
The full-flow playwright suite was passing on a backend that returned errors:
1. Step 12 asserted only `#pos-status` visible + non-empty. moonlight-pay
writes both success and failure text into that element, so "Payment
processing failed: 500" was an unconditional green.
2. Step 13 asserted "merchant page has #balance-display OR #tx-list
visible" — both are UI scaffolding present on a freshly-loaded page,
regardless of whether any payment landed.
3. The `beforeAll` cleanup tried to TRUNCATE pay-platform tables via
`execSync("psql …")` — psql isn't in the test-runner container, so the
cleanup silently no-op'd with "DB cleanup skipped (psql not available)".
Deterministic keys + uncleaned `council_pps` left stale PP rows that
pay-platform randomly picked, 500'ing half the time.
4. Step 8 filled `#pp-pk` with `profiles.provider.publicKey` — the
operator wallet pubkey, not the derived PP keypair the operator's
provider-console flow actually registers. pay-platform stored the wrong
key and instant-execute's bundle submission 500'd with "PP not found
or inactive".
5. provider-platform's add-bundle gates on the submitter's entity row
being APPROVED. pay-platform's pay-service identity auto-creates as
UNVERIFIED via SEP-10 first-time auth and is never promoted — bundle
submission would 403 if the right PP got picked. The loose Step 12
assertion hid this entirely.
Fixes:
* Replace the execSync(psql) cleanup with a node-pg client
(helpers/db.ts:cleanupPayPlatformDb) that authoritatively truncates
`councils`, `pay_accounts`, AND `council_pps`. Adds `pg` + `@types/pg`
to playwright/package.json.
* helpers/db.ts:fetchActivePpPublicKey() discovers the derived PP pubkey
from provider-platform's DB after Step 4. New Step 6b fills it for
later use, and Step 8 fills `#pp-pk` with it instead of the operator
pubkey.
* Step 6b also registers pay-service as APPROVED via a new
helpers/register-entity.ts (the SEP-43/raw signed-challenge flow
matching provider-platform's POST /providers/:pp/entities). Mirrors
what a real deployment seeds at install time.
* New Step 13b exercises the public KYC route at
#/entities/register?provider=<pp_pk> end-to-end (POS user wallet,
Stellar Wallets Kit modal, signed-challenge submission, success card).
Independent of the payment flow; smokes the new UI added in
provider-console#37.
* Step 12 now reads `#pos-status` text and fails on
`failed|reject|error|expired|insufficient`. Step 13 queries
pay-platform's `transactions` table directly for a COMPLETED IN
transaction for the merchant — protocol-level proof that the bundle
landed, not just that UI scaffolding rendered.
Net result: the suite that previously passed against a backend silently
500'ing now actually verifies the payment settles end-to-end.
…e KYC UI Previously Step 6b registered pay-service via a direct fetch(/providers/:pp/entities/challenge) → sign → POST /entities call — faster but it bypassed the very route this PR exists to validate. Move the registration onto the public KYC route at provider-console#/entities/register?provider=<pp> so Step 6b exercises the real flow: Stellar Wallets Kit modal → Freighter sign-challenge popup → name submission → success card. * helpers/keys.ts adds the pay-service identity to DerivedProfiles. The ROLES enum already exposed PAY_SERVICE; only the profile return was missing. * The full-flow test creates a payServiceCtx in beforeAll (its own Chromium + Freighter, Friendbot-funded by createUserContext) and closes it in afterAll. * Step 6b now opens a page in payServiceCtx, navigates to the KYC route, drives the modal-then-popup approval pattern Step 12 already uses, and asserts the success card renders. * Step 13b (the previous POS-user UI smoke) is removed — Step 6b now covers the same UI path with a more meaningful identity (the bundle submitter), so 13b became redundant. * helpers/register-entity.ts (API-direct SEP-43/raw flow) is removed — no remaining consumers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#/entities/register?provider=<ppPubkey>) introduced by Migrate all per-PP API calls to URL-scoped paths + KYC submission route provider-console#37: connect Freighter → sign SEP-43/raw challenge → submit name → success card.council_ppsaccumulation, and a wrong-pubkey fill in Step 8.Bugs the loose assertions hid
#pos-statusvisible + non-empty. moonlight-pay writes BOTH success and failure text into that element.pay-platform.transactionsfor a COMPLETED IN row withwallet_public_key = merchant.publicKeyand assertssum(amount_stroops) > 0.beforeAllusedexecSync("psql …")to truncate stale rows — psql isn't in the test-runner container, the call no-op'd ("DB cleanup skipped").helpers/db.ts:cleanupPayPlatformDb()using node-pg, now truncatingcouncils,pay_accounts, ANDcouncil_ppsCASCADE. Addspg+@types/pgtoplaywright/package.json.#pp-pkwithprofiles.provider.publicKey(the operator wallet pubkey), but provider-console registers a derived PP keypair — pay-platform stored the wrong key andinstant-execute500'd with "PP not found or inactive".helpers/db.ts:fetchActivePpPublicKey(); Step 8 now fills it withppPublicKey.provider-platform's add-bundle gate requires the submitter's entity row to be APPROVED.pay-service(the bundle submitter for POS-instant) is auto-created as UNVERIFIED via SEP-10 first-time auth and never promoted — bundle would 403.helpers/register-entity.ts(SEP-43/raw signed-challenge POST to/providers/:pp/entities).New surface
helpers/db.ts— node-pg helpers: cleanup, PP discovery, completed-inbound-stroops query.helpers/register-entity.ts— the SEP-43/raw signed-challenge flow againstPOST /providers/:pp/entities.Test plan
./test.sh playwright— 16/16 steps pass (was 14/14 passing against a broken backend; now 16/16 passing against a working one). Tested locally against the four PRs merged to main:docker logs providercapture; bundle submission 500'd withresolveChannelContext: PP GBOTA2… not found or inactive,operations_bundlestable was empty, yet all 14 original steps passed.Companion / follow-up
None — this is a test-only PR on
local-dev. No changes to platform behaviour.