@lvce-editor/eslint-plugin-e2e 18.2.0 → 18.4.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/dist/index.js +164 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const meta$
|
|
1
|
+
const meta$d = {
|
|
2
2
|
docs: {
|
|
3
3
|
description: 'Disallow direct click calls in E2E tests'
|
|
4
4
|
},
|
|
@@ -10,7 +10,7 @@ const meta$a = {
|
|
|
10
10
|
const isDirectClickCall = node => {
|
|
11
11
|
return node.callee.type === 'MemberExpression' && node.callee.property.type === 'Identifier' && node.callee.property.name === 'click';
|
|
12
12
|
};
|
|
13
|
-
const create$
|
|
13
|
+
const create$d = context => {
|
|
14
14
|
return {
|
|
15
15
|
CallExpression(node) {
|
|
16
16
|
if (!isDirectClickCall(node)) {
|
|
@@ -26,12 +26,59 @@ const create$a = context => {
|
|
|
26
26
|
|
|
27
27
|
const noDirectClick = {
|
|
28
28
|
__proto__: null,
|
|
29
|
-
create: create$
|
|
30
|
-
meta: meta$
|
|
29
|
+
create: create$d,
|
|
30
|
+
meta: meta$d
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const meta$c = {
|
|
34
|
+
docs: {
|
|
35
|
+
description: 'Disallow disabling the memory clipboard in finally blocks'
|
|
36
|
+
},
|
|
37
|
+
messages: {
|
|
38
|
+
noDisableMemoryClipBoardInFinally: 'Do not call ClipBoard.disableMemoryClipBoard() in a finally block. The memory clipboard is disabled automatically after each test.'
|
|
39
|
+
},
|
|
40
|
+
type: 'problem'
|
|
41
|
+
};
|
|
42
|
+
const isDisableMemoryClipBoardCall = node => {
|
|
43
|
+
const {
|
|
44
|
+
callee
|
|
45
|
+
} = node;
|
|
46
|
+
return callee.type === 'MemberExpression' && callee.object.type === 'Identifier' && callee.object.name === 'ClipBoard' && callee.property.type === 'Identifier' && callee.property.name === 'disableMemoryClipBoard';
|
|
47
|
+
};
|
|
48
|
+
const isInFinallyBlock = (context, node) => {
|
|
49
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
50
|
+
return ancestors.some(ancestor => {
|
|
51
|
+
if (ancestor.type !== 'TryStatement') {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const {
|
|
55
|
+
finalizer
|
|
56
|
+
} = ancestor;
|
|
57
|
+
return finalizer !== null && finalizer !== undefined && ancestors.includes(finalizer);
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const create$c = context => {
|
|
61
|
+
return {
|
|
62
|
+
CallExpression(node) {
|
|
63
|
+
if (!isDisableMemoryClipBoardCall(node) || !isInFinallyBlock(context, node)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
context.report({
|
|
67
|
+
messageId: 'noDisableMemoryClipBoardInFinally',
|
|
68
|
+
node
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const noDisableMemoryClipBoardInFinally = {
|
|
75
|
+
__proto__: null,
|
|
76
|
+
create: create$c,
|
|
77
|
+
meta: meta$c
|
|
31
78
|
};
|
|
32
79
|
|
|
33
80
|
const allowedTypeImportSource = '@lvce-editor/test-with-playwright';
|
|
34
|
-
const meta$
|
|
81
|
+
const meta$b = {
|
|
35
82
|
docs: {
|
|
36
83
|
description: 'Disallow imports in e2e tests except type imports from @lvce-editor/test-with-playwright'
|
|
37
84
|
},
|
|
@@ -49,7 +96,7 @@ const isAllowedTypeImport = node => {
|
|
|
49
96
|
}
|
|
50
97
|
return node.specifiers.length > 0 && node.specifiers.every(specifier => specifier.importKind === 'type');
|
|
51
98
|
};
|
|
52
|
-
const create$
|
|
99
|
+
const create$b = context => {
|
|
53
100
|
return {
|
|
54
101
|
ImportDeclaration(node) {
|
|
55
102
|
if (isAllowedTypeImport(node)) {
|
|
@@ -65,11 +112,53 @@ const create$9 = context => {
|
|
|
65
112
|
|
|
66
113
|
const noImports = {
|
|
67
114
|
__proto__: null,
|
|
68
|
-
create: create$
|
|
69
|
-
meta: meta$
|
|
115
|
+
create: create$b,
|
|
116
|
+
meta: meta$b
|
|
70
117
|
};
|
|
71
118
|
|
|
72
|
-
const meta$
|
|
119
|
+
const meta$a = {
|
|
120
|
+
docs: {
|
|
121
|
+
description: 'Disallow inline import.meta.resolve calls in Main.openUri calls'
|
|
122
|
+
},
|
|
123
|
+
messages: {
|
|
124
|
+
noInlineImportMetaResolveInOpenUri: 'Assign import.meta.resolve(...) to a variable before passing the URI to Main.openUri(...).'
|
|
125
|
+
},
|
|
126
|
+
type: 'problem'
|
|
127
|
+
};
|
|
128
|
+
const isIdentifier$3 = (node, name) => {
|
|
129
|
+
return node.type === 'Identifier' && node.name === name;
|
|
130
|
+
};
|
|
131
|
+
const isImportMeta$1 = node => {
|
|
132
|
+
return node.type === 'MetaProperty' && isIdentifier$3(node.meta, 'import') && isIdentifier$3(node.property, 'meta');
|
|
133
|
+
};
|
|
134
|
+
const isImportMetaResolveCall = node => {
|
|
135
|
+
return node.type === 'CallExpression' && node.callee.type === 'MemberExpression' && !node.callee.computed && isImportMeta$1(node.callee.object) && isIdentifier$3(node.callee.property, 'resolve');
|
|
136
|
+
};
|
|
137
|
+
const isMainOpenUriCall = node => {
|
|
138
|
+
return node.callee.type === 'MemberExpression' && !node.callee.computed && isIdentifier$3(node.callee.object, 'Main') && isIdentifier$3(node.callee.property, 'openUri');
|
|
139
|
+
};
|
|
140
|
+
const create$a = context => {
|
|
141
|
+
return {
|
|
142
|
+
CallExpression(node) {
|
|
143
|
+
const [uri] = node.arguments;
|
|
144
|
+
if (!isMainOpenUriCall(node) || !uri || !isImportMetaResolveCall(uri)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
context.report({
|
|
148
|
+
messageId: 'noInlineImportMetaResolveInOpenUri',
|
|
149
|
+
node: uri
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const noInlineImportMetaResolveInOpenUri = {
|
|
156
|
+
__proto__: null,
|
|
157
|
+
create: create$a,
|
|
158
|
+
meta: meta$a
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const meta$9 = {
|
|
73
162
|
docs: {
|
|
74
163
|
description: 'Disallow inline locator expressions inside expect calls'
|
|
75
164
|
},
|
|
@@ -126,7 +215,7 @@ const containsInlineLocatorCall = node => {
|
|
|
126
215
|
const isExpectCall$2 = node => {
|
|
127
216
|
return node.callee.type === 'Identifier' && node.callee.name === 'expect';
|
|
128
217
|
};
|
|
129
|
-
const create$
|
|
218
|
+
const create$9 = context => {
|
|
130
219
|
return {
|
|
131
220
|
CallExpression(node) {
|
|
132
221
|
if (!isExpectCall$2(node)) {
|
|
@@ -146,11 +235,11 @@ const create$8 = context => {
|
|
|
146
235
|
|
|
147
236
|
const noInlineLocatorInExpect = {
|
|
148
237
|
__proto__: null,
|
|
149
|
-
create: create$
|
|
150
|
-
meta: meta$
|
|
238
|
+
create: create$9,
|
|
239
|
+
meta: meta$9
|
|
151
240
|
};
|
|
152
241
|
|
|
153
|
-
const meta$
|
|
242
|
+
const meta$8 = {
|
|
154
243
|
docs: {
|
|
155
244
|
description: 'Disallow inline nth locator expressions inside expect calls'
|
|
156
245
|
},
|
|
@@ -213,7 +302,7 @@ const containsInlineNthCall = node => {
|
|
|
213
302
|
const isExpectCall$1 = node => {
|
|
214
303
|
return node.callee.type === 'Identifier' && node.callee.name === 'expect';
|
|
215
304
|
};
|
|
216
|
-
const create$
|
|
305
|
+
const create$8 = context => {
|
|
217
306
|
return {
|
|
218
307
|
CallExpression(node) {
|
|
219
308
|
if (!isExpectCall$1(node)) {
|
|
@@ -233,11 +322,11 @@ const create$7 = context => {
|
|
|
233
322
|
|
|
234
323
|
const noInlineNthInExpect = {
|
|
235
324
|
__proto__: null,
|
|
236
|
-
create: create$
|
|
237
|
-
meta: meta$
|
|
325
|
+
create: create$8,
|
|
326
|
+
meta: meta$8
|
|
238
327
|
};
|
|
239
328
|
|
|
240
|
-
const meta$
|
|
329
|
+
const meta$7 = {
|
|
241
330
|
docs: {
|
|
242
331
|
description: 'Disallow lazy nth-based variable names for locator variables'
|
|
243
332
|
},
|
|
@@ -298,7 +387,7 @@ const containsNthCall = node => {
|
|
|
298
387
|
const hasLazyNthVariableName = node => {
|
|
299
388
|
return isIdentifierNode$1(node) && lazyNthVariableNamePattern.test(node.name);
|
|
300
389
|
};
|
|
301
|
-
const create$
|
|
390
|
+
const create$7 = context => {
|
|
302
391
|
return {
|
|
303
392
|
VariableDeclarator(node) {
|
|
304
393
|
if (!isVariableDeclaratorNode$1(node)) {
|
|
@@ -319,6 +408,57 @@ const create$6 = context => {
|
|
|
319
408
|
};
|
|
320
409
|
|
|
321
410
|
const noLazyNthVariableName = {
|
|
411
|
+
__proto__: null,
|
|
412
|
+
create: create$7,
|
|
413
|
+
meta: meta$7
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
const meta$6 = {
|
|
417
|
+
docs: {
|
|
418
|
+
description: 'Disallow clicking context menu item locators directly in E2E tests'
|
|
419
|
+
},
|
|
420
|
+
messages: {
|
|
421
|
+
noMenuItemClick: 'Do not call .click() on a .MenuItem locator. Use ContextMenu.selectItem(...) instead.'
|
|
422
|
+
},
|
|
423
|
+
type: 'problem'
|
|
424
|
+
};
|
|
425
|
+
const isMenuItemLocatorCall = node => {
|
|
426
|
+
if (node.type !== 'CallExpression') {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
if (node.callee.type === 'Identifier' && node.callee.name === 'Locator') {
|
|
430
|
+
const [selector] = node.arguments;
|
|
431
|
+
return selector?.type === 'Literal' && selector.value === '.MenuItem';
|
|
432
|
+
}
|
|
433
|
+
return node.callee.type === 'MemberExpression' && node.callee.object.type !== 'Super' && isMenuItemLocatorCall(node.callee.object);
|
|
434
|
+
};
|
|
435
|
+
const isClickCall = node => {
|
|
436
|
+
return node.callee.type === 'MemberExpression' && node.callee.property.type === 'Identifier' && node.callee.property.name === 'click';
|
|
437
|
+
};
|
|
438
|
+
const create$6 = context => {
|
|
439
|
+
const menuItemLocators = new Set();
|
|
440
|
+
return {
|
|
441
|
+
CallExpression(node) {
|
|
442
|
+
if (!isClickCall(node) || node.callee.object.type === 'Super') {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const locator = node.callee.object;
|
|
446
|
+
if (locator.type === 'Identifier' && menuItemLocators.has(locator.name) || isMenuItemLocatorCall(locator)) {
|
|
447
|
+
context.report({
|
|
448
|
+
messageId: 'noMenuItemClick',
|
|
449
|
+
node: node.callee.property
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
VariableDeclarator(node) {
|
|
454
|
+
if (node.id.type === 'Identifier' && node.init && isMenuItemLocatorCall(node.init)) {
|
|
455
|
+
menuItemLocators.add(node.id.name);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
const noMenuItemClick = {
|
|
322
462
|
__proto__: null,
|
|
323
463
|
create: create$6,
|
|
324
464
|
meta: meta$6
|
|
@@ -649,10 +789,13 @@ const plugin = {
|
|
|
649
789
|
},
|
|
650
790
|
rules: {
|
|
651
791
|
'no-direct-click': noDirectClick,
|
|
792
|
+
'no-disable-memory-clipboard-in-finally': noDisableMemoryClipBoardInFinally,
|
|
652
793
|
'no-imports': noImports,
|
|
794
|
+
'no-inline-import-meta-resolve-in-open-uri': noInlineImportMetaResolveInOpenUri,
|
|
653
795
|
'no-inline-locator-in-expect': noInlineLocatorInExpect,
|
|
654
796
|
'no-inline-nth-in-expect': noInlineNthInExpect,
|
|
655
797
|
'no-lazy-nth-variable-name': noLazyNthVariableName,
|
|
798
|
+
'no-menu-item-click': noMenuItemClick,
|
|
656
799
|
'no-skip-zero': noSkipZero,
|
|
657
800
|
'prefer-direct-api-destructuring': preferDirectApiDestructuring,
|
|
658
801
|
'prefer-execute-extension-command': preferExecuteExtensionCommand,
|
|
@@ -668,10 +811,13 @@ const recommended = [{
|
|
|
668
811
|
},
|
|
669
812
|
rules: {
|
|
670
813
|
'e2e/no-direct-click': 'error',
|
|
814
|
+
'e2e/no-disable-memory-clipboard-in-finally': 'error',
|
|
671
815
|
'e2e/no-imports': 'error',
|
|
816
|
+
'e2e/no-inline-import-meta-resolve-in-open-uri': 'error',
|
|
672
817
|
'e2e/no-inline-locator-in-expect': 'error',
|
|
673
818
|
'e2e/no-inline-nth-in-expect': 'error',
|
|
674
819
|
'e2e/no-lazy-nth-variable-name': 'error',
|
|
820
|
+
'e2e/no-menu-item-click': 'error',
|
|
675
821
|
'e2e/no-skip-zero': 'error',
|
|
676
822
|
'e2e/prefer-direct-api-destructuring': 'error',
|
|
677
823
|
'e2e/prefer-execute-extension-command': 'error',
|