ci: Vitest unit tests + ESLint + GitHub Actions (CI & release)#24
Merged
Conversation
ce092e7 to
e1ba8f6
Compare
Test infrastructure ------------------- - Vitest + happy-dom: 5 test files, 83 unit tests covering ContentExtractor (cleanText keeping Unicode scripts, detectPageType edge cases, title extraction), TechniqueAnalyzer (risk bands, keyword matching boundaries, weight escalation), SuspiciousSitesManager (exact/contains/pattern matching plus the Storm1516 social-account format, handle extraction, logging gate), UIManager (escapeHtml, sanitizeHexColor, isSafeHttpUrl, adjustColor clamp, tooltip), and manifest sanity (JSON validity, declared paths exist). - tests/helpers/loadScript.js loads each content-script source as it would run in Chrome (indirect eval inside happy-dom's window), keeping the production code unchanged. Source-side adjustments to make the modules testable ---------------------------------------------------- - Suspicioussitesmanager.js: expose `window.SuspiciousSitesManager` (the class, in addition to the instance). Gate the "no databases loaded" warning behind DIMA_DEBUG — same noise-reduction rationale as the previous review pass. Tidy an unused destructure variable. Tooling ------- - package.json with vitest, happy-dom, eslint, globals; scripts: test, test:watch, test:coverage, lint, lint:fix, ci. - eslint.config.js (flat config): browser globals for source, node + vitest globals for tests, no-eq-eq smart, no-redeclare disabled because database files declare their own globals at top level. - vitest.config.js: happy-dom env, coverage scoped to modules/ + content.js. - .gitignore. GitHub Actions -------------- - ci.yml: lint + tests on every push to main and every PR. - release.yml: on tag v*.*.*, verify tag matches manifest.version, run npm ci, zip the runtime files (manifest, content.js, modules/, data/, docs, README, LICENSE, icons), upload as workflow artifact and create a draft GitHub release. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
contentExtractor.test.js — add three cases that exercise the matchStem switch on `article` and `blog`: - /articles/foo -> news - /blogs/post -> blog - blogs.example.com -> blog animations.test.js — new file. Scans content.js for @Keyframes declarations and uiManager.js for `animation:` references, asserting that every name begins with `dima`. Prevents a future change from re-introducing a generic keyframe name (fadeIn, slideIn, ...) that would collide with the host page's CSS namespace. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
accessibility.test.js — exercise createButton() against happy-dom and
assert that the rendered badge:
- carries role=button and tabindex=0
- exposes an aria-label including score and risk level
- hides the decorative 🧠 from screen readers
- fires showModal on Enter and on Space
- preventDefault on Space (so the host page doesn't scroll)
- ignores unrelated keys
syncInit.test.js — guard the bootstrap of Suspicioussitesmanager.js:
- no setTimeout(...) call in the init block (comments are stripped
so the historical note explaining why the delay was removed
doesn't trip the assertion)
- window.checkSuspiciousSite is callable immediately after the
module is loaded (no async wait)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e1ba8f6 to
8ac91c8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack sur la PR de review (#23). Contient l'infra qualité qui manquait au projet.
Pourquoi cette PR
Le repo n'avait ni tests, ni lint, ni workflow. Cette PR pose une base minimale mais sérieuse pour:
.zipChrome de release automatiquement à partir d'un tag.Ce qui est ajouté
Tests (
tests/)Vitest + happy-dom, 5 fichiers, 83 tests, ~1.5s :
contentExtractor.test.js—cleanTextpréserve cyrillique/chinois/arabe (régression locked-in),detectPageType(14 cas dont edge cases tels quebusinessnews.example.com → generaletexample.com/products/12 → commerce),extractTitle,shouldSkipElement(pattern strict avec frontières[-_]|$)techniqueAnalyzer.test.js— bandes de scoreFaible/Modéré/Élevé/Très Élevé/Critique,findKeywordMatches(frontières de mot, multi-mots, multi-occurrences, case-insensitive), pondération contextuelle (TE0153 sur news → 1.4, TE0221 sur social → 1.6), pondération dynamique (escalade selon occurrences, bonus techniques critiques), cap du score global à 100, filtrage tactique/techniquesuspiciousSitesManager.test.js—checkSitepour les 3matchType(exact/contains/pattern), format Storm1516 natif sur X/Twitter et Telegram, refus si plateforme incompatible,extractSocialHandle,getRiskConfig(4 niveaux), gating console.log derrièreDIMA_DEBUGuiManager.test.js—escapeHtml(XSS),sanitizeHexColor(rejette shorthand, named colors, payloads d'injection CSS),isSafeHttpUrl(rejettejavascript:/data:/file:),adjustColor(clamp black/white),generateTooltipmanifest.test.js— JSON valide, MV3, chaque chemin déclaré (content_scripts, icons, web_accessible_resources) existe sur disqueLoader (
tests/helpers/loadScript.js) : les content scripts du plugin exposent leurs classes viawindow.X = X. Unevalindirect dans lewindowhappy-dom de Vitest les rend disponibles sans modifier la source.Lint
eslint.config.js(flat config, ESLint 9) — globals navigateur pour la source, globals Node + Vitest pour les tests,eqeqeq: smart. 0 erreur, 0 warning.Workflows GitHub Actions
.github/workflows/ci.yml— sur chaque pushmainet chaque PR :npm cinpm run lintnpm testmanifest.jsonparseable.github/workflows/release.yml— sur tagv*.*.*:manifest.version(sinon erreur explicite)manifest.json,content.js,modules/,data/,documentation/,README.md,LICENSE, icônes — pas denode_modules, pas de tests)Source touchée
Une seule modif côté source pour rendre la classe testable :
modules/Suspicioussitesmanager.js: exposewindow.SuspiciousSitesManager(la classe, pas seulement l'instance) + gate duconsole.warn"aucune base chargée" derrièreDIMA_DEBUG(cohérent avec le reste).Comment l'utiliser
Localement :
Pour publier une version :
Base
Cette branche part de
review/code-review-fixes(#23) — les tests verrouillent les comportements corrigés là-bas (UnicodecleanText,escapeHtml,sanitizeHexColor,detectPageTypestrict). À merger après #23.🤖 Generated with Claude Code