@atlaskit/eslint-plugin-platform 0.6.1 → 0.7.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 (126) hide show
  1. package/CHANGELOG.md +103 -28
  2. package/afm-jira/tsconfig.json +20 -0
  3. package/dist/cjs/index.js +48 -2
  4. package/dist/cjs/rules/constants.js +11 -0
  5. package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +54 -6
  6. package/dist/cjs/rules/ensure-native-and-af-exports-synced/index.js +16 -7
  7. package/dist/cjs/rules/ensure-valid-emotion-css-prop/index.js +91 -0
  8. package/dist/cjs/rules/inline-usage/index.js +94 -0
  9. package/dist/cjs/rules/no-alias/index.js +64 -0
  10. package/dist/cjs/rules/no-module-level-eval/index.js +45 -0
  11. package/dist/cjs/rules/no-preconditioning/index.js +108 -0
  12. package/dist/cjs/rules/prefer-fg/index.js +106 -0
  13. package/dist/cjs/rules/static-feature-flags/index.js +63 -0
  14. package/dist/cjs/rules/use-recommended-utils/index.js +47 -0
  15. package/dist/cjs/rules/util/registration-utils.js +2 -1
  16. package/dist/cjs/rules/utils.js +53 -0
  17. package/dist/es2019/index.js +52 -2
  18. package/dist/es2019/rules/constants.js +5 -0
  19. package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +52 -6
  20. package/dist/es2019/rules/ensure-native-and-af-exports-synced/index.js +15 -7
  21. package/dist/es2019/rules/ensure-valid-emotion-css-prop/index.js +87 -0
  22. package/dist/es2019/rules/inline-usage/index.js +90 -0
  23. package/dist/es2019/rules/no-alias/index.js +58 -0
  24. package/dist/es2019/rules/no-module-level-eval/index.js +39 -0
  25. package/dist/es2019/rules/no-preconditioning/index.js +105 -0
  26. package/dist/es2019/rules/prefer-fg/index.js +81 -0
  27. package/dist/es2019/rules/static-feature-flags/index.js +54 -0
  28. package/dist/es2019/rules/use-recommended-utils/index.js +41 -0
  29. package/dist/es2019/rules/util/registration-utils.js +2 -1
  30. package/dist/es2019/rules/utils.js +29 -0
  31. package/dist/esm/index.js +48 -2
  32. package/dist/esm/rules/constants.js +5 -0
  33. package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +54 -6
  34. package/dist/esm/rules/ensure-native-and-af-exports-synced/index.js +16 -7
  35. package/dist/esm/rules/ensure-valid-emotion-css-prop/index.js +85 -0
  36. package/dist/esm/rules/inline-usage/index.js +87 -0
  37. package/dist/esm/rules/no-alias/index.js +57 -0
  38. package/dist/esm/rules/no-module-level-eval/index.js +39 -0
  39. package/dist/esm/rules/no-preconditioning/index.js +102 -0
  40. package/dist/esm/rules/prefer-fg/index.js +99 -0
  41. package/dist/esm/rules/static-feature-flags/index.js +56 -0
  42. package/dist/esm/rules/use-recommended-utils/index.js +41 -0
  43. package/dist/esm/rules/util/registration-utils.js +2 -1
  44. package/dist/esm/rules/utils.js +45 -0
  45. package/dist/types/index.d.ts +15 -0
  46. package/dist/types/rules/constants.d.ts +3 -0
  47. package/dist/types/rules/ensure-valid-emotion-css-prop/index.d.ts +3 -0
  48. package/dist/types/rules/inline-usage/index.d.ts +3 -0
  49. package/dist/types/rules/no-alias/index.d.ts +3 -0
  50. package/dist/types/rules/no-module-level-eval/index.d.ts +3 -0
  51. package/dist/types/rules/no-preconditioning/index.d.ts +3 -0
  52. package/dist/types/rules/prefer-fg/index.d.ts +3 -0
  53. package/dist/types/rules/static-feature-flags/index.d.ts +3 -0
  54. package/dist/types/rules/use-recommended-utils/index.d.ts +3 -0
  55. package/dist/types/rules/util/registration-utils.d.ts +1 -0
  56. package/dist/types/rules/utils.d.ts +7 -0
  57. package/dist/types-ts4.5/index.d.ts +15 -0
  58. package/dist/types-ts4.5/rules/constants.d.ts +3 -0
  59. package/dist/types-ts4.5/rules/ensure-valid-emotion-css-prop/index.d.ts +3 -0
  60. package/dist/types-ts4.5/rules/inline-usage/index.d.ts +3 -0
  61. package/dist/types-ts4.5/rules/no-alias/index.d.ts +3 -0
  62. package/dist/types-ts4.5/rules/no-module-level-eval/index.d.ts +3 -0
  63. package/dist/types-ts4.5/rules/no-preconditioning/index.d.ts +3 -0
  64. package/dist/types-ts4.5/rules/prefer-fg/index.d.ts +3 -0
  65. package/dist/types-ts4.5/rules/static-feature-flags/index.d.ts +3 -0
  66. package/dist/types-ts4.5/rules/use-recommended-utils/index.d.ts +3 -0
  67. package/dist/types-ts4.5/rules/util/registration-utils.d.ts +1 -0
  68. package/dist/types-ts4.5/rules/utils.d.ts +7 -0
  69. package/index.js +9 -9
  70. package/package.json +43 -44
  71. package/report.api.md +31 -30
  72. package/src/__tests__/utils/_tester.tsx +16 -16
  73. package/src/index.tsx +102 -51
  74. package/src/rules/constants.tsx +20 -0
  75. package/src/rules/ensure-atlassian-team/__tests__/unit/rule.test.ts +19 -19
  76. package/src/rules/ensure-atlassian-team/index.ts +39 -52
  77. package/src/rules/ensure-critical-dependency-resolutions/__test__/unit/rule.test.tsx +146 -81
  78. package/src/rules/ensure-critical-dependency-resolutions/index.tsx +152 -97
  79. package/src/rules/ensure-feature-flag-prefix/__tests__/unit/rule.test.tsx +51 -51
  80. package/src/rules/ensure-feature-flag-prefix/index.tsx +65 -80
  81. package/src/rules/ensure-feature-flag-registration/__tests__/unit/rule.test.tsx +97 -97
  82. package/src/rules/ensure-feature-flag-registration/index.tsx +88 -105
  83. package/src/rules/ensure-native-and-af-exports-synced/__tests__/unit/rule.test.tsx +180 -180
  84. package/src/rules/ensure-native-and-af-exports-synced/index.tsx +162 -168
  85. package/src/rules/ensure-publish-valid/__tests__/unit/rule.test.ts +34 -36
  86. package/src/rules/ensure-publish-valid/index.ts +66 -81
  87. package/src/rules/ensure-test-runner-arguments/__tests__/unit/rule.test.tsx +93 -93
  88. package/src/rules/ensure-test-runner-arguments/index.tsx +107 -121
  89. package/src/rules/ensure-test-runner-nested-count/__tests__/unit/rule.test.tsx +43 -43
  90. package/src/rules/ensure-test-runner-nested-count/index.tsx +68 -70
  91. package/src/rules/ensure-valid-emotion-css-prop/__tests__/unit/rule.test.ts +142 -0
  92. package/src/rules/ensure-valid-emotion-css-prop/index.ts +96 -0
  93. package/src/rules/inline-usage/README.md +53 -0
  94. package/src/rules/inline-usage/__tests__/rule.test.tsx +106 -0
  95. package/src/rules/inline-usage/index.tsx +130 -0
  96. package/src/rules/no-alias/README.md +29 -0
  97. package/src/rules/no-alias/__tests__/rule.test.tsx +76 -0
  98. package/src/rules/no-alias/index.tsx +75 -0
  99. package/src/rules/no-duplicate-dependencies/__tests__/unit/rule.test.ts +44 -44
  100. package/src/rules/no-duplicate-dependencies/index.ts +68 -73
  101. package/src/rules/no-invalid-feature-flag-usage/__tests__/unit/rule.test.tsx +64 -64
  102. package/src/rules/no-invalid-feature-flag-usage/index.tsx +105 -112
  103. package/src/rules/no-invalid-storybook-decorator-usage/__tests__/unit/rule.test.tsx +13 -13
  104. package/src/rules/no-invalid-storybook-decorator-usage/index.tsx +28 -30
  105. package/src/rules/no-module-level-eval/README.md +53 -0
  106. package/src/rules/no-module-level-eval/__tests__/test.tsx +133 -0
  107. package/src/rules/no-module-level-eval/index.tsx +52 -0
  108. package/src/rules/no-pre-post-installs/__tests__/unit/rule.test.ts +36 -36
  109. package/src/rules/no-pre-post-installs/index.ts +27 -27
  110. package/src/rules/no-preconditioning/README.md +69 -0
  111. package/src/rules/no-preconditioning/__tests__/rule.test.tsx +164 -0
  112. package/src/rules/no-preconditioning/index.tsx +138 -0
  113. package/src/rules/prefer-fg/README.md +3 -0
  114. package/src/rules/prefer-fg/__tests__/rule.test.tsx +83 -0
  115. package/src/rules/prefer-fg/index.tsx +108 -0
  116. package/src/rules/static-feature-flags/README.md +3 -0
  117. package/src/rules/static-feature-flags/__tests__/test.tsx +135 -0
  118. package/src/rules/static-feature-flags/index.tsx +103 -0
  119. package/src/rules/use-recommended-utils/README.md +67 -0
  120. package/src/rules/use-recommended-utils/__tests__/rule.test.tsx +78 -0
  121. package/src/rules/use-recommended-utils/index.tsx +57 -0
  122. package/src/rules/util/handle-ast-object.ts +21 -32
  123. package/src/rules/util/registration-utils.ts +31 -30
  124. package/src/rules/utils.tsx +46 -0
  125. package/tsconfig.app.json +35 -35
  126. package/tsconfig.dev.json +39 -39
