Skip to content

Commit 1d540a7

Browse files
authored
[kbn-eslint-plugin-eslint] add scout_no_describe_configure rule (elastic#234390)
## Summary Adding new rule to prevent playwright runner configuration overrides in spec files. It is important to keep runner functionality unified across all the Scout tests and having custom logic may lead to unexpected CI behavior or wrong test results ingestion. We already have unified functionality in place: - retrying failure is handled on CI script level - parallel test execution is limited to test spec level (we don't allow concurrent run of tests within the same file) - explicit timeouts for test execution is not recommended, but can be accepted for individual cases Adding smth like: ``` spaceTest.describe('Discover app - errors', { tag: tags.ESS_ONLY }, () => { spaceTest.describe.configure({ retries: 2, timeout: 120000, }); ``` will be blocked by pre-commit hook: ``` *[scout/scout_no_describe_configure][~/github/kibana]$ gc "add configure" ERROR /Users/dmle/github/kibana/x-pack/platform/plugins/private/discover_enhanced/test/scout/ui/parallel_tests/error_handling.spec.ts 12:3 error Using describe.configure is not allowed in Scout tests @kbn/eslint/scout_no_describe_configure ```
1 parent b628562 commit 1d540a7

4 files changed

Lines changed: 202 additions & 0 deletions

File tree

.eslintrc.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,6 +2421,17 @@ module.exports = {
24212421
],
24222422
},
24232423
},
2424+
{
2425+
// Custom rules for scout tests
2426+
files: [
2427+
'src/platform/plugins/**/test/scout/**/*.ts',
2428+
'x-pack/platform/**/plugins/**/test/scout/**/*.ts',
2429+
'x-pack/solutions/**/plugins/test/scout/**/*.ts',
2430+
],
2431+
rules: {
2432+
'@kbn/eslint/scout_no_describe_configure': 'error',
2433+
},
2434+
},
24242435
{
24252436
// Deployment-agnostic test files must use proper context and services
24262437
files: [

packages/kbn-eslint-plugin-eslint/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ module.exports = {
2323
require_kibana_feature_privileges_naming: require('./rules/require_kibana_feature_privileges_naming'),
2424
no_deprecated_imports: require('./rules/no_deprecated_imports'),
2525
deployment_agnostic_test_context: require('./rules/deployment_agnostic_test_context'),
26+
scout_no_describe_configure: require('./rules/scout_no_describe_configure'),
2627
},
2728
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
/** @typedef {import("eslint").Rule.RuleModule} Rule */
11+
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.CallExpression} CallExpression */
12+
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.MemberExpression} MemberExpression */
13+
14+
const ERROR_MSG = 'Using describe.configure is not allowed in Scout tests.';
15+
16+
/**
17+
* Checks if a node represents *.describe.configure()
18+
* @param {CallExpression} node
19+
* @returns {boolean}
20+
*/
21+
const isDescribeConfigure = (node) => {
22+
// Check for *.describe.configure()
23+
return (
24+
node.callee.type === 'MemberExpression' &&
25+
node.callee.property.type === 'Identifier' &&
26+
node.callee.property.name === 'configure' &&
27+
node.callee.object.type === 'MemberExpression' &&
28+
node.callee.object.property.type === 'Identifier' &&
29+
node.callee.object.property.name === 'describe'
30+
);
31+
};
32+
33+
/** @type {Rule} */
34+
module.exports = {
35+
meta: {
36+
type: 'problem',
37+
docs: {
38+
description: 'Disallow describe.configure in Scout tests',
39+
category: 'Best Practices',
40+
},
41+
fixable: null,
42+
schema: [],
43+
},
44+
create: (context) => ({
45+
CallExpression(node) {
46+
if (isDescribeConfigure(node)) {
47+
context.report({
48+
node,
49+
message: ERROR_MSG,
50+
});
51+
}
52+
},
53+
}),
54+
};
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
const { RuleTester } = require('eslint');
11+
const rule = require('./scout_no_describe_configure');
12+
const dedent = require('dedent');
13+
14+
const ruleTester = new RuleTester({
15+
parser: require.resolve('@typescript-eslint/parser'),
16+
parserOptions: {
17+
sourceType: 'module',
18+
ecmaVersion: 2018,
19+
ecmaFeatures: {
20+
jsx: true,
21+
},
22+
},
23+
});
24+
25+
ruleTester.run('@kbn/eslint/scout_no_describe_configure', rule, {
26+
valid: [
27+
{
28+
code: dedent`
29+
test('should work', () => {
30+
expect(true).toBe(true);
31+
});
32+
`,
33+
},
34+
{
35+
code: dedent`
36+
test.describe('my test suite', () => {
37+
test('should work', () => {
38+
expect(true).toBe(true);
39+
});
40+
});
41+
`,
42+
},
43+
{
44+
code: dedent`
45+
spaceTest.describe('my space-aware test suite', () => {
46+
spaceTest('should work', () => {
47+
expect(true).toBe(true);
48+
});
49+
});
50+
`,
51+
},
52+
{
53+
code: dedent`
54+
describe('my test suite', () => {
55+
test('should work', () => {
56+
expect(true).toBe(true);
57+
});
58+
});
59+
`,
60+
},
61+
{
62+
code: dedent`
63+
const describeBlock = test.describe;
64+
describeBlock('my test suite', () => {
65+
test('should work', () => {
66+
expect(true).toBe(true);
67+
});
68+
});
69+
`,
70+
},
71+
],
72+
73+
invalid: [
74+
{
75+
code: dedent`
76+
test.describe.configure({ mode: 'parallel' });
77+
`,
78+
errors: [
79+
{
80+
message: 'Using describe.configure is not allowed in Scout tests.',
81+
},
82+
],
83+
},
84+
{
85+
code: dedent`
86+
test.describe.configure({
87+
mode: 'parallel',
88+
retries: 2
89+
});
90+
`,
91+
errors: [
92+
{
93+
message: 'Using describe.configure is not allowed in Scout tests.',
94+
},
95+
],
96+
},
97+
{
98+
code: dedent`
99+
test.describe('my suite', () => {
100+
test.describe.configure({ mode: 'serial' });
101+
102+
test('should work', () => {
103+
expect(true).toBe(true);
104+
});
105+
});
106+
`,
107+
errors: [
108+
{
109+
message: 'Using describe.configure is not allowed in Scout tests.',
110+
},
111+
],
112+
},
113+
{
114+
code: dedent`
115+
const myTest = test;
116+
myTest.describe.configure({ mode: 'parallel' });
117+
`,
118+
errors: [
119+
{
120+
message: 'Using describe.configure is not allowed in Scout tests.',
121+
},
122+
],
123+
},
124+
{
125+
code: dedent`
126+
// Different object with describe.configure should also be caught
127+
spaceTest.describe.configure({});
128+
`,
129+
errors: [
130+
{
131+
message: 'Using describe.configure is not allowed in Scout tests.',
132+
},
133+
],
134+
},
135+
],
136+
});

0 commit comments

Comments
 (0)