eslint-plugin-test-governance 0.12.0 → 0.12.1

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/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ All notable changes to this project are documented here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.12.1] - 2026-11-04
10
+
11
+ ### Fixed
12
+
13
+ - `node:test`'s `tags` option, added in Node 26.2, is read like Vitest's: `{ tags: ['new'] }` puts a test or
14
+ describe in the `@new` state, also when the options come first, as in `test({ tags: ['new'] }, fn)`. The README
15
+ now also says that `fail` exists in `node:test`, where `test.expectFailure` and `{ expectFailure }` already put a
16
+ test in it.
17
+
9
18
  ## [0.12.0] - 2026-11-04
10
19
 
11
20
  ### Added
@@ -484,7 +493,8 @@ First release.
484
493
  - Support for ESLint 9 and 10 flat config, JavaScript and TypeScript test files, `.extend()`
485
494
  fixtures, describe blocks, runtime skips and tags in titles or the `tag` option.
486
495
 
487
- [Unreleased]: https://github.com/Huldoser/eslint-plugin-test-governance/compare/v0.12.0...HEAD
496
+ [Unreleased]: https://github.com/Huldoser/eslint-plugin-test-governance/compare/v0.12.1...HEAD
497
+ [0.12.1]: https://github.com/Huldoser/eslint-plugin-test-governance/compare/v0.12.0...v0.12.1
488
498
  [0.12.0]: https://github.com/Huldoser/eslint-plugin-test-governance/compare/v0.11.1...v0.12.0
489
499
  [0.11.1]: https://github.com/Huldoser/eslint-plugin-test-governance/compare/v0.11.0...v0.11.1
490
500
  [0.11.0]: https://github.com/Huldoser/eslint-plugin-test-governance/compare/v0.10.1...v0.11.0
package/README.md CHANGED
@@ -161,8 +161,9 @@ as is `xit('title')` in Jasmine.
161
161
  In Mocha, `this.skip()` counts in a test or hook written as a `function`; an arrow function gets no
162
162
  Mocha context, so its `this` is not the test's. `this.slow(ms)` only sets Mocha's speed threshold, so
163
163
  it isn't the `slow` state.
164
- Vitest writes tag names without the `@`, as in `{ tags: ['flaky'] }`, so a name in `tags` counts as the
165
- tag with an `@` in front: `'flaky'` is `@flaky`, and a custom state with `when: '@flaky'` matches it.
164
+ Vitest, and `node:test` since Node 26.2, write tag names without the `@`, as in `{ tags: ['flaky'] }`, so a
165
+ name in `tags` counts as the tag with an `@` in front: `'flaky'` is `@flaky`, and a custom state with
166
+ `when: '@flaky'` matches it.
166
167
  In `node:test`, an option counts with any value but `false` or `undefined`, as Node reads it, so
167
168
  `{ skip: 'broker sandbox is down' }` always skips. `t.skip()` and `t.todo()` take a message, not a
168
169
  condition, and in a test or hook written as a `function`, `this.skip()` and `this.todo()` do the same.
@@ -232,21 +233,21 @@ yourself. `framework` is required, and every other option has a default. The rul
232
233
  of their own: they all read these shared settings, so they always agree on ticket formats, states
233
234
  and markers. To turn a rule off, set it to `'off'` as usual.
234
235
 
