@eggjs/mock 6.0.7 → 6.1.0-beta.2
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/README.md +35 -56
- package/README.zh_CN.md +30 -50
- package/dist/_virtual/rolldown_runtime.js +7 -0
- package/dist/app/extend/agent.d.ts +39 -0
- package/dist/app/extend/agent.js +48 -0
- package/dist/app/extend/application.d.ts +176 -0
- package/dist/app/extend/application.js +385 -0
- package/dist/app/middleware/cluster_app_mock.d.ts +6 -0
- package/dist/app/middleware/cluster_app_mock.js +97 -0
- package/dist/app.d.ts +10 -0
- package/dist/app.js +17 -0
- package/dist/bootstrap.d.ts +9 -0
- package/dist/bootstrap.js +14 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +48 -0
- package/dist/lib/agent_handler.d.ts +7 -0
- package/dist/lib/agent_handler.js +26 -0
- package/dist/lib/app.d.ts +7 -0
- package/dist/lib/app.js +251 -0
- package/dist/lib/app_handler.d.ts +9 -0
- package/dist/lib/app_handler.js +56 -0
- package/dist/lib/cluster.d.ts +126 -0
- package/dist/lib/cluster.js +283 -0
- package/dist/lib/context.d.ts +4 -0
- package/dist/lib/context.js +13 -0
- package/dist/lib/format_options.d.ts +10 -0
- package/dist/lib/format_options.js +65 -0
- package/dist/lib/inject_context.d.ts +9 -0
- package/dist/lib/inject_context.js +106 -0
- package/dist/lib/mock_agent.d.ts +9 -0
- package/dist/lib/mock_agent.js +45 -0
- package/dist/lib/mock_custom_loader.d.ts +4 -0
- package/dist/lib/mock_custom_loader.js +35 -0
- package/dist/lib/mock_http_server.d.ts +6 -0
- package/dist/lib/mock_http_server.js +17 -0
- package/dist/lib/mock_httpclient.d.ts +40 -0
- package/dist/lib/mock_httpclient.js +110 -0
- package/dist/lib/parallel/agent.d.ts +24 -0
- package/dist/lib/parallel/agent.js +111 -0
- package/dist/lib/parallel/app.d.ts +24 -0
- package/dist/lib/parallel/app.js +98 -0
- package/dist/lib/parallel/util.d.ts +6 -0
- package/dist/lib/parallel/util.js +59 -0
- package/dist/lib/prerequire.d.ts +1 -0
- package/dist/lib/prerequire.js +1 -0
- package/dist/lib/request_call_function.d.ts +1 -0
- package/dist/lib/request_call_function.js +37 -0
- package/dist/lib/restore.d.ts +4 -0
- package/dist/lib/restore.js +16 -0
- package/dist/{commonjs/lib → lib}/start-cluster.d.ts +1 -1
- package/dist/lib/start-cluster.js +19 -0
- package/dist/lib/supertest.d.ts +16 -0
- package/dist/lib/supertest.js +39 -0
- package/dist/lib/tmp/empty.d.ts +1 -0
- package/dist/lib/tmp/empty.js +1 -0
- package/{src/lib/types.ts → dist/lib/types.d.ts} +12 -29
- package/dist/lib/types.js +1 -0
- package/dist/lib/utils.d.ts +12 -0
- package/dist/lib/utils.js +40 -0
- package/dist/register.d.ts +12 -0
- package/dist/register.js +65 -0
- package/dist/typings/index.d.ts +1 -0
- package/package.json +68 -100
- package/dist/commonjs/app/extend/agent.d.ts +0 -34
- package/dist/commonjs/app/extend/agent.js +0 -49
- package/dist/commonjs/app/extend/application.d.ts +0 -172
- package/dist/commonjs/app/extend/application.js +0 -450
- package/dist/commonjs/app/middleware/cluster_app_mock.d.ts +0 -3
- package/dist/commonjs/app/middleware/cluster_app_mock.js +0 -101
- package/dist/commonjs/app.d.ts +0 -6
- package/dist/commonjs/app.js +0 -20
- package/dist/commonjs/bootstrap.d.ts +0 -5
- package/dist/commonjs/bootstrap.js +0 -59
- package/dist/commonjs/index.d.ts +0 -77
- package/dist/commonjs/index.js +0 -114
- package/dist/commonjs/lib/agent_handler.d.ts +0 -3
- package/dist/commonjs/lib/agent_handler.js +0 -28
- package/dist/commonjs/lib/app.d.ts +0 -3
- package/dist/commonjs/lib/app.js +0 -301
- package/dist/commonjs/lib/app_handler.d.ts +0 -5
- package/dist/commonjs/lib/app_handler.js +0 -71
- package/dist/commonjs/lib/cluster.d.ts +0 -114
- package/dist/commonjs/lib/cluster.js +0 -337
- package/dist/commonjs/lib/context.d.ts +0 -1
- package/dist/commonjs/lib/context.js +0 -16
- package/dist/commonjs/lib/format_options.d.ts +0 -5
- package/dist/commonjs/lib/format_options.js +0 -100
- package/dist/commonjs/lib/inject_context.d.ts +0 -6
- package/dist/commonjs/lib/inject_context.js +0 -132
- package/dist/commonjs/lib/mock_agent.d.ts +0 -5
- package/dist/commonjs/lib/mock_agent.js +0 -49
- package/dist/commonjs/lib/mock_custom_loader.d.ts +0 -1
- package/dist/commonjs/lib/mock_custom_loader.js +0 -37
- package/dist/commonjs/lib/mock_http_server.d.ts +0 -2
- package/dist/commonjs/lib/mock_http_server.js +0 -24
- package/dist/commonjs/lib/mock_httpclient.d.ts +0 -36
- package/dist/commonjs/lib/mock_httpclient.js +0 -147
- package/dist/commonjs/lib/parallel/agent.d.ts +0 -20
- package/dist/commonjs/lib/parallel/agent.js +0 -125
- package/dist/commonjs/lib/parallel/app.d.ts +0 -20
- package/dist/commonjs/lib/parallel/app.js +0 -115
- package/dist/commonjs/lib/parallel/util.d.ts +0 -3
- package/dist/commonjs/lib/parallel/util.js +0 -77
- package/dist/commonjs/lib/prerequire.d.ts +0 -1
- package/dist/commonjs/lib/prerequire.js +0 -26
- package/dist/commonjs/lib/request_call_function.d.ts +0 -1
- package/dist/commonjs/lib/request_call_function.js +0 -52
- package/dist/commonjs/lib/restore.d.ts +0 -1
- package/dist/commonjs/lib/restore.js +0 -16
- package/dist/commonjs/lib/start-cluster.js +0 -23
- package/dist/commonjs/lib/supertest.d.ts +0 -11
- package/dist/commonjs/lib/supertest.js +0 -48
- package/dist/commonjs/lib/tmp/empty.d.ts +0 -1
- package/dist/commonjs/lib/tmp/empty.js +0 -3
- package/dist/commonjs/lib/types.d.ts +0 -68
- package/dist/commonjs/lib/types.js +0 -3
- package/dist/commonjs/lib/utils.d.ts +0 -9
- package/dist/commonjs/lib/utils.js +0 -80
- package/dist/commonjs/package.json +0 -3
- package/dist/commonjs/register.d.ts +0 -8
- package/dist/commonjs/register.js +0 -80
- package/dist/esm/app/extend/agent.d.ts +0 -34
- package/dist/esm/app/extend/agent.js +0 -46
- package/dist/esm/app/extend/application.d.ts +0 -172
- package/dist/esm/app/extend/application.js +0 -444
- package/dist/esm/app/middleware/cluster_app_mock.d.ts +0 -3
- package/dist/esm/app/middleware/cluster_app_mock.js +0 -99
- package/dist/esm/app.d.ts +0 -6
- package/dist/esm/app.js +0 -17
- package/dist/esm/bootstrap.d.ts +0 -5
- package/dist/esm/bootstrap.js +0 -15
- package/dist/esm/index.d.ts +0 -77
- package/dist/esm/index.js +0 -91
- package/dist/esm/lib/agent_handler.d.ts +0 -3
- package/dist/esm/lib/agent_handler.js +0 -24
- package/dist/esm/lib/app.d.ts +0 -3
- package/dist/esm/lib/app.js +0 -295
- package/dist/esm/lib/app_handler.d.ts +0 -5
- package/dist/esm/lib/app_handler.js +0 -65
- package/dist/esm/lib/cluster.d.ts +0 -114
- package/dist/esm/lib/cluster.js +0 -328
- package/dist/esm/lib/context.d.ts +0 -1
- package/dist/esm/lib/context.js +0 -13
- package/dist/esm/lib/format_options.d.ts +0 -5
- package/dist/esm/lib/format_options.js +0 -94
- package/dist/esm/lib/inject_context.d.ts +0 -6
- package/dist/esm/lib/inject_context.js +0 -126
- package/dist/esm/lib/mock_agent.d.ts +0 -5
- package/dist/esm/lib/mock_agent.js +0 -45
- package/dist/esm/lib/mock_custom_loader.d.ts +0 -1
- package/dist/esm/lib/mock_custom_loader.js +0 -34
- package/dist/esm/lib/mock_http_server.d.ts +0 -2
- package/dist/esm/lib/mock_http_server.js +0 -18
- package/dist/esm/lib/mock_httpclient.d.ts +0 -36
- package/dist/esm/lib/mock_httpclient.js +0 -144
- package/dist/esm/lib/parallel/agent.d.ts +0 -20
- package/dist/esm/lib/parallel/agent.js +0 -117
- package/dist/esm/lib/parallel/app.d.ts +0 -20
- package/dist/esm/lib/parallel/app.js +0 -110
- package/dist/esm/lib/parallel/util.d.ts +0 -3
- package/dist/esm/lib/parallel/util.js +0 -73
- package/dist/esm/lib/prerequire.d.ts +0 -1
- package/dist/esm/lib/prerequire.js +0 -25
- package/dist/esm/lib/request_call_function.d.ts +0 -1
- package/dist/esm/lib/request_call_function.js +0 -47
- package/dist/esm/lib/restore.d.ts +0 -1
- package/dist/esm/lib/restore.js +0 -13
- package/dist/esm/lib/start-cluster.d.ts +0 -2
- package/dist/esm/lib/start-cluster.js +0 -18
- package/dist/esm/lib/supertest.d.ts +0 -11
- package/dist/esm/lib/supertest.js +0 -40
- package/dist/esm/lib/tmp/empty.d.ts +0 -1
- package/dist/esm/lib/tmp/empty.js +0 -2
- package/dist/esm/lib/types.d.ts +0 -68
- package/dist/esm/lib/types.js +0 -2
- package/dist/esm/lib/utils.d.ts +0 -9
- package/dist/esm/lib/utils.js +0 -69
- package/dist/esm/package.json +0 -3
- package/dist/esm/register.d.ts +0 -8
- package/dist/esm/register.js +0 -75
- package/dist/package.json +0 -4
- package/src/app/extend/agent.ts +0 -57
- package/src/app/extend/application.ts +0 -512
- package/src/app/middleware/cluster_app_mock.ts +0 -102
- package/src/app.ts +0 -18
- package/src/bootstrap.ts +0 -25
- package/src/index.ts +0 -112
- package/src/lib/agent_handler.ts +0 -28
- package/src/lib/app.ts +0 -314
- package/src/lib/app_handler.ts +0 -77
- package/src/lib/cluster.ts +0 -363
- package/src/lib/context.ts +0 -14
- package/src/lib/format_options.ts +0 -103
- package/src/lib/inject_context.ts +0 -134
- package/src/lib/mock_agent.ts +0 -57
- package/src/lib/mock_custom_loader.ts +0 -36
- package/src/lib/mock_http_server.ts +0 -19
- package/src/lib/mock_httpclient.ts +0 -183
- package/src/lib/parallel/agent.ts +0 -128
- package/src/lib/parallel/app.ts +0 -123
- package/src/lib/parallel/util.ts +0 -66
- package/src/lib/prerequire.ts +0 -25
- package/src/lib/request_call_function.ts +0 -49
- package/src/lib/restore.ts +0 -14
- package/src/lib/start-cluster.ts +0 -23
- package/src/lib/supertest.ts +0 -45
- package/src/lib/tmp/.gitkeep +0 -0
- package/src/lib/tmp/empty.ts +0 -0
- package/src/lib/utils.ts +0 -82
- package/src/register.ts +0 -80
- package/src/typings/index.d.ts +0 -4
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage } from 'node:http';
|
|
2
|
-
import { mock } from 'mm';
|
|
3
|
-
import type { HttpClient } from 'urllib';
|
|
4
|
-
import { Logger } from 'egg-logger';
|
|
5
|
-
import { EggCore, type EggCoreOptions, type Context as EggCoreContext } from '@eggjs/core';
|
|
6
|
-
import type { Context as EggContext } from 'egg';
|
|
7
|
-
import { MockResultFunction, MockResultOptions, MockHttpClientMethod } from '../../lib/mock_httpclient.js';
|
|
8
|
-
import { EggTestRequest } from '../../lib/supertest.js';
|
|
9
|
-
import { MockOptions } from '../../lib/types.js';
|
|
10
|
-
export interface MockContextOptions {
|
|
11
|
-
/**
|
|
12
|
-
* mock ctxStorage or not, default is `true`
|
|
13
|
-
*/
|
|
14
|
-
mockCtxStorage?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
* reuse ctxStorage or not, default is `true`
|
|
17
|
-
*/
|
|
18
|
-
reuseCtxStorage?: boolean;
|
|
19
|
-
}
|
|
20
|
-
export interface MockContextData {
|
|
21
|
-
headers?: Record<string, string | string[]>;
|
|
22
|
-
[key: string]: any;
|
|
23
|
-
}
|
|
24
|
-
export interface MockContext extends EggContext, EggCoreContext {
|
|
25
|
-
service: any;
|
|
26
|
-
}
|
|
27
|
-
export default abstract class ApplicationUnittest extends EggCore {
|
|
28
|
-
[key: string]: any;
|
|
29
|
-
options: MockOptions & EggCoreOptions;
|
|
30
|
-
_mockHttpClient?: MockHttpClientMethod;
|
|
31
|
-
httpclient: HttpClient;
|
|
32
|
-
/**
|
|
33
|
-
* mock Context
|
|
34
|
-
* @function App#mockContext
|
|
35
|
-
* @param {Object} data - ctx data
|
|
36
|
-
* @param {Object} [options] - mock ctx options
|
|
37
|
-
* @example
|
|
38
|
-
* ```js
|
|
39
|
-
* const ctx = app.mockContext({
|
|
40
|
-
* user: {
|
|
41
|
-
* name: 'Jason'
|
|
42
|
-
* }
|
|
43
|
-
* });
|
|
44
|
-
* console.log(ctx.user.name); // Jason
|
|
45
|
-
*
|
|
46
|
-
* // controller
|
|
47
|
-
* module.exports = function*() {
|
|
48
|
-
* this.body = this.user.name;
|
|
49
|
-
* };
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
mockContext(data?: MockContextData, options?: MockContextOptions): MockContext;
|
|
53
|
-
mockContextScope(fn: (ctx?: MockContext) => Promise<any>, data?: MockContextData): Promise<any>;
|
|
54
|
-
/**
|
|
55
|
-
* mock cookie session
|
|
56
|
-
* @function App#mockSession
|
|
57
|
-
* @param {Object} data - session object
|
|
58
|
-
*/
|
|
59
|
-
mockSession(data: any): this;
|
|
60
|
-
/**
|
|
61
|
-
* Mock service
|
|
62
|
-
* @function App#mockService
|
|
63
|
-
* @param {String} service - name
|
|
64
|
-
* @param {String} methodName - method
|
|
65
|
-
* @param {Object|Function|Error} fn - mock you data
|
|
66
|
-
*/
|
|
67
|
-
mockService(service: string | any, methodName: string, fn: any): this;
|
|
68
|
-
/**
|
|
69
|
-
* mock service that return error
|
|
70
|
-
* @function App#mockServiceError
|
|
71
|
-
* @param {String} service - name
|
|
72
|
-
* @param {String} methodName - method
|
|
73
|
-
* @param {Error} [err] - error information
|
|
74
|
-
*/
|
|
75
|
-
mockServiceError(service: string | any, methodName: string, err?: string | Error): this;
|
|
76
|
-
_mockFn(obj: any, name: string, data: any): void;
|
|
77
|
-
/**
|
|
78
|
-
* mock request
|
|
79
|
-
* @function App#mockRequest
|
|
80
|
-
* @param {Request} req - mock request
|
|
81
|
-
*/
|
|
82
|
-
mockRequest(req: MockContextData): IncomingMessage;
|
|
83
|
-
/**
|
|
84
|
-
* mock cookies
|
|
85
|
-
* @function App#mockCookies
|
|
86
|
-
*/
|
|
87
|
-
mockCookies(cookies: Record<string, string | string[]>): this;
|
|
88
|
-
/**
|
|
89
|
-
* mock header
|
|
90
|
-
* @function App#mockHeaders
|
|
91
|
-
*/
|
|
92
|
-
mockHeaders(headers: Record<string, string | string[]>): this;
|
|
93
|
-
/**
|
|
94
|
-
* mock csrf
|
|
95
|
-
* @function App#mockCsrf
|
|
96
|
-
* @since 1.11
|
|
97
|
-
*/
|
|
98
|
-
mockCsrf(): this;
|
|
99
|
-
/**
|
|
100
|
-
* mock httpclient
|
|
101
|
-
* @alias mockHttpClient
|
|
102
|
-
* @function App#mockHttpclient
|
|
103
|
-
*/
|
|
104
|
-
mockHttpclient(mockUrl: string | RegExp, mockMethod: string | string[] | MockResultOptions | MockResultFunction, mockResult?: MockResultOptions | MockResultFunction | string): this;
|
|
105
|
-
/**
|
|
106
|
-
* mock httpclient
|
|
107
|
-
* @function App#mockHttpClient
|
|
108
|
-
*/
|
|
109
|
-
mockHttpClient(mockUrl: string | RegExp, mockMethod: string | string[] | MockResultOptions | MockResultFunction, mockResult?: MockResultOptions | MockResultFunction | string): this;
|
|
110
|
-
/**
|
|
111
|
-
* @deprecated Please use app.mockHttpClient instead of app.mockUrllib
|
|
112
|
-
*/
|
|
113
|
-
mockUrllib(mockUrl: string | RegExp, mockMethod: string | string[] | MockResultOptions | MockResultFunction, mockResult?: MockResultOptions | MockResultFunction | string): this;
|
|
114
|
-
/**
|
|
115
|
-
* get mock httpclient agent
|
|
116
|
-
* @function App#mockHttpclientAgent
|
|
117
|
-
*/
|
|
118
|
-
mockAgent(): import("urllib").MockAgent<import("urllib").MockAgent.Options>;
|
|
119
|
-
mockAgentRestore(): Promise<void>;
|
|
120
|
-
/**
|
|
121
|
-
* @see mm#restore
|
|
122
|
-
* @function App#mockRestore
|
|
123
|
-
*/
|
|
124
|
-
mockRestore(): Promise<void>;
|
|
125
|
-
/**
|
|
126
|
-
* @see mm
|
|
127
|
-
* @function App#mm
|
|
128
|
-
*/
|
|
129
|
-
get mm(): typeof mock;
|
|
130
|
-
/**
|
|
131
|
-
* override loadAgent
|
|
132
|
-
* @function App#loadAgent
|
|
133
|
-
*/
|
|
134
|
-
loadAgent(): void;
|
|
135
|
-
/**
|
|
136
|
-
* mock serverEnv
|
|
137
|
-
* @function App#mockEnv
|
|
138
|
-
* @param {String} env - serverEnv
|
|
139
|
-
*/
|
|
140
|
-
mockEnv(env: string): this;
|
|
141
|
-
/**
|
|
142
|
-
* http request helper
|
|
143
|
-
* @function App#httpRequest
|
|
144
|
-
* @return {SupertestRequest} req - supertest request
|
|
145
|
-
* @see https://github.com/visionmedia/supertest
|
|
146
|
-
*/
|
|
147
|
-
httpRequest(): EggTestRequest;
|
|
148
|
-
/**
|
|
149
|
-
* collection logger message, then can be use on `expectLog()`
|
|
150
|
-
* @param {String|Logger} [logger] - logger instance, default is `app.logger`
|
|
151
|
-
* @function App#mockLog
|
|
152
|
-
*/
|
|
153
|
-
mockLog(logger?: string | Logger): void;
|
|
154
|
-
__checkExpectLog(expectOrNot: boolean, str: string | RegExp, logger?: string | Logger): void;
|
|
155
|
-
/**
|
|
156
|
-
* expect str/regexp in the logger, if your server disk is slow, please call `mockLog()` first.
|
|
157
|
-
* @param {String|RegExp} str - test str or regexp
|
|
158
|
-
* @param {String|Logger} [logger] - logger instance, default is `ctx.logger`
|
|
159
|
-
* @function App#expectLog
|
|
160
|
-
*/
|
|
161
|
-
expectLog(str: string | RegExp, logger?: string | Logger): void;
|
|
162
|
-
/**
|
|
163
|
-
* not expect str/regexp in the logger, if your server disk is slow, please call `mockLog()` first.
|
|
164
|
-
* @param {String|RegExp} str - test str or regexp
|
|
165
|
-
* @param {String|Logger} [logger] - logger instance, default is `ctx.logger`
|
|
166
|
-
* @function App#notExpectLog
|
|
167
|
-
*/
|
|
168
|
-
notExpectLog(str: string | RegExp, logger?: string | Logger): void;
|
|
169
|
-
backgroundTasksFinished(): Promise<void>;
|
|
170
|
-
get _backgroundTasks(): Promise<any>[];
|
|
171
|
-
set _backgroundTasks(tasks: Promise<any>[]);
|
|
172
|
-
}
|
|
@@ -1,444 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import http from 'node:http';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import assert from 'node:assert';
|
|
5
|
-
import mergeDescriptors from 'merge-descriptors';
|
|
6
|
-
import { isAsyncFunction, isObject } from 'is-type-of';
|
|
7
|
-
import { mock, restore } from 'mm';
|
|
8
|
-
import { Transport } from 'egg-logger';
|
|
9
|
-
import { EggCore } from '@eggjs/core';
|
|
10
|
-
import { getMockAgent, restoreMockAgent } from '../../lib/mock_agent.js';
|
|
11
|
-
import { createMockHttpClient, } from '../../lib/mock_httpclient.js';
|
|
12
|
-
import { request as supertestRequest } from '../../lib/supertest.js';
|
|
13
|
-
const debug = debuglog('@eggjs/mock/app/extend/application');
|
|
14
|
-
const ORIGIN_TYPES = Symbol('@eggjs/mock originTypes');
|
|
15
|
-
const BACKGROUND_TASKS = Symbol('Application#backgroundTasks');
|
|
16
|
-
const REUSED_CTX = Symbol('Context#reusedInSuite');
|
|
17
|
-
export default class ApplicationUnittest extends EggCore {
|
|
18
|
-
_mockHttpClient;
|
|
19
|
-
/**
|
|
20
|
-
* mock Context
|
|
21
|
-
* @function App#mockContext
|
|
22
|
-
* @param {Object} data - ctx data
|
|
23
|
-
* @param {Object} [options] - mock ctx options
|
|
24
|
-
* @example
|
|
25
|
-
* ```js
|
|
26
|
-
* const ctx = app.mockContext({
|
|
27
|
-
* user: {
|
|
28
|
-
* name: 'Jason'
|
|
29
|
-
* }
|
|
30
|
-
* });
|
|
31
|
-
* console.log(ctx.user.name); // Jason
|
|
32
|
-
*
|
|
33
|
-
* // controller
|
|
34
|
-
* module.exports = function*() {
|
|
35
|
-
* this.body = this.user.name;
|
|
36
|
-
* };
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
mockContext(data, options) {
|
|
40
|
-
data = data ?? {};
|
|
41
|
-
function mockRequest(req) {
|
|
42
|
-
for (const key in data?.headers) {
|
|
43
|
-
mock(req.headers, key, data.headers[key]);
|
|
44
|
-
mock(req.headers, key.toLowerCase(), data.headers[key]);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
// try to use app.options.mockCtxStorage first
|
|
48
|
-
const mockCtxStorage = this.options.mockCtxStorage ?? true;
|
|
49
|
-
options = Object.assign({ mockCtxStorage }, options);
|
|
50
|
-
if ('_customMockContext' in this && typeof this._customMockContext === 'function') {
|
|
51
|
-
this._customMockContext(data);
|
|
52
|
-
}
|
|
53
|
-
// 使用者自定义mock,可以覆盖上面的 mock
|
|
54
|
-
for (const key in data) {
|
|
55
|
-
mock(this.context, key, data[key]);
|
|
56
|
-
}
|
|
57
|
-
const req = this.mockRequest(data);
|
|
58
|
-
const res = new http.ServerResponse(req);
|
|
59
|
-
if (options.reuseCtxStorage !== false) {
|
|
60
|
-
if (this.currentContext && !this.currentContext[REUSED_CTX]) {
|
|
61
|
-
mockRequest(this.currentContext.request.req);
|
|
62
|
-
this.currentContext[REUSED_CTX] = true;
|
|
63
|
-
return this.currentContext;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
const ctx = this.createContext(req, res);
|
|
67
|
-
if (options.mockCtxStorage) {
|
|
68
|
-
mock(this.ctxStorage, 'getStore', () => ctx);
|
|
69
|
-
}
|
|
70
|
-
return ctx;
|
|
71
|
-
}
|
|
72
|
-
async mockContextScope(fn, data) {
|
|
73
|
-
const ctx = this.mockContext(data, {
|
|
74
|
-
mockCtxStorage: false,
|
|
75
|
-
reuseCtxStorage: false,
|
|
76
|
-
});
|
|
77
|
-
return await this.ctxStorage.run(ctx, async () => {
|
|
78
|
-
return await fn(ctx);
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* mock cookie session
|
|
83
|
-
* @function App#mockSession
|
|
84
|
-
* @param {Object} data - session object
|
|
85
|
-
*/
|
|
86
|
-
mockSession(data) {
|
|
87
|
-
if (!data) {
|
|
88
|
-
return this;
|
|
89
|
-
}
|
|
90
|
-
if (isObject(data) && !('save' in data)) {
|
|
91
|
-
// keep session.save() work
|
|
92
|
-
Object.defineProperty(data, 'save', {
|
|
93
|
-
value: () => { },
|
|
94
|
-
enumerable: false,
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
mock(this.context, 'session', data);
|
|
98
|
-
return this;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Mock service
|
|
102
|
-
* @function App#mockService
|
|
103
|
-
* @param {String} service - name
|
|
104
|
-
* @param {String} methodName - method
|
|
105
|
-
* @param {Object|Function|Error} fn - mock you data
|
|
106
|
-
*/
|
|
107
|
-
mockService(service, methodName, fn) {
|
|
108
|
-
if (typeof service === 'string') {
|
|
109
|
-
const splits = service.split('.');
|
|
110
|
-
service = this.serviceClasses;
|
|
111
|
-
for (const key of splits) {
|
|
112
|
-
service = service[key];
|
|
113
|
-
}
|
|
114
|
-
service = service.prototype || service;
|
|
115
|
-
}
|
|
116
|
-
this._mockFn(service, methodName, fn);
|
|
117
|
-
return this;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* mock service that return error
|
|
121
|
-
* @function App#mockServiceError
|
|
122
|
-
* @param {String} service - name
|
|
123
|
-
* @param {String} methodName - method
|
|
124
|
-
* @param {Error} [err] - error information
|
|
125
|
-
*/
|
|
126
|
-
mockServiceError(service, methodName, err) {
|
|
127
|
-
if (typeof err === 'string') {
|
|
128
|
-
err = new Error(err);
|
|
129
|
-
}
|
|
130
|
-
if (!err) {
|
|
131
|
-
// mockServiceError(service, methodName)
|
|
132
|
-
err = new Error(`mock ${methodName} error`);
|
|
133
|
-
}
|
|
134
|
-
this.mockService(service, methodName, err);
|
|
135
|
-
return this;
|
|
136
|
-
}
|
|
137
|
-
_mockFn(obj, name, data) {
|
|
138
|
-
const origin = obj[name];
|
|
139
|
-
assert(typeof origin === 'function', `property ${name} in original object must be function`);
|
|
140
|
-
// keep origin properties' type to support mock multi times
|
|
141
|
-
if (!obj[ORIGIN_TYPES])
|
|
142
|
-
obj[ORIGIN_TYPES] = {};
|
|
143
|
-
let type = obj[ORIGIN_TYPES][name];
|
|
144
|
-
if (!type) {
|
|
145
|
-
type = obj[ORIGIN_TYPES][name] = isAsyncFunction(origin) ? 'async' : 'sync';
|
|
146
|
-
}
|
|
147
|
-
if (typeof data === 'function') {
|
|
148
|
-
const fn = data;
|
|
149
|
-
// if original is async function
|
|
150
|
-
// but the mock function is normal function, need to change it return a promise
|
|
151
|
-
if (type === 'async' && !isAsyncFunction(fn)) {
|
|
152
|
-
mock(obj, name, function (...args) {
|
|
153
|
-
return new Promise(resolve => {
|
|
154
|
-
resolve(fn.apply(this, args));
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
mock(obj, name, fn);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
if (type === 'async') {
|
|
163
|
-
mock(obj, name, () => {
|
|
164
|
-
return new Promise((resolve, reject) => {
|
|
165
|
-
if (data instanceof Error)
|
|
166
|
-
return reject(data);
|
|
167
|
-
resolve(data);
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
mock(obj, name, () => {
|
|
173
|
-
if (data instanceof Error) {
|
|
174
|
-
throw data;
|
|
175
|
-
}
|
|
176
|
-
return data;
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* mock request
|
|
181
|
-
* @function App#mockRequest
|
|
182
|
-
* @param {Request} req - mock request
|
|
183
|
-
*/
|
|
184
|
-
mockRequest(req) {
|
|
185
|
-
req = { ...req };
|
|
186
|
-
const headers = req.headers ?? {};
|
|
187
|
-
for (const key in req.headers) {
|
|
188
|
-
headers[key.toLowerCase()] = req.headers[key];
|
|
189
|
-
}
|
|
190
|
-
if (!headers['x-forwarded-for']) {
|
|
191
|
-
headers['x-forwarded-for'] = '127.0.0.1';
|
|
192
|
-
}
|
|
193
|
-
headers['x-mock-request-from'] = '@eggjs/mock';
|
|
194
|
-
req.headers = headers;
|
|
195
|
-
mergeDescriptors(req, {
|
|
196
|
-
query: {},
|
|
197
|
-
querystring: '',
|
|
198
|
-
host: '127.0.0.1',
|
|
199
|
-
hostname: '127.0.0.1',
|
|
200
|
-
protocol: 'http',
|
|
201
|
-
secure: 'false',
|
|
202
|
-
method: 'GET',
|
|
203
|
-
url: '/',
|
|
204
|
-
path: '/',
|
|
205
|
-
socket: {
|
|
206
|
-
remoteAddress: '127.0.0.1',
|
|
207
|
-
remotePort: 7001,
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
return req;
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* mock cookies
|
|
214
|
-
* @function App#mockCookies
|
|
215
|
-
*/
|
|
216
|
-
mockCookies(cookies) {
|
|
217
|
-
if (!cookies) {
|
|
218
|
-
return this;
|
|
219
|
-
}
|
|
220
|
-
const createContext = this.createContext;
|
|
221
|
-
mock(this, 'createContext', function (req, res) {
|
|
222
|
-
const ctx = createContext.call(this, req, res);
|
|
223
|
-
const getCookie = ctx.cookies.get;
|
|
224
|
-
mock(ctx.cookies, 'get', function (key, opts) {
|
|
225
|
-
if (cookies[key]) {
|
|
226
|
-
return cookies[key];
|
|
227
|
-
}
|
|
228
|
-
return getCookie.call(this, key, opts);
|
|
229
|
-
});
|
|
230
|
-
return ctx;
|
|
231
|
-
});
|
|
232
|
-
return this;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* mock header
|
|
236
|
-
* @function App#mockHeaders
|
|
237
|
-
*/
|
|
238
|
-
mockHeaders(headers) {
|
|
239
|
-
if (!headers) {
|
|
240
|
-
return this;
|
|
241
|
-
}
|
|
242
|
-
const getHeader = this.request.get;
|
|
243
|
-
mock(this.request, 'get', function (field) {
|
|
244
|
-
const value = findHeaders(headers, field);
|
|
245
|
-
if (value)
|
|
246
|
-
return value;
|
|
247
|
-
return getHeader.call(this, field);
|
|
248
|
-
});
|
|
249
|
-
return this;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* mock csrf
|
|
253
|
-
* @function App#mockCsrf
|
|
254
|
-
* @since 1.11
|
|
255
|
-
*/
|
|
256
|
-
mockCsrf() {
|
|
257
|
-
mock(this.context, 'assertCSRF', () => { });
|
|
258
|
-
mock(this.context, 'assertCsrf', () => { });
|
|
259
|
-
return this;
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* mock httpclient
|
|
263
|
-
* @alias mockHttpClient
|
|
264
|
-
* @function App#mockHttpclient
|
|
265
|
-
*/
|
|
266
|
-
mockHttpclient(mockUrl, mockMethod, mockResult) {
|
|
267
|
-
return this.mockHttpClient(mockUrl, mockMethod, mockResult);
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* mock httpclient
|
|
271
|
-
* @function App#mockHttpClient
|
|
272
|
-
*/
|
|
273
|
-
mockHttpClient(mockUrl, mockMethod, mockResult) {
|
|
274
|
-
if (!this._mockHttpClient) {
|
|
275
|
-
this._mockHttpClient = createMockHttpClient(this);
|
|
276
|
-
}
|
|
277
|
-
this._mockHttpClient(mockUrl, mockMethod, mockResult);
|
|
278
|
-
return this;
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* @deprecated Please use app.mockHttpClient instead of app.mockUrllib
|
|
282
|
-
*/
|
|
283
|
-
mockUrllib(mockUrl, mockMethod, mockResult) {
|
|
284
|
-
this.deprecate('[@eggjs/mock] Please use app.mockHttpClient instead of app.mockUrllib');
|
|
285
|
-
return this.mockHttpClient(mockUrl, mockMethod, mockResult);
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* get mock httpclient agent
|
|
289
|
-
* @function App#mockHttpclientAgent
|
|
290
|
-
*/
|
|
291
|
-
mockAgent() {
|
|
292
|
-
return getMockAgent(this);
|
|
293
|
-
}
|
|
294
|
-
async mockAgentRestore() {
|
|
295
|
-
await restoreMockAgent();
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* @see mm#restore
|
|
299
|
-
* @function App#mockRestore
|
|
300
|
-
*/
|
|
301
|
-
async mockRestore() {
|
|
302
|
-
await this.mockAgentRestore();
|
|
303
|
-
restore();
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* @see mm
|
|
307
|
-
* @function App#mm
|
|
308
|
-
*/
|
|
309
|
-
get mm() {
|
|
310
|
-
return mock;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* override loadAgent
|
|
314
|
-
* @function App#loadAgent
|
|
315
|
-
*/
|
|
316
|
-
loadAgent() { }
|
|
317
|
-
/**
|
|
318
|
-
* mock serverEnv
|
|
319
|
-
* @function App#mockEnv
|
|
320
|
-
* @param {String} env - serverEnv
|
|
321
|
-
*/
|
|
322
|
-
mockEnv(env) {
|
|
323
|
-
mock(this.config, 'env', env);
|
|
324
|
-
mock(this.config, 'serverEnv', env);
|
|
325
|
-
debug('mock env: %o', env);
|
|
326
|
-
return this;
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* http request helper
|
|
330
|
-
* @function App#httpRequest
|
|
331
|
-
* @return {SupertestRequest} req - supertest request
|
|
332
|
-
* @see https://github.com/visionmedia/supertest
|
|
333
|
-
*/
|
|
334
|
-
httpRequest() {
|
|
335
|
-
return supertestRequest(this);
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* collection logger message, then can be use on `expectLog()`
|
|
339
|
-
* @param {String|Logger} [logger] - logger instance, default is `app.logger`
|
|
340
|
-
* @function App#mockLog
|
|
341
|
-
*/
|
|
342
|
-
mockLog(logger) {
|
|
343
|
-
logger = logger ?? this.logger;
|
|
344
|
-
if (typeof logger === 'string') {
|
|
345
|
-
logger = this.getLogger(logger);
|
|
346
|
-
}
|
|
347
|
-
// make sure mock once
|
|
348
|
-
if ('_mockLogs' in logger && logger._mockLogs)
|
|
349
|
-
return;
|
|
350
|
-
const transport = new Transport(logger.options);
|
|
351
|
-
// https://github.com/eggjs/egg-logger/blob/master/lib/logger.js#L64
|
|
352
|
-
const log = logger.log;
|
|
353
|
-
const mockLogs = [];
|
|
354
|
-
mock(logger, '_mockLogs', mockLogs);
|
|
355
|
-
mock(logger, 'log', (level, args, meta) => {
|
|
356
|
-
const message = transport.log(level, args, meta);
|
|
357
|
-
mockLogs.push(message);
|
|
358
|
-
log.apply(logger, [level, args, meta]);
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
__checkExpectLog(expectOrNot, str, logger) {
|
|
362
|
-
logger = logger || this.logger;
|
|
363
|
-
if (typeof logger === 'string') {
|
|
364
|
-
logger = this.getLogger(logger);
|
|
365
|
-
}
|
|
366
|
-
const filepath = logger.options.file;
|
|
367
|
-
let content;
|
|
368
|
-
if ('_mockLogs' in logger && logger._mockLogs) {
|
|
369
|
-
content = logger._mockLogs.join('\n');
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
content = fs.readFileSync(filepath, 'utf8');
|
|
373
|
-
}
|
|
374
|
-
let match;
|
|
375
|
-
let type;
|
|
376
|
-
if (str instanceof RegExp) {
|
|
377
|
-
match = str.test(content);
|
|
378
|
-
type = 'RegExp';
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
match = content.includes(String(str));
|
|
382
|
-
type = 'String';
|
|
383
|
-
}
|
|
384
|
-
if (expectOrNot) {
|
|
385
|
-
assert(match, `Can't find ${type}:"${str}" in ${filepath}, log content: ...${content.substring(content.length - 500)}`);
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
assert(!match, `Find ${type}:"${str}" in ${filepath}, log content: ...${content.substring(content.length - 500)}`);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* expect str/regexp in the logger, if your server disk is slow, please call `mockLog()` first.
|
|
393
|
-
* @param {String|RegExp} str - test str or regexp
|
|
394
|
-
* @param {String|Logger} [logger] - logger instance, default is `ctx.logger`
|
|
395
|
-
* @function App#expectLog
|
|
396
|
-
*/
|
|
397
|
-
expectLog(str, logger) {
|
|
398
|
-
this.__checkExpectLog(true, str, logger);
|
|
399
|
-
}
|
|
400
|
-
/**
|
|
401
|
-
* not expect str/regexp in the logger, if your server disk is slow, please call `mockLog()` first.
|
|
402
|
-
* @param {String|RegExp} str - test str or regexp
|
|
403
|
-
* @param {String|Logger} [logger] - logger instance, default is `ctx.logger`
|
|
404
|
-
* @function App#notExpectLog
|
|
405
|
-
*/
|
|
406
|
-
notExpectLog(str, logger) {
|
|
407
|
-
this.__checkExpectLog(false, str, logger);
|
|
408
|
-
}
|
|
409
|
-
async backgroundTasksFinished() {
|
|
410
|
-
const tasks = this._backgroundTasks;
|
|
411
|
-
debug('waiting %d background tasks', tasks.length);
|
|
412
|
-
if (tasks.length === 0)
|
|
413
|
-
return;
|
|
414
|
-
this._backgroundTasks = [];
|
|
415
|
-
await Promise.all(tasks);
|
|
416
|
-
debug('finished %d background tasks', tasks.length);
|
|
417
|
-
if (this._backgroundTasks.length) {
|
|
418
|
-
debug('new background tasks created: %s', this._backgroundTasks.length);
|
|
419
|
-
await this.backgroundTasksFinished();
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
get _backgroundTasks() {
|
|
423
|
-
if (!this[BACKGROUND_TASKS]) {
|
|
424
|
-
this[BACKGROUND_TASKS] = [];
|
|
425
|
-
}
|
|
426
|
-
return this[BACKGROUND_TASKS];
|
|
427
|
-
}
|
|
428
|
-
set _backgroundTasks(tasks) {
|
|
429
|
-
this[BACKGROUND_TASKS] = tasks;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
function findHeaders(headers, key) {
|
|
433
|
-
if (!headers || !key) {
|
|
434
|
-
return null;
|
|
435
|
-
}
|
|
436
|
-
key = key.toLowerCase();
|
|
437
|
-
for (const headerKey in headers) {
|
|
438
|
-
if (key === headerKey.toLowerCase()) {
|
|
439
|
-
return headers[headerKey];
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
return null;
|
|
443
|
-
}
|
|
444
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBwL2V4dGVuZC9hcHBsaWNhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3JDLE9BQU8sSUFBeUIsTUFBTSxXQUFXLENBQUM7QUFDbEQsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pCLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQztBQUNqQyxPQUFPLGdCQUFnQixNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBRW5DLE9BQU8sRUFBRSxTQUFTLEVBQW1DLE1BQU0sWUFBWSxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxPQUFPLEVBQXVELE1BQU0sYUFBYSxDQUFDO0FBRTNGLE9BQU8sRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RSxPQUFPLEVBQ0wsb0JBQW9CLEdBR3JCLE1BQU0sOEJBQThCLENBQUM7QUFDdEMsT0FBTyxFQUFFLE9BQU8sSUFBSSxnQkFBZ0IsRUFBa0IsTUFBTSx3QkFBd0IsQ0FBQztBQUdyRixNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsb0NBQW9DLENBQUMsQ0FBQztBQUU3RCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQztBQUN2RCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0FBQy9ELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0FBdUJuRCxNQUFNLENBQUMsT0FBTyxPQUFnQixtQkFBb0IsU0FBUSxPQUFPO0lBRy9ELGVBQWUsQ0FBd0I7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
|