@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.
Files changed (2) hide show
  1. package/dist/index.js +164 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const meta$a = {
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$a = context => {
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$a,
30
- meta: meta$a
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$9 = {
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$9 = context => {
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$9,
69
- meta: meta$9
115
+ create: create$b,
116
+ meta: meta$b
70
117
  };
71
118
 
72
- const meta$8 = {
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$8 = context => {
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$8,
150
- meta: meta$8
238
+ create: create$9,
239
+ meta: meta$9
151
240
  };
152
241
 
153
- const meta$7 = {
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$7 = context => {
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$7,
237
- meta: meta$7
325
+ create: create$8,
326
+ meta: meta$8
238
327
  };
239
328
 
240
- const meta$6 = {
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$6 = context => {
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',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/eslint-plugin-e2e",
3
- "version": "18.2.0",
3
+ "version": "18.4.0",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",