-
Notifications
You must be signed in to change notification settings - Fork 2
Enable coverage all:true, fix Vitest 4 threshold format, migrate fix-article-navigation to TypeScript #697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
3821a48
c5c00d5
3ad2ffe
41bce96
f8cadfb
78994a3
5d66764
e53195c
629e127
822cb3e
310206e
6afac64
b0d8b4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,241 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env node | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Fix Article Navigation: Language Switcher + Back-to-News Top Nav | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * This script ensures ALL news articles have: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 1. A language switcher nav (14 languages) after <body> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 2. An article-top-nav div with a localized back-to-news link before the article | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * It auto-discovers all articles in the news/ directory and processes them | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * idempotently — safe to run multiple times. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Usage: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * npx tsx scripts/fix-article-navigation.ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * npx tsx scripts/fix-article-navigation.ts --dry-run | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @author Hack23 AB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @license Apache-2.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import fs from 'fs'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import path from 'path'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { fileURLToPath } from 'url'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ── Language configuration ──────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const LANGUAGES = ['en', 'sv', 'da', 'no', 'fi', 'de', 'fr', 'es', 'nl', 'ar', 'he', 'ja', 'ko', 'zh'] as const; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type Lang = typeof LANGUAGES[number]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const LANG_DISPLAY: Readonly<Record<Lang, [string, string]>> = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| en: ['🇬🇧', 'English'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sv: ['🇸🇪', 'Svenska'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| da: ['🇩🇰', 'Dansk'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| no: ['🇳🇴', 'Norsk'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi: ['🇫🇮', 'Suomi'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| de: ['🇩🇪', 'Deutsch'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fr: ['🇫🇷', 'Français'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| es: ['🇪🇸', 'Español'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nl: ['🇳🇱', 'Nederlands'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ar: ['🇸🇦', 'العربية'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| he: ['🇮🇱', 'עברית'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ja: ['🇯🇵', '日本語'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ko: ['🇰🇷', '한국어'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| zh: ['🇨🇳', '中文'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } as const; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const LANG_SWITCHER_ARIA: Readonly<Record<Lang, string>> = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| en: 'Language', sv: 'Språk', da: 'Sprog', no: 'Språk', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi: 'Kieli', de: 'Sprache', fr: 'Langue', es: 'Idioma', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nl: 'Taal', ar: 'اللغة', he: 'שפה', ja: '言語', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ko: '언어', zh: '语言', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } as const; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const BACK_TO_NEWS: Readonly<Record<Lang, string>> = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| en: 'Back to News', sv: 'Tillbaka till nyheter', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| da: 'Tilbage til nyheder', no: 'Tilbake til nyheter', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi: 'Takaisin uutisiin', de: 'Zurück zu Nachrichten', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fr: 'Retour aux actualités', es: 'Volver a noticias', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nl: 'Terug naar nieuws', ar: 'العودة إلى الأخبار', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| he: 'חזרה לחדשות', ja: 'ニュースに戻る', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ko: '뉴스로 돌아가기', zh: '返回新闻', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } as const; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ── Language configuration ──────────────────────────────────────────────── | |
| const LANGUAGES = ['en', 'sv', 'da', 'no', 'fi', 'de', 'fr', 'es', 'nl', 'ar', 'he', 'ja', 'ko', 'zh'] as const; | |
| type Lang = typeof LANGUAGES[number]; | |
| const LANG_DISPLAY: Readonly<Record<Lang, [string, string]>> = { | |
| en: ['🇬🇧', 'English'], | |
| sv: ['🇸🇪', 'Svenska'], | |
| da: ['🇩🇰', 'Dansk'], | |
| no: ['🇳🇴', 'Norsk'], | |
| fi: ['🇫🇮', 'Suomi'], | |
| de: ['🇩🇪', 'Deutsch'], | |
| fr: ['🇫🇷', 'Français'], | |
| es: ['🇪🇸', 'Español'], | |
| nl: ['🇳🇱', 'Nederlands'], | |
| ar: ['🇸🇦', 'العربية'], | |
| he: ['🇮🇱', 'עברית'], | |
| ja: ['🇯🇵', '日本語'], | |
| ko: ['🇰🇷', '한국어'], | |
| zh: ['🇨🇳', '中文'], | |
| } as const; | |
| const LANG_SWITCHER_ARIA: Readonly<Record<Lang, string>> = { | |
| en: 'Language', sv: 'Språk', da: 'Sprog', no: 'Språk', | |
| fi: 'Kieli', de: 'Sprache', fr: 'Langue', es: 'Idioma', | |
| nl: 'Taal', ar: 'اللغة', he: 'שפה', ja: '言語', | |
| ko: '언어', zh: '语言', | |
| } as const; | |
| const BACK_TO_NEWS: Readonly<Record<Lang, string>> = { | |
| en: 'Back to News', sv: 'Tillbaka till nyheter', | |
| da: 'Tilbage til nyheder', no: 'Tilbake til nyheter', | |
| fi: 'Takaisin uutisiin', de: 'Zurück zu Nachrichten', | |
| fr: 'Retour aux actualités', es: 'Volver a noticias', | |
| nl: 'Terug naar nieuws', ar: 'العودة إلى الأخبار', | |
| he: 'חזרה לחדשות', ja: 'ニュースに戻る', | |
| ko: '뉴스로 돌아가기', zh: '返回新闻', | |
| } as const; | |
| import { | |
| ALL_LANG_CODES, | |
| LANG_DISPLAY as TEMPLATE_LANG_DISPLAY, | |
| LANG_SWITCHER_ARIA_LABELS, | |
| BACK_TO_NEWS as TEMPLATE_BACK_TO_NEWS, | |
| } from './article-template/helpers'; | |
| // ── Language configuration ──────────────────────────────────────────────── | |
| const LANGUAGES = ALL_LANG_CODES; | |
| type Lang = (typeof LANGUAGES)[number]; | |
| const LANG_DISPLAY: Readonly<Record<Lang, [string, string]>> = TEMPLATE_LANG_DISPLAY; | |
| const LANG_SWITCHER_ARIA: Readonly<Record<Lang, string>> = LANG_SWITCHER_ARIA_LABELS; | |
| const BACK_TO_NEWS: Readonly<Record<Lang, string>> = TEMPLATE_BACK_TO_NEWS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 5d66764. Removed all locally-duplicated language constants (LANGUAGES, LANG_DISPLAY, LANG_SWITCHER_ARIA, BACK_TO_NEWS, newsIndexFor, generateLanguageSwitcher) and now imports ALL_LANG_CODES, FOOTER_LABELS from ./article-template/constants.js and getNewsIndexFilename, generateArticleLanguageSwitcher from ./article-template/helpers.js.
Copilot
AI
Mar 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scripts/fix-article-navigation.ts introduces non-trivial HTML rewrite logic (switcher insertion/rewrite, top-nav insertion patterns, and --dry-run behavior) but has no direct unit tests. Given the repo has extensive Vitest coverage for other scripts, add tests that validate the transformation is idempotent and that both insertion patterns work on representative HTML inputs (including cases where switcher exists but top-nav/back-to-news is missing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 5d66764 as tests/fix-article-navigation.test.ts (15 tests). The string-transformation logic was extracted into an exported pure transformContent() function, making it testable without file I/O. Tests cover: switcher insertion position, 14-language generation, active-lang marking, Pattern A/B top-nav insertion, missing back-to-news repair, and idempotency across 4 fixture variants.
Copilot
AI
Mar 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
processArticle() only adds article-top-nav when it's completely missing (hasTopnav). If an article already contains article-top-nav but is missing the required .back-to-news link (or has a wrong/unstyled link), this script will not fix it even though the header comment says it ensures a localized back-to-news link. Consider checking for back-to-news separately and either inserting the missing anchor or regenerating/replacing the existing top-nav block when the link is absent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5d66764. transformContent() now checks when article-top-nav is present but has no back-to-news link, replaces the entire div with a freshly generated localized one, and reports the count as Top nav fixed (missing back-to-news link) in the summary.
Copilot
AI
Mar 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The summary prints “Language switchers added/updated”, but the counter is incremented only when a switcher is newly added (not when it’s updated/replaced). Either adjust the counter to include updates or change the summary label so the reported numbers are accurate.
| console.log(`Language switchers added/updated: ${switchersAdded}`); | |
| console.log(`Language switchers added: ${switchersAdded}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 41bce96 — label changed to Language switchers added: to match what the counter actually tracks.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,14 +26,19 @@ export default defineConfig({ | |
| reporter: ['text', 'html', 'lcov', 'json'], | ||
| reportsDirectory: './builds/coverage', | ||
|
|
||
| // Disabled: tests don't import dashboard modules (by design) | ||
| all: false, | ||
| // Enabled: include all source files so zero-coverage modules are visible | ||
| all: true, | ||
|
|
||
| // Coverage thresholds | ||
| lines: 70, | ||
| functions: 70, | ||
| branches: 60, | ||
| statements: 70, | ||
| // Coverage thresholds — intentionally low during transition while all:true | ||
| // exposes previously-hidden zero-coverage files. Raise incrementally as | ||
| // tests are added for the dashboard and browser modules. | ||
| // Target thresholds (raise as coverage improves): lines:70, functions:70, branches:60, statements:70 | ||
| thresholds: { | ||
| lines: 25, | ||
| functions: 20, | ||
| branches: 25, | ||
| statements: 25, | ||
|
Comment on lines
+32
to
+40
|
||
| }, | ||
|
|
||
| // Include patterns | ||
| include: [ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file is intended to be executed via
npx tsx ..., but it has a#!/usr/bin/env nodeshebang. If someone runs the script directly (e.g., makes it executable and calls it), Node will try to execute TypeScript and fail. Align the shebang with the documented execution method (e.g., use a tsx-compatible shebang) or remove the shebang to avoid accidental misuse.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 41bce96 — shebang updated to
#!/usr/bin/env -S npx tsx.