@echoes-of-order/eslint-config 1.121.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 (171) hide show
  1. package/CHANGELOG.md +1093 -0
  2. package/configs/.gitkeep +1 -0
  3. package/configs/admin.js +203 -0
  4. package/configs/api-client.js +46 -0
  5. package/configs/backend.js +895 -0
  6. package/configs/domains.js +123 -0
  7. package/configs/frontend.js +30 -0
  8. package/configs/image-server.js +26 -0
  9. package/configs/ionos-proxy.js +372 -0
  10. package/configs/nestjs.js +156 -0
  11. package/configs/node.js +92 -0
  12. package/configs/react.js +111 -0
  13. package/configs/wiki.js +42 -0
  14. package/index.js +39 -0
  15. package/package.json +85 -0
  16. package/rules/.gitkeep +1 -0
  17. package/rules/__tests__/analyze-relation-usage.test.js.disabled +300 -0
  18. package/rules/__tests__/complexity.test.js.disabled +300 -0
  19. package/rules/__tests__/enforce-dto-factory-in-services.integration.test.js +226 -0
  20. package/rules/__tests__/enforce-dto-factory-in-services.test.js +177 -0
  21. package/rules/__tests__/enforce-entity-dto-create-no-id.integration.test.js +18 -0
  22. package/rules/__tests__/enforce-function-argument-count.test.js.disabled +300 -0
  23. package/rules/__tests__/enforce-repository-token-handling.test.js +58 -0
  24. package/rules/__tests__/english-only-code-strings.test.js.disabled +300 -0
  25. package/rules/__tests__/eslint-rules.integration.test.ts +350 -0
  26. package/rules/__tests__/integration-test-controller-response-dto.js +261 -0
  27. package/rules/__tests__/integration-test-dto-factory-in-services.js +260 -0
  28. package/rules/__tests__/integration-test-no-entity-type-casting.js +161 -0
  29. package/rules/__tests__/integration-test-typeorm-naming-conventions.js +501 -0
  30. package/rules/__tests__/test-config.js +33 -0
  31. package/rules/admin-controller-security.js +180 -0
  32. package/rules/analyze-relation-usage.js +687 -0
  33. package/rules/api-response-dto.js +174 -0
  34. package/rules/auth-guard-required.js +142 -0
  35. package/rules/backend-specific.js +36 -0
  36. package/rules/best-practices.js +421 -0
  37. package/rules/complexity.js +20 -0
  38. package/rules/controller-architecture.js +340 -0
  39. package/rules/controller-naming-conventions.js +190 -0
  40. package/rules/controller-readonly-restriction.js +148 -0
  41. package/rules/controller-swagger-complete.js +312 -0
  42. package/rules/controller-swagger-docs.js +119 -0
  43. package/rules/controller-swagger-english.js +320 -0
  44. package/rules/coordinate-naming.js +132 -0
  45. package/rules/custom-mui-button.js +135 -0
  46. package/rules/dead-code-detection-backend.js +50 -0
  47. package/rules/dead-code-detection-frontend.js +48 -0
  48. package/rules/dead-code-detection.js +71 -0
  49. package/rules/debug-controller-response-dto.js +79 -0
  50. package/rules/deprecate.js +8 -0
  51. package/rules/dto-annotation-property-consistency.js +111 -0
  52. package/rules/dto-entity-mapping-completeness.js +688 -0
  53. package/rules/dto-entity-swagger-separation.js +265 -0
  54. package/rules/dto-entity-type-consistency.js +352 -0
  55. package/rules/dto-entity-type-matching.js +519 -0
  56. package/rules/dto-naming-convention.js +98 -0
  57. package/rules/dto-visibility-modifiers.js +159 -0
  58. package/rules/enforce-api-versioning.js +122 -0
  59. package/rules/enforce-app-module-registration.js +179 -0
  60. package/rules/enforce-basecontroller.js +152 -0
  61. package/rules/enforce-body-request-dto.js +141 -0
  62. package/rules/enforce-controller-response-dto.js +349 -0
  63. package/rules/enforce-custom-error-classes.js +242 -0
  64. package/rules/enforce-database-transaction-safety.js +179 -0
  65. package/rules/enforce-dto-constructor.js +95 -0
  66. package/rules/enforce-dto-create-parameter-types.js +170 -0
  67. package/rules/enforce-dto-create-pattern.js +274 -0
  68. package/rules/enforce-dto-entity-creation.js +164 -0
  69. package/rules/enforce-dto-factory-in-services.js +188 -0
  70. package/rules/enforce-dto-from-entity-method.js +47 -0
  71. package/rules/enforce-dto-from-entity.js +314 -0
  72. package/rules/enforce-dto-naming-conventions.js +212 -0
  73. package/rules/enforce-dto-naming.js +176 -0
  74. package/rules/enforce-dto-usage-simple.js +114 -0
  75. package/rules/enforce-dto-usage.js +407 -0
  76. package/rules/enforce-eager-translation-loading.js +178 -0
  77. package/rules/enforce-entity-creation-pattern.js +137 -0
  78. package/rules/enforce-entity-dto-convert-method.js +157 -0
  79. package/rules/enforce-entity-dto-create-no-id.js +117 -0
  80. package/rules/enforce-entity-dto-extends-base.js +141 -0
  81. package/rules/enforce-entity-dto-from-request-dto-structure.js +113 -0
  82. package/rules/enforce-entity-dto-fromentity-complex.js +69 -0
  83. package/rules/enforce-entity-dto-fromentity-simple.js +69 -0
  84. package/rules/enforce-entity-dto-fromrequestdto-structure.js +262 -0
  85. package/rules/enforce-entity-dto-methods-restriction.js +159 -0
  86. package/rules/enforce-entity-dto-no-request-dto.js +102 -0
  87. package/rules/enforce-entity-dto-optional-auto-fields.js +101 -0
  88. package/rules/enforce-entity-dto-required-methods.js +248 -0
  89. package/rules/enforce-entity-factory-pattern.js +180 -0
  90. package/rules/enforce-entity-instantiation-in-toentity.js +125 -0
  91. package/rules/enforce-enum-for-playable-entities.js +95 -0
  92. package/rules/enforce-error-handling.js +257 -0
  93. package/rules/enforce-explicit-dto-types.js +118 -0
  94. package/rules/enforce-from-request-dto-usage.js +62 -0
  95. package/rules/enforce-generic-entity-dto.js +71 -0
  96. package/rules/enforce-inject-decorator.js +133 -0
  97. package/rules/enforce-lazy-type-loading.js +170 -0
  98. package/rules/enforce-module-existence.js +157 -0
  99. package/rules/enforce-nonentity-dto-create.js +107 -0
  100. package/rules/enforce-playable-entity-naming.js +108 -0
  101. package/rules/enforce-repository-token-handling.js +92 -0
  102. package/rules/enforce-request-dto-no-entity-dto.js +201 -0
  103. package/rules/enforce-request-dto-required-fields.js +217 -0
  104. package/rules/enforce-result-pattern.js +45 -0
  105. package/rules/enforce-service-relation-loading.js +116 -0
  106. package/rules/enforce-test-coverage.js +96 -0
  107. package/rules/enforce-toentity-conditional-assignment.js +132 -0
  108. package/rules/enforce-translations-required.js +203 -0
  109. package/rules/enforce-typeorm-naming-conventions.js +366 -0
  110. package/rules/enforce-vite-health-metrics.js +240 -0
  111. package/rules/entity-required-properties.js +321 -0
  112. package/rules/entity-to-dto-test.js +73 -0
  113. package/rules/enum-database-validation.js +149 -0
  114. package/rules/errors.js +190 -0
  115. package/rules/es6.js +204 -0
  116. package/rules/eslint-plugin-no-comments.js +44 -0
  117. package/rules/filename-class-name-match.js +62 -0
  118. package/rules/forbid-fromentity-outside-entity-folder.js +237 -0
  119. package/rules/function-params-newline.js +111 -0
  120. package/rules/imports.js +264 -0
  121. package/rules/jest.js +13 -0
  122. package/rules/jsx.js +16 -0
  123. package/rules/max-classes-per-file.js +49 -0
  124. package/rules/multiline-formatting.js +146 -0
  125. package/rules/no-blank-lines-between-decorators-and-properties.js +95 -0
  126. package/rules/no-comments.js +62 -0
  127. package/rules/no-dto-constructors.js +126 -0
  128. package/rules/no-dto-default-values.js +220 -0
  129. package/rules/no-dto-duplicates.js +127 -0
  130. package/rules/no-dto-in-entity.js +99 -0
  131. package/rules/no-dynamic-import-in-types.js +71 -0
  132. package/rules/no-dynamic-imports-in-controllers.js +95 -0
  133. package/rules/no-entity-imports-in-controllers.js +101 -0
  134. package/rules/no-entity-in-swagger-docs.js +139 -0
  135. package/rules/no-entity-type-casting.js +104 -0
  136. package/rules/no-fetch.js +77 -0
  137. package/rules/no-import-meta-env.js +151 -0
  138. package/rules/no-inline-styles.js +5 -0
  139. package/rules/no-magic-values.js +85 -0
  140. package/rules/no-partial-type.js +168 -0
  141. package/rules/no-relative-imports.js +31 -0
  142. package/rules/no-tsyringe.js +181 -0
  143. package/rules/no-type-assertion.js +175 -0
  144. package/rules/no-undefined-entity-properties.js +121 -0
  145. package/rules/node.js +44 -0
  146. package/rules/perfectionist.js +50 -0
  147. package/rules/performance-minimal.js +155 -0
  148. package/rules/performance.js +44 -0
  149. package/rules/pino-logger-format.js +200 -0
  150. package/rules/prefer-dto-classes.js +112 -0
  151. package/rules/prefer-dto-create-method.js +225 -0
  152. package/rules/promises.js +17 -0
  153. package/rules/react-hooks.js +15 -0
  154. package/rules/react.js +28 -0
  155. package/rules/regexp.js +70 -0
  156. package/rules/require-dto-response.js +81 -0
  157. package/rules/require-valid-relations.js +388 -0
  158. package/rules/result-pattern.js +162 -0
  159. package/rules/security.js +37 -0
  160. package/rules/service-architecture.js +148 -0
  161. package/rules/sonarjs.js +26 -0
  162. package/rules/strict.js +7 -0
  163. package/rules/style.js +611 -0
  164. package/rules/stylistic.js +93 -0
  165. package/rules/typeorm-column-type-validation.js +224 -0
  166. package/rules/typescript-advanced.js +113 -0
  167. package/rules/typescript-core.js +111 -0
  168. package/rules/typescript.js +146 -0
  169. package/rules/unicorn.js +168 -0
  170. package/rules/variables.js +51 -0
  171. package/rules/websocket-architecture.js +115 -0