235
- | Option | Type | Default | Description |
236
- | ----------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
237
- | `framework` | `'playwright' \| 'jest' \| 'vitest' \| 'mocha' \| 'cypress' \| 'webdriverio' \| 'node-test' \| 'jasmine'` | required | The test framework of the files the config applies to. Each framework's config, such as `configs.playwright`, sets it, and `configure()` needs it. See [Frameworks](#frameworks). |
238
- | `ticket` | `TicketSpec \| TicketSpec[]` | `{ preset: 'any' }` | Accepted ticket formats. An array accepts a ticket that matches any entry. See [Ticket presets](#ticket-presets). |
239
- | `placeholders` | `string[]` | see above | Tickets rejected as placeholders. `*` matches any characters. Case-insensitive; a leading `#` is ignored. Your list replaces the default one, so repeat the defaults you want to keep. Tickets numbered 0 are always rejected. |
240
- | `lifecycleTags` | `boolean` | `false` | Turns on the `new` (`@new`) and `quarantined` (`@quarantined`) states. |
241
- | `states` | `{ [state]: boolean \| { enabled?, tag?, marker?, ticket? } }` | `skip`, `fixme` and `todo` on | Turns built-in states (`skip`, `fixme`, `fail`, `slow`, `todo`, `retry`, `new`, `quarantined`) on or off, renames their tag or marker, or gives them their own ticket format. `fail`, `slow` and `retry` are off by default; a setting for `new` or `quarantined` here wins over `lifecycleTags`. Only `new` and `quarantined` have a tag to rename; see [Tag names](#tag-names). `fixme` and `slow` exist only in Playwright, `todo` in every framework but Playwright, `fail` in Playwright, Jest and Vitest, and `retry` in every framework but node:test and Jasmine, so turning one on elsewhere has no effect. |
242
- | `customStates` | `{ [name]: { when, marker, ticket? } }` | `{}` | Adds a state for a tag, e.g. `{ 'needs-data': { when: '@needs-data', marker: 'NEEDS-DATA' } }`. `when` is a tag and `marker` an uppercase keyword; neither can be shared with another state. |
243
- | `requireTicketForConditional` | `boolean` | `false` | Require a ticket for conditional skips too: `test.skip(condition, ...)`, `if (...) test.skip()`, `(condition ? test.skip : test)(...)`, a skip in a `catch` block, after other code in a `try` block with a `catch`, or after an early `return` or `throw`. |
244
- | `allowBlankLine` | `boolean` | `false` | Let blank lines separate a marker from its test. |
245
- | `allowNotes` | `boolean` | `false` | Allow free text after the tickets, e.g. `// SKIP: TRADE-123 flaky on CI`. Applies to markers and to `FIXME` / `TODO` comments. |
246
- | `comments` | `false \| { keywords?: string[] }` | `{ keywords: ['FIXME', 'TODO'] }` | Comment keywords that must start with a ticket anywhere in a test file, e.g. `// TODO: TRADE-123`. Your keywords replace the default ones. `false` allows free-form comments. |
247
- | `annotations` | `false \| { type?: string, only?: boolean }` | `{ type: 'issue' }` | Accept the ticket from a test annotation as well: Playwright's `annotation` of the given type or Vitest's `meta` key of that name. One valid annotation covers every state the test is in, and a describe's covers its tests. `only: true` makes it the only place for a test's or describe's ticket. See [Tickets from annotations](#tickets-from-annotations). |
248
- | `testFunctions` | `string[]` | `['test']` | Names treated as the framework's `test`. Jest and Vitest default to `['test', 'it']`, Mocha, Cypress and WebdriverIO to `['it', 'specify', 'test']`, and Jasmine to `['it']`. Your list replaces the default one, so include those names if you still need them. See below. |
249
- | `reportUnreadableTags` | `boolean` | `false` | When a tag state is on, report titles that aren't static text, and tags or details that can't be read in the file, such as ones imported from another module, since their tags can't be checked. |
236
+ | Option | Type | Default | Description |
237
+ | ----------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
238
+ | `framework` | `'playwright' \| 'jest' \| 'vitest' \| 'mocha' \| 'cypress' \| 'webdriverio' \| 'node-test' \| 'jasmine'` | required | The test framework of the files the config applies to. Each framework's config, such as `configs.playwright`, sets it, and `configure()` needs it. See [Frameworks](#frameworks). |
239
+ | `ticket` | `TicketSpec \| TicketSpec[]` | `{ preset: 'any' }` | Accepted ticket formats. An array accepts a ticket that matches any entry. See [Ticket presets](#ticket-presets). |
240
+ | `placeholders` | `string[]` | see above | Tickets rejected as placeholders. `*` matches any characters. Case-insensitive; a leading `#` is ignored. Your list replaces the default one, so repeat the defaults you want to keep. Tickets numbered 0 are always rejected. |
241
+ | `lifecycleTags` | `boolean` | `false` | Turns on the `new` (`@new`) and `quarantined` (`@quarantined`) states. |
242
+ | `states` | `{ [state]: boolean \| { enabled?, tag?, marker?, ticket? } }` | `skip`, `fixme` and `todo` on | Turns built-in states (`skip`, `fixme`, `fail`, `slow`, `todo`, `retry`, `new`, `quarantined`) on or off, renames their tag or marker, or gives them their own ticket format. `fail`, `slow` and `retry` are off by default; a setting for `new` or `quarantined` here wins over `lifecycleTags`. Only `new` and `quarantined` have a tag to rename; see [Tag names](#tag-names). `fixme` and `slow` exist only in Playwright, `todo` in every framework but Playwright, `fail` in Playwright, Jest, Vitest and node:test, and `retry` in every framework but node:test and Jasmine, so turning one on elsewhere has no effect. |
243
+ | `customStates` | `{ [name]: { when, marker, ticket? } }` | `{}` | Adds a state for a tag, e.g. `{ 'needs-data': { when: '@needs-data', marker: 'NEEDS-DATA' } }`. `when` is a tag and `marker` an uppercase keyword; neither can be shared with another state. |
244
+ | `requireTicketForConditional` | `boolean` | `false` | Require a ticket for conditional skips too: `test.skip(condition, ...)`, `if (...) test.skip()`, `(condition ? test.skip : test)(...)`, a skip in a `catch` block, after other code in a `try` block with a `catch`, or after an early `return` or `throw`. |
245
+ | `allowBlankLine` | `boolean` | `false` | Let blank lines separate a marker from its test. |
246
+ | `allowNotes` | `boolean` | `false` | Allow free text after the tickets, e.g. `// SKIP: TRADE-123 flaky on CI`. Applies to markers and to `FIXME` / `TODO` comments. |
247
+ | `comments` | `false \| { keywords?: string[] }` | `{ keywords: ['FIXME', 'TODO'] }` | Comment keywords that must start with a ticket anywhere in a test file, e.g. `// TODO: TRADE-123`. Your keywords replace the default ones. `false` allows free-form comments. |
248
+ | `annotations` | `false \| { type?: string, only?: boolean }` | `{ type: 'issue' }` | Accept the ticket from a test annotation as well: Playwright's `annotation` of the given type or Vitest's `meta` key of that name. One valid annotation covers every state the test is in, and a describe's covers its tests. `only: true` makes it the only place for a test's or describe's ticket. See [Tickets from annotations](#tickets-from-annotations). |
249
+ | `testFunctions` | `string[]` | `['test']` | Names treated as the framework's `test`. Jest and Vitest default to `['test', 'it']`, Mocha, Cypress and WebdriverIO to `['it', 'specify', 'test']`, and Jasmine to `['it']`. Your list replaces the default one, so include those names if you still need them. See below. |
250
+ | `reportUnreadableTags` | `boolean` | `false` | When a tag state is on, report titles that aren't static text, and tags or details that can't be read in the file, such as ones imported from another module, since their tags can't be checked. |
250
251
 
251
252
  ### Tag names
252
253
 
@@ -843,12 +843,12 @@ const NO_TAGS = {
843
843
  unreadAnnotations: [],
844
844
  };
845
845
  function collectTags(sourceCode, call, hasTitle, framework, details) {
846
- if (!hasTitle)
847
- return NO_TAGS;
848
846
  const source = sourceCode.text;
849
847
  const tags = [];
850
848
  const title = { texts: [], unread: new Set() };
851
- readTexts(sourceCode, call.arguments[0], title);
849
+ // node:test's `test({ tags: ['db'] }, fn)` has no title, only options.
850
+ if (hasTitle)
851
+ readTexts(sourceCode, call.arguments[0], title);
852
852
  for (const found of title.texts)
853
853
  scanTags(source, found, tags);
854
854
  const values = { texts: [], unread: new Set() };
@@ -236,7 +236,9 @@ const nodeTest = {
236
236
  anyOptionValue: true,
237
237
  exclusiveStates: ['skip', 'todo', 'fail'],
238
238
  optionalTitle: true,
239
- plainTags: false,
239
+ // Node 26.2's `{ tags: ['db'] }`: names without their `@`, as Vitest writes them.
240
+ tagKey: 'tags',
241
+ plainTags: true,
240
242
  info: { param: 0, methods: NODE_TEST_CONTEXT },
241
243
  subtests: true,
242
244
  skipWithoutBody: true,
@@ -44,7 +44,7 @@ export interface GovernanceOptions {
44
44
  * `skip`, `fixme` and `todo` are on by default, `fail`, `slow` and `retry` off; a setting for `new` or
45
45
  * `quarantined` wins over `lifecycleTags`. Only `new` and `quarantined` have a tag, e.g.
46
46
  * `{ quarantined: { tag: '@flaky', marker: 'FLAKY' } }`. `fixme` and `slow` exist only in Playwright,
47
- * `todo` in every framework but Playwright, `fail` in Playwright, Jest and Vitest, and `retry` in every
47
+ * `todo` in every framework but Playwright, `fail` in Playwright, Jest, Vitest and node:test, and `retry` in every
48
48
  * framework but node:test and Jasmine.
49
49
  */
50
50
  states?: Partial<Record<BuiltinStateName, boolean | StateOverride>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-test-governance",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "ESLint rules that require a ticket comment above skipped, fixme, todo and tagged Playwright, Jest, Vitest, Mocha, Cypress, WebdriverIO, node:test and Jasmine tests.",
5
5
  "keywords": [
6
6
  "eslint",