Skip to content

TypeScript Quality Tools -- Stryker and SonarJS

Status: Requested — validated on experimental branch Repository: arda-frontend-app Validated branch: jmpicnic/stryker-exp

Two complementary quality tools have been validated for adoption:

  • Stryker — mutation testing. Makes small automated changes to production code (mutants) and runs tests. Surviving mutants reveal test gaps.
  • SonarJS — complexity metrics. Measures cognitive and cyclomatic complexity via ESLint rules.

The SonarJS portion has a full proposal at SonarJS Integration and is ready to implement. The Stryker portion is still in the requested state.

Stryker creates thousands of small source mutations (flip operators, replace strings, remove blocks), runs the test suite for each, and identifies “surviving” mutants — mutations that did not cause any test to fail. Surviving mutants indicate gaps in test effectiveness.

Mutation score = (killed + timeout) / total mutants. Focus on the production code score.

Trial run on itemFormValidator.ts: 85.71% mutation score (6 killed, 1 survived, 4 TS errors). The surviving mutant was typeof form.name === 'string' replaced with true — no test covers the non-string case.

Known Restrictions (Next.js + Stryker SWC)

Section titled “Known Restrictions (Next.js + Stryker SWC)”

Stryker’s instrumenter breaks three Next.js SWC compile-time validations. Three files must be excluded from mutation:

FileIssue
src/app/order-queue/page.tsxnext/dynamic() options must be object literal
src/app/receiving/page.tsxSame as above
src/components/ui/loader.tsx<style jsx> children must be template literals

These files are still tested — just not mutated. The exclusions can be removed if SWC compatibility improves.

  • stryker.config.mjs — main config with Jest runner, TypeScript checker, HTML reporter.
  • jest.config.stryker.js — restricted Jest config that skips src/tests/ and mocks next/dynamic.
  • tsconfig.stryker.json — excludes test/mock/e2e files for the TypeScript checker.
  • __mocks__/next/dynamic.js — mock to avoid SWC validation errors.

Recommended: PR-scoped mutation testing (only files changed in the PR). Full codebase runs (35,000+ mutants) take 13-20 hours on a 4-core machine and are suited for weekly scheduled jobs.

  1. Week 1: Establish baselines with permissive thresholds (SonarJS cognitive 25, cyclomatic 20; no Stryker break threshold).
  2. Weeks 2-4: Fix worst hotspots. Run scoped Stryker on src/lib/ to establish mutation score baseline.
  3. Month 2: Tighten SonarJS thresholds (cognitive 20, cyclomatic 15). Set thresholds.break: 60 for Stryker on src/lib/.
  4. Ongoing: Add Stryker PR gate. Ratchet SonarJS --max-warnings down each sprint.