You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Run the test suite against both deployment modes (full and lean) in CI
Summary
MMGIS can be deployed in two shapes from the same codebase, selected by a deployment-mode setting: the full application — everything it ships today — and a lean deployment that deliberately turns a set of server features off (geodata management, the bundled sidecar services, the on-disk mission filesystem, the link shortener, server-side raster utilities) for a lighter, smaller-footprint hosting setup.
Today the automated test suite exercises essentially one of those shapes. A change that quietly breaks the other — a feature wrongly left on in lean, or wrongly dropped — can pass CI and reach production unnoticed.
This issue does two things: it runs the existing test suite in both shapes, and it adds a new check that verifies the right features are present or absent in each mode — the full-only features gone in lean, and the lean-only publishing flow gone in full. It also confirms the lean app boots without the services it doesn't deploy. Together, a change that breaks either shape fails CI before merge.
Beyond catching mode-specific bugs today, this is also groundwork. A separate, planned change will reorganize how the two modes are wired throughout the code, and it will claim to change nothing in either mode — a claim only worth trusting if the tests already run both modes. So this coverage should be in place first.
Motivation
If we only test one mode, we miss bugs in the other. The tests run the full app today, so a bug that only shows up in lean — a feature left on that should be off, or one turned off that should still work — passes CI and ships.
It makes the planned gating refactor safe to do. That refactor promises "nothing changes in either mode." You can only trust that promise if the tests actually run both modes.
It protects lean right away — from everyone, not just this refactor. The moment it lands, anyone who breaks lean gets a red build.
It tells contributors there are two modes. Write your change for the full app, then check that lean still passes.
Scope
In scope:
Run the end-to-end / app-boot suite once per deployment shape in CI.
Confirm the features that are supposed to differ between the modes actually do. Take a handful that full has and lean leaves out, and check each one works in full and is gone in lean. Dashboard publishing is the one feature that goes the other way — it exists only in lean — so check that it works in lean and is gone in full.
Confirm the lean app boots in CI without the services it doesn't deploy.
A short contributor note on the two-mode posture.
Out of scope:
The gating-consolidation refactor itself (separate issue — this is its prerequisite).
Any new application behavior in either mode.
A full→lean data migration path.
Acceptance criteria
Verifiable without reading code:
CI runs the suite in both shapes, full and lean, as distinguishable legs; both go green on a no-op change.
The differences between the modes are real, both directions. A handful of features that full has and lean leaves out — geodata management, drawing, the sidecar services, the on-disk mission filesystem, the link shortener, server-side raster utilities — are shown working in full and gone in lean. Dashboard publishing, which exists only in lean, is shown the other way: working in lean and gone in full.
The lean app boots in CI without the services it doesn't deploy (no sidecar services, no separate spatial-catalog database) — initialization and startup succeed.
Gated-off features still have their database tables in lean, so a later mode flip needs no data migration — asserted, not assumed.
A breaking change to either shape fails CI. Demonstrable: deliberately mis-gating a feature turns the relevant leg red.
Dependencies
This work stacks on the unit-test issues and lands after them, in this order:
jsdom/Vitest test-environment migration — makes the unit suite actually run, on the supported Node version. Owns the runner switch and the CI Node bump.
Stale-unit-test fixes — makes that suite green.
This issue — adds the both-modes (full + lean) coverage on top of a green suite.
Gating-consolidation refactor — builds on this.
You don't add a mode matrix to a red suite, so steps 1–2 must be in place first. The Node-version bump and the unit-runner switch belong to step 1, not here — this issue assumes them.
Right-sizing note
One focused CI/test-coverage PR. It is the prerequisite for the separate gating-consolidation issue; it carries no application-code change of its own.
Implementation sketch — rough guide, written as of 42b9e0ad on 2026-06-16; re-verify against latest before relying on it
Relationship to the test-environment work
The Vitest + jsdom migration and the stale-test fixes are separate, upstream issues (the jsdom test-environment migration and its follow-on stale-test fixes — see Dependencies). By the time this work starts, they have already: switched the unit runner to vitest run, narrowed playwright.config.js to tests/e2e, added vitest.config.ts, and bumped CI Node to 20 in .github/workflows/playwright-tests.yml. This issue assumes all of that and does not redo it — it adds only the deployment-mode matrix to the e2e/boot leg.
Base branch: branch off the tip of that test-fix stack, not off development. The downstream gating-consolidation work then branches off this branch.
What's already covered vs. the gap
tests/unit/deploymentMode.spec.js already unit-tests the mode helper exhaustively (default full, explicit full/lean, throw on unknown) by busting the require cache to load it under a fresh env each test. tests/unit/bakeGuards.spec.js covers the static-bake guards.
Implication: unit-level logic can assert both modes within a single run via the cache-bust pattern — it does not need a CI matrix. The matrix is for the leg that boots the real app, where the mode is resolved once at process start.
The gap is whole-app both-modes coverage: does the lean process actually boot, and are the gated routes actually present/absent end-to-end.
Rough plan
Add a mode: [full, lean] job matrix to the e2e / boot job in .github/workflows/playwright-tests.yml; write MMGIS_DEPLOYMENT_MODE=${{ matrix.mode }} into the existing env-setup step; surface the mode in the job/report names so the two legs are distinguishable.
Make the lean leg honest: it needs lean preconditions (sidecar WITH_* env off, no separate STAC database) or scripts/init-db.js and the boot will fail. Verify both succeed under lean in CI.
Where current e2e tests hard-code a full-only route (sidecar proxy, datasets/geodatasets, draw, /Missions/...), make them mode-aware or skip-in-lean with an inline reason rather than letting them fail.
Short contributor note (README or agent-context file): two modes exist; author in full, confirm lean.
How the present/absent checks work (step 4, in plain terms)
Add one new end-to-end test file (in tests/e2e/) that checks each feature is there or gone depending on which mode the app started in.
Make one list by hand — the features that differ between the two modes. For each: where to look for it (a web address to hit, or a button to find on the page) and which mode it belongs to. Everything full-only goes in the "full" column; publishing goes in the "lean" column.
The test reads which mode the app booted in — the CI job already passes that in (MMGIS_DEPLOYMENT_MODE), so the test just reads it.
For each feature in the list, it checks one of two things:
If the feature belongs to the running mode → it should be reachable (the address answers; the button is on the page).
If it doesn't → it should be gone (the address says "not found"; the button isn't there).
Because publishing sits in the "lean" column and everything else in the "full" column, the same loop covers both directions — gone-in-lean and gone-in-full — with no special cases. CI runs this one file in both legs, so it proves both modes.
Gotchas
GOTCHA — don't put unit gate-logic behind the matrix. Unit specs already test both modes in one run via require-cache busting. Only the app-boot/e2e leg needs the [full, lean] matrix; matrixing the unit run is wasted CI time.
GOTCHA — the lean leg fails at init/boot without lean preconditions. The suite assumes a working app; lean needs sidecar env off and no spatial-catalog DB or startup throws. Set these in the lean leg's env before debugging "test" failures.
GOTCHA — pre-existing full-only test assumptions. Some e2e tests assume full-only routes exist and will go red under lean until made mode-aware. This is expected fix-up work, not a product bug; isolate it here so it isn't later confused with a refactor regression.
GOTCHA — confirm what a missing route actually returns. A feature that isn't mounted might answer with a real "not found" or with the app's catch-all page. Check the real behavior and assert against that, rather than assuming "not found."
GOTCHA — hand-write the "off in lean" list from the spec, don't read it from the code. The expected on/off set comes from the deployment ADR / feature inventory, written into the assertions by a person. Once the next PR adds a capability table, do not make these checks read from it — a test that takes its expected answers from the thing it's testing can't catch a wrong table entry, which is the exact bug this guards against. Keeping the list independent is the point.
Run the test suite against both deployment modes (full and lean) in CI
Summary
MMGIS can be deployed in two shapes from the same codebase, selected by a deployment-mode setting: the full application — everything it ships today — and a lean deployment that deliberately turns a set of server features off (geodata management, the bundled sidecar services, the on-disk mission filesystem, the link shortener, server-side raster utilities) for a lighter, smaller-footprint hosting setup.
Today the automated test suite exercises essentially one of those shapes. A change that quietly breaks the other — a feature wrongly left on in lean, or wrongly dropped — can pass CI and reach production unnoticed.
This issue does two things: it runs the existing test suite in both shapes, and it adds a new check that verifies the right features are present or absent in each mode — the full-only features gone in lean, and the lean-only publishing flow gone in full. It also confirms the lean app boots without the services it doesn't deploy. Together, a change that breaks either shape fails CI before merge.
Beyond catching mode-specific bugs today, this is also groundwork. A separate, planned change will reorganize how the two modes are wired throughout the code, and it will claim to change nothing in either mode — a claim only worth trusting if the tests already run both modes. So this coverage should be in place first.
Motivation
Scope
In scope:
Out of scope:
Acceptance criteria
Verifiable without reading code:
Dependencies
This work stacks on the unit-test issues and lands after them, in this order:
You don't add a mode matrix to a red suite, so steps 1–2 must be in place first. The Node-version bump and the unit-runner switch belong to step 1, not here — this issue assumes them.
Right-sizing note
One focused CI/test-coverage PR. It is the prerequisite for the separate gating-consolidation issue; it carries no application-code change of its own.
Implementation sketch — rough guide, written as of
42b9e0adon 2026-06-16; re-verify against latest before relying on itRelationship to the test-environment work
The Vitest + jsdom migration and the stale-test fixes are separate, upstream issues (the jsdom test-environment migration and its follow-on stale-test fixes — see Dependencies). By the time this work starts, they have already: switched the unit runner to
vitest run, narrowedplaywright.config.jstotests/e2e, addedvitest.config.ts, and bumped CI Node to 20 in.github/workflows/playwright-tests.yml. This issue assumes all of that and does not redo it — it adds only the deployment-mode matrix to the e2e/boot leg.Base branch: branch off the tip of that test-fix stack, not off
development. The downstream gating-consolidation work then branches off this branch.What's already covered vs. the gap
tests/unit/deploymentMode.spec.jsalready unit-tests the mode helper exhaustively (defaultfull, explicitfull/lean, throw on unknown) by busting the require cache to load it under a fresh env each test.tests/unit/bakeGuards.spec.jscovers the static-bake guards.Rough plan
mode: [full, lean]job matrix to the e2e / boot job in.github/workflows/playwright-tests.yml; writeMMGIS_DEPLOYMENT_MODE=${{ matrix.mode }}into the existing env-setup step; surface the mode in the job/report names so the two legs are distinguishable.WITH_*env off, no separate STAC database) orscripts/init-db.jsand the boot will fail. Verify both succeed under lean in CI./Missions/...), make them mode-aware or skip-in-lean with an inline reason rather than letting them fail.How the present/absent checks work (step 4, in plain terms)
Add one new end-to-end test file (in
tests/e2e/) that checks each feature is there or gone depending on which mode the app started in.MMGIS_DEPLOYMENT_MODE), so the test just reads it.Because publishing sits in the "lean" column and everything else in the "full" column, the same loop covers both directions — gone-in-lean and gone-in-full — with no special cases. CI runs this one file in both legs, so it proves both modes.
Gotchas
[full, lean]matrix; matrixing the unit run is wasted CI time.