Skip to content

test(e2e): pin the browser-catalogue contract from the browser's side - #424

Merged
rubenvdlinde merged 4 commits into
developmentfrom
test/l10n-browser-catalogue
Aug 24, 2026
Merged

test(e2e): pin the browser-catalogue contract from the browser's side#424
rubenvdlinde merged 4 commits into
developmentfrom
test/l10n-browser-catalogue

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Adds the test that would have caught the defect the l10n rollout just fixed.

Why an e2e, when an l10n check already exists

Nextcloud serves only l10n/<locale>.js to a browser — raw JSON out of an app directory is a 404. With no .js, t('<app>', key) has nothing registered and returns the key, so the entire interface renders English no matter which language the user picked, while every server-rendered string is translated. Nothing errors and nothing logs.

Six apps in the fleet ran a test:l10n step that passed throughout — it reads the JSON, the half that was never broken. A check that validates the source cannot see that the artefact the runtime loads does not exist. So this asserts from the browser's side:

  1. GET l10n/<locale>.js → 200, is an OC.L10N.register call, and names the current app id.
  2. The running app has that catalogue registered, and t() resolves a real key through it rather than falling back to returning the key.

Must-fail control

Delete l10n/nl.js and both scenarios fail — the first on the 404, the second on the missing registration:

Error: l10n/nl.js must be served, not 404
  Expected: 200
  Received: 404

Design

The file is identical in every app. The app id is read from appinfo/info.xml at run time instead of hardcoded, so it survives a rename — and a catalogue registered under a pre-rename id, which t() silently ignores, fails scenario 1. No fixture strings: the assertion picks a translated key out of the app's own registered catalogue at run time, so it needs no edit when copy changes.

This test found a second, unrelated defect while being written: four apps (dossiq, larpinq, planninq, keepiq) were mounted in the dev environment under their pre-rename directory name, leaving them unreachable in both spellings — /apps/planix/ 500 and /apps/planninq/ 404. Fixed in ConductionNL/.github#556.

The l10n rollout fixed a defect no existing check could see: `l10n/<locale>.js`
was missing, so `t('<app>', key)` had nothing registered and handed the key
back — the whole interface rendered English regardless of the user's language,
while every server-rendered string was translated. Nothing errored.

Six apps in the fleet ran an l10n check that passed the entire time, because
it reads the JSON — the half that was never broken. A check that validates the
SOURCE cannot see that the ARTEFACT the runtime loads does not exist, so this
test asserts from the browser instead:

  1. GET l10n/<locale>.js returns 200, is an OC.L10N.register call, and names
     the CURRENT app id. (Raw JSON out of an app directory is a 404, which is
     what made every translation unreachable.)
  2. The running app has that catalogue registered, and t() resolves a real
     key through it rather than falling back to returning the key.

Must-fail verified: delete l10n/nl.js and both scenarios fail — the first on
404, the second on the missing registration.

Written to be identical in every app: the app id is read from
appinfo/info.xml at run time rather than hardcoded, so it survives a rename —
and a catalogue registered under a pre-rename id, which `t()` silently
ignores, fails scenario 1. No fixture strings either: the assertion picks a
translated key out of the app's own registered catalogue at run time, so it
does not need editing when copy changes.
The file is meant to be byte-identical in every app, so it has to satisfy the
strictest formatter in the fleet. decidiq's format check objected; this is its
prettier output, verified to also satisfy every other app that runs one.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/buildiq @ d91664f

Check PHP Vue Security License Tests
lint ⏭️
phpcs
phpmd
psalm
phpstan
phpmetrics ⏭️
eslint
stylelint
build
test-l10n
check-gitignore
format
check-l10n-js
composer ⏭️ ✅ 106/106
npm ⏭️ ⏭️
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-23 20:32 UTC

Download the full PDF report from the workflow artifacts.

The spec fetched /custom_apps/<app>/l10n/<locale>.js. That is right on a dev
box, where apps are bind-mounted under custom_apps — and wrong in CI, which
checks the app out under apps/. So it failed for a reason that had nothing to
do with the catalogue.

It now reads OC.appswebroots[appId] from the running instance and fetches
relative to that. The assertion gets stronger rather than weaker: an app that
does not resolve at all has no webroot entry, which is how the decidesk ->
decidiq mount drift surfaced.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/buildiq @ fdd715a

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
composer ✅ 106/106
npm ✅ 625/625
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-23 20:59 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/buildiq @ fc75ad2

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
composer ✅ 106/106
npm ✅ 625/625
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-23 22:01 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/buildiq @ fc75ad2

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
composer ✅ 106/106
npm ✅ 625/625
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-23 22:45 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/buildiq @ 9d3f986

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
composer ✅ 106/106
npm ✅ 625/625
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-24 00:48 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 54c8cf9 into development Aug 24, 2026
43 checks passed
@rubenvdlinde
rubenvdlinde deleted the test/l10n-browser-catalogue branch August 24, 2026 04:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants