@accesslint/codemod
v0.1.2
Published
Codemod that migrates jest-axe projects to @accesslint/jest
Downloads
355
Maintainers
Readme
@accesslint/codemod
Automated migration from jest-axe, vitest-axe, and jasmine-axe to their AccessLint equivalents.
Quick start
# Migrate a jest-axe project
npx @accesslint/codemod jest-axe 'src/**/*.{test,spec}.{ts,tsx}'
# Migrate a vitest-axe project
npx @accesslint/codemod vitest-axe 'src/**/*.{test,spec}.{ts,tsx}'
# Auto-detect from package.json and run all applicable migrations
npx @accesslint/codemod auto 'src/**/*.{test,spec}.{ts,tsx}'Recommended flow: run with --dry --print first to inspect the diff, then rerun without --dry.
npx @accesslint/codemod jest-axe --dry --print 'src/**/*.test.tsx'Subcommands
| Subcommand | Source | Target |
| ------------- | ------------------- | ---------------------- |
| jest-axe | jest-axe | @accesslint/jest |
| vitest-axe | vitest-axe | @accesslint/vitest |
| jasmine-axe | jasmine-axe | @accesslint/jest |
| auto | detected from package.json | per-plugin |
What's transformed
Imports are rewritten to a side-effect import of the target package:
- import { axe, toHaveNoViolations } from "jest-axe"; + import "@accesslint/jest";Named, aliased, namespace, and CJS
require()forms are all recognized.expect.extend(toHaveNoViolations)is removed — the side-effect import auto-registers thetoBeAccessible()matcher. Identifier, object ({ toHaveNoViolations }), and spread ({ ...toHaveNoViolations }) forms are all handled.Two-statement pattern is collapsed:
- const results = await axe(container); - expect(results).toHaveNoViolations(); + expect(container).toBeAccessible();Inline pattern is collapsed:
- expect(await axe(container)).toHaveNoViolations(); + expect(container).toBeAccessible();
What's not transformed
configureAxe(...)globals — there is no per-project global in AccessLint; options are per-call. WhenconfigureAxeis imported, the codemod keeps the source import (forconfigureAxeonly), adds the target side-effect import, and prepends a TODO comment reminding you to reapply those options viatoBeAccessible({ disabledRules, failOn, ... }).axe rule IDs → AccessLint rule IDs —
axe(container, { rules: { "color-contrast": { enabled: false } } })is collapsed toexpect(container).toBeAccessible()with a TODO comment. AccessLint uses namespaced rule IDs (distinguishable/color-contrast); see the rule-ID mapping table in@accesslint/jest's README and reapply astoBeAccessible({ disabledRules: ["distinguishable/color-contrast"] }).Builder-shaped axe plugins —
@axe-core/playwright,@axe-core/webdriverjs,@axe-core/puppeteer, andcypress-axeuse a different API (new AxeBuilder({ page }).analyze()/cy.checkA11y(...)) and target@accesslint/playwright. These aren't supported in v0.1.
Flags
| Flag | Default | Meaning |
| ------------------------ | ------------------- | ------- |
| --dry | false | Don't write files; report what would change |
| --print | false | Print transformed source to stdout (use with --dry) |
| --parser=<name> | tsx | jscodeshift parser: babel, babylon, flow, ts, tsx |
| --extensions=<csv> | js,jsx,ts,tsx | Comma-separated list of file extensions to process |
| --verbose=<0\|1\|2> | 0 | Verbosity level |
After running
- Review any
TODO(accesslint-codemod):comments — those are the spots that need a human decision (typicallyconfigureAxeoptions or per-call axe rule filters). - Install the target package (the codemod doesn't touch your
package.json):npm install --save-dev @accesslint/jest # or @accesslint/vitest npm uninstall jest-axe # or vitest-axe / jasmine-axe - Run your test script and confirm nothing regressed. Some assertions may produce different violation counts because AccessLint and axe are independent rule implementations — see
@accesslint/jest's "What's different" notes.
License
MIT