@@ -0,0 +1,29 @@
1
+ # Avoid aliasing feature flag utils (feature-flags/no-alias)
2
+
3
+ Ensure feature flag usage is statically analyzable. This applies to all methods, weather you are
4
+ writing production code, unit testing or storybooks.
5
+
6
+ ## Examples
7
+
8
+ 👎 Examples of **incorrect** code for this rule:
9
+
10
+ ```tsx
11
+ // Do not alias utils
12
+ import { ff as getBoolean } from '@atlassian/jira-feature-flagging';
13
+
14
+ // Do not reassign utils
15
+ import { fg } from '@atlassian/jira-feature-gating';
16
+ const aliasedFG = fg;
17
+ ```
18
+
19
+ 👍 Examples of **correct** code for this rule: Do not alias utils
20
+
21
+ ```tsx
22
+ import { ff } from '@atlassian/jira-feature-flagging';
23
+
24
+ export const doSomething = () => {
25
+ if (ff('my.flag')) {
26
+ console.log('hello');
27
+ }
28
+ };
29
+ ```
@@ -0,0 +1,76 @@
1
+ import outdent from 'outdent';
2
+ import { tester } from '../../../__tests__/utils/_tester';
3
+ import rule from '../index';
4
+
5
+ tester.run('feature-flags/no-alias', rule, {
6
+ valid: [
7
+ {
8
+ name: '`@atlassian/jira-feature-flagging` imports are not aliased',
9
+ code: outdent`
10
+ import { ff, ffVal } from '@atlassian/jira-feature-flagging';
11
+ `,
12
+ },
13
+ {
14
+ name: '`@atlassian/jira-feature-flagging-utils` imports are not aliased',
15
+ code: outdent`
16
+ import { componentWithFF } from '@atlassian/jira-feature-flagging-utils';
17
+ `,
18
+ },
19
+ {
20
+ name: '`@atlassian/jira-feature-gating` imports are not aliased',
21
+ code: outdent`
22
+ import { fg } from '@atlassian/jira-feature-gating';
23
+ `,
24
+ },
25
+ {
26
+ name: '`@atlassian/jira-feature-gates-test-mocks` imports are not aliased',
27
+ code: outdent`
28
+ import { passGate } from '@atlassian/jira-feature-gates-test-mocks';
29
+ `,
30
+ },
31
+ {
32
+ name: '`@atlassian/jira-feature-gates-storybook-mocks` imports are not aliased',
33
+ code: outdent`
34
+ import { withGate } from '@atlassian/jira-feature-gates-storybook-mocks';
35
+ `,
36
+ },
37
+ {
38
+ name: 'Aliases for non related imports are allowed',
39
+ code: outdent`
40
+ import { memo as m } from 'react';
41
+ import * as r from 'redux';
42
+ `,
43
+ },
44
+ ],
45
+ invalid: [
46
+ {
47
+ name: 'Do not alias utils',
48
+ code: outdent`
49
+ import { ff as getBoolean } from '@atlassian/jira-feature-flagging';
50
+ `,
51
+ errors: [{ messageId: 'noSpecifierAlias' }],
52
+ },
53
+ {
54
+ name: 'Do not alias multiple utils',
55
+ code: outdent`
56
+ import { ff as getBoolean, ffVal as getFeatureFlagValue } from '@atlassian/jira-feature-flagging';
57
+ `,
58
+ errors: [{ messageId: 'noSpecifierAlias' }, { messageId: 'noSpecifierAlias' }],
59
+ },
60
+ {
61
+ name: 'Do not allow namespace imports',
62
+ code: outdent`
63
+ import * as ffUtils from '@atlassian/jira-feature-flagging';
64
+ `,
65
+ errors: [{ messageId: 'noNamespaceSpecifier' }],
66
+ },
67
+ {
68
+ name: 'Do not reassign utils',
69
+ code: outdent`
70
+ import { fg } from '@atlassian/jira-feature-gating';
71
+ const aliasedFG = fg;
72
+ `,
73
+ errors: [{ messageId: 'noReassignment' }],
74
+ },
75
+ ],
76
+ });
@@ -0,0 +1,75 @@
1
+ import type { Rule } from 'eslint';
2
+ import {
3
+ FEATURE_API_IMPORT_SOURCES,
4
+ FEATURE_MOCKS_IMPORT_SOURCES,
5
+ FEATURE_UTILS_IMPORT_SOURCES,
6
+ } from '../constants';
7
+ import { isIdentifierImportedFrom, type Node } from '../utils';
8
+
9
+ const IMPORT_SOURCES = new Set([
10
+ ...FEATURE_API_IMPORT_SOURCES,
11
+ ...FEATURE_MOCKS_IMPORT_SOURCES,
12
+ ...FEATURE_UTILS_IMPORT_SOURCES,
13
+ ]);
14
+
15
+ const rule: Rule.RuleModule = {
16
+ meta: {
17
+ docs: {
18
+ url: 'https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/browse/platform/packages/platform/eslint-plugin/src/rules/ff/no-alias/README.md',
19
+ description:
20
+ 'Disallow aliasing of feature flag utils to ensure feature flag usage is statically analyzable',
21
+ },
22
+ messages: {
23
+ noSpecifierAlias:
24
+ 'Do not alias feature flag utils. Feature flag usage should be statically analyzable',
25
+ noNamespaceSpecifier:
26
+ 'Destructure feature flag utils from import. Feature flag usage should be statically analyzable',
27
+ noReassignment:
28
+ 'Do not reassign feature flag utils. Feature flag usage should be statically analyzable',
29
+ },
30
+ },
31
+ create(context) {
32
+ return {
33
+ ImportDeclaration: (node) => {
34
+ if (typeof node.source.value === 'string' && !IMPORT_SOURCES.has(node.source.value)) {
35
+ return;
36
+ }
37
+
38
+ node.specifiers?.forEach((specifier) => {
39
+ if (specifier.type === 'ImportSpecifier') {
40
+ const { imported, local } = specifier;
41
+
42
+ if (imported.name !== local.name) {
43
+ context.report({
44
+ messageId: 'noSpecifierAlias',
45
+ node: specifier,
46
+ });
47
+ }
48
+ } else if (specifier.type === 'ImportNamespaceSpecifier') {
49
+ context.report({
50
+ messageId: 'noNamespaceSpecifier',
51
+ node: specifier,
52
+ });
53
+ }
54
+ });
55
+ },
56
+ 'VariableDeclaration[kind="const"] > VariableDeclarator[id.type="Identifier"][init.type="Identifier"]':
57
+ (node: Node<'VariableDeclarator'>) => {
58
+ if (!node.init || node.init.type !== 'Identifier') {
59
+ return;
60
+ }
61
+
62
+ const isReassignment = isIdentifierImportedFrom(node.init.name, IMPORT_SOURCES, context);
63
+
64
+ if (isReassignment) {
65
+ context.report({
66
+ messageId: 'noReassignment',
67
+ node,
68
+ });
69
+ }
70
+ },
71
+ };
72
+ },
73
+ };
74
+
75
+ export default rule;
@@ -2,10 +2,10 @@ import { tester } from '../../../../__tests__/utils/_tester';
2
2
  import rule from '../../index';
