|
| 1 | +# Enforce using `.each` or `.for` consistently (`vitest/consistent-each-for`) |
| 2 | + |
| 3 | +⚠️ This rule _warns_ in the 🌐 `all` config. |
| 4 | + |
| 5 | +<!-- end auto-generated rule header --> |
| 6 | + |
| 7 | +## Rule Details |
| 8 | + |
| 9 | +Vitest provides two ways to run parameterized tests: `.each` and `.for`. This rule enforces consistency in the usage of these methods. |
| 10 | + |
| 11 | +**Key Differences:** |
| 12 | + |
| 13 | +- **`.each`**: Spreads array arguments to individual parameters |
| 14 | +- **`.for`**: Keeps arrays intact, provides better TestContext support |
| 15 | + |
| 16 | +This rule allows you to configure which method to prefer for different test function types (`test`, `it`, `describe`, `suite`). |
| 17 | + |
| 18 | +Examples of **incorrect** code when configured to prefer `.for`: |
| 19 | + |
| 20 | +```js |
| 21 | +// { test: 'for' } |
| 22 | +test.each([[1, 1, 2]])('test', (a, b, expected) => { |
| 23 | + expect(a + b).toBe(expected) |
| 24 | +}) |
| 25 | +``` |
| 26 | + |
| 27 | +```js |
| 28 | +// { describe: 'for' } |
| 29 | +describe.each([[1], [2]])('suite %s', (n) => { |
| 30 | + test('test', () => {}) |
| 31 | +}) |
| 32 | +``` |
| 33 | + |
| 34 | +Examples of **correct** code when configured to prefer `.for`: |
| 35 | + |
| 36 | +```js |
| 37 | +// { test: 'for' } |
| 38 | +test.for([[1, 1, 2]])('test', ([a, b, expected]) => { |
| 39 | + expect(a + b).toBe(expected) |
| 40 | +}) |
| 41 | +``` |
| 42 | + |
| 43 | +```js |
| 44 | +// { describe: 'for' } |
| 45 | +describe.for([[1], [2]])('suite %s', ([n]) => { |
| 46 | + test('test', () => {}) |
| 47 | +}) |
| 48 | +``` |
| 49 | + |
| 50 | +Examples of **incorrect** code when configured to prefer `.each`: |
| 51 | + |
| 52 | +```js |
| 53 | +// { test: 'each' } |
| 54 | +test.for([[1, 1, 2]])('test', ([a, b, expected]) => { |
| 55 | + expect(a + b).toBe(expected) |
| 56 | +}) |
| 57 | +``` |
| 58 | + |
| 59 | +Examples of **correct** code when configured to prefer `.each`: |
| 60 | + |
| 61 | +```js |
| 62 | +// { test: 'each' } |
| 63 | +test.each([[1, 1, 2]])('test', (a, b, expected) => { |
| 64 | + expect(a + b).toBe(expected) |
| 65 | +}) |
| 66 | +``` |
| 67 | + |
| 68 | +```js |
| 69 | +// { test: 'each' } |
| 70 | +test.skip.each([[1, 2]])('test', (a, b) => { |
| 71 | + expect(a).toBeLessThan(b) |
| 72 | +}) |
| 73 | +``` |
| 74 | + |
| 75 | +## Options |
| 76 | + |
| 77 | +<!-- begin auto-generated rule options list --> |
| 78 | + |
| 79 | +| Name | Type | Choices | |
| 80 | +| :--------- | :----- | :------------ | |
| 81 | +| `describe` | String | `each`, `for` | |
| 82 | +| `it` | String | `each`, `for` | |
| 83 | +| `suite` | String | `each`, `for` | |
| 84 | +| `test` | String | `each`, `for` | |
| 85 | + |
| 86 | +<!-- end auto-generated rule options list --> |
| 87 | + |
| 88 | +## Configuration |
| 89 | + |
| 90 | +Typical configuration to enforce `.for` for tests and `.each` for describe blocks: |
| 91 | + |
| 92 | +```js |
| 93 | +// eslint.config.js |
| 94 | +export default [ |
| 95 | + { |
| 96 | + rules: { |
| 97 | + 'vitest/consistent-each-for': [ |
| 98 | + 'warn', |
| 99 | + { |
| 100 | + test: 'for', |
| 101 | + it: 'for', |
| 102 | + describe: 'each', |
| 103 | + suite: 'each', |
| 104 | + }, |
| 105 | + ], |
| 106 | + }, |
| 107 | + }, |
| 108 | +] |
| 109 | +``` |
| 110 | + |
| 111 | +You can configure each function type independently. If a function type is not configured, the rule won't enforce any preference for it. |
0 commit comments