fix(test): close the test-entry leak into real trip content
A ui-test entry had survived into the active trip's dailies. Three independent failures had to line up for that, and all three were real: 1. cleanupEntry() used host-side fs.rmSync. Grav's Apache workers run as root, so every entry the form creates is root-owned and recursive removal needs write permission on that directory — which the host user lacks. Cleanup had never worked for form-created entries; it just threw inside a path nothing checked. It now falls back to `docker exec … rm -rf` in the container that actually serves USER_DIR. 2. globalTeardown's dailies sweep keyed off a `parent:` in post-form.md — a key deliberately removed (the write target comes from site.yaml active_trip, and CLAUDE.md forbids re-adding a static parent). The regex could never match, so dailiesDir was always null and the sweep silently did nothing. It now reuses helpers' own resolution instead of keeping a divergent copy. 3. Nothing pinned the suite to this checkout's server. playwright.config.js defaults to :8081, so a worktree run hit the MAIN checkout — entries created in one content tree while the specs asserted and cleaned up in another. test-ui now passes GRAV_BASE_URL from GRAV_PORT, and globalSetup hard-fails when the server's bind mount disagrees with the tree the specs read. Also fixed, found on the way to a green run: - test-account interpolated the password into an `sh -c` string, so a password containing a shell metacharacter was re-parsed by the container's shell (`sh: 2: <fragment>: not found`, no account, every UI run dead). It now travels via `docker exec -e`, making the recipe indifferent to its contents. - `make start` in a worktree always failed: travel-memories declares `env_file: .env` and worktree-new creates none. It degrades to start-grav there — a worktree with no server is what sent runs to :8081 in the first place. - test-form-config asserted a hero_image field that 8cf1145 deliberately removed; it had been failing ever since. Verified: config 22/22, post 6/6, location-override 20/20, and a full UI run now leaves zero ui-test entries behind. The remaining UI failures are pre-existing on main — site.yaml pins owner_username to a real account while the suite logs in as testrunner, so owner-only controls never render for it. Only trip-publish.spec.js patches that; delete-flow, edit-mode and anon-view do not. Left for a separate branch.
This commit is contained in:
@@ -330,6 +330,10 @@ test('submitting with an unresolved lat/lng mismatch is blocked', async ({ page
|
||||
});
|
||||
|
||||
// ── U4: lazy-load boundary — an ordinary GPS-only submit never fetches maplibre-gl ──
|
||||
// The URL pattern deliberately covers BOTH halves of the lazy boundary: the JS
|
||||
// chunk (js/post/maplibre-gl-*.js) and the stylesheet
|
||||
// (css-compiled/maplibre-gl.css, <link>ed by location-map.js at panel-open —
|
||||
// see its ensureMaplibreCss). Neither may be requested when the panel stays shut.
|
||||
test('an ordinary submit without opening the panel never fetches the maplibre-gl chunk', async ({ page }) => {
|
||||
const chunkRequests = [];
|
||||
page.on('request', (req) => {
|
||||
@@ -346,7 +350,32 @@ test('an ordinary submit without opening the panel never fetches the maplibre-gl
|
||||
await expect(page.locator('.notices')).toContainText('Entry posted successfully!', { timeout: 15_000 });
|
||||
created.push(tag);
|
||||
|
||||
expect(chunkRequests, 'maplibre-gl must not be fetched when the panel is never opened').toHaveLength(0);
|
||||
expect(chunkRequests, 'neither the maplibre-gl chunk nor its stylesheet may be fetched when the panel is never opened').toHaveLength(0);
|
||||
});
|
||||
|
||||
// ── The other half of that boundary: opening the panel DOES apply the vendor CSS ──
|
||||
// Without this, the guard above could keep passing while the stylesheet silently
|
||||
// stopped loading at all (a broken href, a missed build step), leaving the map
|
||||
// unstyled with nothing to catch it. Asserts the <link> exists AND parsed —
|
||||
// link.sheet is null until the browser has actually applied it.
|
||||
test('opening the panel lazily links maplibre\'s stylesheet and applies it', async ({ page }) => {
|
||||
await page.goto('/post');
|
||||
|
||||
const hrefBefore = await page.evaluate(() => Array.from(document.styleSheets)
|
||||
.map((s) => s.href || '').filter((h) => /maplibre-gl\.css/.test(h)));
|
||||
expect(hrefBefore, 'the vendor stylesheet must not be present before the panel opens').toHaveLength(0);
|
||||
|
||||
await openLocationDetails(page);
|
||||
await expect(page.locator('#location-map canvas.maplibregl-canvas')).toHaveCount(1, { timeout: 10_000 });
|
||||
|
||||
await expect.poll(
|
||||
() => page.evaluate(() => {
|
||||
const link = Array.from(document.querySelectorAll('link[rel="stylesheet"]'))
|
||||
.find((l) => /maplibre-gl\.css/.test(l.href));
|
||||
return link ? link.sheet !== null : false;
|
||||
}),
|
||||
{ message: 'maplibre\'s stylesheet must be linked and applied once the panel opens', timeout: 10_000 }
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
// ── Full submit: a search-picked location round-trips into the frontmatter ──
|
||||
|
||||
Reference in New Issue
Block a user