Add unit tests for various dashboards including Coalition, Committees, Election Cycle, Ministry, Pre-Election, and Seasonal Patterns#112
Conversation
pethers
commented
Feb 11, 2026
- Implement tests for DOM structure, accessibility, data processing, and chart configuration for each dashboard.
- Ensure proper ARIA labels and heading hierarchy for accessibility compliance.
- Validate data parsing and processing logic for CSV data in each dashboard context.
- Include loading state tests to verify UI behavior during data fetching.
…, Election Cycle, Ministry, Pre-Election, and Seasonal Patterns - Implement tests for DOM structure, accessibility, data processing, and chart configuration for each dashboard. - Ensure proper ARIA labels and heading hierarchy for accessibility compliance. - Validate data parsing and processing logic for CSV data in each dashboard context. - Include loading state tests to verify UI behavior during data fetching.
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…ltiple language files; enhance data transformation in JavaScript files for improved chart compatibility and accuracy; refactor mock data generation and anomaly handling in coalition and committee dashboards.
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
- Implemented a new script `refresh-dashboard-data.sh` to download and refresh CSV files used by various dashboard JavaScript files. - Created comprehensive tests for the Politician Career & Productivity Analytics Dashboard, covering DOM structure, data sources, CSV parsing, rendering, and error handling. - Included tests for data processing related to risk summary, influence metrics, experience distribution, and behavioral trends. - Ensured accessibility features and error handling in the dashboard components.
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…gration - Introduced `distribution_person_status.csv` for tracking active MPs and their statuses. - Added `distribution_risk_evolution_temporal.csv` for risk severity assessments over time. - Implemented `stats-loader.js` to fetch and parse CSV data, updating DOM elements with real-time statistics. - Created unit tests in `stats-loader.test.js` to validate CSV parsing, DOM updates, and error handling.
🔍 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 |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…s, election predictions, and initialization - Implement tests for Dashboard CIA Visualizations Renderer covering key metrics, party performance, rankings, voting patterns, and committee network visualizations. - Create tests for Election 2026 Predictions Module focusing on seat predictions, coalition scenarios, key factors, and summary statistics. - Develop tests for Dashboard Initialization Module to ensure proper loading state management, error handling, and DOM structure validation.
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
| it('should display error message from exception', () => { | ||
| const error = new Error('Network timeout'); | ||
| const errorMessage = document.getElementById('error-message'); | ||
| errorMessage.textContent = (error && error.message) || 'An unknown error occurred'; |
| it('should handle falsy error message', () => { | ||
| const error = null; | ||
| const errorMessage = document.getElementById('error-message'); | ||
| errorMessage.textContent = (error && error.message) || 'An unknown error occurred while loading dashboard data.'; |
|
|
||
| it('should handle missing forecast data gracefully', () => { | ||
| const data = null; | ||
| if (!data || !data.forecast || !Array.isArray(data.forecast.parties)) { |
|
|
||
| it('should handle invalid voting patterns data', () => { | ||
| const votingPatterns = { votingMatrix: null }; | ||
| const isValid = votingPatterns && votingPatterns.votingMatrix && |
|
|
||
| it('should handle missing election date', () => { | ||
| const data = { electionDate: null }; | ||
| if (!data || !data.electionDate) { |
|
|
||
| it('should handle missing forecast data', () => { | ||
| const data = null; | ||
| if (!data || !data.forecast || !Array.isArray(data.forecast.parties)) { |
…urces - Updated test descriptions to reflect CSV parsing and loading logic. - Introduced new tests for CSV parsing, including handling of headers, quoted fields, and numeric conversions. - Implemented tests for loading CSV data with fallback mechanisms. - Maintained existing JSON loading tests for election analysis while adapting others to CSV. - Enhanced parallel loading tests to include all relevant data sources.
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…t in dashboard pages
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…shboard - Created index_nl.html for Dutch language support with localized content and metadata. - Created index_no.html for Norwegian language support with localized content and metadata. - Created index_zh.html for Chinese language support with localized content and metadata. - Included hreflang tags for all language versions to improve SEO and accessibility.
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…nguages - Updated sitemap files for Spanish, Finnish, French, Hebrew, Japanese, Korean, Dutch, Norwegian, Swedish, and Chinese to include links and descriptions for the CIA Intelligence Dashboard in Danish, Norwegian, Finnish, German, French, Spanish, Dutch, Arabic, Hebrew, Japanese, Korean, and Chinese. - Modified vite.config.js to include new dashboard pages for each language.
🔍 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 broadens dashboard support across languages by adding localized dashboard entrypoints, new dashboard UI sections on multiple index pages, local-first CSV loading helpers, and a large set of Vitest-based DOM/data/config tests. It also updates sitemaps and dashboard pages with expanded SEO metadata and hreflang coverage.
Changes:
- Add/expand Vitest tests for multiple dashboards (DOM structure, accessibility attributes, CSV schema checks, loading/error states).
- Introduce/extend local-first CSV loading (hero stats loader; party dashboard local-first fetch; committees dashboard now uses loaded CSV data instead of random mock values).
- Expand multilingual dashboard discoverability (Vite multi-page inputs, sitemap links, sitemap.xml alternates, dashboard page SEO/hreflang/JSON-LD).
Reviewed changes
Copilot reviewed 84 out of 85 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.js | Adds all localized dashboard/index_*.html pages to Vite multi-page inputs. |
| tests/stats-loader.test.js | Adds tests for hero stats DOM and CSV parsing assumptions. |
| tests/seasonal-patterns-dashboard.test.js | Adds Seasonal Patterns dashboard DOM/CSV schema/accessibility tests. |
| tests/pre-election-dashboard.test.js | Adds Pre-Election dashboard DOM/CSV schema/chart/accessibility tests. |
| tests/party-dashboard.test.js | Extends party dashboard tests (but currently mismatched with implementation paths). |
| tests/ministry-dashboard.test.js | Adds Ministry dashboard DOM/CSV schema/data fetching/accessibility tests. |
| tests/election-cycle-dashboard.test.js | Adds Election Cycle dashboard DOM/CSV schema/chart/accessibility tests. |
| tests/dashboard-init.test.js | Adds tests for dashboard init loading/error/content orchestration structure. |
| tests/committees-dashboard.test.js | Adds Committees dashboard DOM/CSV schema/accessibility tests. |
| sitemap.html | Adds links for all localized dashboard pages. |
| sitemap.xml | Adds hreflang alternates for dashboard pages and new <url> entries for localized dashboards. |
| sitemap_sv.html | Adds localized dashboard links to Swedish sitemap page. |
| sitemap_zh.html | Adds localized dashboard links to Chinese sitemap page. |
| sitemap_no.html | Adds localized dashboard links to Norwegian sitemap page. |
| sitemap_nl.html | Adds localized dashboard links to Dutch sitemap page. |
| sitemap_ko.html | Adds localized dashboard links to Korean sitemap page. |
| sitemap_ja.html | Adds localized dashboard links to Japanese sitemap page. |
| sitemap_he.html | Adds localized dashboard links to Hebrew sitemap page. |
| sitemap_fr.html | Adds localized dashboard links to French sitemap page. |
| sitemap_fi.html | Adds localized dashboard links to Finnish sitemap page. |
| sitemap_es.html | Adds localized dashboard links to Spanish sitemap page. |
| sitemap_de.html | Adds localized dashboard links to German sitemap page. |
| sitemap_da.html | Adds localized dashboard links to Danish sitemap page. |
| sitemap_ar.html | Adds localized dashboard links to Arabic sitemap page. |
| scripts/committees-dashboard.js | Replaces mock/random committee network/heatmap/productivity values with values derived from loaded CSV data. |
| js/stats-loader.js | Adds a hero “stats loader” to populate homepage hero stats from CSV (local-first + remote fallback). |
| js/party-dashboard.js | Updates party dashboard fetching to local-first (cia-data/party/...) with remote fallback + caching. |
| index.html | Updates event date copy; adds hero stat element IDs; includes js/stats-loader.js. |
| index_sv.html | Adds Election Cycle + Committee dashboard sections and includes stats loader + module scripts. |
| index_no.html | Adds Election Cycle + Committee dashboard sections and includes stats loader + module scripts. |
| index_da.html | Adds Election Cycle + Committee dashboard sections and includes stats loader + module scripts. |
| index_de.html | Adds Election Cycle + Committee dashboard sections and includes stats loader + module scripts. |
| index_nl.html | Adds Election Cycle + Committee dashboard sections and includes stats loader + module scripts. |
| index_zh.html | Adds Election Cycle + Committee dashboard sections and includes stats loader + module scripts. |
| index_ja.html | Adds Election Cycle + Committee dashboard sections and includes stats loader + module scripts. |
| dashboard/index.html | Adds hreflang set, enriched OG/Twitter meta, JSON-LD, and a <noscript> notice; adds “Key Election Factors” container. |
| dashboard/index_sv.html | Same SEO/hreflang/JSON-LD additions for Swedish dashboard; updates footer language links; adds “Key Election Factors” container. |
| dashboard/dashboard-init.js | Switches init to loader.loadAll() and calls renderKeyFactors(). |
| cia-data/seasonal/view_riksdagen_seasonal_anomaly_detection_sample.csv | Resolves previously conflicted content / keeps sample anomaly data. |
| cia-data/seasonal/view_riksdagen_seasonal_activity_patterns_sample.csv | Resolves previously conflicted content / keeps sample seasonal data. |
| cia-data/refresh-dashboard-data.sh | Adds a “refresh” script to download referenced dashboard CSV files. |
| cia-data/download-csv.sh | Simplifies/updates the CSV download script. |
| cia-data/party/distribution_coalition_alignment.csv | Updates local coalition alignment CSV (currently header-only). |
| cia-data/anomaly/distribution_anomaly_by_party.csv | Updates anomaly-by-party CSV (currently header-only). |
| cia-data/distribution_politician_risk_levels.csv | Updates local risk-level counts/percentages. |
| cia-data/distribution_party_effectiveness_trends.csv | Adds local party effectiveness trends CSV at root. |
| cia-data/distribution_risk_evolution_temporal.csv | Adds local temporal risk evolution CSV at root. |
| cia-data/distribution_ministry_risk_levels.csv | Adds local ministry risk levels CSV at root. |
| cia-data/distribution_ministry_risk_quarterly.csv | Adds local ministry risk quarterly CSV at root. |
| cia-data/distribution_ministry_productivity_matrix.csv | Adds local ministry productivity matrix CSV at root. |
| cia-data/distribution_ministry_effectiveness.csv | Adds local ministry effectiveness CSV at root. |
| cia-data/distribution_influence_buckets.csv | Adds local influence buckets CSV at root. |
| cia-data/distribution_experience_levels.csv | Adds local experience levels CSV at root. |
| cia-data/distribution_experience_by_party.csv | Adds local experience-by-party CSV at root. |
Comments suppressed due to low confidence (2)
cia-data/party/distribution_coalition_alignment.csv:2
- This local CSV is effectively empty (header only). Dashboards using a local-first strategy will have no coalition alignment data when running offline/without remote fallback. Either include the intended rows in this committed sample CSV, or remove/rename it so the app doesn't prefer an empty local file over a populated remote source.
party1,party2,shared_votes,aligned_votes,opposed_votes,alignment_rate,coalition_likelihood,bloc_relationship
cia-data/anomaly/distribution_anomaly_by_party.csv:2
- This local CSV is effectively empty (header only). The coalition/anomaly dashboards prefer local-first data, so an empty committed file will prevent meaningful offline behavior and may hide data issues. Commit the expected data rows (or avoid shipping an empty local file so remote fallback can work).
party,anomaly_classification,politician_count,avg_rebellions
| @@ -145,10 +201,15 @@ describe('Party Performance Dashboard', () => { | |||
| ); | |||
|
|
|||
| global.fetch = mockFetch; | |||
|
|
|||
| const response = await fetch('test-url'); | |||
| const response = await fetch('cia-data/distribution_party_effectiveness_trends.csv'); | |||
| expect(response.ok).toBe(false); | |||
| }); | |||
There was a problem hiding this comment.
This test overwrites global.fetch but never restores it, which can leak into subsequent tests because the global fetch mock is set once in tests/setup.js. Add cleanup (e.g., restore the original fetch in afterEach or use vi.stubGlobal/vi.unstubAllGlobals) to keep tests isolated.
| // Calculate risk rules from risk levels data | ||
| if (riskText) { | ||
| const risks = parseCSV(riskText); | ||
| const totalPoliticians = risks.reduce((sum, r) => sum + (parseInt(r.politician_count) || 0), 0); | ||
| if (totalPoliticians > 0) { | ||
| // Update the risk rules with total politicians monitored by risk assessment | ||
| updateStat('stat-risk-rules', '45'); | ||
| } |
There was a problem hiding this comment.
The risk-levels fetch computes totalPoliticians but then hard-codes stat-risk-rules to "45". The comment says it updates based on the risk assessment, but the actual value is constant, which is misleading and adds unnecessary network work. Either remove the risk-level fetch/aggregation if the value is meant to be static, or update the UI/logic so the fetched value is actually reflected.
| <script src="js/stats-loader.js"></script> | ||
|
|
||
| <script type="module" src="scripts/committees-dashboard.js"></script> | ||
|
|
||
| <script type="module" src="js/election-cycle-dashboard.js"></script> | ||
|
|
There was a problem hiding this comment.
stats-loader.js is included on this page, but the hero stat numbers do not have the expected IDs (stat-mps, stat-parties, etc.). This causes CSV fetches without any DOM updates. Add the IDs to the hero stats in this file or remove the script include to avoid wasted requests.
| <script src="js/stats-loader.js"></script> | ||
|
|
||
| <script type="module" src="scripts/committees-dashboard.js"></script> | ||
|
|
||
| <script type="module" src="js/election-cycle-dashboard.js"></script> | ||
|
|
There was a problem hiding this comment.
stats-loader.js is included on this page, but the hero stat numbers do not have the expected IDs (stat-mps, stat-parties, etc.), so the loader can't update anything. Either add the IDs to this file's hero stats or remove the script include to prevent wasted network calls.
| <script src="js/stats-loader.js"></script> | ||
|
|
||
| <script type="module" src="scripts/committees-dashboard.js"></script> | ||
|
|
||
| <script type="module" src="js/election-cycle-dashboard.js"></script> | ||
|
|
There was a problem hiding this comment.
stats-loader.js is included on this page, but the hero stat numbers do not have the expected IDs (stat-mps, stat-parties, etc.), so the loader will fetch CSVs but not update the UI. Add the IDs to the hero stats markup in this file or remove the script include.
|
|
||
| it('should handle invalid voting patterns data', () => { | ||
| const votingPatterns = { votingMatrix: null }; | ||
| const isValid = votingPatterns && votingPatterns.votingMatrix && |
There was a problem hiding this comment.
This guard always evaluates to true.
|
|
||
| it('should handle missing election date', () => { | ||
| const data = { electionDate: null }; | ||
| if (!data || !data.electionDate) { |
There was a problem hiding this comment.
This guard always evaluates to false.
|
|
||
| it('should handle missing forecast data', () => { | ||
| const data = null; | ||
| if (!data || !data.forecast || !Array.isArray(data.forecast.parties)) { |
There was a problem hiding this comment.
This guard always evaluates to true.
|
|
||
| // Should not throw, should fall back to mock data | ||
| try { | ||
| const response = await fetch('cia-data/nonexistent.csv'); |
There was a problem hiding this comment.
Unused variable response.
| globalThis.fetch = mockFetch; | ||
|
|
||
| try { | ||
| const response = await globalThis.fetch('fake-url.csv'); |
There was a problem hiding this comment.
Unused variable response.