create-dp-koa 1.0.1 → 1.1.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/package.json +1 -1
- package/template/.cursor/commands/cheatsheet-backend-controller.md +2 -2
- package/template/.cursor/commands/implement-backend-api-controller.md +6 -4
- package/template/.cursor/rules/11-backend-controller-recipes.skill.md +89 -10
- package/template/.trae/skills/11-backend-controller-recipes.skill.md +91 -10
- package/template/docs/FRAMEWORK_V2_UPGRADE_GUIDE.md +134 -0
- package/template/package.json +2 -0
- package/template/scripts/sync-template.mjs +39 -1
- package/template/src/app.ts +21 -16
- package/template/src/controllers/demo/AnnotationDemoController.ts +1 -3
- package/template/src/controllers/example/EnterpriseExampleController.ts +2 -9
- package/template/src/controllers/example/ExampleController.ts +13 -4
- package/template/src/entity/index.ts +1 -15
- package/template/src/framework/decorator/processor/AnnotationProcessor.ts +5 -1
- package/template/src/routers/index.ts +1 -37
- package/template/src/utils/testDataInitializer.ts +2 -269
- package/template/test/controllers/example/ExampleController.test.ts +29 -31
- package/template/test/framework/annotation/AnnotationDecorators.test.ts +15 -15
- package/template/test/framework/annotation/AnnotationExecutor.test.ts +27 -32
- package/template/test/framework/annotation/AnnotationProcessor.test.ts +25 -24
- package/template/test/framework/annotation/CustomProcessors.test.ts +15 -25
- package/template/test/framework/annotation/NewRouter.test.ts +9 -7
- package/template/test/framework/annotation/ProcessorManager.test.ts +14 -27
- package/template/test/framework/databaseConfig.test.ts +2 -2
- package/template/test/integration/integration.test.ts +15 -72
- package/template/webpack.config.js +2 -0
- package/template/package-lock.json +0 -13240
- package/template/src/controllers/cacheManagement.controller.ts +0 -131
- package/template/src/controllers/captcha.controller.ts +0 -57
- package/template/src/controllers/example/NewAnnotationExampleController.ts +0 -159
- package/template/src/controllers/example/SwaggerExampleController.ts +0 -205
- package/template/src/controllers/example/TransactionExample.controller.ts +0 -336
- package/template/src/controllers/health.controller.ts +0 -235
- package/template/src/controllers/home/register.controller.ts +0 -58
- package/template/src/controllers/home/ytGoods.controller.ts +0 -92
- package/template/src/controllers/home/ytShop.controller.ts +0 -135
- package/template/src/controllers/home/ytUser.controller.ts +0 -89
- package/template/src/controllers/logManagement.controller.ts +0 -396
- package/template/src/controllers/public/emailSend.controller.ts +0 -65
- package/template/src/controllers/public/ytUserAuth.controller.ts +0 -174
- package/template/src/controllers/testData.controller.ts +0 -253
- package/template/src/dto/controller/example/NewAnnotationExampleController.dto.ts +0 -73
- package/template/src/dto/controller/home/emailSend.controller.dto.ts +0 -40
- package/template/src/dto/controller/home/register.controller.dto.ts +0 -45
- package/template/src/dto/controller/home/ytGoods.controller.dto.ts +0 -55
- package/template/src/dto/controller/home/ytShop.controller.dto.ts +0 -69
- package/template/src/dto/controller/home/ytUser.controller.dto.ts +0 -44
- package/template/src/dto/controller/public/ytUserAuth.controller.dto.ts +0 -63
- package/template/src/dto/goods.dto.ts +0 -212
- package/template/src/dto/service/ytService.dto.ts +0 -13
- package/template/src/dto/user.dto.ts +0 -177
- package/template/src/entity/columnTypes.ts +0 -13
- package/template/src/entity/goodsImagesUnlockKey.entity.ts +0 -33
- package/template/src/entity/goodsUnlocker.entity.ts +0 -34
- package/template/src/entity/shop.entity.ts +0 -52
- package/template/src/entity/shopUser.entity.ts +0 -41
- package/template/src/entity/ytGoods.entity.ts +0 -94
- package/template/src/entity/ytUser.entity.ts +0 -96
- package/template/src/examples/SwaggerProcessorExample.ts +0 -169
- package/template/src/examples/TransactionManagerDemo.ts +0 -377
- package/template/src/framework/utils/dynamicSwagger.ts +0 -410
- package/template/src/repository/UserRepository.ts +0 -122
- package/template/src/service/paramValidateTest.service.ts +0 -139
- package/template/src/service/ytGoods.service.ts +0 -42
- package/template/src/service/ytShop.service.ts +0 -90
- package/template/src/service/ytUser.service.ts +0 -451
- package/template/src/test/swaggerParameterTest.ts +0 -90
- package/template/test/controllers/controllers.test.ts +0 -173
- package/template/test/controllers/example/NewAnnotationExampleController.test.ts +0 -200
- package/template/test/framework/TransactionManagerDemo.test.ts +0 -363
- package/template/test/service/business.test.ts +0 -87
- package/template/test/service/paramValidateTest.service.test.ts +0 -184
- package/template/test/service/ytUser.service.test.ts +0 -566
- package/template/yarn.lock +0 -7354
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AnnotationExecutor,
|
|
1
|
+
import { AnnotationExecutor, AnnotationProcessor } from '../../../src/framework/decorator/processor/AnnotationProcessor';
|
|
2
|
+
import { annotationRegistry } from '../../../src/framework/decorator/processor/AnnotationRegistry';
|
|
2
3
|
import { Context } from 'koa';
|
|
3
4
|
|
|
4
5
|
// 模拟 Koa Context
|
|
@@ -18,10 +19,14 @@ const createMockContext = (): Context => ({
|
|
|
18
19
|
|
|
19
20
|
// 测试用的注解处理器
|
|
20
21
|
class TestProcessor implements AnnotationProcessor {
|
|
21
|
-
readonly name
|
|
22
|
-
readonly priority
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly priority: number;
|
|
23
24
|
|
|
24
25
|
public processCallCount = 0;
|
|
26
|
+
constructor(name = 'TestProcessor', priority = 100) {
|
|
27
|
+
this.name = name;
|
|
28
|
+
this.priority = priority;
|
|
29
|
+
}
|
|
25
30
|
public lastAnnotationData: any = null;
|
|
26
31
|
public shouldReturn = true;
|
|
27
32
|
|
|
@@ -45,12 +50,12 @@ describe('注解执行器测试', () => {
|
|
|
45
50
|
beforeEach(() => {
|
|
46
51
|
testProcessor = new TestProcessor();
|
|
47
52
|
mockContext = createMockContext();
|
|
48
|
-
|
|
53
|
+
annotationRegistry.clear();
|
|
49
54
|
});
|
|
50
55
|
|
|
51
56
|
describe('AnnotationExecutor.execute', () => {
|
|
52
57
|
test('应该能够执行所有相关处理器', async () => {
|
|
53
|
-
|
|
58
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
54
59
|
|
|
55
60
|
const mockController = {
|
|
56
61
|
$_Annotations: new Map([
|
|
@@ -73,7 +78,7 @@ describe('注解执行器测试', () => {
|
|
|
73
78
|
});
|
|
74
79
|
|
|
75
80
|
test('应该跳过没有注解数据的方法', async () => {
|
|
76
|
-
|
|
81
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
77
82
|
|
|
78
83
|
const mockController = {
|
|
79
84
|
$_Annotations: new Map([
|
|
@@ -96,7 +101,7 @@ describe('注解执行器测试', () => {
|
|
|
96
101
|
|
|
97
102
|
test('处理器返回false应该中断执行', async () => {
|
|
98
103
|
testProcessor.shouldReturn = false;
|
|
99
|
-
|
|
104
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
100
105
|
|
|
101
106
|
const mockController = {
|
|
102
107
|
$_Annotations: new Map([
|
|
@@ -117,16 +122,11 @@ describe('注解执行器测试', () => {
|
|
|
117
122
|
});
|
|
118
123
|
|
|
119
124
|
test('应该支持多个处理器', async () => {
|
|
120
|
-
const processor1 = new TestProcessor();
|
|
121
|
-
|
|
122
|
-
processor1.priority = 50;
|
|
123
|
-
|
|
124
|
-
const processor2 = new TestProcessor();
|
|
125
|
-
processor2.name = 'Processor2';
|
|
126
|
-
processor2.priority = 100;
|
|
125
|
+
const processor1 = new TestProcessor('Processor1', 50);
|
|
126
|
+
const processor2 = new TestProcessor('Processor2', 100);
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
annotationRegistry.registerProcessor(processor1);
|
|
129
|
+
annotationRegistry.registerProcessor(processor2);
|
|
130
130
|
|
|
131
131
|
const mockController = {
|
|
132
132
|
$_Annotations: new Map([
|
|
@@ -154,24 +154,20 @@ describe('注解执行器测试', () => {
|
|
|
154
154
|
test('应该按优先级顺序执行处理器', async () => {
|
|
155
155
|
const executionOrder: string[] = [];
|
|
156
156
|
|
|
157
|
-
const processor1 = new TestProcessor();
|
|
158
|
-
processor1.name = 'Processor1';
|
|
159
|
-
processor1.priority = 100;
|
|
157
|
+
const processor1 = new TestProcessor('Processor1', 100);
|
|
160
158
|
processor1.process = jest.fn().mockImplementation(async () => {
|
|
161
159
|
executionOrder.push('Processor1');
|
|
162
160
|
return true;
|
|
163
161
|
});
|
|
164
162
|
|
|
165
|
-
const processor2 = new TestProcessor();
|
|
166
|
-
processor2.name = 'Processor2';
|
|
167
|
-
processor2.priority = 50;
|
|
163
|
+
const processor2 = new TestProcessor('Processor2', 50);
|
|
168
164
|
processor2.process = jest.fn().mockImplementation(async () => {
|
|
169
165
|
executionOrder.push('Processor2');
|
|
170
166
|
return true;
|
|
171
167
|
});
|
|
172
168
|
|
|
173
|
-
|
|
174
|
-
|
|
169
|
+
annotationRegistry.registerProcessor(processor1);
|
|
170
|
+
annotationRegistry.registerProcessor(processor2);
|
|
175
171
|
|
|
176
172
|
const mockController = {
|
|
177
173
|
$_Annotations: new Map([
|
|
@@ -193,7 +189,8 @@ describe('注解执行器测试', () => {
|
|
|
193
189
|
});
|
|
194
190
|
|
|
195
191
|
test('应该兼容旧的注解系统', async () => {
|
|
196
|
-
|
|
192
|
+
const legacyProcessor = new TestProcessor('ParameterValidation', 100);
|
|
193
|
+
annotationRegistry.registerProcessor(legacyProcessor);
|
|
197
194
|
|
|
198
195
|
const mockController = {
|
|
199
196
|
$_MethdosParamInfo: new Map([
|
|
@@ -209,19 +206,17 @@ describe('注解执行器测试', () => {
|
|
|
209
206
|
);
|
|
210
207
|
|
|
211
208
|
expect(result).toBe(true);
|
|
212
|
-
expect(
|
|
209
|
+
expect(legacyProcessor.processCallCount).toBe(1);
|
|
213
210
|
});
|
|
214
211
|
|
|
215
212
|
test('处理器抛出异常不应该中断执行', async () => {
|
|
216
|
-
const errorProcessor = new TestProcessor();
|
|
217
|
-
errorProcessor.name = 'ErrorProcessor';
|
|
213
|
+
const errorProcessor = new TestProcessor('ErrorProcessor', 100);
|
|
218
214
|
errorProcessor.process = jest.fn().mockRejectedValue(new Error('Test error'));
|
|
219
215
|
|
|
220
|
-
const normalProcessor = new TestProcessor();
|
|
221
|
-
normalProcessor.name = 'NormalProcessor';
|
|
216
|
+
const normalProcessor = new TestProcessor('NormalProcessor', 100);
|
|
222
217
|
|
|
223
|
-
|
|
224
|
-
|
|
218
|
+
annotationRegistry.registerProcessor(errorProcessor);
|
|
219
|
+
annotationRegistry.registerProcessor(normalProcessor);
|
|
225
220
|
|
|
226
221
|
const mockController = {
|
|
227
222
|
$_Annotations: new Map([
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AnnotationProcessor
|
|
1
|
+
import { AnnotationProcessor } from '../../../src/framework/decorator/processor/AnnotationProcessor';
|
|
2
|
+
import { annotationRegistry } from '../../../src/framework/decorator/processor/AnnotationRegistry';
|
|
2
3
|
import { Context } from 'koa';
|
|
3
4
|
|
|
4
5
|
// 模拟 Koa Context
|
|
@@ -72,14 +73,14 @@ describe('注解处理器系统测试', () => {
|
|
|
72
73
|
beforeEach(() => {
|
|
73
74
|
testProcessor = new TestProcessor();
|
|
74
75
|
mockContext = createMockContext();
|
|
75
|
-
|
|
76
|
+
annotationRegistry.clear();
|
|
76
77
|
});
|
|
77
78
|
|
|
78
|
-
describe('
|
|
79
|
+
describe('annotationRegistry', () => {
|
|
79
80
|
test('应该能够注册处理器', () => {
|
|
80
|
-
|
|
81
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
81
82
|
|
|
82
|
-
const retrievedProcessor =
|
|
83
|
+
const retrievedProcessor = annotationRegistry.getProcessor('TestProcessor');
|
|
83
84
|
expect(retrievedProcessor).toBe(testProcessor);
|
|
84
85
|
});
|
|
85
86
|
|
|
@@ -87,34 +88,34 @@ describe('注解处理器系统测试', () => {
|
|
|
87
88
|
const processor1 = new ConfigurableTestProcessor('Processor1', 50);
|
|
88
89
|
const processor2 = new ConfigurableTestProcessor('Processor2', 100);
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
annotationRegistry.registerProcessor(processor2);
|
|
92
|
+
annotationRegistry.registerProcessor(processor1);
|
|
92
93
|
|
|
93
|
-
const allProcessors =
|
|
94
|
+
const allProcessors = annotationRegistry.getAllProcessors();
|
|
94
95
|
expect(allProcessors).toHaveLength(2);
|
|
95
96
|
expect(allProcessors[0]).toBe(processor1); // 优先级高的在前面
|
|
96
97
|
expect(allProcessors[1]).toBe(processor2);
|
|
97
98
|
});
|
|
98
99
|
|
|
99
100
|
test('应该能够移除处理器', () => {
|
|
100
|
-
|
|
101
|
-
expect(
|
|
101
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
102
|
+
expect(annotationRegistry.getProcessor('TestProcessor')).toBe(testProcessor);
|
|
102
103
|
|
|
103
|
-
const removed =
|
|
104
|
+
const removed = annotationRegistry.unregisterProcessor('TestProcessor');
|
|
104
105
|
expect(removed).toBe(true);
|
|
105
|
-
expect(
|
|
106
|
+
expect(annotationRegistry.getProcessor('TestProcessor')).toBeUndefined();
|
|
106
107
|
});
|
|
107
108
|
|
|
108
109
|
test('应该能够清空所有处理器', () => {
|
|
109
|
-
|
|
110
|
-
expect(
|
|
110
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
111
|
+
expect(annotationRegistry.getAllProcessors()).toHaveLength(1);
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
expect(
|
|
113
|
+
annotationRegistry.clear();
|
|
114
|
+
expect(annotationRegistry.getAllProcessors()).toHaveLength(0);
|
|
114
115
|
});
|
|
115
116
|
|
|
116
117
|
test('移除不存在的处理器应该返回false', () => {
|
|
117
|
-
const removed =
|
|
118
|
+
const removed = annotationRegistry.unregisterProcessor('NonExistentProcessor');
|
|
118
119
|
expect(removed).toBe(false);
|
|
119
120
|
});
|
|
120
121
|
});
|
|
@@ -125,11 +126,11 @@ describe('注解处理器系统测试', () => {
|
|
|
125
126
|
const processor2 = new ConfigurableTestProcessor('Processor2', 50);
|
|
126
127
|
const processor3 = new ConfigurableTestProcessor('Processor3', 100);
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
annotationRegistry.registerProcessor(processor1);
|
|
130
|
+
annotationRegistry.registerProcessor(processor2);
|
|
131
|
+
annotationRegistry.registerProcessor(processor3);
|
|
131
132
|
|
|
132
|
-
const allProcessors =
|
|
133
|
+
const allProcessors = annotationRegistry.getAllProcessors();
|
|
133
134
|
expect(allProcessors[0]).toBe(processor2); // 优先级 50
|
|
134
135
|
expect(allProcessors[1]).toBe(processor3); // 优先级 100
|
|
135
136
|
expect(allProcessors[2]).toBe(processor1); // 优先级 200
|
|
@@ -138,7 +139,7 @@ describe('注解处理器系统测试', () => {
|
|
|
138
139
|
|
|
139
140
|
describe('处理器执行', () => {
|
|
140
141
|
test('应该能够执行处理器', async () => {
|
|
141
|
-
|
|
142
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
142
143
|
|
|
143
144
|
const mockController = {
|
|
144
145
|
$_Annotations: new Map([
|
|
@@ -148,7 +149,7 @@ describe('注解处理器系统测试', () => {
|
|
|
148
149
|
])
|
|
149
150
|
};
|
|
150
151
|
|
|
151
|
-
const result = await
|
|
152
|
+
const result = await annotationRegistry.getAllProcessors()[0].process(
|
|
152
153
|
mockContext,
|
|
153
154
|
mockController,
|
|
154
155
|
'testMethod',
|
|
@@ -163,7 +164,7 @@ describe('注解处理器系统测试', () => {
|
|
|
163
164
|
|
|
164
165
|
test('处理器返回false应该中断执行', async () => {
|
|
165
166
|
testProcessor.shouldReturn = false;
|
|
166
|
-
|
|
167
|
+
annotationRegistry.registerProcessor(testProcessor);
|
|
167
168
|
|
|
168
169
|
const result = await testProcessor.process(
|
|
169
170
|
mockContext,
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { LoggingProcessor, PermissionProcessor, RateLimitProcessor } from '../../../src/framework/decorator/processor/processors/CustomProcessors';
|
|
2
2
|
import { Context } from 'koa';
|
|
3
3
|
|
|
4
|
+
jest.mock('@src/framework/utils/logger', () => ({
|
|
5
|
+
logger: {
|
|
6
|
+
debug: jest.fn(),
|
|
7
|
+
}
|
|
8
|
+
}));
|
|
9
|
+
|
|
4
10
|
// 模拟 Koa Context
|
|
5
11
|
const createMockContext = (): Context => ({
|
|
6
12
|
status: 200,
|
|
@@ -23,12 +29,6 @@ describe('自定义处理器测试', () => {
|
|
|
23
29
|
beforeEach(() => {
|
|
24
30
|
mockContext = createMockContext();
|
|
25
31
|
jest.clearAllMocks();
|
|
26
|
-
// 清空控制台输出
|
|
27
|
-
jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
jest.restoreAllMocks();
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
describe('LoggingProcessor', () => {
|
|
@@ -57,36 +57,26 @@ describe('自定义处理器测试', () => {
|
|
|
57
57
|
);
|
|
58
58
|
|
|
59
59
|
expect(result).toBe(true);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
);
|
|
63
|
-
expect(console.log).toHaveBeenCalledWith(
|
|
64
|
-
'[Logging] 请求参数:',
|
|
65
|
-
[{ id: 1 }]
|
|
66
|
-
);
|
|
60
|
+
const { logger } = require('@src/framework/utils/logger');
|
|
61
|
+
expect(logger.debug).toHaveBeenCalledWith('[Logging] 开始处理请求: TestController.testMethod');
|
|
62
|
+
expect(logger.debug).toHaveBeenCalledWith('[Logging] 请求参数:', [{ id: 1 }]);
|
|
67
63
|
expect(mockContext.state.loggingStartTime).toBeDefined();
|
|
68
64
|
});
|
|
69
65
|
|
|
70
|
-
test('logResponse
|
|
66
|
+
test('logResponse实例方法应该记录响应日志', async () => {
|
|
71
67
|
mockContext.state.loggingStartTime = Date.now() - 100; // 100ms前
|
|
72
68
|
|
|
73
|
-
|
|
69
|
+
await processor.logResponse(
|
|
74
70
|
mockContext,
|
|
75
71
|
{ constructor: { name: 'TestController' } },
|
|
76
72
|
'testMethod',
|
|
77
73
|
{ data: 'test' }
|
|
78
74
|
);
|
|
79
75
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
);
|
|
83
|
-
expect(
|
|
84
|
-
'[Logging] 响应数据:',
|
|
85
|
-
{ data: 'test' }
|
|
86
|
-
);
|
|
87
|
-
expect(console.log).toHaveBeenCalledWith(
|
|
88
|
-
expect.stringMatching(/\[Logging\] 处理耗时: \d+ms/)
|
|
89
|
-
);
|
|
76
|
+
const { logger } = require('@src/framework/utils/logger');
|
|
77
|
+
expect(logger.debug).toHaveBeenCalledWith('[Logging] 完成处理请求: TestController.testMethod');
|
|
78
|
+
expect(logger.debug).toHaveBeenCalledWith('[Logging] 响应数据:', { data: 'test' });
|
|
79
|
+
expect(logger.debug).toHaveBeenCalledWith(expect.stringMatching(/\[Logging\] 处理耗时: \d+ms/));
|
|
90
80
|
});
|
|
91
81
|
});
|
|
92
82
|
|
|
@@ -7,6 +7,7 @@ import { Context } from 'koa';
|
|
|
7
7
|
const createMockContext = (): Context => ({
|
|
8
8
|
status: 200,
|
|
9
9
|
body: null,
|
|
10
|
+
query: { id: '123' },
|
|
10
11
|
request: {
|
|
11
12
|
body: { name: 'test' },
|
|
12
13
|
headers: { 'content-type': 'application/json' },
|
|
@@ -37,6 +38,9 @@ jest.mock('../../../src/framework/utils/cache', () => ({
|
|
|
37
38
|
// 模拟日志
|
|
38
39
|
jest.mock('../../../src/framework/utils/logger', () => ({
|
|
39
40
|
logger: {
|
|
41
|
+
info: jest.fn(),
|
|
42
|
+
warn: jest.fn(),
|
|
43
|
+
debug: jest.fn(),
|
|
40
44
|
error: jest.fn()
|
|
41
45
|
}
|
|
42
46
|
}));
|
|
@@ -137,7 +141,7 @@ describe('新路由系统集成测试', () => {
|
|
|
137
141
|
await callControllerWithProcessors(mockContext, mockController, 'testMethod');
|
|
138
142
|
|
|
139
143
|
expect(mockContext.status).toBe(400);
|
|
140
|
-
expect(mockContext.body).
|
|
144
|
+
expect(mockContext.body).toEqual({ data: '' });
|
|
141
145
|
});
|
|
142
146
|
|
|
143
147
|
test('应该能够处理缓存注解', async () => {
|
|
@@ -211,9 +215,8 @@ describe('新路由系统集成测试', () => {
|
|
|
211
215
|
|
|
212
216
|
await callControllerWithProcessors(mockContext, mockController, 'testMethod');
|
|
213
217
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
);
|
|
218
|
+
const { logger } = require('../../../src/framework/utils/logger');
|
|
219
|
+
expect(logger.debug).toHaveBeenCalled();
|
|
217
220
|
expect(mockContext.body).toEqual({ data: 'test' });
|
|
218
221
|
});
|
|
219
222
|
|
|
@@ -260,9 +263,8 @@ describe('新路由系统集成测试', () => {
|
|
|
260
263
|
|
|
261
264
|
await callControllerWithProcessors(mockContext, mockController, 'testMethod');
|
|
262
265
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
);
|
|
266
|
+
const { logger } = require('../../../src/framework/utils/logger');
|
|
267
|
+
expect(logger.debug).toHaveBeenCalled();
|
|
266
268
|
expect(mockController.testMethod).toHaveBeenCalled();
|
|
267
269
|
expect(mockContext.status).toBe(200);
|
|
268
270
|
expect(mockContext.set).toHaveBeenCalledWith('Content-Type', 'application/json');
|
|
@@ -11,8 +11,13 @@ import { LoggingProcessor, PermissionProcessor, RateLimitProcessor } from '../..
|
|
|
11
11
|
|
|
12
12
|
// 测试用的注解处理器
|
|
13
13
|
class TestProcessor implements AnnotationProcessor {
|
|
14
|
-
readonly name
|
|
15
|
-
readonly priority
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly priority: number;
|
|
16
|
+
|
|
17
|
+
constructor(name = 'TestProcessor', priority = 100) {
|
|
18
|
+
this.name = name;
|
|
19
|
+
this.priority = priority;
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
async process(): Promise<boolean> {
|
|
18
23
|
return true;
|
|
@@ -59,13 +64,8 @@ describe('处理器管理器测试', () => {
|
|
|
59
64
|
});
|
|
60
65
|
|
|
61
66
|
test('应该能够获取所有处理器', () => {
|
|
62
|
-
const processor1 = new TestProcessor();
|
|
63
|
-
|
|
64
|
-
processor1.priority = 50;
|
|
65
|
-
|
|
66
|
-
const processor2 = new TestProcessor();
|
|
67
|
-
processor2.name = 'Processor2';
|
|
68
|
-
processor2.priority = 100;
|
|
67
|
+
const processor1 = new TestProcessor('Processor1', 50);
|
|
68
|
+
const processor2 = new TestProcessor('Processor2', 100);
|
|
69
69
|
|
|
70
70
|
ProcessorManager.registerProcessor(processor1);
|
|
71
71
|
ProcessorManager.registerProcessor(processor2);
|
|
@@ -195,17 +195,9 @@ describe('处理器管理器测试', () => {
|
|
|
195
195
|
|
|
196
196
|
describe('处理器优先级', () => {
|
|
197
197
|
test('应该按优先级排序所有处理器', () => {
|
|
198
|
-
const processor1 = new TestProcessor();
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const processor2 = new TestProcessor();
|
|
203
|
-
processor2.name = 'Processor2';
|
|
204
|
-
processor2.priority = 50;
|
|
205
|
-
|
|
206
|
-
const processor3 = new TestProcessor();
|
|
207
|
-
processor3.name = 'Processor3';
|
|
208
|
-
processor3.priority = 100;
|
|
198
|
+
const processor1 = new TestProcessor('Processor1', 200);
|
|
199
|
+
const processor2 = new TestProcessor('Processor2', 50);
|
|
200
|
+
const processor3 = new TestProcessor('Processor3', 100);
|
|
209
201
|
|
|
210
202
|
ProcessorManager.registerProcessor(processor1);
|
|
211
203
|
ProcessorManager.registerProcessor(processor2);
|
|
@@ -230,13 +222,8 @@ describe('处理器管理器测试', () => {
|
|
|
230
222
|
|
|
231
223
|
describe('处理器覆盖', () => {
|
|
232
224
|
test('注册同名处理器应该覆盖原有处理器', () => {
|
|
233
|
-
const processor1 = new TestProcessor();
|
|
234
|
-
|
|
235
|
-
processor1.priority = 100;
|
|
236
|
-
|
|
237
|
-
const processor2 = new TestProcessor();
|
|
238
|
-
processor2.name = 'TestProcessor';
|
|
239
|
-
processor2.priority = 200;
|
|
225
|
+
const processor1 = new TestProcessor('TestProcessor', 100);
|
|
226
|
+
const processor2 = new TestProcessor('TestProcessor', 200);
|
|
240
227
|
|
|
241
228
|
ProcessorManager.registerProcessor(processor1);
|
|
242
229
|
expect(ProcessorManager.getProcessor('TestProcessor')).toBe(processor1);
|
|
@@ -65,7 +65,7 @@ describe('数据库配置管理测试', () => {
|
|
|
65
65
|
expect((config as any).password).toBe('testpass');
|
|
66
66
|
expect((config as any).database).toBe('testdb');
|
|
67
67
|
expect(config.entities).toEqual(entities);
|
|
68
|
-
expect(config.synchronize).toBe(
|
|
68
|
+
expect(config.synchronize).toBe(false);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
test('应该生成 MySQL 数据库配置', () => {
|
|
@@ -87,7 +87,7 @@ describe('数据库配置管理测试', () => {
|
|
|
87
87
|
expect((config as any).password).toBe('testpass');
|
|
88
88
|
expect((config as any).database).toBe('testdb');
|
|
89
89
|
expect(config.entities).toEqual(entities);
|
|
90
|
-
expect(config.synchronize).toBe(
|
|
90
|
+
expect(config.synchronize).toBe(false);
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
test('应该使用默认 PostgreSQL 配置(未设置 db_type 时)', () => {
|
|
@@ -16,62 +16,17 @@ describe('集成测试', () => {
|
|
|
16
16
|
|
|
17
17
|
const dataSource = TestDatabaseHelper.getTestDataSource();
|
|
18
18
|
expect(dataSource).toBeDefined();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const users = await dataSource!.query('SELECT * FROM yt_user');
|
|
22
|
-
expect(users.length).toBeGreaterThan(0);
|
|
23
|
-
expect(users[0].nickName).toBe('测试用户1');
|
|
24
|
-
|
|
25
|
-
// 检查店铺数据
|
|
26
|
-
const shops = await dataSource!.query('SELECT * FROM shop');
|
|
27
|
-
expect(shops.length).toBeGreaterThan(0);
|
|
28
|
-
expect(shops[0].name).toBe('测试店铺1');
|
|
29
|
-
|
|
30
|
-
// 检查商品数据
|
|
31
|
-
const goods = await dataSource!.query('SELECT * FROM yt_goods');
|
|
32
|
-
expect(goods.length).toBeGreaterThan(0);
|
|
33
|
-
expect(goods[0].name).toBe('测试商品1');
|
|
34
|
-
|
|
35
|
-
// 检查解锁密钥数据
|
|
36
|
-
const unlockKeys = await dataSource!.query('SELECT * FROM goods_images_unlock_key');
|
|
37
|
-
expect(unlockKeys.length).toBeGreaterThan(0);
|
|
38
|
-
expect(unlockKeys[0].key).toBe('TEST_KEY_001');
|
|
19
|
+
// 精简模式下仅保证初始化调用可执行
|
|
20
|
+
await expect(testDataInitializer.initializeTestData()).resolves.toBeUndefined();
|
|
39
21
|
});
|
|
40
22
|
|
|
41
23
|
test('应该能够清空测试数据', async () => {
|
|
42
|
-
await testDataInitializer.clearTestData();
|
|
43
|
-
|
|
44
|
-
const dataSource = TestDatabaseHelper.getTestDataSource();
|
|
45
|
-
|
|
46
|
-
// 检查所有表都应该为空
|
|
47
|
-
const users = await dataSource!.query('SELECT COUNT(*) as count FROM yt_user');
|
|
48
|
-
const shops = await dataSource!.query('SELECT COUNT(*) as count FROM shop');
|
|
49
|
-
const goods = await dataSource!.query('SELECT COUNT(*) as count FROM yt_goods');
|
|
50
|
-
const unlockKeys = await dataSource!.query('SELECT COUNT(*) as count FROM goods_images_unlock_key');
|
|
51
|
-
|
|
52
|
-
expect(users[0].count).toBe(0);
|
|
53
|
-
expect(shops[0].count).toBe(0);
|
|
54
|
-
expect(goods[0].count).toBe(0);
|
|
55
|
-
expect(unlockKeys[0].count).toBe(0);
|
|
24
|
+
await expect(testDataInitializer.clearTestData()).resolves.toBeUndefined();
|
|
56
25
|
});
|
|
57
26
|
|
|
58
27
|
test('应该能够重新初始化测试数据', async () => {
|
|
59
|
-
// 先清空
|
|
60
28
|
await testDataInitializer.clearTestData();
|
|
61
|
-
|
|
62
|
-
// 再初始化
|
|
63
|
-
await testDataInitializer.initializeTestData();
|
|
64
|
-
|
|
65
|
-
const dataSource = TestDatabaseHelper.getTestDataSource();
|
|
66
|
-
|
|
67
|
-
// 检查数据是否重新创建
|
|
68
|
-
const users = await dataSource!.query('SELECT COUNT(*) as count FROM yt_user');
|
|
69
|
-
const shops = await dataSource!.query('SELECT COUNT(*) as count FROM shop');
|
|
70
|
-
const goods = await dataSource!.query('SELECT COUNT(*) as count FROM yt_goods');
|
|
71
|
-
|
|
72
|
-
expect(users[0].count).toBeGreaterThan(0);
|
|
73
|
-
expect(shops[0].count).toBeGreaterThan(0);
|
|
74
|
-
expect(goods[0].count).toBeGreaterThan(0);
|
|
29
|
+
await expect(testDataInitializer.initializeTestData()).resolves.toBeUndefined();
|
|
75
30
|
});
|
|
76
31
|
});
|
|
77
32
|
|
|
@@ -91,22 +46,14 @@ describe('集成测试', () => {
|
|
|
91
46
|
|
|
92
47
|
test('应该能够执行复杂查询', async () => {
|
|
93
48
|
const dataSource = TestDatabaseHelper.getTestDataSource();
|
|
94
|
-
|
|
95
|
-
// 查询用户和店铺的关联信息
|
|
96
49
|
const result = await dataSource!.query(`
|
|
97
|
-
SELECT
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
FROM yt_user u
|
|
101
|
-
JOIN shop_and_user su ON u.id = su.userId
|
|
102
|
-
JOIN shop s ON su.shopId = s.id
|
|
103
|
-
WHERE u.id = 1
|
|
50
|
+
SELECT name
|
|
51
|
+
FROM sqlite_master
|
|
52
|
+
WHERE type = 'table'
|
|
104
53
|
`);
|
|
105
54
|
|
|
106
55
|
expect(result).toBeDefined();
|
|
107
|
-
expect(result
|
|
108
|
-
expect(result[0].nickName).toBe('测试用户1');
|
|
109
|
-
expect(result[0].shopName).toBe('测试店铺1');
|
|
56
|
+
expect(Array.isArray(result)).toBe(true);
|
|
110
57
|
});
|
|
111
58
|
});
|
|
112
59
|
|
|
@@ -115,19 +62,15 @@ describe('集成测试', () => {
|
|
|
115
62
|
const { createCache, CacheType } = require('../../src/framework/utils/cache');
|
|
116
63
|
const cache = createCache('integration-test', CacheType.TEMP);
|
|
117
64
|
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// 将数据存入缓存
|
|
123
|
-
const cacheKey = `user_${users[0].id}`;
|
|
124
|
-
cache.set(cacheKey, users[0]);
|
|
65
|
+
const payload = { id: 1, nickName: 'cache-user' };
|
|
66
|
+
const cacheKey = `user_${payload.id}`;
|
|
67
|
+
cache.set(cacheKey, payload);
|
|
125
68
|
|
|
126
69
|
// 从缓存获取数据
|
|
127
70
|
const cachedUser = cache.get(cacheKey);
|
|
128
71
|
expect(cachedUser).toBeDefined();
|
|
129
|
-
expect(cachedUser.id).toBe(
|
|
130
|
-
expect(cachedUser.nickName).toBe(
|
|
72
|
+
expect(cachedUser.id).toBe(payload.id);
|
|
73
|
+
expect(cachedUser.nickName).toBe(payload.nickName);
|
|
131
74
|
});
|
|
132
75
|
});
|
|
133
76
|
|
|
@@ -144,9 +87,9 @@ describe('集成测试', () => {
|
|
|
144
87
|
test('应该能够处理无效的数据操作', async () => {
|
|
145
88
|
const dataSource = TestDatabaseHelper.getTestDataSource();
|
|
146
89
|
|
|
147
|
-
//
|
|
90
|
+
// sqlite 系统表写入应失败
|
|
148
91
|
await expect(
|
|
149
|
-
dataSource!.query('INSERT INTO
|
|
92
|
+
dataSource!.query('INSERT INTO sqlite_master (name) VALUES (?)', ['test'])
|
|
150
93
|
).rejects.toThrow();
|
|
151
94
|
});
|
|
152
95
|
});
|
|
@@ -39,6 +39,8 @@ module.exports = {
|
|
|
39
39
|
})
|
|
40
40
|
],
|
|
41
41
|
externals: {
|
|
42
|
+
"dp-koa-framework-core": "commonjs dp-koa-framework-core",
|
|
43
|
+
"dp-koa-framework-libs": "commonjs dp-koa-framework-libs",
|
|
42
44
|
'express': 'commonjs express',
|
|
43
45
|
'koa-router': 'commonjs koa-router',
|
|
44
46
|
'koa': 'commonjs koa',
|