Skip to content

Commit

Permalink
Merge pull request #228 from playwright-community/max-expects
Browse files Browse the repository at this point in the history
feat: Add `max-expects` rule
  • Loading branch information
mskelton authored Feb 18, 2024
2 parents 3f3113f + acf80a0 commit 71004af
Show file tree
Hide file tree
Showing 5 changed files with 480 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ command line option.\
[suggestions](https://eslint.org/docs/latest/developer-guide/working-with-rules#providing-suggestions).

|| 🔧 | 💡 | Rule | Description |
| :-: | :-: | :-: | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| :-: | :-: | :-: | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --- |
|| | | [expect-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/expect-expect.md) | Enforce assertion to be made in a test body |
|| | | [max-expects](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/max-expects.md) | Enforces a maximum number assertion calls in a test body | |
|| | | [max-nested-describe](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls |
|| 🔧 | | [missing-playwright-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/missing-playwright-await.md) | Enforce Playwright APIs to be awaited |
| | | | [no-commented-out-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-commented-out-test.md) | Disallow commented out tests |
Expand Down
65 changes: 65 additions & 0 deletions docs/rules/max-expects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Enforces a maximum number assertion calls in a test body (`max-expects`)

As more assertions are made, there is a possible tendency for the test to be
more likely to mix multiple objectives. To avoid this, this rule reports when
the maximum number of assertions is exceeded.

## Rule details

This rule enforces a maximum number of `expect()` calls.

The following patterns are considered warnings (with the default option of
`{ "max": 5 } `):

```js
test('should not pass', () => {
expect(true).toBeDefined();
expect(true).toBeDefined();
expect(true).toBeDefined();
expect(true).toBeDefined();
expect(true).toBeDefined();
expect(true).toBeDefined();
});
```

The following patterns are **not** considered warnings (with the default option
of `{ "max": 5 } `):

```js
test('shout pass');

test('shout pass', () => {});

test.skip('shout pass', () => {});

test('should pass', function () {
expect(true).toBeDefined();
});

test('should pass', () => {
expect(true).toBeDefined();
expect(true).toBeDefined();
expect(true).toBeDefined();
expect(true).toBeDefined();
expect(true).toBeDefined();
});
```

## Options

```json
{
"playwright/max-expects": [
"error",
{
"max": 5
}
]
}
```

### `max`

Enforces a maximum number of `expect()`.

This has a default value of `5`.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import globals from 'globals';
import expectExpect from './rules/expect-expect';
import maxExpects from './rules/max-expects';
import maxNestedDescribe from './rules/max-nested-describe';
import missingPlaywrightAwait from './rules/missing-playwright-await';
import noCommentedOutTests from './rules/no-commented-out-tests';
Expand Down Expand Up @@ -42,6 +43,7 @@ const index = {
configs: {},
rules: {
'expect-expect': expectExpect,
'max-expects': maxExpects,
'max-nested-describe': maxNestedDescribe,
'missing-playwright-await': missingPlaywrightAwait,
'no-commented-out-tests': noCommentedOutTests,
Expand Down
72 changes: 72 additions & 0 deletions src/rules/max-expects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Rule } from 'eslint';
import * as ESTree from 'estree';
import { getExpectType, getParent, isTestCall } from '../utils/ast';

export default {
create(context) {
const options = {
max: 5,
...((context.options?.[0] as Record<string, unknown>) ?? {}),
};

let count = 0;

const maybeResetCount = (node: ESTree.Node) => {
const parent = getParent(node);
const isTestFn =
parent?.type !== 'CallExpression' || isTestCall(context, parent);

if (isTestFn) {
count = 0;
}
};

return {
ArrowFunctionExpression: maybeResetCount,
'ArrowFunctionExpression:exit': maybeResetCount,
CallExpression(node) {
if (!getExpectType(context, node)) return;

count += 1;

if (count > options.max) {
context.report({
data: {
count: count.toString(),
max: options.max.toString(),
},
messageId: 'exceededMaxAssertion',
node,
});
}
},
FunctionExpression: maybeResetCount,
'FunctionExpression:exit': maybeResetCount,
};
},
meta: {
docs: {
category: 'Best Practices',
description: 'Enforces a maximum number assertion calls in a test body',
recommended: false,
url: 'https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/max-expects.md',
},
messages: {
exceededMaxAssertion:
'Too many assertion calls ({{ count }}) - maximum allowed is {{ max }}',
},
schema: [
{
additionalProperties: false,
properties: {
max: {
minimum: 1,
type: 'integer',
},
},
type: 'object',
},
],
type: 'suggestion',
},
} as Rule.RuleModule;
Loading

0 comments on commit 71004af

Please sign in to comment.