codebyplan 1.13.3 → 1.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/package.json +1 -1
- package/templates/hooks/README.md +3 -19
- package/templates/hooks/cbp-test-hooks.sh +1 -9
- package/templates/hooks/hooks.json +0 -11
- package/templates/skills/cbp-setup-eslint/SKILL.md +4 -3
- package/templates/skills/cbp-setup-eslint/reference/base.md +44 -55
- package/templates/skills/cbp-setup-eslint/reference/cli.md +43 -36
- package/templates/skills/cbp-setup-eslint/reference/e2e.md +57 -47
- package/templates/skills/cbp-setup-eslint/reference/jest.md +22 -38
- package/templates/skills/cbp-setup-eslint/reference/nestjs.md +39 -40
- package/templates/skills/cbp-setup-eslint/reference/nextjs.md +39 -40
- package/templates/skills/cbp-setup-eslint/reference/node.md +25 -54
- package/templates/skills/cbp-setup-eslint/reference/react-native.md +33 -37
- package/templates/skills/cbp-setup-eslint/reference/react.md +33 -58
- package/templates/skills/cbp-setup-eslint/reference/tailwind.md +45 -49
- package/templates/skills/cbp-setup-eslint/reference/testing-react.md +28 -37
- package/templates/skills/cbp-setup-eslint/reference/vitest.md +25 -45
- package/templates/hooks/cbp-notify.sh +0 -68
package/dist/cli.js
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The `codebyplan` npm package ships a small, portable set of Claude Code hooks. They run in your project, use only generic primitives (`git rev-parse`, `${CLAUDE_PROJECT_DIR}`, `${CLAUDE_PLUGIN_ROOT}`), and degrade gracefully (exit 0) when their preconditions aren't met.
|
|
4
4
|
|
|
5
|
-
Hook registration lives in [`hooks/hooks.json`](./hooks.json) — PreToolUse
|
|
5
|
+
Hook registration lives in [`hooks/hooks.json`](./hooks.json) — PreToolUse and PostToolUse events are wired. (`Notification`, `SessionStart`, `SessionEnd`, `Stop`, and `SubagentStop` are also schema-permitted but unused here.)
|
|
6
6
|
|
|
7
7
|
**`cbp-statusline.sh` is auto-wired via `settings.project.base.json`.** The `statusLine` block is shipped inside `templates/settings.project.base.json` and merged into the consumer's `.claude/settings.json` automatically by `codebyplan claude install` (and on every `codebyplan claude update`). No manual copy-paste is required.
|
|
8
8
|
|
|
@@ -176,22 +176,6 @@ Walks up from the edited file to the nearest `package.json` and uses that packag
|
|
|
176
176
|
|
|
177
177
|
---
|
|
178
178
|
|
|
179
|
-
### `notify.sh` — Notification, matcher `*`
|
|
180
|
-
|
|
181
|
-
Sends a desktop notification when Claude Code emits a notification event (waiting for input, task complete, etc.). Title is `[<project-name>] Claude Code`; body is the notification message; clicking the notification focuses VS Code at the project directory (macOS only).
|
|
182
|
-
|
|
183
|
-
**Cross-platform graceful skip**: exits 0 silently when `terminal-notifier` is not on `$PATH`. Linux, Windows, and macOS hosts without Homebrew see a no-op — no errors, no warnings.
|
|
184
|
-
|
|
185
|
-
**VS Code click action**: only attached when running on macOS (`$OSTYPE` matches `darwin*`) AND the `code` CLI is on `$PATH`. On other hosts the notification still fires but is non-clickable.
|
|
186
|
-
|
|
187
|
-
**Install hint** (macOS): `brew install terminal-notifier`. On other platforms the hook is a no-op — substitute your own notification mechanism via a settings.json override if desired.
|
|
188
|
-
|
|
189
|
-
**Blocks vs warns**: never blocks — exit 0 always. Notification hooks must never block Claude.
|
|
190
|
-
|
|
191
|
-
**Opt out**: settings.json override or plugin disable.
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
179
|
### `auto-test-hooks.sh` — PostToolUse, matcher `Edit|Write`
|
|
196
180
|
|
|
197
181
|
Triggers `test-hooks.sh` automatically when any `*/hooks/*.sh` file is edited. Catches accidental breakage of the plugin's own hooks (or your project's `.claude/hooks/` if you author your own) at edit time, before the broken hook runs against future tool calls.
|
|
@@ -244,9 +228,9 @@ After a `complete_round` MCP call succeeds, reconciles the round's `files_change
|
|
|
244
228
|
|
|
245
229
|
### `test-hooks.sh` — invoked by `auto-test-hooks.sh`
|
|
246
230
|
|
|
247
|
-
Test suite for the plugin's
|
|
231
|
+
Test suite for the plugin's 9 registered hooks. Runs two passes:
|
|
248
232
|
|
|
249
|
-
1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `
|
|
233
|
+
1. **Header check** — every registered hook (`lint-format-on-edit`, `test-coverage-gate`, `pre-commit-quality-gate`, `maestro-yaml-validate`, `auto-test-hooks`, `mcp-migration-guard`, `validate-git-stash-deny`, `cbp-mcp-round-sync`) carries the required `# Hook:` and `# Purpose:` header comments. `statusline` uses its own `# Claude Code Status Line` marker.
|
|
250
234
|
2. **Functional smoke tests** — each hook is invoked with synthetic stdin matching its fast-path / graceful-degrade input; all must exit 0.
|
|
251
235
|
|
|
252
236
|
Not in `hooks.json` — invoked indirectly via `auto-test-hooks.sh` on hook edits, or directly via `bash ${CLAUDE_PLUGIN_ROOT}/hooks/test-hooks.sh`.
|
|
@@ -62,7 +62,7 @@ for hook_file in "$HOOKS_DIR"/*.sh; do
|
|
|
62
62
|
|
|
63
63
|
# Check for header comments (required for documentation generation).
|
|
64
64
|
# Accept either marker convention used across the plugin's hooks:
|
|
65
|
-
# - "# Hook:" + "# Purpose:" (used by
|
|
65
|
+
# - "# Hook:" + "# Purpose:" (used by auto-test-hooks, etc.)
|
|
66
66
|
# - "# @event:" + a description line (used by maestro-yaml-validate, etc.)
|
|
67
67
|
if (grep -q '^# Hook:' "$hook_file" && grep -q '^# Purpose:' "$hook_file") \
|
|
68
68
|
|| grep -q '^# @event:' "$hook_file"; then
|
|
@@ -77,14 +77,6 @@ echo ""
|
|
|
77
77
|
# ===== FUNCTIONAL SMOKE TESTS =====
|
|
78
78
|
echo "## Functional Smoke Tests"
|
|
79
79
|
|
|
80
|
-
# cbp-notify.sh — graceful-degrade: exit 0 whether or not terminal-notifier is installed
|
|
81
|
-
ACTUAL_EXIT=$(echo '{"message":"test","cwd":"/tmp"}' | bash "$HOOKS_DIR/cbp-notify.sh" >/dev/null 2>&1; echo $?)
|
|
82
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
83
|
-
test_result "cbp-notify.sh graceful-degrade exits 0" "passed" "passed"
|
|
84
|
-
else
|
|
85
|
-
test_result "cbp-notify.sh graceful-degrade exits 0" "passed" "failed"
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
80
|
# cbp-lint-format-on-edit.sh — graceful-degrade: CLAUDE_PROJECT_DIR unset → exit 0
|
|
89
81
|
if [ ! -f "$HOOKS_DIR/cbp-lint-format-on-edit.sh" ]; then
|
|
90
82
|
test_result "cbp-lint-format-on-edit.sh present" "passed" "missing"
|
|
@@ -181,13 +181,14 @@ command + which apps still need their `eslint.config.mjs` generated.
|
|
|
181
181
|
`reference/*.md`, never silently skip
|
|
182
182
|
- `codebyplan eslint init` failure is non-fatal — print the manual command and still write eslint.json
|
|
183
183
|
- Atomic write (tmp + mv) — never leave eslint.json partial
|
|
184
|
-
- Reference docs
|
|
185
|
-
|
|
184
|
+
- Reference docs contain **only the official upstream ESLint setup** per stack (verbatim from each
|
|
185
|
+
tool's own docs) — they are not CBP preset opinions. `codebyplan eslint init` generates from the DB
|
|
186
|
+
presets, which may differ; the reference docs are the canonical official guidance
|
|
186
187
|
|
|
187
188
|
## Additional resources
|
|
188
189
|
|
|
189
190
|
- TypeScript foundation (ESLint v10 flat config): [reference/base.md](reference/base.md)
|
|
190
|
-
- Next.js: [reference/nextjs.md](reference/nextjs.md) · React
|
|
191
|
+
- Next.js: [reference/nextjs.md](reference/nextjs.md) · React: [reference/react.md](reference/react.md)
|
|
191
192
|
- Node / Hono / Express: [reference/node.md](reference/node.md) · NestJS: [reference/nestjs.md](reference/nestjs.md)
|
|
192
193
|
- CLI tools: [reference/cli.md](reference/cli.md) · Tailwind CSS: [reference/tailwind.md](reference/tailwind.md)
|
|
193
194
|
- React Native / Expo: [reference/react-native.md](reference/react-native.md)
|
|
@@ -1,82 +1,71 @@
|
|
|
1
|
-
# base — TypeScript
|
|
1
|
+
# base — TypeScript (official typescript-eslint setup)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
> **Official source**: https://typescript-eslint.io/getting-started/ (+ typed-linting). Verified
|
|
4
|
+
> 2026-05-31. ESLint flat config (`eslint.config.mjs`). This is the typescript-eslint quickstart
|
|
5
|
+
> verbatim — no additions.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
> only native format (legacy `.eslintrc*` was removed). `defineConfig` from `eslint/config`
|
|
9
|
-
> is the canonical wrapper for every stack below.
|
|
7
|
+
The foundation for any TypeScript project.
|
|
10
8
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
| Package | Latest | Purpose |
|
|
14
|
-
| ------- | ------ | ------- |
|
|
15
|
-
| `eslint` | `10.4.1` | the linter (flat config only) |
|
|
16
|
-
| `@eslint/js` | `10.0.1` | `js.configs.recommended` |
|
|
17
|
-
| `typescript-eslint` | `8.60.0` | unified parser + plugin + presets |
|
|
18
|
-
| `eslint-config-prettier` | `10.x` | turns off formatting rules (subpath `/flat`) |
|
|
19
|
-
| `eslint-plugin-security` | `^3` | OWASP-style heuristics |
|
|
20
|
-
| `eslint-plugin-no-secrets` | `^2.1` | high-entropy string detection |
|
|
21
|
-
| `globals` | `17.6.0` | env global definitions |
|
|
9
|
+
## Install
|
|
22
10
|
|
|
23
11
|
```bash
|
|
24
|
-
|
|
25
|
-
eslint-plugin-security eslint-plugin-no-secrets globals
|
|
12
|
+
npm install --save-dev eslint @eslint/js typescript typescript-eslint
|
|
26
13
|
```
|
|
27
14
|
|
|
28
|
-
##
|
|
15
|
+
## eslint.config.mjs — quickstart (no type info)
|
|
29
16
|
|
|
30
17
|
```js
|
|
31
|
-
//
|
|
18
|
+
// @ts-check
|
|
19
|
+
import js from "@eslint/js";
|
|
32
20
|
import { defineConfig } from "eslint/config";
|
|
21
|
+
import tseslint from "typescript-eslint";
|
|
22
|
+
|
|
23
|
+
export default defineConfig(
|
|
24
|
+
js.configs.recommended,
|
|
25
|
+
tseslint.configs.recommended,
|
|
26
|
+
);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## eslint.config.mjs — typed linting (recommended by typescript-eslint)
|
|
30
|
+
|
|
31
|
+
```js
|
|
33
32
|
import js from "@eslint/js";
|
|
33
|
+
import { defineConfig } from "eslint/config";
|
|
34
34
|
import tseslint from "typescript-eslint";
|
|
35
|
-
import security from "eslint-plugin-security";
|
|
36
|
-
import noSecrets from "eslint-plugin-no-secrets";
|
|
37
|
-
import prettier from "eslint-config-prettier/flat";
|
|
38
35
|
|
|
39
|
-
export default defineConfig(
|
|
36
|
+
export default defineConfig(
|
|
40
37
|
js.configs.recommended,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{ plugins: { "no-secrets": noSecrets }, rules: { "no-secrets/no-secrets": ["warn", { tolerance: 4.5 }] } },
|
|
38
|
+
tseslint.configs.recommended,
|
|
39
|
+
tseslint.configs.recommendedTypeChecked,
|
|
44
40
|
{
|
|
45
41
|
languageOptions: {
|
|
46
42
|
parserOptions: {
|
|
47
|
-
projectService: true,
|
|
48
|
-
tsconfigRootDir: import.meta.dirname,
|
|
43
|
+
projectService: true,
|
|
49
44
|
},
|
|
50
45
|
},
|
|
51
46
|
},
|
|
52
|
-
|
|
53
|
-
prettier, // MUST be last
|
|
54
|
-
]);
|
|
47
|
+
);
|
|
55
48
|
```
|
|
56
49
|
|
|
57
|
-
##
|
|
50
|
+
## Run
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
config files with `tseslint.configs.disableTypeChecked`.
|
|
63
|
-
- **`projectService: true`** replaces the old `project: "./tsconfig.json"`. It auto-finds the
|
|
64
|
-
nearest `tsconfig.json` per file and lints out-of-project files (like `eslint.config.mjs`)
|
|
65
|
-
without a `tsconfig.eslint.json`. Always pair it with `tsconfigRootDir: import.meta.dirname`.
|
|
66
|
-
- **`tseslint.config()` is deprecated** in favour of core `defineConfig` from `eslint/config`
|
|
67
|
-
(a near-exact clone). The `tseslint.configs.*` presets are unchanged.
|
|
68
|
-
- **Prettier last.** `eslint-config-prettier/flat` must come after every rule-defining config
|
|
69
|
-
so it can switch off conflicting stylistic rules.
|
|
52
|
+
```bash
|
|
53
|
+
npx eslint .
|
|
54
|
+
```
|
|
70
55
|
|
|
71
|
-
##
|
|
56
|
+
## Notes (from the official docs)
|
|
72
57
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
58
|
+
- The base recommended config is `js.configs.recommended` (from `@eslint/js`, imported as `js`) —
|
|
59
|
+
**not** `eslint.configs.recommended`. `defineConfig` is imported from `eslint/config`.
|
|
60
|
+
- `tseslint.configs.recommendedTypeChecked` adds rules that **require type information**; enable it
|
|
61
|
+
with `parserOptions.projectService: true`.
|
|
62
|
+
- typescript-eslint *"strongly recommend[s] you do use type-aware linting,"* while noting it incurs a
|
|
63
|
+
performance penalty (TypeScript builds the project before ESLint lints).
|
|
64
|
+
- `// @ts-check` type-checks the config file itself (optional). Use `eslint.config.js` if
|
|
65
|
+
`package.json` has `"type": "module"`.
|
|
66
|
+
- Stricter presets are available: `strict` / `strictTypeChecked`, `stylistic` / `stylisticTypeChecked`.
|
|
77
67
|
|
|
78
|
-
##
|
|
68
|
+
## Source
|
|
79
69
|
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
- `projectService`: https://typescript-eslint.io/blog/project-service/
|
|
70
|
+
- https://typescript-eslint.io/getting-started/
|
|
71
|
+
- https://typescript-eslint.io/getting-started/typed-linting/
|
|
@@ -1,56 +1,63 @@
|
|
|
1
|
-
# cli — Node CLI tool
|
|
1
|
+
# cli — Node CLI tool (convention — no official preset)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
> **There is no official "CLI" ESLint config or preset.** Neither ESLint nor Node publishes one. A
|
|
4
|
+
> "CLI config" is a convention: a scoped `files` override inside your normal flat config that relaxes
|
|
5
|
+
> a few rules a CLI legitimately trips. Only the individual official rule/plugin docs below are
|
|
6
|
+
> authoritative (verified 2026-05-31).
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
> rule-override block.
|
|
8
|
+
## What a CLI override does
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
A CLI legitimately (a) talks to the user via `console`, and (b) operates on user-supplied
|
|
13
|
-
filesystem paths and dynamic keys — so the `eslint-plugin-security` heuristics that flag those
|
|
14
|
-
produce noise, not findings. Relax them, **scoped narrowly** to the CLI surface.
|
|
15
|
-
|
|
16
|
-
## Flat config (override block)
|
|
10
|
+
A CLI prints to stdout/stderr and operates on user-supplied paths, so two official rules are commonly
|
|
11
|
+
relaxed **scoped to the CLI source**:
|
|
17
12
|
|
|
18
13
|
```js
|
|
19
|
-
// eslint.config.mjs — appended after base
|
|
14
|
+
// eslint.config.mjs — appended after your base config
|
|
20
15
|
export default [
|
|
21
|
-
// ...base
|
|
16
|
+
// ...your base config (e.g. typescript-eslint, see base.md)...
|
|
22
17
|
{
|
|
23
|
-
files: ["bin
|
|
18
|
+
files: ["bin/**", "src/cli/**"],
|
|
24
19
|
rules: {
|
|
25
|
-
"no-console": "off",
|
|
26
|
-
|
|
27
|
-
// CLIs operate on user paths and dynamic keys by design:
|
|
20
|
+
"no-console": "off",
|
|
21
|
+
// only if eslint-plugin-security is installed (see below):
|
|
28
22
|
"security/detect-non-literal-fs-filename": "off",
|
|
29
23
|
"security/detect-object-injection": "off",
|
|
30
|
-
|
|
31
|
-
// optional, if eslint-plugin-n is in use (CLIs call process.exit):
|
|
32
|
-
// "n/no-process-exit": "off",
|
|
33
24
|
},
|
|
34
25
|
},
|
|
35
26
|
];
|
|
36
27
|
```
|
|
37
28
|
|
|
38
|
-
##
|
|
29
|
+
## Official sources for the individual rules
|
|
30
|
+
|
|
31
|
+
### `no-console` (core ESLint rule)
|
|
32
|
+
Disallows `console` calls (treated as debugging output). It is **off** in `eslint:recommended`, so you
|
|
33
|
+
only need to turn it `off` if your base config enabled it. The rule page shows the inline form, e.g.:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Source: https://eslint.org/docs/latest/rules/no-console
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
### `eslint-plugin-security` (official community plugin)
|
|
42
|
+
The `security/*` rules above exist only if this plugin is installed and registered:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install --save-dev eslint-plugin-security
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
const pluginSecurity = require('eslint-plugin-security');
|
|
50
|
+
module.exports = [pluginSecurity.configs.recommended];
|
|
51
|
+
```
|
|
45
52
|
|
|
46
|
-
|
|
53
|
+
Its README notes the plugin *"finds a lot of false positives which need triage by a human"* — which is
|
|
54
|
+
why CLIs relax `detect-non-literal-fs-filename` / `detect-object-injection` on user-path code.
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
`security/detect-non-literal-fs-filename`, `security/detect-object-injection` all off) and is
|
|
50
|
-
capability-gated on `cli-bin`. The repo's own `packages/codebyplan-package/eslint.config.mjs`
|
|
51
|
-
already applies this. No divergence — this doc just documents the convention.
|
|
56
|
+
Source: https://github.com/eslint-community/eslint-plugin-security
|
|
52
57
|
|
|
53
|
-
##
|
|
58
|
+
## Notes
|
|
54
59
|
|
|
55
|
-
-
|
|
56
|
-
|
|
60
|
+
- Keep the relaxations **narrowly scoped via `files`** — do not disable these repo-wide.
|
|
61
|
+
- If your project does not use `eslint-plugin-security`, only the `no-console: "off"` line applies.
|
|
62
|
+
- The ESLint `no-console` page does **not** ship a full standalone `eslint.config.mjs` example — only
|
|
63
|
+
the inline-comment and `rules`-object forms shown above.
|
|
@@ -1,68 +1,78 @@
|
|
|
1
|
-
# e2e — Playwright / WebdriverIO / Mocha
|
|
1
|
+
# e2e — Playwright / WebdriverIO / Mocha (official setups)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
> **Official sources** (verified 2026-05-31):
|
|
4
|
+
> - Playwright — https://github.com/mskelton/eslint-plugin-playwright
|
|
5
|
+
> - WebdriverIO — https://github.com/webdriverio/webdriverio/tree/main/packages/eslint-plugin-wdio
|
|
6
|
+
> - Mocha — https://github.com/lo1tuma/eslint-plugin-mocha
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
> sometimes returns); Mocha 11.x uses **`configs.recommended`** — NOT `configs.flat.recommended`.
|
|
8
|
+
Each E2E runner has its own official plugin. Use the one(s) matching your test runner.
|
|
10
9
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
| Package | Latest | Flat key |
|
|
14
|
-
| ------- | ------ | -------- |
|
|
15
|
-
| `eslint-plugin-playwright` | `2.10.4` | `configs['flat/recommended']` |
|
|
16
|
-
| `eslint-plugin-wdio` | `9.27.2` | `configs['flat/recommended']` |
|
|
17
|
-
| `eslint-plugin-mocha` | `11.3.0` | `configs.recommended` (NOT `.flat`) |
|
|
10
|
+
## Playwright
|
|
18
11
|
|
|
19
12
|
```bash
|
|
20
|
-
|
|
21
|
-
pnpm add -D eslint-plugin-wdio eslint-plugin-mocha # Tauri / WebdriverIO desktop
|
|
13
|
+
npm install -D eslint-plugin-playwright
|
|
22
14
|
```
|
|
23
15
|
|
|
24
|
-
## Flat config
|
|
25
|
-
|
|
26
16
|
```js
|
|
27
|
-
|
|
17
|
+
import { defineConfig } from "@eslint/config";
|
|
28
18
|
import playwright from "eslint-plugin-playwright";
|
|
29
|
-
// desktop: import { configs as wdioConfigs } from "eslint-plugin-wdio";
|
|
30
|
-
// desktop: import mocha from "eslint-plugin-mocha";
|
|
31
19
|
|
|
32
|
-
export default [
|
|
33
|
-
// Playwright — scope to the web e2e dir
|
|
20
|
+
export default defineConfig([
|
|
34
21
|
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
rules: {
|
|
22
|
+
files: ["tests/**"],
|
|
23
|
+
extends: [playwright.configs["flat/recommended"]],
|
|
24
|
+
rules: {
|
|
25
|
+
// Customize Playwright rules
|
|
26
|
+
},
|
|
38
27
|
},
|
|
28
|
+
]);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Key: **`playwright.configs["flat/recommended"]`**. The README notes you may need to change `files` to
|
|
32
|
+
match your Playwright test patterns.
|
|
33
|
+
|
|
34
|
+
## WebdriverIO
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install eslint-plugin-wdio --save-dev
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
// eslint.config.mjs
|
|
42
|
+
import { configs as wdioConfig } from "eslint-plugin-wdio";
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// { ...mocha.configs.recommended, files: ["test/**/*.{ts,js}"] },
|
|
44
|
+
export default [
|
|
45
|
+
wdioConfig["flat/recommended"],
|
|
43
46
|
];
|
|
44
47
|
```
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
Key: **`configs["flat/recommended"]`**. Requires ESLint v9 + flat config.
|
|
50
|
+
|
|
51
|
+
## Mocha
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm install --save-dev eslint-plugin-mocha
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
import mochaPlugin from "eslint-plugin-mocha";
|
|
59
|
+
|
|
60
|
+
export default [
|
|
61
|
+
mochaPlugin.configs.recommended, // or `mochaPlugin.configs.all`
|
|
62
|
+
];
|
|
63
|
+
```
|
|
47
64
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
`undefined` in 11.x (it only exists on the unreleased 12.x main branch) and crashes config
|
|
52
|
-
load. Don't copy a `.flat.recommended` example.
|
|
53
|
-
- **WebdriverIO**: `eslint-plugin-wdio@9` requires ESLint 9+; when `typescript-eslint` is
|
|
54
|
-
present its recommended config auto-swaps `wdio/await-expect` → `wdio/no-floating-promise`.
|
|
55
|
-
- The CBP web app keeps Playwright specs in `e2e/**` with a Vitest sibling override for
|
|
56
|
-
`e2e/**/__tests__/**` — mirror that split if you co-locate unit tests under `e2e/`.
|
|
65
|
+
Key (latest published v11.x): **`mochaPlugin.configs.recommended`** — **NOT** `configs.flat.recommended`
|
|
66
|
+
and **NOT** `configs["flat/recommended"]`. Plain dot-notation, no `flat` segment. Scope to your spec
|
|
67
|
+
files via a `{ files: [...], ...mochaPlugin.configs.recommended }` wrapper if needed.
|
|
57
68
|
|
|
58
|
-
##
|
|
69
|
+
## Notes (from the official docs)
|
|
59
70
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
- Scope each runner's config to its test directory via `files` so the rules don't bleed onto other
|
|
72
|
+
files.
|
|
73
|
+
- **No `flat/` prefix** on the key: Mocha (`configs.recommended`). **Bracketed `flat/` key**:
|
|
74
|
+
Playwright, WebdriverIO. Mocha's README is flat-config only (no legacy `.eslintrc` shown).
|
|
63
75
|
|
|
64
|
-
##
|
|
76
|
+
## Source
|
|
65
77
|
|
|
66
|
-
|
|
67
|
-
- WebdriverIO: https://github.com/webdriverio/webdriverio/tree/main/packages/eslint-plugin-wdio
|
|
68
|
-
- Mocha: https://github.com/lo1tuma/eslint-plugin-mocha
|
|
78
|
+
See the three URLs above.
|
|
@@ -1,59 +1,43 @@
|
|
|
1
|
-
# jest — Jest test-
|
|
1
|
+
# jest — Jest test files (official eslint-plugin-jest setup)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
override on top of [base](base.md).
|
|
3
|
+
> **Official source**: https://github.com/jest-community/eslint-plugin-jest (verified 2026-05-31). This
|
|
4
|
+
> is the plugin's official flat-config usage.
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
> `configs['flat/recommended']` / `['flat/style']` (the un-prefixed keys are legacy eslintrc).
|
|
9
|
-
|
|
10
|
-
## Packages
|
|
11
|
-
|
|
12
|
-
| Package | Latest | Purpose |
|
|
13
|
-
| ------- | ------ | ------- |
|
|
14
|
-
| `eslint-plugin-jest` | `29.15.2` | Jest rules |
|
|
6
|
+
## Install
|
|
15
7
|
|
|
16
8
|
```bash
|
|
17
|
-
|
|
9
|
+
npm install --save-dev eslint eslint-plugin-jest
|
|
18
10
|
```
|
|
19
11
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## Flat config
|
|
12
|
+
## eslint.config.mjs — recommended config
|
|
23
13
|
|
|
24
14
|
```js
|
|
25
|
-
// eslint.config.mjs
|
|
26
15
|
import jest from "eslint-plugin-jest";
|
|
27
16
|
|
|
28
17
|
export default [
|
|
29
18
|
{
|
|
30
|
-
|
|
19
|
+
// update this to match your test files
|
|
20
|
+
files: ["**/*.spec.js", "**/*.test.js"],
|
|
31
21
|
...jest.configs["flat/recommended"],
|
|
32
|
-
rules: {
|
|
33
|
-
...jest.configs["flat/recommended"].rules,
|
|
34
|
-
...jest.configs["flat/style"].rules, // optional stylistic rules
|
|
35
|
-
// type-aware: hand the unbound-method check to the jest-aware version
|
|
36
|
-
"@typescript-eslint/unbound-method": "off",
|
|
37
|
-
"jest/unbound-method": "error",
|
|
38
|
-
},
|
|
39
22
|
},
|
|
40
23
|
];
|
|
41
24
|
```
|
|
42
25
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- Keys are **`configs['flat/recommended']`** / **`['flat/style']`** (bracketed) — the
|
|
46
|
-
unprefixed `configs.recommended` is the legacy eslintrc preset.
|
|
47
|
-
- **`jest/unbound-method`** extends `@typescript-eslint/unbound-method`; turn the base rule
|
|
48
|
-
off on test files and enable the jest version (needs `@typescript-eslint/parser` + type
|
|
49
|
-
info). Type-aware jest rules safely no-op when type info is absent.
|
|
50
|
-
- Avoid pinning `flat/all` long-term — it enables every rule and can break on minor releases.
|
|
26
|
+
The README's manual-rules example registers globals explicitly:
|
|
27
|
+
`languageOptions: { globals: jest.environments.globals.globals }`.
|
|
51
28
|
|
|
52
|
-
##
|
|
29
|
+
## Notes (from the official docs)
|
|
53
30
|
|
|
54
|
-
|
|
55
|
-
|
|
31
|
+
- Config keys: **`jest.configs["flat/recommended"]`** and **`jest.configs["flat/style"]`** (the
|
|
32
|
+
`flat/`-prefixed keys are the flat-config ones; unprefixed keys are legacy `.eslintrc`).
|
|
33
|
+
- Rules assume test files, so the README says it's *"generally not suitable to include them in your
|
|
34
|
+
top-level configuration"* — scope with `files`/`ignores`.
|
|
35
|
+
- **Type-aware `unbound-method`**: the README notes *"`unbound-method` depends on
|
|
36
|
+
`@typescript-eslint/eslint-plugin`, as it extends the original `unbound-method` rule."* To use it you
|
|
37
|
+
need `@typescript-eslint/parser` with type info, and you turn off the base rule in favour of
|
|
38
|
+
`jest/unbound-method`.
|
|
39
|
+
- The README shows both legacy `.eslintrc` and flat config.
|
|
56
40
|
|
|
57
|
-
##
|
|
41
|
+
## Source
|
|
58
42
|
|
|
59
|
-
-
|
|
43
|
+
- https://github.com/jest-community/eslint-plugin-jest
|