fix(e2e): seed the Goals and ProcessTemplate the specs assert on - #1052
Merged
Conversation
`Goals: index lists all five seeded goals` failed on
getByText('Duurzame omzetgroei 2028') -> element(s) not found. The five goals
it names were never created on CI.
The spec's docblock points at lib/Settings/register.d/66-organisation-goals.json,
but that file declares only the Goal SCHEMA. The five objects live in three
different profile files -- association.json (1), corporate.json (2),
municipality.json (2) -- so no single `example_profile` yields all five, and the
seed deliberately picks `none` to keep a whole demo dataset out of the lists
other specs assert on. The spec was written against the older behaviour where
installing planted everything.
Measured on development 67e0f6c: E2E 4 failed / 139 passed, this among them.
Seeded in the governance fixture, beside the objects the other specs need:
- No SEED_TAG prefix. The titles ARE the assertion and are matched with
{ exact: true }, so prefixing them the way the sibling objects are prefixed
would break the test this exists to fix.
- Titles, descriptions, horizons, deadlines and statuses copied verbatim from
the profiles, so the fixture and the shipped example sets cannot drift into
disagreeing about what a Goal looks like.
- `body` repointed at this run's governance body. The profiles reference their
own bodies by slug (gemeenteraad-amsterdam, ledenraad-vng,
raad-van-bestuur-acme-bv), none of which exist here; a dangling reference
would seed an object the index cannot resolve. `owner` is dropped for the
same reason -- femke-halsema is not a user on this instance, and the field is
not required.
- 'goal': 5 added to the readability verifier, for the reason that block
exists: a create that answered 2xx but is not listable would leave the spec
failing on "element(s) not found", which reads as a missing feature rather
than a seed that did not land.
This fixes ONE of decidiq's four E2E failures. The other three are not seeding
gaps and are left alone deliberately -- see the PR body.
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
August 31, 2026 08:27
Contributor
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 537/537 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | 🚨 NO VERDICT — enabled but never ran | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-31 08:33 UTC
Download the full PDF report from the workflow artifacts.
`Template list shows built-in templates as read-only` failed at
expect(page.locator('[data-testid="process-template-list"]')).toBeVisible()
Received: hidden
not because the list is missing but because it is EMPTY. ProcessTemplates.vue
renders `<ul v-if="!store.loading">` regardless of row count, and an empty <ul>
is a zero-height box, which Playwright reports as hidden.
ProcessTemplateService::list() already carries a comment describing exactly
this shape from the last time it returned zero rows.
Same root cause as the Goals in the previous commit: the built-in templates are
not shipped with the schema, they live in the profile files (association.json,
corporate.json and municipality.json declare three each), so
`example_profile=none` leaves the catalogue empty.
ONE is seeded, deliberately. The spec asserts the list renders, then takes the
FIRST item carrying `process-template-builtin` and checks it is read-only.
Seeding all nine would push a full catalogue into every other list that reads
this schema, which is what the `none` profile exists to avoid.
`Municipal Council` is the template that matches the rest of this fixture — the
governance body seeded above is a Gemeenteraad. It is copied verbatim from
municipality.json (states, transitions, guards, voting rule and quorum rule
included), verified structurally identical minus `@self` and `slug`: `@self` is
import metadata the object API sets itself, and the slug is assigned
server-side.
'process-template': 1 added to the readability verifier for the same reason as
'goal': 5 — an unlistable create would resurface as "hidden", which reads as a
CSS or mount problem rather than a seed that did not land.
rubenvdlinde
added a commit
that referenced
this pull request
Aug 31, 2026
…#1053) `v2 grid renders the KPI row, list widgets and governance-health chart` failed with: Error: strict mode violation: getByText('Minutes awaiting approval') resolved to 2 elements 1) <h3 class="cn-widget-wrapper__title" id="cn-widget-wrapper-title-minutes-in-review"> 2) <h4 class="cn-kpi-card__title" title="Minutes awaiting approval"> The phrase is rendered twice on this dashboard: once as the widget's own heading and once as a KPI card title -- src/manifest.json declares the stats-block with "id": "minutes-in-review", "title": "Minutes awaiting approval", and repeats that title inside content.entries. So the assertion failed on a dashboard that is entirely correct, and it fails louder the more complete the row gets, which is the wrong direction for a layout test. CnWidgetWrapper renders its heading as `<h3 :id="titleId">` with `titleId = cn-widget-wrapper-title-${widgetId}` and `resolvedWidgetId()` returning the supplied widgetId, so `#cn-widget-wrapper-title-minutes-in-review` addresses exactly the stats-block this line is about -- the same id the manifest declares and the same element the CI log named -- and stays correct if another surface shows the same phrase. Every other assertion in this test already locates its widget by a stable attribute rather than by text; this line was the exception. One of decidiq's four E2E failures. Not related to the seeding gap in #1052. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Contributor
Quality Report — ConductionNL/decidiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-nav-ceiling | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 537/537 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | 🚨 NO VERDICT — enabled but never ran | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-31 08:46 UTC
Download the full PDF report from the workflow artifacts.
rubenvdlinde
added a commit
that referenced
this pull request
Aug 31, 2026
…its (#1054) `quick-filter dropdown label "All urgent" renders intact at every tested viewport` failed as a bare: Test timeout of 20000ms exceeded. The test could not pass reliably no matter how healthy the app was. playwright.config.ts sets `timeout: 20_000` per test. This one loops THREE viewports, and each iteration navigates and then allows `waitForSelector(15_000)` plus `expect(select).toBeVisible({ 10_000 })` -- 25s of permitted waiting in the FIRST iteration alone, against a 20s total budget. The symptom is misleading in a specific way: a whole-test timeout names no element, so it reads like a slow or broken dropdown rather than a budget that was never large enough for the work the test does. 90s matches the sibling multi-step specs (voting-rules.spec.ts uses 90_000; goals-pages.spec.ts uses 120_000) and the per-step waits are left untouched, so a genuinely stuck dropdown still fails on its OWN 10s assertion with a message naming the element. The fourth and last of decidiq's E2E failures. The other three: two seeding gaps in #1052, one strict-mode locator violation in #1053. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
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.
Two of decidiq's four E2E failures share one root cause: objects the specs assert on live in the profile files, and CI runs with
example_profile=none.1.
goals-pages.spec.ts— five GoalsFailed on
getByText('Duurzame omzetgroei 2028')→ element(s) not found.The spec's docblock points at
lib/Settings/register.d/66-organisation-goals.json, but that file declares only theGoalschema. The five objects live in three different profiles:corporate.jsonmunicipality.jsonassociation.jsonSo no single
example_profileyields all five. The spec was written against the older behaviour where installing planted everything — the behaviour #1024 is replacing.SEED_TAGprefix: the titles are the assertion ({ exact: true }), so prefixing them the way sibling objects are prefixed would break the test this exists to fix.bodyrepointed at this run's governance body. The profiles reference bodies by slug (gemeenteraad-amsterdam,ledenraad-vng,raad-van-bestuur-acme-bv), none of which exist here; a dangling reference would seed an object the index cannot resolve.ownerdropped likewise —femke-halsemais not a user on this instance and the field is not required.2.
process-configuration.spec.ts— one built-in ProcessTemplateFailed at
expect(list).toBeVisible()withReceived: hidden— not because the list is missing but because it is empty.ProcessTemplates.vuerenders<ul v-if="!store.loading">regardless of row count, and an empty<ul>is a zero-height box.ProcessTemplateService::list()already carries a comment describing exactly this shape from the last time it returned zero rows.Built-in templates are likewise not shipped with the schema — association/corporate/municipality declare three each.
One is seeded, deliberately. The spec asserts the list renders, then takes the first item carrying
process-template-builtin. Seeding all nine would push a full catalogue into every other list reading this schema, which is whatnoneexists to avoid.Municipal Councilmatches the rest of the fixture (the seeded body is a Gemeenteraad) and is copied verbatim frommunicipality.json— verified structurally identical minus@selfandslug, which are import metadata and server-assigned respectively.Verifier
'goal': 5and'process-template': 1added to the readability check, for the reason that block exists: a create that answers 2xx but is not listable would resurface as "element(s) not found" or "hidden" — reading as a missing feature or a CSS problem rather than a seed that did not land.Scope
The other two failures are not seeding gaps and are handled separately:
dashboard-layout.spec.ts:33— a strict-mode violation; "Minutes awaiting approval" renders twice (widget<h3>+ KPI card<h4>). Fixed in fix(e2e): match the minutes widget by id, not by a phrase shown twice #1053.urgent-decision-procedure.spec.ts:23— viewport-dependent quick-filter dropdown. Still open.Verification
bash -nparses; both embedded Python heredocs compile; all five goal payloads validate against the schema's enums (horizon: multi-year/annual/quarterly,status: active/at-risk/draft) and its six required fields; the template payload parses and carries all three required fields (name,initialState,stateMachine) with 7 states and 6 transitions.