Repository navigation
test(acceptance): give every worker its own UCP test data - #249
Conversation
`UcpTestDataService` extends the ATS data service with storefront, headless and feed channels, UCP activation and UCP row cleanup. `UcpAgentProfileHost` publishes a test agent's ES256 profile under the shop's `public/` directory. `UcpAclUsers` logs one Administration user per UCP role into a separate page. `UcpConsole` wraps `ucp:signing-keys:*`. Known blocker D8 records that path-prefixed domains resolve to the wrong channel.
Björn Meyer (BrocksiNet)
left a comment
There was a problem hiding this comment.
Two fixture issues need fixing: repeated ACL fixture use fails within the same worker, and the published agent profile cannot negotiate any shopping capability. Details inline.
TypeScript checking passed. The ACL loader failure was reproduced locally; the negotiation finding was verified against SDK 0.0.7. Full acceptance journeys were not run against a live shop.
The privilege mapping is evaluated once per worker and reused, since Node runs an imported module only once. Test agents publish every shopping capability at the protocol version, and `publish()` accepts an override. Workers delete only their own profile files, never the shared directory. New `Setup` specs cover the repeated read and the negotiation.
The ATS registry cleanup now runs even when the UCP cleanup throws. D1 describes what SDK 0.0.7 still does: verification requires `created`, and its own signing still covers `@target-uri`. A doc comment no longer names an issue number.
Björn Meyer (BrocksiNet)
left a comment
There was a problem hiding this comment.
Both earlier findings are fixed (the cached mapping, and the capabilities with their override). typecheck and lint are clean. On trunk, 6 of 7 Setup specs pass with a working console; the details are inline. Nits:
- README:108 says the worker channel's
/.well-known/ucp"is its own". D8 says the opposite. resolvePluginDir()falls back tocustom/plugins/agentic-commerce, but lanes mount the plugin asSwagAgenticCommerce.readAdminPrivilegeMapping()also caches a failed read. ResetprivilegeMappingon failure so one error doesn't fail every later caller in the worker.- The D5 description says "typed array payload". #224 made the MCP payload an object schema. Rewording D1 and D5 is also outside this PR's scope.
- The README fixture table has cells of about 700 characters. A short paragraph per fixture would read better than Prettier's padded table.
- The default
docker compose exec -T webprefix silently skips key cleanup on podman-only machines, wheredockeris only a shell alias thatspawnSynccan't see. That's worth one line in the README.
Delete signing keys only for the channels a test activated, and continue past a failed deletion. The created channels are now always deleted, and every cleanup failure is reported together. Restore each surviving channel's UCP config from a snapshot taken before the first write; the fixed default emptied its capabilities. Probe the console with the real command, and resolve the Shopware project only when a fixture first needs it, which lets HTTP-only runners use the data service. Find the plugin under any `custom/plugins` directory name, and retry an ACL read that failed. Reword D5 and D8, and describe each fixture in its own README paragraph. Retry creating an ACL user up to three times. Core revokes refresh tokens on every user insert, and MariaDB 11.6 and newer rejects that with error 1020 while other workers log in, which failed about one `Setup` run in three. Remove the retry once core skips the revocation for new users.
|
All six addressed in ddbda70: the README no longer claims the worker channel's profile is its own; One more change you did not ask for: the ACL fixture now retries user creation up to three times. Creating a user failed with a 500 in about one full |
Björn Meyer (BrocksiNet)
left a comment
There was a problem hiding this comment.
All four findings and the six nits hold up on trunk:
- An HTTP-only runner passes the data-service specs.
- A console prefix that can't reach the lane counts as unavailable, and nothing leaks.
- With a working console,
Setuppasses three times in a row, the feed-channel spec included, with no channels left behind. - After a D8 run, every stored UCP config row is byte-identical.
One non-blocking note on the ACL retry is inline.
One more nit: when the console is unavailable, key cleanup is skipped without a word. Three such runs left 6 signing keys with private keys in ucp_signing_keys for channels that no longer exist. A console.warn or a test annotation naming the channels would make that visible.
Move the user-creation retry from the ACL fixture into `UcpTestDataService::createUserRetryingTokenConflicts()`. Each attempt presets the user id. When an attempt fails but the user exists, the user is registered for cleanup and returned. Before Shopware 6.7.13.1 core commits the user row before the token revocation that fails with MariaDB error 1020, so the retry left one user behind per failed attempt. Warn when the UCP console is unavailable at cleanup, naming the sales channels whose signing keys stay in `ucp_signing_keys`. The skip was silent before.
|
Done: when the console is unavailable, cleanup warns with the reason and the ids of the sales channels whose keys stay in |
Each Playwright worker owns its UCP test data.
UcpTestDataServiceextends the ATSTestDataServicewith a second storefront channel, a headless channel and a product-feed channel, each on a path-prefixed domain, plusactivateUcp()and a cleanup that resets the UCP rows it wrote and deletes the channels it created.UcpAgentProfileHostwrites a test agent's profile with an ES256 public key into the shop'spublic/directory, where the web container fetches it fromlocalhost. It never falls back to the shop's own profile.UcpAclUserscreates a non-admin user per UCP role from the privilege sets in the Administration ACL file and logs it in.UcpConsolerunsucp:signing-keys:*throughbin/console.Each fixture is proven by its own spec, tagged setup so it runs in the project the journeys already depend on. Two specs that need a path-prefixed domain to resolve to its own channel run in
UcpKnownBlockedas D8: core strips the prefix from the request URI before the SDK builds its request, and the plugin resolves the channel from that URI alone. Under a prefixed domain/.well-known/ucpserves the root channel or the global configuration.Closes #189.