diff --git a/.changeset/code-quality-false-negatives.md b/.changeset/code-quality-false-negatives.md deleted file mode 100644 index 8b1cc37..0000000 --- a/.changeset/code-quality-false-negatives.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@noctcore/eslint-plugin-code-quality': patch ---- - -Close four gaps in the test-discipline rules and fix a crash. - -**A project that spreads `recommended` as-is sees no new errors.** The only rule here that is in `recommended`, `no-vacuous-expect`, reports less than before. The other three rules are opt-in, and a project that enabled them can see new errors: - -- `typed-mock-over-double-cast` now sees a mock that was created first and put in the object by name: `const fn = vi.fn(); const svc = { fn } as unknown as Service;`, also as `{ run: fn }`, nested in an inner object, through a chain (`jest.fn().mockResolvedValue(...)`) and when the name is assigned its mock later (`let get; beforeEach(() => { get = jest.fn(); })`). A mock that arrives through a spread, an import, a parameter or a helper's return value is still not followed. -- `no-message-only-throw-assertion` now reads a message held in a variable: `const expected = /no access/; expect(run).toThrow(expected)` is a message check, for a string, a template, a regex literal or `new RegExp(...)`, as long as the variable is initialised where it is declared and never assigned again. Such a variable no longer counts as a class pin for a later message check on the same subject either. An import, a parameter and a call result are still read as an error class. -- `no-sleep-in-unit-tests` no longer exempts a whole file because one test fakes its timers. A `fakeTimerMethods` call now covers the test it is in, else the `describe` it is in (directly or in a `beforeEach` / `beforeAll`), else the whole file, so a file that installs fake timers at the top level behaves as before. A real sleep in a sibling test or suite is reported. A sleep helper defined in the file is judged by its callers: it stays silent when every call to it runs under fake timers. - -Reports less: - -- `no-vacuous-expect` no longer treats a `container` / `baseElement` from any call as a render root. A root from a `render*` call still counts for every presence check. A root from another call (`setup()`, `docker.inspect(id)`) counts only when the assertion is DOM-specific: it reads `firstChild`, `innerHTML` and the like off the root, or uses `toBeInTheDocument`, `toBeVisible` or `not.toBeEmptyDOMElement`. So `const { container } = await docker.inspect(id); expect(container).not.toBeNull();` is accepted, and so is the same check on the root of a render helper whose name does not start with `render`. A weak matcher there (`toBeTruthy`, `toBeDefined`) is still reported, as `soleWeakExpect`. - -Crash fixed: - -- `no-sleep-in-unit-tests` threw `Cannot read properties of null (reading 'type')` on a `setTimeout(...)` call at the top level of a unit test file. diff --git a/packages/eslint-plugin-code-quality/CHANGELOG.md b/packages/eslint-plugin-code-quality/CHANGELOG.md index 2fa17d5..f3335b2 100644 --- a/packages/eslint-plugin-code-quality/CHANGELOG.md +++ b/packages/eslint-plugin-code-quality/CHANGELOG.md @@ -1,5 +1,25 @@ # @noctcore/eslint-plugin-code-quality +## 0.4.1 + +### Patch Changes + +- [#61](https://github.com/noctcore/eslint-plugins/pull/61) [`9f24ad7`](https://github.com/noctcore/eslint-plugins/commit/9f24ad7dd37c70b760041fe6f3e945e90ba35b97) Thanks [@Shironex](https://github.com/Shironex)! - Close four gaps in the test-discipline rules and fix a crash. + + **A project that spreads `recommended` as-is sees no new errors.** The only rule here that is in `recommended`, `no-vacuous-expect`, reports less than before. The other three rules are opt-in, and a project that enabled them can see new errors: + + - `typed-mock-over-double-cast` now sees a mock that was created first and put in the object by name: `const fn = vi.fn(); const svc = { fn } as unknown as Service;`, also as `{ run: fn }`, nested in an inner object, through a chain (`jest.fn().mockResolvedValue(...)`) and when the name is assigned its mock later (`let get; beforeEach(() => { get = jest.fn(); })`). A mock that arrives through a spread, an import, a parameter or a helper's return value is still not followed. + - `no-message-only-throw-assertion` now reads a message held in a variable: `const expected = /no access/; expect(run).toThrow(expected)` is a message check, for a string, a template, a regex literal or `new RegExp(...)`, as long as the variable is initialised where it is declared and never assigned again. Such a variable no longer counts as a class pin for a later message check on the same subject either. An import, a parameter and a call result are still read as an error class. + - `no-sleep-in-unit-tests` no longer exempts a whole file because one test fakes its timers. A `fakeTimerMethods` call now covers the test it is in, else the `describe` it is in (directly or in a `beforeEach` / `beforeAll`), else the whole file, so a file that installs fake timers at the top level behaves as before. A real sleep in a sibling test or suite is reported. A sleep helper defined in the file is judged by its callers: it stays silent when every call to it runs under fake timers. + + Reports less: + + - `no-vacuous-expect` no longer treats a `container` / `baseElement` from any call as a render root. A root from a `render*` call still counts for every presence check. A root from another call (`setup()`, `docker.inspect(id)`) counts only when the assertion is DOM-specific: it reads `firstChild`, `innerHTML` and the like off the root, or uses `toBeInTheDocument`, `toBeVisible` or `not.toBeEmptyDOMElement`. So `const { container } = await docker.inspect(id); expect(container).not.toBeNull();` is accepted, and so is the same check on the root of a render helper whose name does not start with `render`. A weak matcher there (`toBeTruthy`, `toBeDefined`) is still reported, as `soleWeakExpect`. + + Crash fixed: + + - `no-sleep-in-unit-tests` threw `Cannot read properties of null (reading 'type')` on a `setTimeout(...)` call at the top level of a unit test file. + ## 0.4.0 ### Minor Changes diff --git a/packages/eslint-plugin-code-quality/package.json b/packages/eslint-plugin-code-quality/package.json index ee7e97e..5996c4f 100644 --- a/packages/eslint-plugin-code-quality/package.json +++ b/packages/eslint-plugin-code-quality/package.json @@ -1,6 +1,6 @@ { "name": "@noctcore/eslint-plugin-code-quality", - "version": "0.4.0", + "version": "0.4.1", "description": "Portable code-quality, comment-hygiene and test-discipline ESLint rules: guard clauses, deterministic time, no stray process.exit, and tests that cannot pass vacuously.", "license": "MIT", "type": "module", diff --git a/packages/eslint-plugin-code-quality/src/index.ts b/packages/eslint-plugin-code-quality/src/index.ts index 7b62386..139ecc1 100644 --- a/packages/eslint-plugin-code-quality/src/index.ts +++ b/packages/eslint-plugin-code-quality/src/index.ts @@ -3,7 +3,7 @@ import { rules } from './rules'; /** Flat-config namespace: rule ids are keyed `noctcore-code-quality/`. */ const NAMESPACE = 'noctcore-code-quality'; -const VERSION = '0.4.0'; +const VERSION = '0.4.1'; const plugin = { meta: { name: '@noctcore/eslint-plugin-code-quality', version: VERSION },