vitest-auto-spy 5.59.1 → 5.60.0
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 +18 -1
- package/README.md +1 -0
- package/agent-docs/eslint.md +7 -4
- package/dist/cli.js +1 -1
- package/dist/eslint-plugin.cjs +60 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,22 @@ The latest released version here must always match the one published on
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [5.60.0] - 2026-10-06
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **`no-redundant-as-instance`** in `vitest-auto-spy/eslint-plugin`, `warn` in `recommended`:
|
|
18
|
+
`expect(service.open()).toBe(asInstance(ref))`. The three comparing matchers take their argument as
|
|
19
|
+
a free type parameter, so the unwrap buys nothing there — it keeps an import alive and reads as if
|
|
20
|
+
the types needed it. `--fix` drops the wrapper and, when that was the import's last use, the import
|
|
21
|
+
too. Slots typed against the real class are untouched: `toHaveBeenCalledWith(asInstance(cart))`
|
|
22
|
+
can be load-bearing, and so can a wrapper that is part of the argument (`[asInstance(x)]`,
|
|
23
|
+
`asInstance(x).id`). Three such call sites in two consumer suites (5.59.1). The plugin now ships
|
|
24
|
+
fifty-eight rules. `/eslint-plugin` is 53.45 → 53.84 kB (+0.39 kB, +0.7 %): the rule, minus the
|
|
25
|
+
matcher set that `no-constant-expect`, `prefer-to-have-signal-value` and
|
|
26
|
+
`no-vacuous-absence-assertion` each carried a copy of, and the `matcherOf` walk `no-constant-expect`
|
|
27
|
+
duplicated — both now shared out of `absence-assertion.ts`.
|
|
28
|
+
|
|
13
29
|
## [5.59.1] - 2026-09-30
|
|
14
30
|
|
|
15
31
|
## [5.59.0] - 2026-09-30
|
|
@@ -6825,7 +6841,8 @@ moved under 1 %: `/angular` +192 B (+1.0 %) for the override queue and the HTTP
|
|
|
6825
6841
|
This copy ships with the package and carries 5.x only. Releases before 5.0.0 are in the
|
|
6826
6842
|
[full changelog](https://github.com/ASDAlexey/vitest-auto-spy/blob/master/CHANGELOG.md).
|
|
6827
6843
|
|
|
6828
|
-
[Unreleased]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.
|
|
6844
|
+
[Unreleased]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.60.0...HEAD
|
|
6845
|
+
[5.60.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.59.1...v5.60.0
|
|
6829
6846
|
[5.59.1]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.59.0...v5.59.1
|
|
6830
6847
|
[5.59.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.58.0...v5.59.0
|
|
6831
6848
|
[5.58.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.57.0...v5.58.0
|
package/README.md
CHANGED
|
@@ -3596,6 +3596,7 @@ Rolling it out on a large suite, and the options each rule takes:
|
|
|
3596
3596
|
| [`no-instance-lifecycle-spy`](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-rules#no-instance-lifecycle-spy) | `warn` | — | Spy on an Angular lifecycle hook through the class prototype — Angular never calls the one on an instance |
|
|
3597
3597
|
| [`no-ts-expect-error-on-double`](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-rules#no-ts-expect-error-on-double) | `error` | — | Do not suppress a type error on a double's configuration — name the overload, or fix the fixture |
|
|
3598
3598
|
| [`no-constant-expect`](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-rules#no-constant-expect) | `error` | — | Assert on a value the code under test produced, not on one the spec spelled out |
|
|
3599
|
+
| [`no-redundant-as-instance`](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-rules#no-redundant-as-instance) | `warn` | `--fix` | Drop asInstance() around a comparing matcher's argument — the unwrap buys nothing there and keeps an import alive |
|
|
3599
3600
|
| [`no-redundant-smoke-test`](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-rules#no-redundant-smoke-test) | `error` | suggest | Delete a test whose whole body asserts that the subject exists, where the block already has tests that use it |
|
|
3600
3601
|
| [`no-self-called-spy`](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-rules#no-self-called-spy) | `error` | — | Do not assert a call the test made itself — drive the production path that should make it |
|
|
3601
3602
|
| [`no-vacuous-absence-assertion`](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-rules#no-vacuous-absence-assertion) | `error` | — | Do not let a whole test rest on assertions that a stream which never emits already satisfies |
|
package/agent-docs/eslint.md
CHANGED
|
@@ -91,6 +91,7 @@ export default [
|
|
|
91
91
|
| `no-instance-lifecycle-spy` | `warn` | — | `vi.spyOn(instance, 'ngOnInit')` (and `ngOnDestroy`, `ngDoCheck`, `ngAfterContent*`, `ngAfterView*`) — a view calls the hook read off the prototype, so the instance spy is never called and its stub never runs → `vi.spyOn(Cls.prototype, …)` before `createComponent`, or assert the effect. `ngOnChanges` is exempt: Angular calls it through the instance |
|
|
92
92
|
| `no-ts-expect-error-on-double` | `error` | — | `@ts-expect-error` / `@ts-ignore` above `nextWith`, `resolveWith`, `mockReturnValue`, `returnValue`, `calledWith(…)` and the other helpers that check a stub against the method's signature → an overloaded method takes `Spy<X, { overload: { m: 'first' } }>`; otherwise the fixture is the wrong shape, checked against `ReturnType<X['m']>`. A reason after the directive does not silence it; a deliberate out-of-type value keeps it under `eslint-disable-next-line … -- <why>` |
|
|
93
93
|
| `no-constant-expect` | `error` | — | `expect(true).toBe(true)`, `expect({ … }).toBeDefined()` — a value the spec spelled out, under a matcher whose answer it already fixes (`toBe` / `toEqual` / `toStrictEqual` against a literal; `toBeTruthy`, `toBeDefined`, `toBeNull`… for any literal) → assert on what the code produced, or `expect.fail(…)` for an unreachable branch |
|
|
94
|
+
| `no-redundant-as-instance` | `warn` | `--fix` | `expect(x).toBe(asInstance(ref))` → `.toBe(ref)`: the comparing matchers take their argument as a free type parameter, so the bridge buys nothing there; `--fix` drops the wrapper and the import once it is unused. `toHaveBeenCalledWith(asInstance(cart))` is left alone — that slot is typed against the real class and the unwrap can be load-bearing; so is a wrapper that is part of the argument (`[asInstance(x)]`, `asInstance(x).id`) |
|
|
94
95
|
| `no-redundant-smoke-test` | `error` | suggest | `it('should create', () => expect(pipe).toBeTruthy())` — every statement of the body an `expect(x)` under `toBeTruthy` / `toBeDefined` / `toBeInstanceOf` (or their negated twins), weighed against the tests that run the same setup: the rest of the block, and everything the blocks nested in it declare → delete it; the suggestion removes the test and the blank line above it. Silent where that test is the block's only running one, and a skipped sibling does not count as proof |
|
|
95
96
|
| `no-self-called-spy` | `error` | — | `vi.spyOn(obj, 'm')`, then `obj.m(…)` written by the test itself, then a positive `toHaveBeenCalled*` — the assertion is satisfied by the test's own line, so the test survives the deletion of the behaviour its title names. Order decides it: a call written **before** the spy is arrangement, and a `mockClear` between the call and the assertion, a negated matcher or arguments the call did not pass all silence it |
|
|
96
97
|
| `no-vacuous-absence-assertion` | `error` | — | a test **all** of whose assertions are satisfied by the stream never emitting. The carrier is a `const` / `let` declared in the test whose every write outside the declaration sits in a `subscribe` callback of that test (the assignment and the `push` forms both count), or a `vi.fn()` the test hands to `subscribe` and never calls itself. Silence satisfies an equality matcher repeating the initialiser's source text, `toBeUndefined` / `not.toBeDefined` on a `let` holding `undefined`, `toBeNull` on one holding `null`, `toBeFalsy` / `not.toBeTruthy` on any falsy literal, `toHaveLength(0)` on `[]` or `''`, and `not.toHaveBeenCalled` / `not.toHaveBeenCalledWith` / `toHaveBeenCalledTimes(0)` on any subject — read literally, so `toBeNull()` on a `let` with no initialiser is **not** reported. One `expect()` a silent source could fail silences the rule, which is what exempts the "nothing yet, trigger, now the value" shape; a test asserting through a local helper is skipped entirely → `await expectNoEmission(source$)`, or `expect(await expectEmission(source$))` |
|
|
@@ -111,22 +112,24 @@ export default [
|
|
|
111
112
|
| `no-save-arguments-by-value` | `error` | — | `spy.calls.saveArgumentsByValue()` — a no-op here, so the spec silently asserts on post-mutation state |
|
|
112
113
|
| `prefer-native-spy-api` | `error` | `--fix` / suggest | `.and` / `.calls` where the spy's own API says the same thing — turn it on for the last mile off the jasmine shim. The fix renames only the member (`and.returnValue` → `mockReturnValue`, `withArgs` → `calledWith`), so comments stay; a rewrite that would drop one is a suggestion |
|
|
113
114
|
|
|
114
|
-
Fifty-
|
|
115
|
+
Fifty-eight rules, **every one an `error` except `prefer-render-shallow`,
|
|
115
116
|
`no-stub-class-double`, `no-structural-double`, `prefer-create-mock`, `no-instance-lifecycle-spy`,
|
|
116
117
|
`prefer-set-inputs`, `no-unasserted-argument`, `prefer-spy-on-own-method`, `prefer-to-have-signal-value`,
|
|
117
|
-
`no-unasserted-console-spy`, `no-real-wait-in-test
|
|
118
|
+
`no-unasserted-console-spy`, `no-real-wait-in-test`, `no-inline-test-data` and
|
|
119
|
+
`no-redundant-as-instance`**; nine fix on their own, nineteen offer suggestions. Fifty-four are syntactic; `no-private-member-access`, `no-mistyped-use-value`,
|
|
118
120
|
`no-unknown-use-value-key` and `prefer-to-have-signal-value` read types, and all four report nothing at all without `parserOptions.project` / `projectService`
|
|
119
121
|
rather than guessing. `no-compile-components` waits the same way for a fact no file holds — which
|
|
120
122
|
builder the project has — and reports nothing until `{ builder: 'inline-resources' }` states it;
|
|
121
123
|
`no-relative-mock-under-builder` waits for a builder target serving the file, or `{ builder: 'unit-test' }`.
|
|
122
124
|
|
|
123
|
-
The
|
|
125
|
+
The thirteen `warn`s do not rank findings by importance. Each names something other than a defect: a
|
|
124
126
|
cheaper render (`prefer-render-shallow`), a heuristic reading with no `provide:` to settle it
|
|
125
127
|
(`no-stub-class-double`, `no-structural-double`, `no-instance-lifecycle-spy`), a repair that turns
|
|
126
128
|
many files red at once (`prefer-create-mock`), a question only the author can answer
|
|
127
129
|
(`no-unasserted-argument`, `no-unasserted-console-spy`, `no-real-wait-in-test`), a place data should
|
|
128
130
|
live rather than a defect (`no-inline-test-data`), or a preferred spelling
|
|
129
|
-
of working code (`prefer-spy-on-own-method`, `prefer-set-inputs`, `prefer-to-have-signal-value
|
|
131
|
+
of working code (`prefer-spy-on-own-method`, `prefer-set-inputs`, `prefer-to-have-signal-value`,
|
|
132
|
+
`no-redundant-as-instance`). Set
|
|
130
133
|
any of the `warn`s to `'error'` once the batch is done.
|
|
131
134
|
|
|
132
135
|
Three rules can report on a _correct_ project, and only one has an option:
|
package/dist/cli.js
CHANGED
|
@@ -1667,7 +1667,7 @@ function foreignPragmaPass() {
|
|
|
1667
1667
|
}
|
|
1668
1668
|
|
|
1669
1669
|
// src/cli/checks/export-map.generated.ts
|
|
1670
|
-
var EXPORT_MAP_VERSION = "5.59.
|
|
1670
|
+
var EXPORT_MAP_VERSION = "5.59.1";
|
|
1671
1671
|
var ENTRY_SPECIFIERS = "vitest-auto-spy vitest-auto-spy/bun vitest-auto-spy/bun-angular vitest-auto-spy/node vitest-auto-spy/rstest vitest-auto-spy/rxjs vitest-auto-spy/console vitest-auto-spy/dom-stubs vitest-auto-spy/diagnostics vitest-auto-spy/jasmine vitest-auto-spy/jasmine-compat vitest-auto-spy/observer-spy vitest-auto-spy/angular vitest-auto-spy/angular/diagnostics vitest-auto-spy/angular/doubles vitest-auto-spy/angular/matchers vitest-auto-spy/angular-http vitest-auto-spy/angular-router vitest-auto-spy/signal-forms vitest-auto-spy/nestjs vitest-auto-spy/react vitest-auto-spy/vue vitest-auto-spy/svelte vitest-auto-spy/setup vitest-auto-spy/zone vitest-auto-spy/eslint-plugin vitest-auto-spy/perf-reporter";
|
|
1672
1672
|
var EXPORTED_BY = {
|
|
1673
1673
|
AccessorImplementations: "0 1 2 3 4 12 20 21 22",
|
package/dist/eslint-plugin.cjs
CHANGED
|
@@ -632,7 +632,7 @@ function repairFor(node, subscribeCall) {
|
|
|
632
632
|
var TESTS = /* @__PURE__ */ new Set(["it", "test"]);
|
|
633
633
|
var NEVER_CALLED = /* @__PURE__ */ new Set(["toHaveBeenCalled", "toHaveBeenCalledWith"]);
|
|
634
634
|
var UNDEFINED_MATCHERS = /* @__PURE__ */ new Set(["toBeDefined", "toBeUndefined"]);
|
|
635
|
-
var
|
|
635
|
+
var EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
636
636
|
var FALSY = /* @__PURE__ */ new Set(["0", "''", '""', "``", "NaN", "false", "null", "undefined"]);
|
|
637
637
|
var EMPTY = /* @__PURE__ */ new Set(["[]", "''", '""', "``"]);
|
|
638
638
|
function testCallOf(fn) {
|
|
@@ -697,7 +697,7 @@ function satisfiedByHeldValue(context, held, matcher) {
|
|
|
697
697
|
if (matcher.negated) {
|
|
698
698
|
return UNDEFINED_MATCHERS.has(matcher.name) ? held === "undefined" : matcher.name === "toBeTruthy" && FALSY.has(held);
|
|
699
699
|
}
|
|
700
|
-
if (
|
|
700
|
+
if (EQUALITY_MATCHERS.has(matcher.name)) {
|
|
701
701
|
return matcher.args.length === 1 && argument !== void 0 && tight(context.sourceCode.getText(argument)) === tight(held);
|
|
702
702
|
}
|
|
703
703
|
if (matcher.name === "toHaveLength") {
|
|
@@ -1724,7 +1724,6 @@ var noUnassertedConsoleSpy = defineRule({
|
|
|
1724
1724
|
});
|
|
1725
1725
|
|
|
1726
1726
|
// src/lib/eslint/constant-expect.ts
|
|
1727
|
-
var COMPARES = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
1728
1727
|
var CLASSIFIES = /* @__PURE__ */ new Set(["toBeDefined", "toBeFalsy", "toBeNaN", "toBeNull", "toBeTruthy", "toBeUndefined"]);
|
|
1729
1728
|
var OBJECT_LITERALS = /* @__PURE__ */ new Set([
|
|
1730
1729
|
"ArrayExpression",
|
|
@@ -1758,17 +1757,8 @@ function isConstant(node) {
|
|
|
1758
1757
|
return LITERALS.has(value.type);
|
|
1759
1758
|
}
|
|
1760
1759
|
}
|
|
1761
|
-
function matcherOf2(expectCall) {
|
|
1762
|
-
let member = expectCall.parent;
|
|
1763
|
-
while (memberName(member) === "not") {
|
|
1764
|
-
member = member.parent;
|
|
1765
|
-
}
|
|
1766
|
-
const name = memberName(member);
|
|
1767
|
-
const call = member.parent;
|
|
1768
|
-
return name && isCallExpression(call) && call.callee === member ? { name, args: call.arguments } : void 0;
|
|
1769
|
-
}
|
|
1770
1760
|
function isDecided(actual, matcher) {
|
|
1771
|
-
if (
|
|
1761
|
+
if (EQUALITY_MATCHERS.has(matcher.name)) {
|
|
1772
1762
|
return isConstant(actual) && matcher.args.every(isConstant);
|
|
1773
1763
|
}
|
|
1774
1764
|
return CLASSIFIES.has(matcher.name) && (OBJECT_LITERALS.has(unwrapped(actual).type) || isConstant(actual));
|
|
@@ -1782,7 +1772,7 @@ var noConstantExpect = defineRule({
|
|
|
1782
1772
|
create: (context) => ({
|
|
1783
1773
|
'CallExpression[callee.name="expect"]': (node) => {
|
|
1784
1774
|
const [actual] = node.arguments;
|
|
1785
|
-
const matcher =
|
|
1775
|
+
const matcher = matcherOf(node);
|
|
1786
1776
|
if (actual && matcher && isDecided(actual, matcher)) {
|
|
1787
1777
|
context.report({ node, messageId: "noConstantExpect", data: { actual: excerpt(context, actual, 40), matcher: matcher.name } });
|
|
1788
1778
|
}
|
|
@@ -3443,6 +3433,55 @@ var noInstanceLifecycleSpy = defineRule({
|
|
|
3443
3433
|
})
|
|
3444
3434
|
});
|
|
3445
3435
|
|
|
3436
|
+
// src/lib/eslint/matcher-as-instance.ts
|
|
3437
|
+
var AS_INSTANCE = "asInstance";
|
|
3438
|
+
function importedAsInstance(context, callee) {
|
|
3439
|
+
const binding = findBinding(context.sourceCode.getScope(callee), callee.name);
|
|
3440
|
+
return binding?.defs.some((definition) => definition.type === "ImportBinding") ? binding : void 0;
|
|
3441
|
+
}
|
|
3442
|
+
function unwrap2(context, fixer, wrapper, value, binding) {
|
|
3443
|
+
const edits = [fixer.replaceText(wrapper, context.sourceCode.getText(value))];
|
|
3444
|
+
const orphaned = binding.references.length === 1 ? dropNamedImport(context.sourceCode, fixer, binding) : void 0;
|
|
3445
|
+
if (orphaned) {
|
|
3446
|
+
edits.push(orphaned);
|
|
3447
|
+
}
|
|
3448
|
+
return edits;
|
|
3449
|
+
}
|
|
3450
|
+
var noRedundantAsInstance = defineRule({
|
|
3451
|
+
name: "no-redundant-as-instance",
|
|
3452
|
+
description: "Pass the value itself to a comparing matcher; asInstance() bridges slots typed as the real class",
|
|
3453
|
+
fixable: true,
|
|
3454
|
+
messages: {
|
|
3455
|
+
noRedundantAsInstance: "`asInstance({{value}})` buys nothing under `.{{matcher}}()`: the matcher takes its argument as a free type parameter, so the value compiles as it is. Pass `{{value}}` directly."
|
|
3456
|
+
},
|
|
3457
|
+
create: (context) => ({
|
|
3458
|
+
'CallExpression[callee.name="expect"]': (node) => {
|
|
3459
|
+
const matcher = matcherOf(node);
|
|
3460
|
+
if (!matcher || !EQUALITY_MATCHERS.has(matcher.name)) {
|
|
3461
|
+
return;
|
|
3462
|
+
}
|
|
3463
|
+
for (const argument of matcher.args) {
|
|
3464
|
+
if (!isCallExpression(argument) || !isIdentifier(argument.callee) || argument.callee.name !== AS_INSTANCE) {
|
|
3465
|
+
continue;
|
|
3466
|
+
}
|
|
3467
|
+
const [value, ...extra] = argument.arguments;
|
|
3468
|
+
if (value === void 0 || extra.length > 0) {
|
|
3469
|
+
continue;
|
|
3470
|
+
}
|
|
3471
|
+
const binding = importedAsInstance(context, argument.callee);
|
|
3472
|
+
if (binding) {
|
|
3473
|
+
context.report({
|
|
3474
|
+
node: argument,
|
|
3475
|
+
messageId: "noRedundantAsInstance",
|
|
3476
|
+
data: { matcher: matcher.name, value: excerpt(context, value, 40) },
|
|
3477
|
+
fix: (fixer) => unwrap2(context, fixer, argument, value, binding)
|
|
3478
|
+
});
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
})
|
|
3483
|
+
});
|
|
3484
|
+
|
|
3446
3485
|
// src/lib/eslint/use-value-types.ts
|
|
3447
3486
|
var PRIMITIVE_CHECKER_METHODS = [
|
|
3448
3487
|
"getTypeAtLocation",
|
|
@@ -5101,7 +5140,6 @@ var preferRenderShallow = defineRule({
|
|
|
5101
5140
|
});
|
|
5102
5141
|
|
|
5103
5142
|
// src/lib/eslint/prefer-to-have-signal-value.ts
|
|
5104
|
-
var MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
5105
5143
|
var VALUE_MATCHERS = /* @__PURE__ */ new Map([
|
|
5106
5144
|
["toBeNull", "null"],
|
|
5107
5145
|
["toBeUndefined", "undefined"]
|
|
@@ -5110,7 +5148,7 @@ var SIGNAL_BRAND = "\u0275SIGNAL";
|
|
|
5110
5148
|
var SIGNAL_BRAND_PROPERTY = /^__@(?:SIGNAL|ɵSIGNAL|ɵWRITABLE_SIGNAL)@\d+$/;
|
|
5111
5149
|
function signalAssertionOf(node) {
|
|
5112
5150
|
const callee = node.callee;
|
|
5113
|
-
if (!isMemberExpression(callee) || callee.computed || !isIdentifier(callee.property) || !(
|
|
5151
|
+
if (!isMemberExpression(callee) || callee.computed || !isIdentifier(callee.property) || !(EQUALITY_MATCHERS.has(callee.property.name) || VALUE_MATCHERS.has(callee.property.name))) {
|
|
5114
5152
|
return void 0;
|
|
5115
5153
|
}
|
|
5116
5154
|
let expected = callee.object;
|
|
@@ -6537,7 +6575,7 @@ function isObjectPattern(node) {
|
|
|
6537
6575
|
function isUnwrapped(node) {
|
|
6538
6576
|
return isCast(node) || node.type === "TSNonNullExpression";
|
|
6539
6577
|
}
|
|
6540
|
-
function
|
|
6578
|
+
function unwrap3(node) {
|
|
6541
6579
|
return isUnwrapped(node) ? node.expression : node;
|
|
6542
6580
|
}
|
|
6543
6581
|
function methodString(node) {
|
|
@@ -6545,7 +6583,7 @@ function methodString(node) {
|
|
|
6545
6583
|
return typeof value === "string" && METHOD_NAME.test(value) ? value : void 0;
|
|
6546
6584
|
}
|
|
6547
6585
|
function listedMethod(value) {
|
|
6548
|
-
const list =
|
|
6586
|
+
const list = unwrap3(value);
|
|
6549
6587
|
const elements = isArrayExpression(list) ? list.elements : [];
|
|
6550
6588
|
const names = elements.filter((element) => element !== null).map(methodString);
|
|
6551
6589
|
return elements.length === 1 ? names[0] : void 0;
|
|
@@ -6586,7 +6624,7 @@ function readsMethod(member, method) {
|
|
|
6586
6624
|
return named === method && !(isAssignmentExpression(parent) && parent.left === member);
|
|
6587
6625
|
}
|
|
6588
6626
|
function isRealObject(scope, node, follow) {
|
|
6589
|
-
const value =
|
|
6627
|
+
const value = unwrap3(node);
|
|
6590
6628
|
if (isIdentifier(value)) {
|
|
6591
6629
|
const bound = follow ? boundValueOf(scope, value) : void 0;
|
|
6592
6630
|
return bound ? isRealObject(scope, bound, false) : DOM_GLOBALS.has(value.name) && bindingState(scope, value.name) === "free";
|
|
@@ -7049,6 +7087,7 @@ var rules = {
|
|
|
7049
7087
|
"no-mistyped-use-value": noMistypedUseValue,
|
|
7050
7088
|
"no-unknown-use-value-key": noUnknownUseValueKey,
|
|
7051
7089
|
"no-instance-lifecycle-spy": noInstanceLifecycleSpy,
|
|
7090
|
+
"no-redundant-as-instance": noRedundantAsInstance,
|
|
7052
7091
|
"no-ts-expect-error-on-double": noTsExpectErrorOnDouble,
|
|
7053
7092
|
"no-constant-expect": noConstantExpect,
|
|
7054
7093
|
"no-compile-components": noCompileComponents,
|
|
@@ -7127,7 +7166,8 @@ var recommendedRules = {
|
|
|
7127
7166
|
[`${PLUGIN_NAME}/no-relative-mock-under-builder`]: "error",
|
|
7128
7167
|
[`${PLUGIN_NAME}/no-real-wait-in-test`]: "warn",
|
|
7129
7168
|
[`${PLUGIN_NAME}/no-disabled-testbed-teardown`]: "error",
|
|
7130
|
-
[`${PLUGIN_NAME}/no-inline-test-data`]: "warn"
|
|
7169
|
+
[`${PLUGIN_NAME}/no-inline-test-data`]: "warn",
|
|
7170
|
+
[`${PLUGIN_NAME}/no-redundant-as-instance`]: "warn"
|
|
7131
7171
|
};
|
|
7132
7172
|
var typeErrorRules = {
|
|
7133
7173
|
[`${PLUGIN_NAME}/prefer-as-spy`]: "error",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-auto-spy",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.60.0",
|
|
4
4
|
"description": "Auto-generate fully-typed test spies from a class — across Vitest, Bun, node:test and Rstest, with Angular/NestJS/React/Vue/Svelte recipes. Drop-in replacement for jest-auto-spies and jasmine-auto-spies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auto-mock",
|