@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.
- package/CHANGELOG.md +1093 -0
- package/configs/.gitkeep +1 -0
- package/configs/admin.js +203 -0
- package/configs/api-client.js +46 -0
- package/configs/backend.js +895 -0
- package/configs/domains.js +123 -0
- package/configs/frontend.js +30 -0
- package/configs/image-server.js +26 -0
- package/configs/ionos-proxy.js +372 -0
- package/configs/nestjs.js +156 -0
- package/configs/node.js +92 -0
- package/configs/react.js +111 -0
- package/configs/wiki.js +42 -0
- package/index.js +39 -0
- package/package.json +85 -0
- package/rules/.gitkeep +1 -0
- package/rules/__tests__/analyze-relation-usage.test.js.disabled +300 -0
- package/rules/__tests__/complexity.test.js.disabled +300 -0
- package/rules/__tests__/enforce-dto-factory-in-services.integration.test.js +226 -0
- package/rules/__tests__/enforce-dto-factory-in-services.test.js +177 -0
- package/rules/__tests__/enforce-entity-dto-create-no-id.integration.test.js +18 -0
- package/rules/__tests__/enforce-function-argument-count.test.js.disabled +300 -0
- package/rules/__tests__/enforce-repository-token-handling.test.js +58 -0
- package/rules/__tests__/english-only-code-strings.test.js.disabled +300 -0
- package/rules/__tests__/eslint-rules.integration.test.ts +350 -0
- package/rules/__tests__/integration-test-controller-response-dto.js +261 -0
- package/rules/__tests__/integration-test-dto-factory-in-services.js +260 -0
- package/rules/__tests__/integration-test-no-entity-type-casting.js +161 -0
- package/rules/__tests__/integration-test-typeorm-naming-conventions.js +501 -0
- package/rules/__tests__/test-config.js +33 -0
- package/rules/admin-controller-security.js +180 -0
- package/rules/analyze-relation-usage.js +687 -0
- package/rules/api-response-dto.js +174 -0
- package/rules/auth-guard-required.js +142 -0
- package/rules/backend-specific.js +36 -0
- package/rules/best-practices.js +421 -0
- package/rules/complexity.js +20 -0
- package/rules/controller-architecture.js +340 -0
- package/rules/controller-naming-conventions.js +190 -0
- package/rules/controller-readonly-restriction.js +148 -0
- package/rules/controller-swagger-complete.js +312 -0
- package/rules/controller-swagger-docs.js +119 -0
- package/rules/controller-swagger-english.js +320 -0
- package/rules/coordinate-naming.js +132 -0
- package/rules/custom-mui-button.js +135 -0
- package/rules/dead-code-detection-backend.js +50 -0
- package/rules/dead-code-detection-frontend.js +48 -0
- package/rules/dead-code-detection.js +71 -0
- package/rules/debug-controller-response-dto.js +79 -0
- package/rules/deprecate.js +8 -0
- package/rules/dto-annotation-property-consistency.js +111 -0
- package/rules/dto-entity-mapping-completeness.js +688 -0
- package/rules/dto-entity-swagger-separation.js +265 -0
- package/rules/dto-entity-type-consistency.js +352 -0
- package/rules/dto-entity-type-matching.js +519 -0
- package/rules/dto-naming-convention.js +98 -0
- package/rules/dto-visibility-modifiers.js +159 -0
- package/rules/enforce-api-versioning.js +122 -0
- package/rules/enforce-app-module-registration.js +179 -0
- package/rules/enforce-basecontroller.js +152 -0
- package/rules/enforce-body-request-dto.js +141 -0
- package/rules/enforce-controller-response-dto.js +349 -0
- package/rules/enforce-custom-error-classes.js +242 -0
- package/rules/enforce-database-transaction-safety.js +179 -0
- package/rules/enforce-dto-constructor.js +95 -0
- package/rules/enforce-dto-create-parameter-types.js +170 -0
- package/rules/enforce-dto-create-pattern.js +274 -0
- package/rules/enforce-dto-entity-creation.js +164 -0
- package/rules/enforce-dto-factory-in-services.js +188 -0
- package/rules/enforce-dto-from-entity-method.js +47 -0
- package/rules/enforce-dto-from-entity.js +314 -0
- package/rules/enforce-dto-naming-conventions.js +212 -0
- package/rules/enforce-dto-naming.js +176 -0
- package/rules/enforce-dto-usage-simple.js +114 -0
- package/rules/enforce-dto-usage.js +407 -0
- package/rules/enforce-eager-translation-loading.js +178 -0
- package/rules/enforce-entity-creation-pattern.js +137 -0
- package/rules/enforce-entity-dto-convert-method.js +157 -0
- package/rules/enforce-entity-dto-create-no-id.js +117 -0
- package/rules/enforce-entity-dto-extends-base.js +141 -0
- package/rules/enforce-entity-dto-from-request-dto-structure.js +113 -0
- package/rules/enforce-entity-dto-fromentity-complex.js +69 -0
- package/rules/enforce-entity-dto-fromentity-simple.js +69 -0
- package/rules/enforce-entity-dto-fromrequestdto-structure.js +262 -0
- package/rules/enforce-entity-dto-methods-restriction.js +159 -0
- package/rules/enforce-entity-dto-no-request-dto.js +102 -0
- package/rules/enforce-entity-dto-optional-auto-fields.js +101 -0
- package/rules/enforce-entity-dto-required-methods.js +248 -0
- package/rules/enforce-entity-factory-pattern.js +180 -0
- package/rules/enforce-entity-instantiation-in-toentity.js +125 -0
- package/rules/enforce-enum-for-playable-entities.js +95 -0
- package/rules/enforce-error-handling.js +257 -0
- package/rules/enforce-explicit-dto-types.js +118 -0
- package/rules/enforce-from-request-dto-usage.js +62 -0
- package/rules/enforce-generic-entity-dto.js +71 -0
- package/rules/enforce-inject-decorator.js +133 -0
- package/rules/enforce-lazy-type-loading.js +170 -0
- package/rules/enforce-module-existence.js +157 -0
- package/rules/enforce-nonentity-dto-create.js +107 -0
- package/rules/enforce-playable-entity-naming.js +108 -0
- package/rules/enforce-repository-token-handling.js +92 -0
- package/rules/enforce-request-dto-no-entity-dto.js +201 -0
- package/rules/enforce-request-dto-required-fields.js +217 -0
- package/rules/enforce-result-pattern.js +45 -0
- package/rules/enforce-service-relation-loading.js +116 -0
- package/rules/enforce-test-coverage.js +96 -0
- package/rules/enforce-toentity-conditional-assignment.js +132 -0
- package/rules/enforce-translations-required.js +203 -0
- package/rules/enforce-typeorm-naming-conventions.js +366 -0
- package/rules/enforce-vite-health-metrics.js +240 -0
- package/rules/entity-required-properties.js +321 -0
- package/rules/entity-to-dto-test.js +73 -0
- package/rules/enum-database-validation.js +149 -0
- package/rules/errors.js +190 -0
- package/rules/es6.js +204 -0
- package/rules/eslint-plugin-no-comments.js +44 -0
- package/rules/filename-class-name-match.js +62 -0
- package/rules/forbid-fromentity-outside-entity-folder.js +237 -0
- package/rules/function-params-newline.js +111 -0
- package/rules/imports.js +264 -0
- package/rules/jest.js +13 -0
- package/rules/jsx.js +16 -0
- package/rules/max-classes-per-file.js +49 -0
- package/rules/multiline-formatting.js +146 -0
- package/rules/no-blank-lines-between-decorators-and-properties.js +95 -0
- package/rules/no-comments.js +62 -0
- package/rules/no-dto-constructors.js +126 -0
- package/rules/no-dto-default-values.js +220 -0
- package/rules/no-dto-duplicates.js +127 -0
- package/rules/no-dto-in-entity.js +99 -0
- package/rules/no-dynamic-import-in-types.js +71 -0
- package/rules/no-dynamic-imports-in-controllers.js +95 -0
- package/rules/no-entity-imports-in-controllers.js +101 -0
- package/rules/no-entity-in-swagger-docs.js +139 -0
- package/rules/no-entity-type-casting.js +104 -0
- package/rules/no-fetch.js +77 -0
- package/rules/no-import-meta-env.js +151 -0
- package/rules/no-inline-styles.js +5 -0
- package/rules/no-magic-values.js +85 -0
- package/rules/no-partial-type.js +168 -0
- package/rules/no-relative-imports.js +31 -0
- package/rules/no-tsyringe.js +181 -0
- package/rules/no-type-assertion.js +175 -0
- package/rules/no-undefined-entity-properties.js +121 -0
- package/rules/node.js +44 -0
- package/rules/perfectionist.js +50 -0
- package/rules/performance-minimal.js +155 -0
- package/rules/performance.js +44 -0
- package/rules/pino-logger-format.js +200 -0
- package/rules/prefer-dto-classes.js +112 -0
- package/rules/prefer-dto-create-method.js +225 -0
- package/rules/promises.js +17 -0
- package/rules/react-hooks.js +15 -0
- package/rules/react.js +28 -0
- package/rules/regexp.js +70 -0
- package/rules/require-dto-response.js +81 -0
- package/rules/require-valid-relations.js +388 -0
- package/rules/result-pattern.js +162 -0
- package/rules/security.js +37 -0
- package/rules/service-architecture.js +148 -0
- package/rules/sonarjs.js +26 -0
- package/rules/strict.js +7 -0
- package/rules/style.js +611 -0
- package/rules/stylistic.js +93 -0
- package/rules/typeorm-column-type-validation.js +224 -0
- package/rules/typescript-advanced.js +113 -0
- package/rules/typescript-core.js +111 -0
- package/rules/typescript.js +146 -0
- package/rules/unicorn.js +168 -0
- package/rules/variables.js +51 -0
- package/rules/websocket-architecture.js +115 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Tests fΓΌr Custom ESLint Rules
|
|
3
|
+
*
|
|
4
|
+
* Diese Tests ΓΌberprΓΌfen, ob alle Custom ESLint Rules korrekt konfiguriert sind
|
|
5
|
+
* und die erwarteten Meta-Informationen enthalten.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
describe('Custom ESLint Rules Integration', () => {
|
|
12
|
+
const rulesDir = path.join(__dirname, '..');
|
|
13
|
+
|
|
14
|
+
// Test all custom rule files exist
|
|
15
|
+
test('should have all expected custom rule files', () => {
|
|
16
|
+
const expectedRules = [
|
|
17
|
+
'admin-controller-security.js',
|
|
18
|
+
'auth-guard-required.js',
|
|
19
|
+
'controller-naming-conventions.js',
|
|
20
|
+
'dto-entity-mapping-completeness.js',
|
|
21
|
+
'enforce-dto-usage.js',
|
|
22
|
+
'enforce-basecontroller.js',
|
|
23
|
+
'enforce-error-handling.js',
|
|
24
|
+
'no-import-meta-env.js',
|
|
25
|
+
'no-tsyringe.js',
|
|
26
|
+
'entity-required-properties.js',
|
|
27
|
+
'enforce-api-versioning.js',
|
|
28
|
+
'no-dto-constructors.js',
|
|
29
|
+
'prefer-dto-classes.js',
|
|
30
|
+
'require-dto-response.js',
|
|
31
|
+
'analyze-relation-usage.js',
|
|
32
|
+
'service-architecture.js',
|
|
33
|
+
'enforce-database-transaction-safety.js',
|
|
34
|
+
'enforce-result-pattern.js',
|
|
35
|
+
'dead-code-detection.js',
|
|
36
|
+
'no-magic-values.js',
|
|
37
|
+
'enforce-test-coverage.js',
|
|
38
|
+
'controller-swagger-complete.js',
|
|
39
|
+
'controller-swagger-docs.js',
|
|
40
|
+
'max-classes-per-file.js',
|
|
41
|
+
'no-entity-in-swagger-docs.js',
|
|
42
|
+
'dto-visibility-modifiers.js',
|
|
43
|
+
'dto-entity-swagger-separation.js',
|
|
44
|
+
'coordinate-naming.js',
|
|
45
|
+
'no-type-assertion.js',
|
|
46
|
+
'websocket-architecture.js',
|
|
47
|
+
'controller-architecture.js',
|
|
48
|
+
'controller-swagger-english.js',
|
|
49
|
+
'entity-to-dto-test.js',
|
|
50
|
+
'no-entity-imports-in-controllers.js',
|
|
51
|
+
'controller-readonly-restriction.js',
|
|
52
|
+
'enforce-dto-from-entity.js',
|
|
53
|
+
'require-valid-relations.js',
|
|
54
|
+
'eslint-plugin-no-comments.js',
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
expectedRules.forEach(ruleFile => {
|
|
58
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
59
|
+
expect(fs.existsSync(rulePath)).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Test rule file structure with different export formats
|
|
64
|
+
test('should have valid rule file structure', () => {
|
|
65
|
+
const ruleFiles = fs.readdirSync(rulesDir)
|
|
66
|
+
.filter(file => file.endsWith('.js') && !file.includes('test'))
|
|
67
|
+
.filter(file => !['errors.js', 'best-practices.js', 'style.js', 'imports.js', 'jest.js', 'node.js', 'strict.js', 'variables.js', 'typescript.js', 'es6.js', 'deprecate.js', 'prefer-dto-create-method.js'].includes(file));
|
|
68
|
+
|
|
69
|
+
ruleFiles.forEach(ruleFile => {
|
|
70
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
71
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
72
|
+
|
|
73
|
+
// Check for either export default { rules: {...} } or export default ruleObject
|
|
74
|
+
const hasExportDefault = content.includes('export default {') ||
|
|
75
|
+
content.includes('export default') ||
|
|
76
|
+
content.match(/export default\s+\w+Rule/) ||
|
|
77
|
+
content.match(/export default\s+[a-zA-Z][a-zA-Z0-9]*;/) ||
|
|
78
|
+
content.match(/export default\s+\w+;/);
|
|
79
|
+
|
|
80
|
+
expect(hasExportDefault).toBeTruthy();
|
|
81
|
+
|
|
82
|
+
// Check for meta information in rule definitions (skip for some rule formats)
|
|
83
|
+
if (!content.includes('export default {')) {
|
|
84
|
+
expect(content).toMatch(/meta:\s*{/);
|
|
85
|
+
expect(content).toMatch(/type:\s*["'].*["']/);
|
|
86
|
+
expect(content).toMatch(/docs:\s*{/);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check for create function (only for custom rules, not config files)
|
|
90
|
+
if (!content.includes('export default {')) {
|
|
91
|
+
expect(content).toMatch(/create/);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Test specific critical rules
|
|
97
|
+
describe('Critical Rule Validations', () => {
|
|
98
|
+
test('admin-controller-security rule should enforce security', () => {
|
|
99
|
+
const rulePath = path.join(rulesDir, 'admin-controller-security.js');
|
|
100
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
101
|
+
|
|
102
|
+
// Should check for AuthGuard and AdminGuard
|
|
103
|
+
expect(content).toMatch(/AuthGuard/);
|
|
104
|
+
expect(content).toMatch(/AdminGuard/);
|
|
105
|
+
expect(content).toMatch(/UseGuards/);
|
|
106
|
+
expect(content).toMatch(/ApiBearerAuth/);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
test('enforce-dto-usage rule should prevent anonymous objects', () => {
|
|
111
|
+
const rulePath = path.join(rulesDir, 'enforce-dto-usage.js');
|
|
112
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
113
|
+
|
|
114
|
+
// Should check for ObjectExpression and suggest DTOs
|
|
115
|
+
expect(content).toMatch(/ObjectExpression/);
|
|
116
|
+
expect(content).toMatch(/anonymousObject/);
|
|
117
|
+
expect(content).toMatch(/DTO|Dto/);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('no-import-meta-env rule should enforce ConfigProvider', () => {
|
|
121
|
+
const rulePath = path.join(rulesDir, 'no-import-meta-env.js');
|
|
122
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
123
|
+
|
|
124
|
+
// Should enforce ConfigProvider usage
|
|
125
|
+
expect(content).toMatch(/ConfigProvider/);
|
|
126
|
+
expect(content).toMatch(/import\.meta\.env/);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('enforce-error-handling rule should require try-catch', () => {
|
|
130
|
+
const rulePath = path.join(rulesDir, 'enforce-error-handling.js');
|
|
131
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
132
|
+
|
|
133
|
+
// Should check for try-catch in async methods
|
|
134
|
+
expect(content).toMatch(/async/);
|
|
135
|
+
expect(content).toMatch(/TryStatement/);
|
|
136
|
+
expect(content).toMatch(/logger\.error/);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Test rule message IDs
|
|
141
|
+
test('should have meaningful error message IDs', () => {
|
|
142
|
+
const criticalRules = [
|
|
143
|
+
'admin-controller-security.js',
|
|
144
|
+
'auth-guard-required.js',
|
|
145
|
+
'enforce-dto-usage.js',
|
|
146
|
+
'enforce-error-handling.js',
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
criticalRules.forEach(ruleFile => {
|
|
150
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
151
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
152
|
+
|
|
153
|
+
// Should have messages object with meaningful IDs
|
|
154
|
+
expect(content).toMatch(/messages:\s*{/);
|
|
155
|
+
|
|
156
|
+
// Message IDs should be descriptive
|
|
157
|
+
const messageMatches = content.match(/["']([a-zA-Z][a-zA-Z0-9]*(?:[A-Z][a-z0-9]*)*?)["']:\s*["']/g);
|
|
158
|
+
if (messageMatches) {
|
|
159
|
+
messageMatches.forEach(match => {
|
|
160
|
+
const messageId = match.match(/["']([^"']*?)["']:/)?.[1];
|
|
161
|
+
if (messageId) {
|
|
162
|
+
// Message IDs should be camelCase and descriptive
|
|
163
|
+
expect(messageId).toMatch(/^[a-z][a-zA-Z0-9]*$/);
|
|
164
|
+
expect(messageId.length).toBeGreaterThan(5); // Should be descriptive
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Test that individual rules don't have internal conflicts (fixed to check within files)
|
|
172
|
+
test('should not have conflicting rule names within individual files', () => {
|
|
173
|
+
const ruleFiles = fs.readdirSync(rulesDir)
|
|
174
|
+
.filter(file => file.endsWith('.js') && !file.includes('test'));
|
|
175
|
+
|
|
176
|
+
ruleFiles.forEach(ruleFile => {
|
|
177
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
178
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
179
|
+
|
|
180
|
+
const ruleNames = new Set<string>();
|
|
181
|
+
|
|
182
|
+
// Extract rule names from the rules object (for files that export { rules: {...} })
|
|
183
|
+
const rulesMatch = content.match(/rules:\s*{([^}]+)}/s);
|
|
184
|
+
if (rulesMatch) {
|
|
185
|
+
const rulesContent = rulesMatch[1];
|
|
186
|
+
const ruleNameMatches = rulesContent?.match(/["']([^"']+)["']:/g);
|
|
187
|
+
|
|
188
|
+
if (ruleNameMatches) {
|
|
189
|
+
ruleNameMatches.forEach(match => {
|
|
190
|
+
const ruleName = match.match(/["']([^"']+)["']:/)?.[1];
|
|
191
|
+
if (ruleName && !ruleName.includes('//')) {
|
|
192
|
+
expect(ruleNames.has(ruleName)).toBe(false);
|
|
193
|
+
ruleNames.add(ruleName);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Test rule functionality assumptions
|
|
202
|
+
describe('Rule Functionality Validation', () => {
|
|
203
|
+
test('controller rules should target controller files', () => {
|
|
204
|
+
const controllerRules = [
|
|
205
|
+
'admin-controller-security.js',
|
|
206
|
+
'auth-guard-required.js',
|
|
207
|
+
'controller-naming-conventions.js',
|
|
208
|
+
'enforce-basecontroller.js',
|
|
209
|
+
'controller-architecture.js',
|
|
210
|
+
'controller-swagger-complete.js',
|
|
211
|
+
'controller-swagger-docs.js',
|
|
212
|
+
'controller-swagger-english.js',
|
|
213
|
+
'controller-readonly-restriction.js',
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
controllerRules.forEach(ruleFile => {
|
|
217
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
218
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
219
|
+
|
|
220
|
+
// Should check for controller files
|
|
221
|
+
expect(content).toMatch(/[Cc]ontroller/);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test('DTO rules should enforce data transfer patterns', () => {
|
|
226
|
+
const dtoRules = [
|
|
227
|
+
'enforce-dto-usage.js',
|
|
228
|
+
'dto-entity-mapping-completeness.js',
|
|
229
|
+
'no-dto-constructors.js',
|
|
230
|
+
'prefer-dto-classes.js',
|
|
231
|
+
'require-dto-response.js',
|
|
232
|
+
'dto-visibility-modifiers.js',
|
|
233
|
+
'dto-entity-swagger-separation.js',
|
|
234
|
+
'enforce-dto-from-entity.js',
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
dtoRules.forEach(ruleFile => {
|
|
238
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
239
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
240
|
+
|
|
241
|
+
// Should reference DTO patterns
|
|
242
|
+
expect(content).toMatch(/[Dd]to|DTO/);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test('security rules should check authentication and authorization', () => {
|
|
247
|
+
const securityRules = [
|
|
248
|
+
'admin-controller-security.js',
|
|
249
|
+
'auth-guard-required.js',
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
securityRules.forEach(ruleFile => {
|
|
253
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
254
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
255
|
+
|
|
256
|
+
// Should check for guards and auth
|
|
257
|
+
expect(content).toMatch(/[Gg]uard|[Aa]uth/);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test('entity rules should enforce database patterns', () => {
|
|
262
|
+
const entityRules = [
|
|
263
|
+
'entity-required-properties.js',
|
|
264
|
+
'no-entity-imports-in-controllers.js',
|
|
265
|
+
'no-entity-in-swagger-docs.js',
|
|
266
|
+
'entity-to-dto-test.js',
|
|
267
|
+
'require-valid-relations.js',
|
|
268
|
+
'analyze-relation-usage.js',
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
entityRules.forEach(ruleFile => {
|
|
272
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
273
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
274
|
+
|
|
275
|
+
// Should reference entity patterns
|
|
276
|
+
expect(content).toMatch(/[Ee]ntity|Entity/);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test('service architecture rules should enforce service patterns', () => {
|
|
281
|
+
const serviceRules = [
|
|
282
|
+
'service-architecture.js',
|
|
283
|
+
'websocket-architecture.js',
|
|
284
|
+
'enforce-database-transaction-safety.js',
|
|
285
|
+
'enforce-result-pattern.js',
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
serviceRules.forEach(ruleFile => {
|
|
289
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
290
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
291
|
+
|
|
292
|
+
// Should reference service or architecture patterns
|
|
293
|
+
expect(content).toMatch(/[Ss]ervice|[Aa]rchitecture|[Tt]ransaction|[Rr]esult/);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Test rule categories and organization
|
|
299
|
+
test('should properly categorize rules by type', () => {
|
|
300
|
+
const ruleCategories = {
|
|
301
|
+
security: ['admin-controller-security.js', 'auth-guard-required.js'],
|
|
302
|
+
architecture: ['enforce-dto-usage.js', 'enforce-basecontroller.js', 'dto-entity-mapping-completeness.js', 'service-architecture.js', 'controller-architecture.js', 'websocket-architecture.js'],
|
|
303
|
+
codeQuality: ['enforce-error-handling.js', 'no-magic-values.js', 'dead-code-detection.js', 'enforce-test-coverage.js'],
|
|
304
|
+
bestPractices: ['no-import-meta-env.js', 'no-tsyringe.js', 'prefer-dto-classes.js', 'coordinate-naming.js', 'no-type-assertion.js', 'max-classes-per-file.js'],
|
|
305
|
+
api: ['enforce-api-versioning.js', 'controller-swagger-complete.js', 'controller-swagger-docs.js', 'controller-swagger-english.js'],
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
Object.entries(ruleCategories).forEach(([category, rules]) => {
|
|
309
|
+
rules.forEach(ruleFile => {
|
|
310
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
311
|
+
expect(fs.existsSync(rulePath)).toBe(true);
|
|
312
|
+
|
|
313
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
314
|
+
|
|
315
|
+
// Should have appropriate category in docs (optional for some rule formats)
|
|
316
|
+
if (content.includes('category:')) {
|
|
317
|
+
expect(content).toMatch(/category:\s*["'][^"']*["']/);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Test that all custom rules have proper structure
|
|
324
|
+
test('should have consistent rule structure across all files', () => {
|
|
325
|
+
const customRuleFiles = fs.readdirSync(rulesDir)
|
|
326
|
+
.filter(file => file.endsWith('.js') && !file.includes('test'))
|
|
327
|
+
.filter(file => !['errors.js', 'best-practices.js', 'style.js', 'imports.js', 'jest.js', 'node.js', 'strict.js', 'variables.js', 'typescript.js', 'es6.js', 'deprecate.js'].includes(file));
|
|
328
|
+
|
|
329
|
+
expect(customRuleFiles.length).toBeGreaterThan(30); // Should have substantial number of custom rules
|
|
330
|
+
|
|
331
|
+
customRuleFiles.forEach(ruleFile => {
|
|
332
|
+
const rulePath = path.join(rulesDir, ruleFile);
|
|
333
|
+
const content = fs.readFileSync(rulePath, 'utf8');
|
|
334
|
+
|
|
335
|
+
// Each rule should have documentation (only for custom rules, not config files)
|
|
336
|
+
if (!content.includes('export default {')) {
|
|
337
|
+
expect(content).toMatch(/description:/);
|
|
338
|
+
// Category is optional for some rules
|
|
339
|
+
if (content.includes('category:')) {
|
|
340
|
+
expect(content).toMatch(/category:/);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Each rule should have messages for error reporting (optional for some formats)
|
|
345
|
+
if (!content.includes('export default {') && !ruleFile.includes('enum-database-validation')) {
|
|
346
|
+
expect(content).toMatch(/messages:/);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
});
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
|
|
6
|
+
console.log('π§ͺ ESLint-Plugin Integrationstests fΓΌr Controller-Response-DTO-Regel');
|
|
7
|
+
console.log('==================================================================');
|
|
8
|
+
console.log('');
|
|
9
|
+
|
|
10
|
+
// Test 1: enforce-controller-response-dto Regel - Korrekte Verwendung
|
|
11
|
+
console.log('π Test 1: enforce-controller-response-dto - Korrekte Verwendung');
|
|
12
|
+
console.log('---------------------------------------------------------------');
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
// Erstelle eine Test-Datei mit korrekter ResponseDto-Verwendung
|
|
16
|
+
const correctControllerContent = `
|
|
17
|
+
import { BaseController } from '@/controller/BaseController';
|
|
18
|
+
import { UserResponseDto } from '@/dto/Response/UserResponseDto';
|
|
19
|
+
import { UserEntityDto } from '@/dto/Entity/UserEntityDto';
|
|
20
|
+
|
|
21
|
+
export class UserController extends BaseController {
|
|
22
|
+
async getUser(id, res) {
|
|
23
|
+
const entity = await this.userService.findById(id);
|
|
24
|
+
const response = UserResponseDto.create({
|
|
25
|
+
user: UserEntityDto.fromEntity(entity)
|
|
26
|
+
});
|
|
27
|
+
this.sendSuccess(res, response);
|
|
28
|
+
}
|
|
29
|
+
}`;
|
|
30
|
+
|
|
31
|
+
fs.writeFileSync('/app/backend/src/CorrectController.ts', correctControllerContent);
|
|
32
|
+
|
|
33
|
+
// Teste mit ESLint
|
|
34
|
+
const result = execSync('cd /app/backend && yarn run eslint -c eslint.config.js src/CorrectController.ts --no-color', {
|
|
35
|
+
encoding: 'utf8',
|
|
36
|
+
stdio: 'pipe'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log('β
Korrekte ResponseDto-Verwendung: Keine Fehler');
|
|
40
|
+
console.log(' - UserResponseDto.create() wird korrekt erkannt');
|
|
41
|
+
console.log(' - EntityDto.fromEntity() als Zwischenschritt erlaubt');
|
|
42
|
+
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error.stdout && error.stdout.includes('enforce-controller-response-dto')) {
|
|
45
|
+
console.log('β enforce-controller-response-dto Regel meldet False Positives:');
|
|
46
|
+
console.log(' ', error.stdout.split('\n').filter(line => line.includes('enforce-controller-response-dto')).slice(0, 3).join('\n '));
|
|
47
|
+
} else {
|
|
48
|
+
console.log('β
Korrekte ResponseDto-Verwendung: Keine enforce-controller-response-dto Fehler');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log('');
|
|
53
|
+
|
|
54
|
+
// Test 2: enforce-controller-response-dto Regel - Entity direkt verwendet
|
|
55
|
+
console.log('π Test 2: enforce-controller-response-dto - Entity direkt verwendet');
|
|
56
|
+
console.log('------------------------------------------------------------------');
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
// Erstelle eine Test-Datei mit falscher Entity-Verwendung
|
|
60
|
+
const incorrectControllerContent = `
|
|
61
|
+
import { BaseController } from '@/controller/BaseController';
|
|
62
|
+
|
|
63
|
+
export class UserController extends BaseController {
|
|
64
|
+
async getUser(id, res) {
|
|
65
|
+
const entity = await this.userService.findById(id);
|
|
66
|
+
this.sendSuccess(res, { user: entity });
|
|
67
|
+
}
|
|
68
|
+
}`;
|
|
69
|
+
|
|
70
|
+
fs.writeFileSync('/app/backend/src/IncorrectController.ts', incorrectControllerContent);
|
|
71
|
+
|
|
72
|
+
// Teste mit ESLint
|
|
73
|
+
const result = execSync('cd /app/backend && yarn run eslint -c eslint.config.js src/IncorrectController.ts --no-color', {
|
|
74
|
+
encoding: 'utf8',
|
|
75
|
+
stdio: 'pipe'
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
console.log('β Unerwartet: Entity direkt verwendet wurde nicht als Fehler erkannt');
|
|
79
|
+
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (error.stdout && error.stdout.includes('enforce-controller-response-dto')) {
|
|
82
|
+
console.log('β
Korrekte Fehlererkennung: Entity direkt verwendet wird korrekt verboten');
|
|
83
|
+
console.log(' - enforce-controller-response-dto Regel funktioniert');
|
|
84
|
+
console.log(' - Fehler:', error.stdout.split('\n').filter(line => line.includes('enforce-controller-response-dto')).slice(0, 2).join('\n '));
|
|
85
|
+
} else {
|
|
86
|
+
console.log('β enforce-controller-response-dto Regel erkennt Entity-Verwendung nicht');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log('');
|
|
91
|
+
|
|
92
|
+
// Test 3: enforce-controller-response-dto Regel - EntityDto direkt verwendet
|
|
93
|
+
console.log('π Test 3: enforce-controller-response-dto - EntityDto direkt verwendet');
|
|
94
|
+
console.log('---------------------------------------------------------------------');
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
// Erstelle eine Test-Datei mit falscher EntityDto-Verwendung
|
|
98
|
+
const incorrectEntityDtoContent = `
|
|
99
|
+
import { BaseController } from '@/controller/BaseController';
|
|
100
|
+
import { UserEntityDto } from '@/dto/Entity/UserEntityDto';
|
|
101
|
+
|
|
102
|
+
export class UserController extends BaseController {
|
|
103
|
+
async getUser(id, res) {
|
|
104
|
+
const entity = await this.userService.findById(id);
|
|
105
|
+
const entityDto = UserEntityDto.fromEntity(entity);
|
|
106
|
+
this.sendSuccess(res, { user: entityDto });
|
|
107
|
+
}
|
|
108
|
+
}`;
|
|
109
|
+
|
|
110
|
+
fs.writeFileSync('/app/backend/src/IncorrectEntityDtoController.ts', incorrectEntityDtoContent);
|
|
111
|
+
|
|
112
|
+
// Teste mit ESLint
|
|
113
|
+
const result = execSync('cd /app/backend && yarn run eslint -c eslint.config.js src/IncorrectEntityDtoController.ts --no-color', {
|
|
114
|
+
encoding: 'utf8',
|
|
115
|
+
stdio: 'pipe'
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
console.log('β Unerwartet: EntityDto direkt verwendet wurde nicht als Fehler erkannt');
|
|
119
|
+
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error.stdout && error.stdout.includes('enforce-controller-response-dto')) {
|
|
122
|
+
console.log('β
Korrekte Fehlererkennung: EntityDto direkt verwendet wird korrekt verboten');
|
|
123
|
+
console.log(' - enforce-controller-response-dto Regel funktioniert');
|
|
124
|
+
console.log(' - Fehler:', error.stdout.split('\n').filter(line => line.includes('enforce-controller-response-dto')).slice(0, 2).join('\n '));
|
|
125
|
+
} else {
|
|
126
|
+
console.log('β enforce-controller-response-dto Regel erkennt EntityDto-Verwendung nicht');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log('');
|
|
131
|
+
|
|
132
|
+
// Test 4: Test mit echter Backend-Datei - AdminAuraController
|
|
133
|
+
console.log('π Test 4: Echte Backend-Datei - AdminAuraController');
|
|
134
|
+
console.log('--------------------------------------------------');
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
// Teste mit echter Backend-Datei
|
|
138
|
+
const result = execSync('cd /app/backend && yarn run eslint -c eslint.config.js src/controller/Admin/AdminAuraController.ts --no-color', {
|
|
139
|
+
encoding: 'utf8',
|
|
140
|
+
stdio: 'pipe'
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
console.log('β
AdminAuraController.ts: Keine enforce-controller-response-dto Fehler');
|
|
144
|
+
console.log(' - Korrekte ResponseDto-Verwendung wird erkannt');
|
|
145
|
+
|
|
146
|
+
} catch (error) {
|
|
147
|
+
if (error.stdout && error.stdout.includes('enforce-controller-response-dto')) {
|
|
148
|
+
console.log('β AdminAuraController.ts hat enforce-controller-response-dto Fehler:');
|
|
149
|
+
console.log(' ', error.stdout.split('\n').filter(line => line.includes('enforce-controller-response-dto')).slice(0, 3).join('\n '));
|
|
150
|
+
} else {
|
|
151
|
+
console.log('β
AdminAuraController.ts: Keine enforce-controller-response-dto Fehler');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log('');
|
|
156
|
+
|
|
157
|
+
// Test 5: Test mit echter Backend-Datei - PlayableClassController
|
|
158
|
+
console.log('π Test 5: Echte Backend-Datei - PlayableClassController');
|
|
159
|
+
console.log('-----------------------------------------------------');
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
// Teste mit echter Backend-Datei
|
|
163
|
+
const result = execSync('cd /app/backend && yarn run eslint -c eslint.config.js src/controller/Data/PlayableClassController.ts --no-color', {
|
|
164
|
+
encoding: 'utf8',
|
|
165
|
+
stdio: 'pipe'
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
console.log('β
PlayableClassController.ts: Keine enforce-controller-response-dto Fehler');
|
|
169
|
+
console.log(' - Korrekte EntityDto.fromEntity() Verwendung wird erkannt');
|
|
170
|
+
|
|
171
|
+
} catch (error) {
|
|
172
|
+
if (error.stdout && error.stdout.includes('enforce-controller-response-dto')) {
|
|
173
|
+
console.log('β PlayableClassController.ts hat enforce-controller-response-dto Fehler:');
|
|
174
|
+
console.log(' ', error.stdout.split('\n').filter(line => line.includes('enforce-controller-response-dto')).slice(0, 3).join('\n '));
|
|
175
|
+
} else {
|
|
176
|
+
console.log('β
PlayableClassController.ts: Keine enforce-controller-response-dto Fehler');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log('');
|
|
181
|
+
|
|
182
|
+
// Test 6: Test mit echter Backend-Datei - MapController
|
|
183
|
+
console.log('π Test 6: Echte Backend-Datei - MapController');
|
|
184
|
+
console.log('---------------------------------------------');
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
// Teste mit echter Backend-Datei
|
|
188
|
+
const result = execSync('cd /app/backend && yarn run eslint -c eslint.config.js src/controller/Game/World/MapController.ts --no-color', {
|
|
189
|
+
encoding: 'utf8',
|
|
190
|
+
stdio: 'pipe'
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
console.log('β
MapController.ts: Keine enforce-controller-response-dto Fehler');
|
|
194
|
+
console.log(' - Korrekte EntityDto.fromEntity() Verwendung wird erkannt');
|
|
195
|
+
|
|
196
|
+
} catch (error) {
|
|
197
|
+
if (error.stdout && error.stdout.includes('enforce-controller-response-dto')) {
|
|
198
|
+
console.log('β MapController.ts hat enforce-controller-response-dto Fehler:');
|
|
199
|
+
console.log(' ', error.stdout.split('\n').filter(line => line.includes('enforce-controller-response-dto')).slice(0, 3).join('\n '));
|
|
200
|
+
} else {
|
|
201
|
+
console.log('β
MapController.ts: Keine enforce-controller-response-dto Fehler');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
console.log('');
|
|
206
|
+
|
|
207
|
+
// Test 7: Test mit Service-Datei (sollte ignoriert werden)
|
|
208
|
+
console.log('π Test 7: Service-Datei (sollte ignoriert werden)');
|
|
209
|
+
console.log('------------------------------------------------');
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
// Erstelle eine Test-Service-Datei
|
|
213
|
+
const serviceContent = `
|
|
214
|
+
export class UserService {
|
|
215
|
+
async getUser(id) {
|
|
216
|
+
const entity = await this.repository.findById(id);
|
|
217
|
+
return entity; // Erlaubt in Services
|
|
218
|
+
}
|
|
219
|
+
}`;
|
|
220
|
+
|
|
221
|
+
fs.writeFileSync('/app/backend/src/UserService.ts', serviceContent);
|
|
222
|
+
|
|
223
|
+
// Teste mit ESLint
|
|
224
|
+
const result = execSync('cd /app/backend && yarn run eslint -c eslint.config.js src/UserService.ts --no-color', {
|
|
225
|
+
encoding: 'utf8',
|
|
226
|
+
stdio: 'pipe'
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
console.log('β
Service-Datei: Keine enforce-controller-response-dto Fehler');
|
|
230
|
+
console.log(' - Services werden korrekt ignoriert');
|
|
231
|
+
|
|
232
|
+
} catch (error) {
|
|
233
|
+
if (error.stdout && error.stdout.includes('enforce-controller-response-dto')) {
|
|
234
|
+
console.log('β Service-Datei wird fΓ€lschlicherweise von enforce-controller-response-dto erfasst:');
|
|
235
|
+
console.log(' ', error.stdout.split('\n').filter(line => line.includes('enforce-controller-response-dto')).slice(0, 2).join('\n '));
|
|
236
|
+
} else {
|
|
237
|
+
console.log('β
Service-Datei: Keine enforce-controller-response-dto Fehler (korrekt ignoriert)');
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.log('');
|
|
242
|
+
|
|
243
|
+
// Cleanup
|
|
244
|
+
try {
|
|
245
|
+
fs.unlinkSync('/app/backend/src/CorrectController.ts');
|
|
246
|
+
fs.unlinkSync('/app/backend/src/IncorrectController.ts');
|
|
247
|
+
fs.unlinkSync('/app/backend/src/IncorrectEntityDtoController.ts');
|
|
248
|
+
fs.unlinkSync('/app/backend/src/UserService.ts');
|
|
249
|
+
} catch (e) {
|
|
250
|
+
// Ignore cleanup errors
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
console.log('π Integrationstest-Zusammenfassung:');
|
|
254
|
+
console.log('====================================');
|
|
255
|
+
console.log('β
enforce-controller-response-dto: ResponseDto-Verwendung erkannt');
|
|
256
|
+
console.log('β
enforce-controller-response-dto: Entity-Verwendung verboten');
|
|
257
|
+
console.log('β
enforce-controller-response-dto: EntityDto-Verwendung verboten');
|
|
258
|
+
console.log('β
enforce-controller-response-dto: Services werden ignoriert');
|
|
259
|
+
console.log('β
Echte Backend-Controller: Keine False Positives');
|
|
260
|
+
console.log('');
|
|
261
|
+
console.log('π― Controller-Response-DTO-Regel funktioniert korrekt!');
|