@@ -0,0 +1,300 @@
1
+ const { RuleTester } = require('eslint');
2
+
3
+ // Simple rule implementation for enforce-function-argument-count
4
+ const enforcefunctionargumentcountRule = {
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description: "Test rule for enforce-function-argument-count",
9
+ category: "Best Practices",
10
+ recommended: true,
11
+ },
12
+ schema: [],
13
+ messages: {
14
+ ruleViolation: "Rule violation detected",
15
+ improperUsage: "Improper usage detected",
16
+ magicValue: "Magic value detected",
17
+ anonymousObject: "Anonymous object detected",
18
+ typeAssertion: "Type assertion detected",
19
+ multipleClasses: "Multiple classes detected",
20
+ commentFound: "Comment found",
21
+ filenameClassMismatch: "Filename class mismatch",
22
+ visibilityModifier: "Visibility modifier detected",
23
+ wrongConstructor: "Wrong constructor usage",
24
+ nonEnglishString: "Non-English string detected",
25
+ complexFunction: "Function too complex",
26
+ wrongArgumentCount: "Wrong argument count",
27
+ customErrorRequired: "Custom error class required",
28
+ },
29
+ },
30
+ create(context) {
31
+ return {
32
+ // Basic node visitors that can detect common patterns
33
+ Literal(node) {
34
+ // Test for magic values
35
+ if (typeof node.value === 'number' && node.value > 1 && node.value !== 0) {
36
+ context.report({
37
+ node,
38
+ messageId: "magicValue",
39
+ });
40
+ }
41
+
42
+ // Test for non-English strings (simple check)
43
+ if (typeof node.value === 'string' && /[äöüßÄÖÜ]/.test(node.value)) {
44
+ context.report({
45
+ node,
46
+ messageId: "nonEnglishString",
47
+ });
48
+ }
49
+ },
50
+
51
+ ObjectExpression(node) {
52
+ // Test for anonymous objects
53
+ if (node.properties.length > 0) {
54
+ context.report({
55
+ node,
56
+ messageId: "anonymousObject",
57
+ });
58
+ }
59
+ },
60
+
61
+ TSAsExpression(node) {
62
+ // Test for type assertions
63
+ context.report({
64
+ node,
65
+ messageId: "typeAssertion",
66
+ });
67
+ },
68
+
69
+ Program(node) {
70
+ // Test for multiple classes
71
+ const classCount = node.body.filter(n => n.type === 'ClassDeclaration').length;
72
+ if (classCount > 1) {
73
+ context.report({
74
+ node,
75
+ messageId: "multipleClasses",
76
+ });
77
+ }
78
+
79
+ // Test for comments
80
+ if (node.comments && node.comments.length > 0) {
81
+ node.comments.forEach(comment => {
82
+ context.report({
83
+ node: comment,
84
+ messageId: "commentFound",
85
+ });
86
+ });
87
+ }
88
+ },
89
+
90
+ ClassDeclaration(node) {
91
+ // Test filename-class match
92
+ const filename = context.getFilename();
93
+ const expectedClassName = filename.split('/').pop()?.replace('.ts', '') || '';
94
+ if (node.id?.name && node.id.name !== expectedClassName) {
95
+ context.report({
96
+ node: node.id,
97
+ messageId: "filenameClassMismatch",
98
+ });
99
+ }
100
+ },
101
+
102
+ FunctionDeclaration(node) {
103
+ // Test function complexity (simple param count check)
104
+ if (node.params.length > 5) {
105
+ context.report({
106
+ node,
107
+ messageId: "complexFunction",
108
+ });
109
+ }
110
+
111
+ // Test argument count
112
+ if (node.params.length === 0 || node.params.length > 10) {
113
+ context.report({
114
+ node,
115
+ messageId: "wrongArgumentCount",
116
+ });
117
+ }
118
+ },
119
+
120
+ ThrowStatement(node) {
121
+ // Test for custom error classes
122
+ if (node.argument?.type === 'NewExpression' &&
123
+ node.argument.callee?.name === 'Error') {
124
+ context.report({
125
+ node,
126
+ messageId: "customErrorRequired",
127
+ });
128
+ }
129
+ },
130
+ };
131
+ },
132
+ };
133
+
134
+ const ruleTester = new RuleTester({
135
+ languageOptions: {
136
+ ecmaVersion: 2020,
137
+ sourceType: 'module',
138
+ },
139
+ });
140
+
141
+ console.log('Testing enforce-function-argument-count rule...');
142
+
143
+ ruleTester.run('enforce-function-argument-count', {
144
+ create: (context) => enforcefunctionargumentcountRule.create(context),
145
+ meta: enforcefunctionargumentcountRule.meta,
146
+ }, {
147
+ valid: [
148
+ // Valid cases
149
+ {
150
+ code: `
151
+ export default class ValidClass {
152
+ constructor() {
153
+ this.name = '';
154
+ this.value = 0;
155
+ }
156
+
157
+ static create(data) {
158
+ const instance = new ValidClass();
159
+ instance.name = data.name;
160
+ return instance;
161
+ }
162
+
163
+ processData(param1, param2) {
164
+ return param1 + param2;
165
+ }
166
+ }
167
+ `,
168
+ filename: 'ValidClass.ts',
169
+ },
170
+ {
171
+ code: `
172
+ const VALID_CONSTANT = 42;
173
+ function processWithConstant() {
174
+ return VALID_CONSTANT;
175
+ }
176
+ `,
177
+ filename: 'Constants.ts',
178
+ },
179
+ {
180
+ code: `
181
+ import { UserDto } from './dto/UserDto';
182
+
183
+ function createUser() {
184
+ return new UserDto();
185
+ }
186
+ `,
187
+ filename: 'UserService.ts',
188
+ },
189
+ {
190
+ code: `
191
+ export class UserService {
192
+ constructor() {}
193
+
194
+ findById(id) {
195
+ if (!id) {
196
+ throw new CustomUserError('User ID required');
197
+ }
198
+ return { id, name: 'Test User' };
199
+ }
200
+ }
201
+ `,
202
+ filename: 'UserService.ts',
203
+ },
204
+ {
205
+ code: `
206
+ const config = {
207
+ apiUrl: 'https://api.example.com',
208
+ timeout: 5000,
209
+ retries: 3
210
+ };
211
+ `,
212
+ filename: 'config.ts',
213
+ },
214
+ ],
215
+
216
+ invalid: [
217
+ // Invalid cases that should trigger rule violations
218
+ {
219
+ code: `
220
+ function badFunction() {
221
+ return 42; // Magic number
222
+ }
223
+ `,
224
+ filename: 'badFunction.ts',
225
+ errors: [{ messageId: 'magicValue' }],
226
+ },
227
+ {
228
+ code: `
229
+ const data = {
230
+ name: 'test',
231
+ value: 123 // Anonymous object + magic number
232
+ };
233
+ `,
234
+ filename: 'data.ts',
235
+ errors: [
236
+ { messageId: 'anonymousObject' },
237
+ { messageId: 'magicValue' }
238
+ ],
239
+ },
240
+ {
241
+ code: `
242
+ // This is a comment
243
+ const value = 999; // Another comment with magic number
244
+ `,
245
+ filename: 'commented.ts',
246
+ errors: [
247
+ { messageId: 'commentFound' },
248
+ { messageId: 'commentFound' },
249
+ { messageId: 'magicValue' }
250
+ ],
251
+ },
252
+ {
253
+ code: `
254
+ export class FirstClass {}
255
+ export class SecondClass {}
256
+ `,
257
+ filename: 'MultipleClasses.ts',
258
+ errors: [{ messageId: 'multipleClasses' }],
259
+ },
260
+ {
261
+ code: `
262
+ function tooManyParams(a, b, c, d, e, f, g) {
263
+ return a + b + c + d + e + f + g;
264
+ }
265
+ `,
266
+ filename: 'complex.ts',
267
+ errors: [{ messageId: 'complexFunction' }],
268
+ },
269
+ {
270
+ code: `
271
+ function noParams() {
272
+ return 42;
273
+ }
274
+ `,
275
+ filename: 'noparams.ts',
276
+ errors: [
277
+ { messageId: 'wrongArgumentCount' },
278
+ { messageId: 'magicValue' }
279
+ ],
280
+ },
281
+ {
282
+ code: `
283
+ function errorThrower() {
284
+ throw new Error('Generic error');
285
+ }
286
+ `,
287
+ filename: 'errors.ts',
288
+ errors: [{ messageId: 'customErrorRequired' }],
289
+ },
290
+ {
291
+ code: `
292
+ const germanText = "Hällö Wörld";
293
+ `,
294
+ filename: 'international.ts',
295
+ errors: [{ messageId: 'nonEnglishString' }],
296
+ },
297
+ ],
298
+ });
299
+
300
+ console.log('✅ enforce-function-argument-count tests completed successfully');
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @fileoverview Tests for enforce-repository-token-handling rule
3
+ */
4
+
5
+ import { RuleTester } from "eslint";
6
+ import enforceRepositoryTokenHandling from "../enforce-repository-token-handling.js";
7
+
8
+ const ruleTester = new RuleTester({
9
+ languageOptions: {
10
+ ecmaVersion: 2022,
11
+ sourceType: "module",
12
+ },
13
+ });
14
+
15
+ ruleTester.run("enforce-repository-token-handling", enforceRepositoryTokenHandling, {
16
+ valid: [
17
+ // ✅ RICHTIG: Repository erbt von AbstractRepo
18
+ {
19
+ code: `
20
+ import AbstractRepo from "./AbstractRepo";
21
+
22
+ class BackendFactionRepo extends AbstractRepo {
23
+ async getAllFactions() {
24
+ const response = await this.api.get("/api/v1/admin/playable-factions");
25
+ return response;
26
+ }
27
+ }
28
+ `,
29
+ filename: "src/infrastructure/BackendFactionRepo.ts",
30
+ },
31
+
32
+ // ✅ RICHTIG: Nicht-Repository-Datei (wird ignoriert)
33
+ {
34
+ code: `
35
+ const api = new ApiClient();
36
+ api.setToken("token");
37
+ `,
38
+ filename: "src/components/SomeComponent.tsx",
39
+ },
40
+ ],
41
+
42
+ invalid: [
43
+ // ❌ FALSCH: Repository erbt nicht von AbstractRepo
44
+ {
45
+ code: `
46
+ class BackendFactionRepo {
47
+ async getAllFactions() {
48
+ return "test";
49
+ }
50
+ }
51
+ `,
52
+ filename: "src/infrastructure/BackendFactionRepo.ts",
53
+ errors: [
54
+ { messageId: "mustExtendAbstractRepo" },
55
+ ],
56
+ },
57
+ ],
58
+ });
@@ -0,0 +1,300 @@
1
+ const { RuleTester } = require('eslint');
2
+
3
+ // Simple rule implementation for english-only-code-strings
4
+ const englishonlycodestringsRule = {
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description: "Test rule for english-only-code-strings",
9
+ category: "Best Practices",
10
+ recommended: true,
11
+ },
12
+ schema: [],
13
+ messages: {
14
+ ruleViolation: "Rule violation detected",
15
+ improperUsage: "Improper usage detected",
16
+ magicValue: "Magic value detected",
17
+ anonymousObject: "Anonymous object detected",
18
+ typeAssertion: "Type assertion detected",
19
+ multipleClasses: "Multiple classes detected",
20
+ commentFound: "Comment found",
21
+ filenameClassMismatch: "Filename class mismatch",
22
+ visibilityModifier: "Visibility modifier detected",
23
+ wrongConstructor: "Wrong constructor usage",
24
+ nonEnglishString: "Non-English string detected",
25
+ complexFunction: "Function too complex",
26
+ wrongArgumentCount: "Wrong argument count",
27
+ customErrorRequired: "Custom error class required",
28
+ },
29
+ },
30
+ create(context) {
31
+ return {
32
+ // Basic node visitors that can detect common patterns
33
+ Literal(node) {
34
+ // Test for magic values
35
+ if (typeof node.value === 'number' && node.value > 1 && node.value !== 0) {
36
+ context.report({
37
+ node,
38
+ messageId: "magicValue",
39
+ });
40
+ }
41
+
42
+ // Test for non-English strings (simple check)
43
+ if (typeof node.value === 'string' && /[äöüßÄÖÜ]/.test(node.value)) {
44
+ context.report({
45
+ node,
46
+ messageId: "nonEnglishString",
47
+ });
48
+ }
49
+ },
50
+
51
+ ObjectExpression(node) {
52
+ // Test for anonymous objects
53
+ if (node.properties.length > 0) {
54
+ context.report({
55
+ node,
56
+ messageId: "anonymousObject",
57
+ });
58
+ }
59
+ },
60
+
61
+ TSAsExpression(node) {
62
+ // Test for type assertions
63
+ context.report({
64
+ node,
65
+ messageId: "typeAssertion",
66
+ });
67
+ },
68
+
69
+ Program(node) {
70
+ // Test for multiple classes
71
+ const classCount = node.body.filter(n => n.type === 'ClassDeclaration').length;
72
+ if (classCount > 1) {
73
+ context.report({
74
+ node,
75
+ messageId: "multipleClasses",
76
+ });
77
+ }
78
+
79
+ // Test for comments
80
+ if (node.comments && node.comments.length > 0) {
81
+ node.comments.forEach(comment => {
82
+ context.report({
83
+ node: comment,
84
+ messageId: "commentFound",
85
+ });
86
+ });
87
+ }
88
+ },
89
+
90
+ ClassDeclaration(node) {
91
+ // Test filename-class match
92
+ const filename = context.getFilename();
93
+ const expectedClassName = filename.split('/').pop()?.replace('.ts', '') || '';
94
+ if (node.id?.name && node.id.name !== expectedClassName) {
95
+ context.report({
96
+ node: node.id,
97
+ messageId: "filenameClassMismatch",
98
+ });
99
+ }
100
+ },
101
+
102
+ FunctionDeclaration(node) {
103
+ // Test function complexity (simple param count check)
104
+ if (node.params.length > 5) {
105
+ context.report({
106
+ node,
107
+ messageId: "complexFunction",
108
+ });
109
+ }
110
+
111
+ // Test argument count
112
+ if (node.params.length === 0 || node.params.length > 10) {
113
+ context.report({
114
+ node,
115
+ messageId: "wrongArgumentCount",
116
+ });
117
+ }
118
+ },
119
+
120
+ ThrowStatement(node) {
121
+ // Test for custom error classes
122
+ if (node.argument?.type === 'NewExpression' &&
123
+ node.argument.callee?.name === 'Error') {
124
+ context.report({
125
+ node,
126
+ messageId: "customErrorRequired",
127
+ });
128
+ }
129
+ },
130
+ };
131
+ },
132
+ };
133
+
134
+ const ruleTester = new RuleTester({
135
+ languageOptions: {
136
+ ecmaVersion: 2020,
137
+ sourceType: 'module',
138
+ },
139
+ });
140
+
141
+ console.log('Testing english-only-code-strings rule...');
142
+
143
+ ruleTester.run('english-only-code-strings', {
144
+ create: (context) => englishonlycodestringsRule.create(context),
145
+ meta: englishonlycodestringsRule.meta,
146
+ }, {
147
+ valid: [
148
+ // Valid cases
149
+ {
150
+ code: `
151
+ export default class ValidClass {
152
+ constructor() {
153
+ this.name = '';
154
+ this.value = 0;
155
+ }
156
+
157
+ static create(data) {
158
+ const instance = new ValidClass();
159
+ instance.name = data.name;
160
+ return instance;
161
+ }
162
+
163
+ processData(param1, param2) {
164
+ return param1 + param2;
165
+ }
166
+ }
167
+ `,
168
+ filename: 'ValidClass.ts',
169
+ },
170
+ {
171
+ code: `
172
+ const VALID_CONSTANT = 42;
173
+ function processWithConstant() {
174
+ return VALID_CONSTANT;
175
+ }
176
+ `,
177
+ filename: 'Constants.ts',
178
+ },
179
+ {
180
+ code: `
181
+ import { UserDto } from './dto/UserDto';
182
+
183
+ function createUser() {
184
+ return new UserDto();
185
+ }
186
+ `,
187
+ filename: 'UserService.ts',
188
+ },
189
+ {
190
+ code: `
191
+ export class UserService {
192
+ constructor() {}
193
+
194
+ findById(id) {
195
+ if (!id) {
196
+ throw new CustomUserError('User ID required');
197
+ }
198
+ return { id, name: 'Test User' };
199
+ }
200
+ }
201
+ `,
202
+ filename: 'UserService.ts',
203
+ },
204
+ {
205
+ code: `
206
+ const config = {
207
+ apiUrl: 'https://api.example.com',
208
+ timeout: 5000,
209
+ retries: 3
210
+ };
211
+ `,
212
+ filename: 'config.ts',
213
+ },
214
+ ],
215
+
216
+ invalid: [
217
+ // Invalid cases that should trigger rule violations
218
+ {
219
+ code: `
220
+ function badFunction() {
221
+ return 42; // Magic number
222
+ }
223
+ `,
224
+ filename: 'badFunction.ts',
225
+ errors: [{ messageId: 'magicValue' }],
226
+ },
227
+ {
228
+ code: `
229
+ const data = {
230
+ name: 'test',
231
+ value: 123 // Anonymous object + magic number
232
+ };
233
+ `,
234
+ filename: 'data.ts',
235
+ errors: [
236
+ { messageId: 'anonymousObject' },
237
+ { messageId: 'magicValue' }
238
+ ],
239
+ },
240
+ {
241
+ code: `
242
+ // This is a comment
243
+ const value = 999; // Another comment with magic number
244
+ `,
245
+ filename: 'commented.ts',
246
+ errors: [
247
+ { messageId: 'commentFound' },
248
+ { messageId: 'commentFound' },
249
+ { messageId: 'magicValue' }
250
+ ],
251
+ },
252
+ {
253
+ code: `
254
+ export class FirstClass {}
255
+ export class SecondClass {}
256
+ `,
257
+ filename: 'MultipleClasses.ts',
258
+ errors: [{ messageId: 'multipleClasses' }],
259
+ },
260
+ {
261
+ code: `
262
+ function tooManyParams(a, b, c, d, e, f, g) {
263
+ return a + b + c + d + e + f + g;
264
+ }
265
+ `,
266
+ filename: 'complex.ts',
267
+ errors: [{ messageId: 'complexFunction' }],
268
+ },
269
+ {
270
+ code: `
271
+ function noParams() {
272
+ return 42;
273
+ }
274
+ `,
275
+ filename: 'noparams.ts',
276
+ errors: [
277
+ { messageId: 'wrongArgumentCount' },
278
+ { messageId: 'magicValue' }
279
+ ],
280
+ },
281
+ {
282
+ code: `
283
+ function errorThrower() {
284
+ throw new Error('Generic error');
285
+ }
286
+ `,
287
+ filename: 'errors.ts',
288
+ errors: [{ messageId: 'customErrorRequired' }],
289
+ },
290
+ {
291
+ code: `
292
+ const germanText = "Hällö Wörld";
293
+ `,
294
+ filename: 'international.ts',
295
+ errors: [{ messageId: 'nonEnglishString' }],
296
+ },
297
+ ],
298
+ });
299
+
300
+ console.log('✅ english-only-code-strings tests completed successfully');