spec(runtime): REQ-OBR-002/003 described an architecture the app abandoned - #459
Merged
Merged
Conversation
…doned
Both requirements mandated a NESTED CnAppRoot inside the Buildiq shell, with
the outer CnAppNav, header and chrome staying visible, mounted by
BuilderHost.vue, and an OUTER router forwarding an opaque path suffix to an
INNER one.
The product deliberately does the opposite, and says so in its own source.
appinfo/routes.php maps the bare `/builder/{slug}` to `dashboard#builder`, a
standalone page booting the `src/builder.js` webpack entry, whose header states
the reason:
It is deliberately NOT the Buildiq SPA: rendering the app inside Buildiq's
shell nests one NcContent in another (double chrome) and, worse, shares
Buildiq's router — which has none of the app's page routes, so page content
never resolves.
BuilderHost.vue still exists and is still registered, but only ever mounts for
builder sub-paths falling through to the SPA catch-all — never for the runtime
route these scenarios navigate to. So `[data-testid="buildiq-builder-host"]`
was genuinely absent while the app rendered correctly, and the two e2e tests
could not pass however they were written. They were left permanently skipped
with a note recommending exactly this rewrite. This is that rewrite.
REQ-OBR-002 now describes the standalone shell, and its scenario asserts the
property the old wording had BACKWARDS: one shell, not two.
REQ-OBR-003 now describes the app's own router resolving its own routes, and
drops the outer/inner forwarding machinery, which has no counterpart in the
shipped design. Its scenario is written around opening a row rather than
deep-linking `00000000-0000-0000-0000-000000000000` — a uuid that exists in no
fixture, so the old scenario could not have been asserted even had the
architecture matched.
THE TEST IS REAL, NOT A STUB
The REQ-OBR-002 test now opens `/builder/hello-world`, asserts the app's own
seeded index content, and then COUNTS mounted CnAppRoot instances via the
existing componentTree helper, requiring exactly one. Counting is the point: the
abandoned design would show two, and a plain visibility check cannot tell those
apart. It also asserts the SPA's builder-host wrapper has count 0 on this route.
No test is written for REQ-OBR-003: "REQ-OBR-004 — the seeded index lists the
three sample messages and opens one" already clicks a row, waits for the URL to
move onto the manifest's `/messages/:id` route, and asserts the detail renders.
That IS the rewritten scenario; a second test would add a passing assertion
without adding coverage.
Verified with the repo's own gate — `npm run format`
(prettier --check "**/*.{js,ts,vue,css,scss}") passes across the tree.
Contributor
Quality Report — ConductionNL/buildiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 642/642 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 05:38 UTC
Download the full PDF report from the workflow artifacts.
Two tests failed on flow creation, not on anything they assert:
creating the fixture flow must succeed (got 400)
seeding the definition must succeed (got 400)
Both fixtures build `openregister.trigger-schedule` nodes with `config: {}`.
OpenRegister validates that config on save now and refuses an empty one: the
node requires a five-field `cron`, and TriggerScheduleNode::validateActingIdentity()
requires a `runAs` naming an existing account — "nobody is present when a
schedule fires, so there is no session to take an identity from, and the flow's
owner is not used as a fallback".
These fixtures exist to be exported and re-imported, never to fire, but they
still have to be documents the platform accepts.
`runAs` is the admin, which is the account the e2e session actually runs as, so
the fixture names something true rather than a placeholder that happens to
exist.
THIRD APP HIT BY THE SAME UPSTREAM CHANGE
integriq's JobToFlowGenerator emitted schedule triggers with no `runAs` (fixed
in ConductionNL/integriq#1568) and its PHPUnit went red on the node's own
validateConfig. decidiq and learniq were untouched. Worth noting for anyone
else seeing a sudden 400 on flow-create: the request shape did not change, the
node's contract did.
Verified: `npm run format` clean across the tree.
THE DEFECT THIS FILE'S HEADER DESCRIBED NO LONGER EXISTS It read: "DocumentActions filters attachments by object['@self'].schema, which OpenRegister returns as the NUMERIC schema id ("21"), while a runtime.documents[] entry declares a schema SLUG ("hello-message"). The two never match, so the surface renders nothing for every real object." The component now injects `cnObjectContext` — whose `schema` is the manifest slug — and resolves candidates through `objectSchemaKeys()`, which collects `[ctx.schema, obj.schema, self.schemaSlug, self.schema]` and matches any of them. Slug and numeric id both hit. A skip reason outliving its cause is how this file came to carry twelve tests asserting nothing, so it is corrected rather than left to age further. It is the second such case in this repo today: the `buildiq#41` quarantine cited across 16 files names a PR that MERGED on 2026-07-27. TWO STUBS BECOME REAL TESTS Both were `goto('/applications')` + `expect(main).toBeVisible()` — bodies that would pass without ever reaching a runtime object. REQ-DDT-004 "no attachments renders nothing" now opens a real object detail on the seeded `hello-world` runtime app (which declares no runtime.documents[] — exactly the fixture the scenario needs) and asserts `.ob-document-actions` has count 0. The component gates its whole root on `v-if="schemaAttachments .length"`, so "renders nothing" is an ABSENT element, not an empty one. REQ-DDT-005 "runtime surface degrades without requests" asserts what the DOM cannot show: that no request to /apps/docudesk/ is issued at all. A surface that renders empty while still calling Docudesk on every object detail is the failure this scenario exists to catch, and it is invisible in markup. THE REQ-DDT-003 STUBS ARE LEFT SKIPPED, DELIBERATELY They need a published app carrying an attachment — real fixture work, not a skip to remove. Their notes now say that instead of citing the retired defect. Enabling them as they stand would produce green tests asserting nothing and would start crediting their scenarios with coverage they do not have. Verified: `npm run format` clean across the tree.
Contributor
Quality Report — ConductionNL/buildiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ❌ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 642/642 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-25 05:46 UTC
Download the full PDF report from the workflow artifacts.
…notes THE QUARANTINE CITED ACROSS THIS SUITE IS STALE Sixteen spec files deferred to "Conduction/buildiq#41: buildiq admin UI not functional in this build". #41 is a PULL REQUEST that MERGED on 2026-07-27, and 47 spec files in this suite already pass against that same UI — applicationDetailOverview.spec.ts alone has 9 passing tests. Every one of those notes now says what actually blocks its test: the body is a stub. Leaving them pointed at a merged PR is how a file ends up carrying twelve tests that assert nothing, which this repo has already done twice. ONE STUB BECOMES A REAL TEST REQ-NTS-005 "designer degrades when nldesign is missing" was `goto('/applications')` + `expect(main).toBeVisible()` — it asserts nothing about themes and passes on any page that renders. It now opens the page designer, scrolls to the Theme section, and asserts BOTH halves of degrading: that the absence is EXPLAINED (`.ob-theme-section__hint` visible) and that the control which cannot work is disabled rather than silently inert (`Change` is `:disabled="!nldesignAvailable"`). Deterministic, not hopeful: this app's CI installs openregister and docudesk and NOT nldesign (code-quality.yml `additional-apps`), so `nldesignAvailable` is false and the degraded branch is the one under test. WHAT IS DELIBERATELY LEFT SKIPPED The other stubs stay disabled with corrected notes. They need real fixtures — a published app carrying a theme, a seeded token-set catalogue — and enabling them as they stand would produce green tests asserting nothing AND start crediting their scenarios with coverage they do not have. gate-19 counts `skip`/`fixme` as off, so while skipped they credit nothing; that is the honest state until bodies exist. Verified: `npm run format` clean across the tree. The one eslint finding on the new import is `import-extensions/extensions`, which fires 71 times across tests/e2e already — no file in this repo uses the `.ts` extension, so the import follows the established convention rather than inventing a new one.
Contributor
Quality Report — ConductionNL/buildiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ✅ | ||||
| build | ❌ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ❌ | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-25 05:49 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Quality Report — ConductionNL/buildiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 642/642 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 06:20 UTC
Download the full PDF report from the workflow artifacts.
Both new runtime tests timed out at 30s, and not for want of the element:
locator.click: Test timeout of 30000ms exceeded
waiting for getByText('Welcome to Buildiq').first()
52 x waiting for element to be visible, enabled and stable
The page snapshot shows the runtime app rendered correctly — the "Messages"
heading, the table, and the "Welcome to Buildiq" cell all present. The click
spent its whole timeout on actionability, which is what a covering overlay
looks like.
The runtime app declares a walkthrough that pops a beat AFTER navigation
settles. `dismissOverlays()` from appFixture checks instantaneously and races
it; `dismissFirstVisitOverlays()` from support/overlays polls with `waitFor()`,
which is why buildiq-runtime.spec.ts drives this same route successfully with
it. Switched, and the row is scrolled into view before the click.
`dismissOverlays` stays imported — the designer tests in this file still use it
on a surface that has no walkthrough.
The conflict was three hunks of the same fix, written twice. This branch carried the earlier partial version — a `NC_ADMIN` constant plus an eight-line comment repeated at each of the two call sites. development has since landed the complete one: `RUN_AS` and `FIXTURE_CRON` as named constants, with the rationale hoisted into their docblocks instead of duplicated, and the finding that `cron` and `runAs` are refused SEPARATELY — so supplying only one still fails, with an error naming only the other, which is why the first attempt at this fix appeared to move the error rather than clear it. Resolved to development's version verbatim for that file. It is now identical there, which is correct: the fixture's schedule config is development's concern, not this branch's. This branch's own contribution is untouched — the openbuild-runtime spec rewrite (+58/-32) and seven other e2e files.
Contributor
Quality Report — ConductionNL/buildiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 642/642 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-25 08:49 UTC
Download the full PDF report from the workflow artifacts.
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.
The requirements described an architecture the app abandoned
REQ-OBR-002/003 mandated a nested
CnAppRootinside the Buildiq shell —outer
CnAppNav, header and chrome staying visible, mounted byBuilderHost.vue— plus an outer router forwarding an opaque path suffix toan inner one.
The product deliberately does the opposite, and says so in its own source.
appinfo/routes.phpmaps the bare/builder/{slug}todashboard#builder, astandalone page booting the
src/builder.jsentry, whose header states why:BuilderHost.vuestill exists and is still registered, but only ever mounts forbuilder sub-paths falling through to the SPA catch-all — never for the
runtime route these scenarios navigate to. So
buildiq-builder-hostwasgenuinely absent while the app rendered correctly, and the two e2e tests could
not pass however they were written. They were left permanently skipped with a
note recommending exactly this rewrite.
What changed
REQ-OBR-002 now describes the standalone shell, and its scenario asserts the
property the old wording had backwards: one shell, not two.
REQ-OBR-003 now describes the app's own router resolving its own routes, and
drops the outer/inner forwarding machinery that has no counterpart in the
shipped design. Its scenario is written around opening a row rather than
deep-linking
00000000-0000-0000-0000-000000000000— a uuid in no fixture, sothe old scenario could not have been asserted even had the architecture matched.
The test is real, not a stub
This matters, because 29 of this repo's disabled tests have bodies that are only
goto(/applications)+expect(main).toBeVisible(). Enabling one of thosewould make it pass while proving nothing, and start crediting its scenario with
coverage it does not have.
The new REQ-OBR-002 test opens
/builder/hello-world, asserts the app's ownseeded index content, then counts mounted
CnAppRootinstances through theexisting
componentTreehelper and requires exactly one. Counting is thepoint: the abandoned design would show two, and a visibility check cannot tell
those apart. It also asserts the SPA's builder-host wrapper has count
0here.No test is written for REQ-OBR-003. "REQ-OBR-004 — the seeded index lists the
three sample messages and opens one" already clicks a row, waits for the URL to
move onto
/messages/:id, and asserts the detail renders. That is therewritten scenario; a second test would add a passing assertion without adding
coverage.
Verification
npm run format— the repo's own gate,prettier --check "**/*.{js,ts,vue,css,scss}"— passes across the tree.Surfaced by the e2e skip-discipline gate, ConductionNL/.github#559.