Skip to content

Commit

Permalink
feat: Add support for custom rule messages (#280)
Browse files Browse the repository at this point in the history
* feat: Add support for custom rule messages

* feat: Add support fort custom rule messages in all rules

* Interpolate messages
  • Loading branch information
mskelton committed Apr 8, 2024
1 parent 4ba597c commit 08fc723
Show file tree
Hide file tree
Showing 51 changed files with 276 additions and 127 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ export default [
}
```

## Settings

### Aliased Playwright Globals

If you import Playwright globals (e.g. `test`, `expect`) with a custom name, you
Expand All @@ -129,6 +131,27 @@ can configure this plugin to be aware of these additional names.
}
```

### Custom Messages

You can customize the error messages for rules using the
`settings.playwright.messages` property. This is useful if you would like to
increase the verbosity of error messages or provide additional context.

Only the message ids you define in this setting will be overridden, so any other
messages will use the default message defined by the plugin.

```json
{
"settings": {
"playwright": {
"messages": {
"conditionalExpect": "Avoid conditional expects as they can lead to false positives"
}
}
}
}
```

## Rules

✅ Set in the `recommended` configuration\
Expand Down
6 changes: 3 additions & 3 deletions src/rules/expect-expect.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Rule } from 'eslint'
import ESTree from 'estree'
import { dig } from '../utils/ast'
import { createRule } from '../utils/createRule'
import { parseFnCall } from '../utils/parseFnCall'

