test(17): complete UAT - 40 passed, 0 issues

This commit is contained in:
2026-10-19 12:24:39 +02:00
parent 0827865796
commit c5b6a83299

View File

@@ -0,0 +1,289 @@
---
status: complete
phase: 17-blog-companions
source: [17-01-SUMMARY.md, 17-02-SUMMARY.md, 17-03-SUMMARY.md, 17-04-SUMMARY.md, 17-05-SUMMARY.md, 17-06-SUMMARY.md]
started: 2026-10-19T10:02:15Z
updated: 2026-10-19T10:24:39Z
---
## Current Test
[testing complete]
## Tests
<!-- MVP user flow. Story: As a blog site editor, I want to manage menus, FAQs and the sitemap in the SummerCMS admin through the shared sitemap, menu and FAQ plugins, so that they are no longer hardcoded in the Nuxt app. -->
### 1. Cold Start Smoke Test
expected: On the UAT server, restart grzybyfunkcjonalne-go and the Nuxt service. Both come up without errors in the journal, and https://uat.grzybyfunkcjonalne.pl shows the homepage with the header menu and the FAQ block, and /gfadmin shows the admin login.
result: pass
### 2. Header menu on the site
expected: Open https://uat.grzybyfunkcjonalne.pl. The header shows the PHP site's menu (main-menu). The categories entry opens a dropdown on hover and on click, listing the Journal categories, each linking to /<slug>. Esc closes the dropdown. The link to the current page is marked active. At phone width the menu collapses behind a toggle that opens and closes it.
result: pass
coverage_id: 17-05/D7
### 3. Homepage FAQ
expected: On the homepage, the FAQ block "what-mushrooms-can-give-you" lists the PHP site's questions. Clicking a question opens its answer and clicking again closes it. The answers read as formatted text, with no stray markup.
result: pass
coverage_id: 17-05/D7
### 4. Edit a menu entry in the admin
expected: In /gfadmin open Menus, then Menu entries of main-menu. Edit an entry: change its title, and for a Journal type pick the reference from the dropdown that loads after you choose the type. Save. Reload the site: the header shows the new title (the save purges the Nuxt cache). Known, not part of this check: a refused save, such as a javascript: URL, shows its error as a raw phrase key (deferred item 1 of 17-04).
result: pass
note: "First run failed against the 2026-10-12 UAT build (no save purge, 300 s page cache); passed after the 2026-10-19 redeploy."
coverage_id: 17-04/D6
### 5. Reorder menu entries
expected: From the Menu entries list, click Reorder. Move an entry with the mouse and with the keyboard; the page announces each move and the tree keeps parents and children together. Reload the site: the header shows the new order.
result: pass
note: "First run failed against the 2026-10-12 UAT build (no save purge, 300 s page cache); passed after the 2026-10-19 redeploy."
coverage_id: 17-02/D4
### 6. Edit a FAQ answer with the rich editor
expected: In /gfadmin open FAQ and the "what-mushrooms-can-give-you" entry. The questions show as repeater rows you can add, collapse, move and remove. Edit an answer in the rich editor: the toolbar (bold, italic, lists, link) works, the link popover sets a link, and the HTML view shows the markup. Type a script element in the HTML view and save: a notice says what was removed. The homepage FAQ shows the edited answer.
result: pass
coverage_id: 17-02/D1, 17-04/D6
### 7. Sitemap definition and settings in the admin
expected: In /gfadmin open Settings, then Sitemap. The definition form lists the items as repeater rows; add a URL item (for example /kontakt) and save. Sitemap settings open and save. https://uat.grzybyfunkcjonalne.pl/sitemap.xml lists the new URL, and in a browser it renders through the XSL stylesheet as a readable table.
result: pass
coverage_id: 17-03/D6
<!-- Technical checks, after the user flow -->
### 8. UAT sitemap matches the live PHP sitemap
expected: The loc set of the UAT /sitemap.xml equals the live grzybyfunkcjonalne.pl sitemap's with the host removed: all 71 live paths are present on UAT, and the only extra is /blog/uat-16-2-blog-editor, a post that exists only in UAT data. You accept that one extra as UAT data, not a difference in the plugin.
result: pass
coverage_id: 17-05/D6
### 9. Plugin READMEs
expected: The READMEs of sm-journal-plugin (menu item types section), sm-sitemap-plugin, sm-menu-plugin and sm-faq-plugin read correctly: API paths, example and error bodies, rate-limit buckets, host CORS paths, the Winter import workflow and the Winter adaptations are documented, and none of them names a consuming application.
result: pass
coverage_id: 17-03/D7, 17-04/D7
<!-- Auto-passed by passing tests in each SUMMARY's coverage block (#1602), not presented -->
### 10. Typed menu item type registry: HasMenuItemTypes collected at boot by signpost.Activate in party, duplicate/empty/invalid types fail boot, layered patterns incl. PatternFrom, Resolve and ReferenceOptions
expected: Typed menu item type registry: HasMenuItemTypes collected at boot by signpost.Activate in party, duplicate/empty/invalid types fail boot, layered patterns incl. PatternFrom, Resolve and ReferenceOptions
result: pass
source: automated
coverage_id: 17-01/D1
### 11. Dependent dropdown (dependsOn) with GET fields/{field}/dependent-options fed by signpost.ReferenceOptions, depths, applies false for a type without references, 401 anonymous
expected: Dependent dropdown (dependsOn) with GET fields/{field}/dependent-options fed by signpost.ReferenceOptions, depths, applies false for a type without references, 401 anonymous
result: pass
source: automated
coverage_id: 17-01/D2
### 12. richeditor field type sanitized through seaglass on every save, clean HTML byte-identical, removals in meta.notices, non-string 422
expected: richeditor field type sanitized through seaglass on every save, clean HTML byte-identical, removals in meta.notices, non-string 422
result: pass
source: automated
coverage_id: 17-01/D3
### 13. repeater field type: nested keys only, per-row required (rows.1.title), nested richeditor sanitized, nested and top-level dependent recheck (form.dependent_invalid), row bounds
expected: repeater field type: nested keys only, per-row required (rows.1.title), nested richeditor sanitized, nested and top-level dependent recheck (form.dependent_invalid), row bounds
result: pass
source: automated
coverage_id: 17-01/D4
### 14. Tree reorder: config_reorder.yaml, GET/POST reorder with partition, both columns written, 409 reorder_stale for omitted or foreign nodes, 422 for cycles
expected: Tree reorder: config_reorder.yaml, GET/POST reorder with partition, both columns written, 409 reorder_stale for omitted or foreign nodes, 422 for cycles
result: pass
source: automated
coverage_id: 17-01/D5
### 15. Singleton controller: GET singleton first-or-create returns a stable id, list/create/delete 404, form schema singleton
expected: Singleton controller: GET singleton first-or-create returns a stable id, list/create/delete 404, form schema singleton
result: pass
source: automated
coverage_id: 17-01/D6
### 16. Every new route has swag annotations, regenerated admin.json/schema.d.ts, inventory entries, token classes, CSRF walk and conformance cases; docs and READMEs pass the docs checker
expected: Every new route has swag annotations, regenerated admin.json/schema.d.ts, inventory entries, token classes, CSRF walk and conformance cases; docs and READMEs pass the docs checker
result: pass
source: automated
coverage_id: 17-01/D7
### 17. Repeater field: add, edit nested, reorder and remove rows change form state only
expected: Repeater field: add, edit nested, reorder and remove rows change form state only
result: pass
source: automated
coverage_id: 17-02/D2
### 18. Dependent dropdown loads options for the sibling value and clears a stale value
expected: Dependent dropdown loads options for the sibling value and clears a stale value
result: pass
source: automated
coverage_id: 17-02/D3
### 19. Dist, types and phrase keys ship with the features; framework tagged v0.1.23 after human approval
expected: Dist, types and phrase keys ship with the features; framework tagged v0.1.23 after human approval
result: pass
source: automated
coverage_id: 17-02/D5
### 20. Journal registers its five PHP menu item types with DefaultPattern/PatternFrom, references, layered patterns, ordered per-locale alternates, nesting subtree, published filters and the x-default rule
expected: Journal registers its five PHP menu item types with DefaultPattern/PatternFrom, references, layered patterns, ordered per-locale alternates, nesting subtree, published filters and the x-default rule
result: pass
source: automated
coverage_id: 17-03/D1
### 21. /sitemap.xml from a stored definition (url item + registry item) equals the PHP golden byte for byte with Content-Type application/xml; 404 without a definition, empty 200 without items
expected: /sitemap.xml from a stored definition (url item + registry item) equals the PHP golden byte for byte with Content-Type application/xml; 404 without a definition, empty 200 without items
result: pass
source: automated
coverage_id: 17-03/D2
### 22. Url::to port (58 PHP cases), escaping, per-alternate list expansion, nesting, tiers (default rules, custom settings, off), manifest lastmod, frontend_url rewrite, BeforeAddItem skip, AddItem extra, priority precision, 50000 URL cap; tier config refusals and host replacement; manifest fail-safe
expected: Url::to port (58 PHP cases), escaping, per-alternate list expansion, nesting, tiers (default rules, custom settings, off), manifest lastmod, frontend_url rewrite, BeforeAddItem skip, AddItem extra, priority precision, 50000 URL cap; tier config refusals and host replacement; manifest fail-safe
result: pass
source: automated
coverage_id: 17-03/D3
### 23. sitemap:import-winter maps and drops items with a report, refuses a non-empty definition without --force, copies settings; /sitemap.xml rewrite with frontend_url; /sitemap.xsl bytes and headers; BeforeAddItem skip; sitemap:import PHP semantics
expected: sitemap:import-winter maps and drops items with a report, refuses a non-empty definition without --force, copies settings; /sitemap.xml rewrite with frontend_url; /sitemap.xsl bytes and headers; BeforeAddItem skip; sitemap:import PHP semantics
result: pass
source: automated
coverage_id: 17-03/D4
### 24. Sitemap admin API: singleton created once, repeater rows stored with PHP keys, 422 on a reference not offered for its type, settings form saves, 403 without golem15.sitemap.access_definitions
expected: Sitemap admin API: singleton created once, repeater rows stored with PHP keys, 422 on a reference not offered for its type, settings form saves, 403 without golem15.sitemap.access_definitions
result: pass
source: automated
coverage_id: 17-03/D5
### 25. FAQ admin: repeater with richeditor answers, script and onclick stripped on save with a notice under content.1.answer, locale column in the list, locale required (422, nothing written), 403 without golem15.faq.faqs
expected: FAQ admin: repeater with richeditor answers, script and onclick stripped on save with a notice under content.1.answer, locale column in the list, locale required (422, nothing written), 403 without golem15.faq.faqs
result: pass
source: automated
coverage_id: 17-04/D1
### 26. Menu admin: PHP beforeSave rules, D-05 type set, dependent reference recheck, url_scheme and target 422s, parent cycle, menu-scoped reorder (409 for a foreign entry), menu filter
expected: Menu admin: PHP beforeSave rules, D-05 type set, dependent reference recheck, url_scheme and target 422s, parent cycle, menu-scoped reorder (409 for a foreign entry), menu filter
result: pass
source: automated
coverage_id: 17-04/D2
### 27. Winter imports: FAQ locale remap by code (unknown aborts), ids kept, sequence bumped, --force/--dry-run/empty file; menu link->url and blog_categories->all-journal-categories, page subtree dropped and reported, ids and parent_id kept, sequences bumped, dry run writes nothing
expected: Winter imports: FAQ locale remap by code (unknown aborts), ids kept, sequence bumped, --force/--dry-run/empty file; menu link->url and blog_categories->all-journal-categories, page subtree dropped and reported, ids and parent_id kept, sequences bumped, dry run writes nothing
result: pass
source: automated
coverage_id: 17-04/D3
### 28. FAQ API: default locale, ?locale=en/pl, raw-SQL unsafe HTML served sanitized, null description, duplicate slug serves lowest id, 404 JSON for inactive, unknown slug, malformed slug, unknown and disabled locale, 429 after 120 requests per client
expected: FAQ API: default locale, ?locale=en/pl, raw-SQL unsafe HTML served sanitized, null description, duplicate slug serves lowest id, 404 JSON for inactive, unknown slug, malformed slug, unknown and disabled locale, 429 after 120 requests per client
result: pass
source: automated
coverage_id: 17-04/D4
### 29. Menu API: 404 JSON for unknown, inactive and malformed codes; unpublished subtree absent; sort_order then id; javascript: URL and bad target null; single type resolved title/URL; url_pattern override; list type keeps stored title/URL with stored child first then generated children (id null, parent type); ?locale=en alternates; unregistered and unresolvable entries left out; 429 after 120 requests
expected: Menu API: 404 JSON for unknown, inactive and malformed codes; unpublished subtree absent; sort_order then id; javascript: URL and bad target null; single type resolved title/URL; url_pattern override; list type keeps stored title/URL with stored child first then generated children (id null, parent type); ?locale=en alternates; unregistered and unresolvable entries left out; 429 after 120 requests
result: pass
source: automated
coverage_id: 17-04/D5
### 30. Host boots the three plugins from their pushed repositories, imports fixture exports, and serves the menu with Journal categories at /<slug>, the sanitized FAQ and the sitemap
expected: Host boots the three plugins from their pushed repositories, imports fixture exports, and serves the menu with Journal categories at /<slug>, the sanitized FAQ and the sitemap
result: pass
source: automated
coverage_id: 17-05/D1
### 31. vue-menu-layer and vue-faq-layer: typed clients, MenuNav and FaqBlock, URL allowlist and rel noopener tests, SSR smokes, tag v0.1.0 on origin
expected: vue-menu-layer and vue-faq-layer: typed clients, MenuNav and FaqBlock, URL allowlist and rel noopener tests, SSR smokes, tag v0.1.0 on origin
result: pass
source: automated
coverage_id: 17-05/D2
### 32. Site app renders MenuNav in the header and FaqBlock on the homepage, app menu and FAQ data deleted, Nuxt sitemap disabled
expected: Site app renders MenuNav in the header and FaqBlock on the homepage, app menu and FAQ data deleted, Nuxt sitemap disabled
result: pass
source: automated
coverage_id: 17-05/D3
### 33. UAT serves /sitemap.xml, /sitemap.xsl, /_menu/ and /_faq/ from Go through nginx with the server-level security headers, GET and HEAD only, and the full smoke passes
expected: UAT serves /sitemap.xml, /sitemap.xsl, /_menu/ and /_faq/ from Go through nginx with the server-level security headers, GET and HEAD only, and the full smoke passes
result: pass
source: automated
coverage_id: 17-05/D4
### 34. Winter menu, FAQ and sitemap rows exported read-only and imported on UAT by the ordered import step
expected: Winter menu, FAQ and sitemap rows exported read-only and imported on UAT by the ordered import step
result: pass
source: automated
coverage_id: 17-05/D5
### 35. Fail-closed phase gate over eight repositories with detectors proven on planted output; --all ends with 'Phase 17 gate passed'
expected: Fail-closed phase gate over eight repositories with detectors proven on planted output; --all ends with 'Phase 17 gate passed'
result: pass
source: automated
coverage_id: 17-06/D1
### 36. Framework unit tests: signpost activation, pattern layers and ReferenceOptions; seaglass byte stability, report and bypass corpus; pact contracts; the party hook; cabana repeater, dependent dropdown, richeditor, reorder and singleton compile and routes; conformance of the new routes' success and error answers
expected: Framework unit tests: signpost activation, pattern layers and ReferenceOptions; seaglass byte stability, report and bypass corpus; pact contracts; the party hook; cabana repeater, dependent dropdown, richeditor, reorder and singleton compile and routes; conformance of the new routes' success and error answers
result: pass
source: automated
coverage_id: 17-06/D2
### 37. Admin SPA specs for the UI-SPEC backstops: richeditor untouched value, link popover, notices, chunk failure; repeater bounds, remove and reorder, collapsed rows; dependent dropdown states and last request wins; reorder announcements, partition switch, tree rules; singleton form
expected: Admin SPA specs for the UI-SPEC backstops: richeditor untouched value, link popover, notices, chunk failure; repeater bounds, remove and reorder, collapsed rows; dependent dropdown states and last request wins; reorder announcements, partition switch, tree rules; singleton form
result: pass
source: automated
coverage_id: 17-06/D3
### 38. Plugin unit tests: Journal menu item types, sitemap parity (Url::to goldens, escaping, fillable, tiers, rewrite, hooks, manifest, item JSON, cap, backend URL), menu links, tree and model, FAQ decode, model and serializer; Postgres APIs, imports and beforeSave
expected: Plugin unit tests: Journal menu item types, sitemap parity (Url::to goldens, escaping, fillable, tiers, rewrite, hooks, manifest, item JSON, cap, backend URL), menu links, tree and model, FAQ decode, model and serializer; Postgres APIs, imports and beforeSave
result: pass
source: automated
coverage_id: 17-06/D4
### 39. Host wiring and layers: TestCompanionsHost with CORS preflight and sitemap headers; menu and FAQ layer link rules, clients and composable bases
expected: Host wiring and layers: TestCompanionsHost with CORS preflight and sitemap headers; menu and FAQ layer link rules, clients and composable bases
result: pass
source: automated
coverage_id: 17-06/D5
### 40. Filled 17-VALIDATION.md: every row with task IDs, gate commands, File Exists and status; Wave 0 ticked; manual rows keep the plan 05 human check
expected: Filled 17-VALIDATION.md: every row with task IDs, gate commands, File Exists and status; Wave 0 ticked; manual rows keep the plan 05 human check
result: pass
source: automated
coverage_id: 17-06/D6
## Summary
total: 40
passed: 40
issues: 0
pending: 0
skipped: 0
blocked: 0
## Gaps
- gap_id: G-17-4
truth: "In /gfadmin open Menus, then Menu entries of main-menu. Edit an entry: change its title, and for a Journal type pick the reference from the dropdown that loads after you choose the type. Save. Reload the site: the header shows the new title (the save purges the Nuxt cache). Known, not part of this check: a refused save, such as a javascript: URL, shows its error as a raw phrase key (deferred item 1 of 17-04)."
status: resolved
resolved_by: UAT redeploy 2026-10-19 (host master, cache purge from 19.3-04)
resolved_at: 2026-10-19
reason: "User reported: didn't work. changed Grzyby Funkcjonalne to Grzyby and uat.grzybyfunkcjonalne.pl still shows Grzyby Funkcjonalne. two options - actually nothing got deployed and I'm testing old hardcoded faq and navigation, or there is this painful 60s cache"
severity: major
test: 4
root_cause: "Not a code gap: UAT runs the 2026-10-12 build (17-05). The save worked (menu API returned the new title) and the page showed it once the Nuxt swr cache (s-maxage=300) expired, as the user later confirmed. The save-triggered purge exists since 19.3-04 (sm-menu-plugin 559d96b, sm-faq-plugin c60ae6e, host d604509/85939c3) but was never deployed to UAT."
artifacts:
- path: "../sm-grzybyfunkcjonalne-app (UAT /srv/grzybyfunkcjonalne/go/bin, 2026-10-12)"
issue: "deployed binary predates the site-cache purge"
missing:
- "Redeploy UAT from current host master, then re-run tests 4 and 5"
- gap_id: G-17-5
truth: "From the Menu entries list, click Reorder. Move an entry with the mouse and with the keyboard; the page announces each move and the tree keeps parents and children together. Reload the site: the header shows the new order."
status: resolved
resolved_by: UAT redeploy 2026-10-19 (host master, cache purge from 19.3-04)
resolved_at: 2026-10-19
reason: "User reported: failed, nothing happened, and my name change from previous step still doesn't appear. switching you to manual mode, confirm that I'm testing proper deployment"
severity: major
test: 5
root_cause: "Same as G-17-4: the reorder saved and appeared on the site after the swr TTL; the deployed UAT build has no save-triggered purge."
artifacts: []
missing:
- "Redeploy UAT from current host master, then re-run tests 4 and 5"