Switching between /mints, /fedimints and /lnurl-mints showed the right list for a moment and then flashed back to the previous ecosystem's mints. The client router keeps every page's script alive, and onReady re-runs each setup on every arrival, so a visited page's setup also ran on the next page. All three grids were marked with the same bare data-mint-grid, so the stale setup found the new grid, fetched its own type and overwrote it. Mark and query each grid by ecosystem (data-mint-grid="cashu" etc.), the way the home page already scopes data-home-grid, so a stale setup finds nothing and bails. Skip the render in hydrateMintGrid when the grid has already been detached by the router. Document the re-run-everywhere contract on onReady, and add a static wiring test so a bare marker cannot come back. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
61 lines
2.4 KiB
JavaScript
61 lines
2.4 KiB
JavaScript
/**
|
|
* The three listing pages must each own their grid.
|
|
*
|
|
* `<ClientRouter />` swaps pages without reloading, and `onReady` in `scripts/reveal.ts`
|
|
* re-runs every page's setup on every arrival — deliberately, since that is what keeps
|
|
* the layout islands alive. So once `/mints` has been visited, its setup also runs on
|
|
* `/fedimints`. If both pages mark their grid the same way, the stale cashu setup finds
|
|
* the fedimint grid, fetches `?type=cashu` and rewrites it: the page shows fedimints for
|
|
* a moment, then flashes back to cashu mints. That happened.
|
|
*
|
|
* The guard is that each page's marker carries its ecosystem, and its script only looks
|
|
* for its own. This checks the template, the query and the hydrate call agree, and that
|
|
* no bare `data-mint-grid` has crept back in. Plain node, source read as text, like
|
|
* `i18n-wiring.test.mjs`.
|
|
*/
|
|
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const pagesDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../src/pages/[...locale]');
|
|
const read = (file) => readFileSync(path.join(pagesDir, file), 'utf8');
|
|
|
|
const LISTINGS = [
|
|
['mints.astro', 'cashu'],
|
|
['fedimints.astro', 'fedimint'],
|
|
['lnurl-mints.astro', 'lnurl'],
|
|
];
|
|
|
|
for (const [file, type] of LISTINGS) {
|
|
test(`${file} marks, queries and hydrates its grid as ${type}`, () => {
|
|
const source = read(file);
|
|
|
|
assert.match(
|
|
source,
|
|
new RegExp(`<div class="mint-grid" data-mint-grid="${type}">`),
|
|
`${file}: template grid is not marked data-mint-grid="${type}"`,
|
|
);
|
|
assert.match(
|
|
source,
|
|
new RegExp(`querySelector<HTMLElement>\\('\\[data-mint-grid="${type}"\\]'\\)`),
|
|
`${file}: script does not query [data-mint-grid="${type}"]`,
|
|
);
|
|
assert.match(
|
|
source,
|
|
new RegExp(`type: '${type}',`),
|
|
`${file}: hydrateMintGrid is not called with type '${type}'`,
|
|
);
|
|
|
|
// A bare marker, in either the template or the query, is the bug coming back.
|
|
assert.doesNotMatch(source, /data-mint-grid[>\s]/, `${file}: bare data-mint-grid in template`);
|
|
assert.doesNotMatch(source, /\[data-mint-grid\]/, `${file}: bare [data-mint-grid] selector`);
|
|
});
|
|
}
|
|
|
|
test('the three listings use three different markers', () => {
|
|
const types = new Set(LISTINGS.map(([, type]) => type));
|
|
assert.equal(types.size, LISTINGS.length);
|
|
});
|