3
3
 
4
4
  describe('test no-duplicate-dependencies rule', () => {
5
- tester.run('no-duplicate-dependencies-rule', rule, {
6
- valid: [
7
- {
8
- code: `
5
+ tester.run('no-duplicate-dependencies-rule', rule, {
6
+ valid: [
7
+ {
8
+ code: `
9
9
  module.exports = {
10
10
  "dependencies": {
11
11
  "foo": "^1.0.0",
@@ -13,10 +13,10 @@ describe('test no-duplicate-dependencies rule', () => {
13
13
  }
14
14
  };
15
15
  `,
16
- filename: 'dependencies.json',
17
- },
18
- {
19
- code: `
16
+ filename: 'dependencies.json',
17
+ },
18
+ {
19
+ code: `
20
20
  module.exports = {
21
21
  "devDependencies": {
22
22
  "foo": "^1.0.0",
@@ -24,10 +24,10 @@ describe('test no-duplicate-dependencies rule', () => {
24
24
  }
25
25
  };
26
26
  `,
27
- filename: 'devDependencies.json',
28
- },
29
- {
30
- code: `
27
+ filename: 'devDependencies.json',
28
+ },
29
+ {
30
+ code: `
31
31
  module.exports = {
32
32
  "dependencies": {
33
33
  "foo": "^1.0.0",
@@ -39,12 +39,12 @@ describe('test no-duplicate-dependencies rule', () => {
39
39
  }
40
40
  };
41
41
  `,
42
- filename: 'devAndDependencies.json',
43
- },
44
- ],
45
- invalid: [
46
- {
47
- code: `
42
+ filename: 'devAndDependencies.json',
43
+ },
44
+ ],
45
+ invalid: [
46
+ {
47
+ code: `
48
48
  module.exports = {
49
49
  "dependencies": {
50
50
  "foo": "^1.0.0",
@@ -57,7 +57,7 @@ describe('test no-duplicate-dependencies rule', () => {
57
57
  }
58
58
  };
59
59
  `,
60
- output: `
60
+ output: `
61
61
  module.exports = {
62
62
  "dependencies": {
63
63
  "foo": "^1.0.0",
@@ -69,18 +69,18 @@ describe('test no-duplicate-dependencies rule', () => {
69
69
  }
70
70
  };
71
71
  `,
72
- errors: [
73
- {
74
- data: {
75
- name: 'foo',
76
- },
77
- messageId: 'unexpectedDuplicateDependency',
78
- },
79
- ],
80
- filename: 'duplicateDependenciesFirst.json',
81
- },
82
- {
83
- code: `
72
+ errors: [
73
+ {
74
+ data: {
75
+ name: 'foo',
76
+ },
77
+ messageId: 'unexpectedDuplicateDependency',
78
+ },
79
+ ],
80
+ filename: 'duplicateDependenciesFirst.json',
81
+ },
82
+ {
83
+ code: `
84
84
  module.exports = {
85
85
  "dependencies": {
86
86
  "bar": "^1.0.0"
@@ -91,7 +91,7 @@ describe('test no-duplicate-dependencies rule', () => {
91
91
  }
92
92
  };
93
93
  `,
94
- output: `
94
+ output: `
95
95
  module.exports = {
96
96
  "dependencies": {
97
97
  "bar": "^1.0.0"
@@ -101,16 +101,16 @@ describe('test no-duplicate-dependencies rule', () => {
101
101
  }
102
102
  };
103
103
  `,
104
- errors: [
105
- {
106
- data: {
107
- name: 'bar',
108
- },
109
- messageId: 'unexpectedDuplicateDependency',
110
- },
111
- ],
112
- filename: 'duplicateDependenciesLast.json',
113
- },
114
- ],
115
- });
104
+ errors: [
105
+ {
106
+ data: {
107
+ name: 'bar',
108
+ },
109
+ messageId: 'unexpectedDuplicateDependency',
110
+ },
111
+ ],
112
+ filename: 'duplicateDependenciesLast.json',
113
+ },
114
+ ],
115
+ });
116
116
  });
@@ -2,83 +2,78 @@
2
2
  import type { Rule } from 'eslint';
3
3
 
4
4
  const rule: Rule.RuleModule = {
5
- meta: {
6
- type: 'problem',
7
- docs: {
8
- description:
9
- 'This rule disallows a dependency to be defined in both dependencies and devDependencies',
10
- recommended: false,
11
- },
12
- fixable: 'code',
13
- messages: {
14
- unexpectedDuplicateDependency: 'Unexpected duplicate dependency {{name}}',
15
- },
16
- },
17
- create(context) {
18
- const dependencies = new Map();
19
- const devDependencies = new Map();
5
+ meta: {
6
+ type: 'problem',
7
+ docs: {
8
+ description:
9
+ 'This rule disallows a dependency to be defined in both dependencies and devDependencies',
10
+ recommended: false,
11
+ },
12
+ fixable: 'code',
13
+ messages: {
14
+ unexpectedDuplicateDependency: 'Unexpected duplicate dependency {{name}}',
15
+ },
16
+ },
17
+ create(context) {
18
+ const dependencies = new Map();
19
+ const devDependencies = new Map();
20
20
 
21
- return {
22
- 'ObjectExpression Property[key.value=dependencies] Property': (
23
- node: Rule.Node,
24
- ) => {
25
- // @ts-expect-error
26
- dependencies.set(node.key.value, node.key);
27
- },
28
- 'ObjectExpression Property[key.value=devDependencies] Property': (
29
- node: Rule.Node,
30
- ) => {
31
- // @ts-expect-error
32
- devDependencies.set(node.key.value, node.key);
33
- },
34
- 'Program:exit': () => {
35
- for (const [dependency, node] of devDependencies) {
36
- if (dependencies.has(dependency)) {
37
- context.report({
38
- data: {
39
- name: dependency,
40
- },
41
- fix(fixer) {
42
- const sourceCode = context.getSourceCode();
43
- const property = node.parent;
44
- const isLastLine =
45
- sourceCode.getTokenAfter(property)?.value === '}';
46
- const end = property.loc.end;
21
+ return {
22
+ 'ObjectExpression Property[key.value=dependencies] Property': (node: Rule.Node) => {
23
+ // @ts-expect-error
24
+ dependencies.set(node.key.value, node.key);
25
+ },
26
+ 'ObjectExpression Property[key.value=devDependencies] Property': (node: Rule.Node) => {
27
+ // @ts-expect-error
28
+ devDependencies.set(node.key.value, node.key);
29
+ },
30
+ 'Program:exit': () => {
31
+ for (const [dependency, node] of devDependencies) {
32
+ if (dependencies.has(dependency)) {
33
+ context.report({
34
+ data: {
35
+ name: dependency,
36
+ },
37
+ fix(fixer) {
38
+ const sourceCode = context.getSourceCode();
39
+ const property = node.parent;
40
+ const isLastLine = sourceCode.getTokenAfter(property)?.value === '}';
41
+ const end = property.loc.end;
47
42
 
48
- if (!isLastLine) {
49
- return fixer.removeRange([
50
- sourceCode.getIndexFromLoc({
51
- line: property.loc.start.line,
52
- column: 0,
53
- }),
54
- sourceCode.getIndexFromLoc({
55
- line: end.line + 1,
56
- column: 0,
57
- }),
58
- ]);
59
- }
43
+ if (!isLastLine) {
44
+ return fixer.removeRange([
45
+ sourceCode.getIndexFromLoc({
46
+ line: property.loc.start.line,
47
+ column: 0,
48
+ }),
49
+ sourceCode.getIndexFromLoc({
50
+ line: end.line + 1,
51
+ column: 0,
52
+ }),
53
+ ]);
54
+ }
60
55
 
61
- const previousToken = sourceCode.getTokenBefore(property)!;
56
+ const previousToken = sourceCode.getTokenBefore(property)!;
62
57
 
63
- return fixer.removeRange([
64
- sourceCode.getIndexFromLoc({
65
- line: previousToken.loc.end.line,
66
- column: previousToken.loc.end.column - 1,
67
- }),
68
- sourceCode.getIndexFromLoc({
69
- line: end.line,
70
- column: end.column,
71
- }),
72
- ]);
73
- },
74
- messageId: 'unexpectedDuplicateDependency',
75
- node,
76
- });
77
- }
78
- }
79
- },
80
- };
81
- },
58
+ return fixer.removeRange([
59
+ sourceCode.getIndexFromLoc({
60
+ line: previousToken.loc.end.line,
61
+ column: previousToken.loc.end.column - 1,
62
+ }),
63
+ sourceCode.getIndexFromLoc({
64
+ line: end.line,
65
+ column: end.column,
66
+ }),
67
+ ]);
68
+ },
69
+ messageId: 'unexpectedDuplicateDependency',
70
+ node,
71
+ });
72
+ }
73
+ }
74
+ },
75
+ };
76
+ },
82
77
  };
83
78
 
84
79
  export default rule;
@@ -2,68 +2,68 @@ import { tester } from '../../../../__tests__/utils/_tester';
2
2
  import rule from '../../index';
3
3
 
4
4
  describe('enforce-feature-flag-usage-structure tests', () => {
5
- tester.run('ensure-feature-flag-registration', rule, {
6
- valid: [
7
- {
8
- // IfStatement
9
- code: `if(getBooleanFF('test-flag')) { }`,
10
- },
11
- {
12
- // negated IfStatement
13
- code: `if(!getBooleanFF('test-flag')) { }`,
14
- },
15
- {
16
- // ConditionalExpression
17
- code: `const val = getBooleanFF('test-flag') ? 'yay' : 'no';`,
18
- },
19
- {
20
- // LogicalExpression
21
- code: `const val = 100 + (getBooleanFF('test-flag') && 50 || 10);`,
22
- },
23
- ],
24
- invalid: [
25
- {
26
- code: `getBooleanFF('test-flag')`,
27
- errors: [{ messageId: 'onlyInlineIf' }],
28
- },
29
- {
30
- code: `const val = getBooleanFF('test-flag')`,
31
- errors: [{ messageId: 'onlyInlineIf' }],
32
- },
33
- {
34
- code: `const ff = "test-flag"; if(getBooleanFF(ff)) { }`,
35
- errors: [{ messageId: 'onlyStringLiteral' }],
36
- },
37
- {
38
- code: `if(getBooleanFF('test-flag') && getBooleanFF('test-flag')) { }`,
39
- errors: [
40
- { messageId: 'multipleFlagCheckInExpression' },
41
- { messageId: 'multipleFlagCheckInExpression' },
42
- ],
43
- },
44
- {
45
- code: `if(!getBooleanFF('test-flag') && !getBooleanFF('test-flag')) { }`,
46
- errors: [
47
- { messageId: 'multipleFlagCheckInExpression' },
48
- { messageId: 'multipleFlagCheckInExpression' },
49
- ],
50
- },
51
- {
52
- code: `if((!getBooleanFF('test-flag') || 1 == true) && getBooleanFF('test-flag')) { }`,
53
- errors: [
54
- { messageId: 'multipleFlagCheckInExpression' },
55
- { messageId: 'multipleFlagCheckInExpression' },
56
- ],
57
- },
58
- {
59
- code: `export default getBooleanFF('test-flag') ? "this is" : "not good";`,
60
- errors: [{ messageId: 'noModuleScope' }],
61
- },
62
- {
63
- only: true,
64
- code: `export const foo = getBooleanFF('test-flag') ? "this is" : "not good";`,
65
- errors: [{ messageId: 'noModuleScope' }],
66
- },
67
- ],
68
- });
5
+ tester.run('ensure-feature-flag-registration', rule, {
6
+ valid: [
7
+ {
8
+ // IfStatement
9
+ code: `if(getBooleanFF('test-flag')) { }`,
10
+ },
11
+ {
12
+ // negated IfStatement
13
+ code: `if(!getBooleanFF('test-flag')) { }`,
14
+ },
15
+ {
16
+ // ConditionalExpression
17
+ code: `const val = getBooleanFF('test-flag') ? 'yay' : 'no';`,
18
+ },
19
+ {
20
+ // LogicalExpression
21
+ code: `const val = 100 + (getBooleanFF('test-flag') && 50 || 10);`,
22
+ },
23
+ ],
24
+ invalid: [
25
+ {
26
+ code: `getBooleanFF('test-flag')`,
27
+ errors: [{ messageId: 'onlyInlineIf' }],
28
+ },
29
+ {
30
+ code: `const val = getBooleanFF('test-flag')`,
31
+ errors: [{ messageId: 'onlyInlineIf' }],
32
+ },
33
+ {
34
+ code: `const ff = "test-flag"; if(getBooleanFF(ff)) { }`,
35
+ errors: [{ messageId: 'onlyStringLiteral' }],
36
+ },
37
+ {
38
+ code: `if(getBooleanFF('test-flag') && getBooleanFF('test-flag')) { }`,
39
+ errors: [
40
+ { messageId: 'multipleFlagCheckInExpression' },
41
+ { messageId: 'multipleFlagCheckInExpression' },
42
+ ],
43
+ },
44
+ {
45
+ code: `if(!getBooleanFF('test-flag') && !getBooleanFF('test-flag')) { }`,
46
+ errors: [
47
+ { messageId: 'multipleFlagCheckInExpression' },
48
+ { messageId: 'multipleFlagCheckInExpression' },
49
+ ],
50
+ },
51
+ {
52
+ code: `if((!getBooleanFF('test-flag') || 1 == true) && getBooleanFF('test-flag')) { }`,
53
+ errors: [
54
+ { messageId: 'multipleFlagCheckInExpression' },
55
+ { messageId: 'multipleFlagCheckInExpression' },
56
+ ],
57
+ },
58
+ {
59
+ code: `export default getBooleanFF('test-flag') ? "this is" : "not good";`,
60
+ errors: [{ messageId: 'noModuleScope' }],
61
+ },
62
+ {
63
+ only: true,
64
+ code: `export const foo = getBooleanFF('test-flag') ? "this is" : "not good";`,
65
+ errors: [{ messageId: 'noModuleScope' }],
66
+ },
67
+ ],
68
+ });
69
69
  });