export default {
export default createRule({
create(context) {
const options = {
assertFunctionNames: [] as string[],
Expand Down Expand Up @@ -69,4 +69,4 @@ export default {
],
type: 'problem',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/max-expects.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Rule } from 'eslint'
import * as ESTree from 'estree'
import { getParent } from '../utils/ast'
import { createRule } from '../utils/createRule'
import { isTypeOfFnCall, parseFnCall } from '../utils/parseFnCall'

export default {
export default createRule({
create(context) {
const options = {
max: 5,
Expand Down Expand Up @@ -78,4 +78,4 @@ export default {
],
type: 'suggestion',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/max-nested-describe.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Rule } from 'eslint'
import * as ESTree from 'estree'
import { createRule } from '../utils/createRule'
import { isTypeOfFnCall } from '../utils/parseFnCall'

export default {
export default createRule({
create(context) {
const { options } = context
const max: number = options[0]?.max ?? 5
Expand Down Expand Up @@ -57,4 +57,4 @@ export default {
],
type: 'suggestion',
},
} as Rule.RuleModule
})
5 changes: 3 additions & 2 deletions src/rules/missing-playwright-await.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Rule } from 'eslint'
import ESTree from 'estree'
import { getParent, getStringValue, isIdentifier } from '../utils/ast'
import { createRule } from '../utils/createRule'
import { ParsedFnCall, parseFnCall } from '../utils/parseFnCall'

const validTypes = new Set([
Expand Down Expand Up @@ -81,7 +82,7 @@ function getCallType(call: ParsedFnCall, awaitableMatchers: Set<string>) {
}
}

export default {
export default createRule({
create(context) {
const options = context.options[0] || {}
const awaitableMatchers = new Set([
Expand Down Expand Up @@ -182,4 +183,4 @@ export default {
],
type: 'problem',
},
} as Rule.RuleModule
})
5 changes: 3 additions & 2 deletions src/rules/no-commented-out-tests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Rule } from 'eslint'
import * as ESTree from 'estree'
import { createRule } from '../utils/createRule'

function getTestNames(context: Rule.RuleContext) {
const aliases = context.settings.playwright?.globalAliases?.test ?? []
Expand All @@ -16,7 +17,7 @@ function hasTests(context: Rule.RuleContext, node: ESTree.Comment) {
return regex.test(node.value)
}

export default {
export default createRule({
create(context) {
function checkNode(node: ESTree.Comment) {
if (!hasTests(context, node)) return
Expand Down Expand Up @@ -45,4 +46,4 @@ export default {
},
type: 'problem',
},
} as Rule.RuleModule
})
5 changes: 3 additions & 2 deletions src/rules/no-conditional-expect.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Rule, Scope } from 'eslint'
import * as ESTree from 'estree'
import { getParent, isPropertyAccessor } from '../utils/ast'
import { createRule } from '../utils/createRule'
import { isTypeOfFnCall, parseFnCall } from '../utils/parseFnCall'
import { KnownCallExpression } from '../utils/types'

Expand Down Expand Up @@ -30,7 +31,7 @@ const getTestCallExpressionsFromDeclaredVariables = (
)
}

export default {
export default createRule({
create(context) {
let conditionalDepth = 0
let inTestCase = false
Expand Down Expand Up @@ -109,4 +110,4 @@ export default {
},
type: 'problem',
},
} as Rule.RuleModule
})
5 changes: 3 additions & 2 deletions src/rules/no-conditional-in-test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Rule } from 'eslint'
import { findParent } from '../utils/ast'
import { createRule } from '../utils/createRule'
import { isTypeOfFnCall } from '../utils/parseFnCall'

export default {
export default createRule({
create(context) {
function checkConditional(node: Rule.Node & Rule.NodeParentExtension) {
const call = findParent(node, 'CallExpression')
Expand Down Expand Up @@ -33,4 +34,4 @@ export default {
schema: [],
type: 'problem',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/no-duplicate-hooks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Rule } from 'eslint'
import { getStringValue } from '../utils/ast'
import { createRule } from '../utils/createRule'
import { isTypeOfFnCall, parseFnCall } from '../utils/parseFnCall'

export default {
export default createRule({
create(context) {
const hookContexts: Array<Record<string, number>> = [{}]

Expand Down Expand Up @@ -55,4 +55,4 @@ export default {
},
type: 'suggestion',
},
} as Rule.RuleModule
})
7 changes: 4 additions & 3 deletions src/rules/no-element-handle.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { AST, Rule } from 'eslint'
import { AST } from 'eslint'
import ESTree from 'estree'
import { isPageMethod } from '../utils/ast'
import { createRule } from '../utils/createRule'

function getPropertyRange(node: ESTree.Node): AST.Range {
return node.type === 'Identifier'
? node.range!
: [node.range![0] + 1, node.range![1] - 1]
}

export default {
export default createRule({
create(context) {
return {
CallExpression(node) {
Expand Down Expand Up @@ -68,4 +69,4 @@ export default {
},
type: 'suggestion',
},
} as Rule.RuleModule
})
24 changes: 24 additions & 0 deletions src/rules/no-eval.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import dedent from 'dedent'
import rule from '../../src/rules/no-eval'
import { runRuleTester, test } from '../utils/rule-tester'

Expand Down Expand Up @@ -63,6 +64,29 @@ runRuleTester('no-eval', rule, {
),
errors: [{ column: 52, endColumn: 63, line: 1, messageId: 'noEvalAll' }],
},

// Custom messages
// Note: This is one of the only test in the project to tests custom
// messages since it's implementation is global in the `createRule` method.
{
code: dedent`
page.$eval("#search", el => el.value);
page.$$eval("#search", el => el.value);
`,
errors: [
{ column: 1, endColumn: 11, line: 1, message: 'no eval' },
{ column: 1, endColumn: 12, line: 2, message: 'no eval all' },
],
name: 'Custom messages',
settings: {
playwright: {
messages: {
noEval: 'no eval',
noEvalAll: 'no eval all',
},
},
},
},
],
valid: [
test('await page.locator(".tweet").evaluate(node => node.innerText)'),
Expand Down
6 changes: 3 additions & 3 deletions src/rules/no-eval.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Rule } from 'eslint'
import { isPageMethod } from '../utils/ast'
import { createRule } from '../utils/createRule'

export default {
export default createRule({
create(context) {
return {
CallExpression(node) {
Expand Down Expand Up @@ -30,4 +30,4 @@ export default {
},
type: 'problem',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/no-focused-test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Rule } from 'eslint'
import { getStringValue } from '../utils/ast'
import { createRule } from '../utils/createRule'
import { parseFnCall } from '../utils/parseFnCall'

export default {
export default createRule({
create(context) {
return {
CallExpression(node) {
Expand Down Expand Up @@ -47,4 +47,4 @@ export default {
},
type: 'problem',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/no-force-option.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Rule } from 'eslint'
import ESTree from 'estree'
import { getStringValue, isBooleanLiteral } from '../utils/ast'
import { createRule } from '../utils/createRule'

function isForceOptionEnabled(node: ESTree.CallExpression) {
const arg = node.arguments.at(-1)
Expand Down Expand Up @@ -31,7 +31,7 @@ const methodsWithForceOption = new Set([
'tap',
])

export default {
export default createRule({
create(context) {
return {
MemberExpression(node) {
Expand Down Expand Up @@ -60,4 +60,4 @@ export default {
},
type: 'suggestion',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/no-get-by-title.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Rule } from 'eslint'
import { isPageMethod } from '../utils/ast'
import { createRule } from '../utils/createRule'

export default {
export default createRule({
create(context) {
return {
CallExpression(node) {
Expand All @@ -24,4 +24,4 @@ export default {
},
type: 'suggestion',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/no-hooks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Rule } from 'eslint'
import { createRule } from '../utils/createRule'
import { parseFnCall } from '../utils/parseFnCall'

export default {
export default createRule({
create(context) {
const options = {
allow: [] as string[],
Expand Down Expand Up @@ -47,4 +47,4 @@ export default {
],
type: 'suggestion',
},
} as Rule.RuleModule
})
5 changes: 3 additions & 2 deletions src/rules/no-nested-step.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Rule } from 'eslint'
import ESTree from 'estree'
import { isPropertyAccessor } from '../utils/ast'
import { createRule } from '../utils/createRule'

function isStepCall(node: ESTree.Node): boolean {
const inner = node.type === 'CallExpression' ? node.callee : node
Expand All @@ -12,7 +13,7 @@ function isStepCall(node: ESTree.Node): boolean {
return isPropertyAccessor(inner, 'step')
}

export default {
export default createRule({
create(context) {
const stack: number[] = []

Expand Down Expand Up @@ -59,4 +60,4 @@ export default {
schema: [],
type: 'problem',
},
} as Rule.RuleModule
})
6 changes: 3 additions & 3 deletions src/rules/no-networkidle.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Rule } from 'eslint'
import ESTree from 'estree'
import { getStringValue, isStringLiteral } from '../utils/ast'
import { createRule } from '../utils/createRule'

const messageId = 'noNetworkidle'
const methods = new Set([
Expand All @@ -13,7 +13,7 @@ const methods = new Set([
'waitForURL',
])

export default {
export default createRule({
create(context) {
return {
CallExpression(node) {
Expand Down Expand Up @@ -61,4 +61,4 @@ export default {
},
type: 'problem',
},
} as Rule.RuleModule
})

0 comments on commit 08fc723

Please sign in to comment.