Fixing empty dashboards and ensuring data loads#2407
Conversation
…shboard pages Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/13182c9a-238b-4723-a6d6-5d5c9e5443e8 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/13182c9a-238b-4723-a6d6-5d5c9e5443e8 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🏷️ Automatic Labeling SummaryThis PR has been automatically labeled based on the files changed and PR metadata. Applied Labels: javascript,performance,testing,refactor,size-l Label Categories
For more information, see |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
There was a problem hiding this comment.
Pull request overview
This PR addresses a production regression where pre-rendered dashboard HTML pages shipped a dev-only module script path (/src/browser/main.ts), causing dashboards to render empty in S3/CloudFront. It does so by extending the staticPagesPlugin to rewrite module script tags to hashed production bundles and by adding regression tests in both unit and Cypress suites.
Changes:
- Extend
scripts/vite-plugin-static-pages.jsto rewrite<script type="module" src="/src/browser/<name>.ts">to the hashed/assets/js/<name>-<hash>.jsbundle (using the Vite manifest or a dist scan fallback). - Add Vitest unit tests covering module-script rewrite scenarios (manifest lookup, fallback scan, no-op when unresolved, non-matching tags).
- Strengthen Cypress dashboard assertions to detect missing JS execution (Chart.js instance attachment) and verify served HTML contains hashed bundle paths.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.js | Updates build comments explaining why dashboard pages require module-script rewriting to avoid empty dashboards in production. |
| scripts/vite-plugin-static-pages.js | Implements module <script> tag rewriting (manifest-backed + fallback scan) and logs rewrite counts. |
| tests/vite-plugin-static-pages.test.ts | Adds unit coverage for the new module-script rewrite behavior and fallbacks. |
| cypress/support/commands.js | Improves waitForChart to verify real Chart.js runtime attachment, not just canvas dimensions. |
| cypress/e2e/dashboards.cy.js | Adds regression tests ensuring dashboard pages ship hashed main-*.js bundles and that window.Chart is registered at runtime. |
| * We only match the canonical absolute `/src/browser/<name>.ts` form (the | ||
| * only one used in this codebase). Captures: 1=before-attrs, 2=name, | ||
| * 3=after-attrs. | ||
| */ | ||
| const MODULE_SCRIPT_RE = | ||
| /<script\b([^>]*?)\bsrc\s*=\s*"\/src\/browser\/([A-Za-z0-9_-]+)\.ts"([^>]*)>\s*<\/script>/gi; |
| const attrsBefore = before.replace(/\bsrc\s*=\s*"[^"]*"/i, '').trim(); | ||
| const attrsAfter = after.replace(/\bsrc\s*=\s*"[^"]*"/i, '').trim(); |
| @@ -284,11 +284,16 @@ export default defineConfig({ | |||
| // (parties, anomaly-detection, network-analysis, voting-cohesion, | |||
| // momentum, coalitions, seasonal-patterns, pre-election, ministers, | |||
| // risk, election-cycle, committees) × 14 languages = 126 files, | |||
| // emitted by scripts/build-dashboard-pages.py. They are pure | |||
| // static HTML that loads existing chart bundles via root-relative | |||
| // <script src="/assets/js/...">, so they don't need to be Rollup | |||
| // entry points — staticPagesPlugin just copies them to dist/ and | |||
| // rewrites the styles.css link to the hashed asset. | |||
| // emitted by scripts/build-dashboard-pages.py. | |||
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…e2e tests Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/6f0effac-0d1b-43cb-9f66-a6536d6be7a9 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
…t.js assertions Root cause: live site served /src/browser/main.ts (dev path) instead of hashed /assets/js/main-*.js. S3/CloudFront returns index.html for unknown paths with text/html, browser silently rejects HTML as JS module → no lazy loader → no charts → empty dashboards. Changes: - Add deploy-s3.yml pre-flight: verify all 9 dashboard HTML files have hashed bundle and no dev paths before deploying - Add tests/dashboard-bundle-integrity.test.ts: validates dist/ output post-build (30 new assertions) - Fix all-dashboards.cy.js: replace weak canvas.width>0 checks with Chart.getChart() verification (proves full pipeline: main.ts loaded → register-globals → dashboard module → CSV fetched → chart rendered) - Add cia-data directory verification to deploy workflow Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/6f0effac-0d1b-43cb-9f66-a6536d6be7a9 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
|
@copilot resolve the merge conflicts in this pull request must get all from main |
…hboards Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
| /** | ||
| * Match a single `<script type="module" src="/src/browser/<name>.ts">` dev | ||
| * tag (the one Vite expects in source) so we can rewrite it to the hashed | ||
| * production bundle (`/assets/js/<name>-<hash>.js`) emitted by Rollup. | ||
| * |
| @@ -284,11 +284,16 @@ export default defineConfig({ | |||
| // (parties, anomaly-detection, network-analysis, voting-cohesion, | |||
| // momentum, coalitions, seasonal-patterns, pre-election, ministers, | |||
| // risk, election-cycle, committees) × 14 languages = 126 files, | |||
| // emitted by scripts/build-dashboard-pages.py. They are pure | |||
| // static HTML that loads existing chart bundles via root-relative | |||
| // <script src="/assets/js/...">, so they don't need to be Rollup | |||
| // entry points — staticPagesPlugin just copies them to dist/ and | |||
| // rewrites the styles.css link to the hashed asset. | |||
| // emitted by scripts/build-dashboard-pages.py. | |||
|
@copilot apply changes based on the comments in this thread and fix Test Dashboard / Dashboard Tests (cypress/e2e/dashboards.cy.js) (pull_request) Improve e2e test of dashboards, improve all |
- Tighten MODULE_SCRIPT_RE to require type="module" (lookahead) so a classic <script src="/src/browser/main.ts"> can never be silently rewritten to a hashed ESM bundle (would throw at runtime). - Strip pre-existing crossorigin attribute from before/after captures so the rewritten <script> never emits duplicate crossorigin="" attributes. - vite.config.js dashboards comment: list the 9 actual dashboard slugs (anomaly-detection, coalitions, committees, election-cycle, ministers, parties, pre-election, risk, seasonal-patterns) so 9×14=126 math holds. - cypress/e2e/dashboards.cy.js "should render charts after data loads": scrollIntoView() the #party-dashboard container before waitForChart so the IntersectionObserver-based lazy loader fires and registerBrowserGlobals attaches Chart.js to window.Chart (root cause of CI failure). - Add 2 regression tests: duplicate-crossorigin avoidance + classic <script> non-rewrite (16/16 vite-plugin-static-pages tests passing). Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/8f896bbf-f838-4686-95c6-8707b2651b9f Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Done in 2e3737f:
|
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
/src/browser/main.ts(dev path) instead of hashed/assets/js/main-*.js— S3 returns index.html for unknown paths with text/html, browser silently rejects HTML as JS module → no lazy loader → no Chart.js → empty dashboardsscripts/vite-plugin-static-pages.jsrewrites the dev script tag to the hashed production bundle indist/dashboards/*.htmltests/dashboard-bundle-integrity.test.ts: validates all 9 dashboard HTML files indist/have hashed main-*.js bundle and no dev paths/src/browser/main.ts, anddist/cia-data/exists before deployingcypress/e2e/all-dashboards.cy.js: replace weakcanvas.width > 0checks withwaitForChart()which usesChart.getChart()to prove the full pipeline worksMODULE_SCRIPT_REnow requirestype="module"via lookahead — classic<script>tags are no longer silently rewritten to a hashed ESM bundlecrossoriginattribute before injectingcrossorigin=""so the output never carries duplicate attributesvite.config.jsdashboards comment now lists the 9 actual slugs (was 12, breaking the 9×14=126 math)tests/vite-plugin-static-pages.test.ts(16/16 passing)Test Dashboard / Dashboard Tests (cypress/e2e/dashboards.cy.js): "should render charts after data loads" timed out because the IntersectionObserver-based lazy loader never fired (canvas was below the headless viewport). Addedcy.get('#party-dashboard').scrollIntoView()soregisterBrowserGlobals()runs andwindow.Chartis set.