@eggjs/mock 6.0.7 → 6.1.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +35 -56
  2. package/README.zh_CN.md +30 -50
  3. package/dist/_virtual/rolldown_runtime.js +7 -0
  4. package/dist/app/extend/agent.d.ts +39 -0
  5. package/dist/app/extend/agent.js +48 -0
  6. package/dist/app/extend/application.d.ts +176 -0
  7. package/dist/app/extend/application.js +385 -0
  8. package/dist/app/middleware/cluster_app_mock.d.ts +6 -0
  9. package/dist/app/middleware/cluster_app_mock.js +97 -0
  10. package/dist/app.d.ts +10 -0
  11. package/dist/app.js +17 -0
  12. package/dist/bootstrap.d.ts +9 -0
  13. package/dist/bootstrap.js +14 -0
  14. package/dist/index.d.ts +81 -0
  15. package/dist/index.js +48 -0
  16. package/dist/lib/agent_handler.d.ts +7 -0
  17. package/dist/lib/agent_handler.js +26 -0
  18. package/dist/lib/app.d.ts +7 -0
  19. package/dist/lib/app.js +251 -0
  20. package/dist/lib/app_handler.d.ts +9 -0
  21. package/dist/lib/app_handler.js +56 -0
  22. package/dist/lib/cluster.d.ts +126 -0
  23. package/dist/lib/cluster.js +283 -0
  24. package/dist/lib/context.d.ts +4 -0
  25. package/dist/lib/context.js +13 -0
  26. package/dist/lib/format_options.d.ts +10 -0
  27. package/dist/lib/format_options.js +65 -0
  28. package/dist/lib/inject_context.d.ts +9 -0
  29. package/dist/lib/inject_context.js +106 -0
  30. package/dist/lib/mock_agent.d.ts +9 -0
  31. package/dist/lib/mock_agent.js +45 -0
  32. package/dist/lib/mock_custom_loader.d.ts +4 -0
  33. package/dist/lib/mock_custom_loader.js +35 -0
  34. package/dist/lib/mock_http_server.d.ts +6 -0
  35. package/dist/lib/mock_http_server.js +17 -0
  36. package/dist/lib/mock_httpclient.d.ts +40 -0
  37. package/dist/lib/mock_httpclient.js +110 -0
  38. package/dist/lib/parallel/agent.d.ts +24 -0
  39. package/dist/lib/parallel/agent.js +111 -0
  40. package/dist/lib/parallel/app.d.ts +24 -0
  41. package/dist/lib/parallel/app.js +98 -0
  42. package/dist/lib/parallel/util.d.ts +6 -0
  43. package/dist/lib/parallel/util.js +59 -0
  44. package/dist/lib/prerequire.d.ts +1 -0
  45. package/dist/lib/prerequire.js +1 -0
  46. package/dist/lib/request_call_function.d.ts +1 -0
  47. package/dist/lib/request_call_function.js +37 -0
  48. package/dist/lib/restore.d.ts +4 -0
  49. package/dist/lib/restore.js +16 -0
  50. package/dist/lib/start-cluster.d.ts +1 -0
  51. package/dist/lib/start-cluster.js +19 -0
  52. package/dist/lib/supertest.d.ts +16 -0
  53. package/dist/lib/supertest.js +39 -0
  54. package/dist/lib/tmp/empty.d.ts +1 -0
  55. package/dist/lib/tmp/empty.js +1 -0
  56. package/{src/lib/types.ts → dist/lib/types.d.ts} +12 -29
  57. package/dist/lib/types.js +1 -0
  58. package/dist/lib/utils.d.ts +12 -0
  59. package/dist/lib/utils.js +40 -0
  60. package/dist/register.d.ts +12 -0
  61. package/dist/register.js +65 -0
  62. package/dist/typings/index.d.ts +1 -0
  63. package/package.json +68 -100
  64. package/dist/commonjs/app/extend/agent.d.ts +0 -34
  65. package/dist/commonjs/app/extend/agent.js +0 -49
  66. package/dist/commonjs/app/extend/application.d.ts +0 -172
  67. package/dist/commonjs/app/extend/application.js +0 -450
  68. package/dist/commonjs/app/middleware/cluster_app_mock.d.ts +0 -3
  69. package/dist/commonjs/app/middleware/cluster_app_mock.js +0 -101
  70. package/dist/commonjs/app.d.ts +0 -6
  71. package/dist/commonjs/app.js +0 -20
  72. package/dist/commonjs/bootstrap.d.ts +0 -5
  73. package/dist/commonjs/bootstrap.js +0 -59
  74. package/dist/commonjs/index.d.ts +0 -77
  75. package/dist/commonjs/index.js +0 -114
  76. package/dist/commonjs/lib/agent_handler.d.ts +0 -3
  77. package/dist/commonjs/lib/agent_handler.js +0 -28
  78. package/dist/commonjs/lib/app.d.ts +0 -3
  79. package/dist/commonjs/lib/app.js +0 -301
  80. package/dist/commonjs/lib/app_handler.d.ts +0 -5
  81. package/dist/commonjs/lib/app_handler.js +0 -71
  82. package/dist/commonjs/lib/cluster.d.ts +0 -114
  83. package/dist/commonjs/lib/cluster.js +0 -337
  84. package/dist/commonjs/lib/context.d.ts +0 -1
  85. package/dist/commonjs/lib/context.js +0 -16
  86. package/dist/commonjs/lib/format_options.d.ts +0 -5
  87. package/dist/commonjs/lib/format_options.js +0 -100
  88. package/dist/commonjs/lib/inject_context.d.ts +0 -6
  89. package/dist/commonjs/lib/inject_context.js +0 -132
  90. package/dist/commonjs/lib/mock_agent.d.ts +0 -5
  91. package/dist/commonjs/lib/mock_agent.js +0 -49
  92. package/dist/commonjs/lib/mock_custom_loader.d.ts +0 -1
  93. package/dist/commonjs/lib/mock_custom_loader.js +0 -37
  94. package/dist/commonjs/lib/mock_http_server.d.ts +0 -2
  95. package/dist/commonjs/lib/mock_http_server.js +0 -24
  96. package/dist/commonjs/lib/mock_httpclient.d.ts +0 -36
  97. package/dist/commonjs/lib/mock_httpclient.js +0 -147
  98. package/dist/commonjs/lib/parallel/agent.d.ts +0 -20
  99. package/dist/commonjs/lib/parallel/agent.js +0 -125
  100. package/dist/commonjs/lib/parallel/app.d.ts +0 -20
  101. package/dist/commonjs/lib/parallel/app.js +0 -115
  102. package/dist/commonjs/lib/parallel/util.d.ts +0 -3
  103. package/dist/commonjs/lib/parallel/util.js +0 -77
  104. package/dist/commonjs/lib/prerequire.d.ts +0 -1
  105. package/dist/commonjs/lib/prerequire.js +0 -26
  106. package/dist/commonjs/lib/request_call_function.d.ts +0 -1
  107. package/dist/commonjs/lib/request_call_function.js +0 -52
  108. package/dist/commonjs/lib/restore.d.ts +0 -1
  109. package/dist/commonjs/lib/restore.js +0 -16
  110. package/dist/commonjs/lib/start-cluster.d.ts +0 -2
  111. package/dist/commonjs/lib/start-cluster.js +0 -23
  112. package/dist/commonjs/lib/supertest.d.ts +0 -11
  113. package/dist/commonjs/lib/supertest.js +0 -48
  114. package/dist/commonjs/lib/tmp/empty.d.ts +0 -1
  115. package/dist/commonjs/lib/tmp/empty.js +0 -3
  116. package/dist/commonjs/lib/types.d.ts +0 -68
  117. package/dist/commonjs/lib/types.js +0 -3
  118. package/dist/commonjs/lib/utils.d.ts +0 -9
  119. package/dist/commonjs/lib/utils.js +0 -80
  120. package/dist/commonjs/package.json +0 -3
  121. package/dist/commonjs/register.d.ts +0 -8
  122. package/dist/commonjs/register.js +0 -80
  123. package/dist/esm/app/extend/agent.d.ts +0 -34
  124. package/dist/esm/app/extend/agent.js +0 -46
  125. package/dist/esm/app/extend/application.d.ts +0 -172
  126. package/dist/esm/app/extend/application.js +0 -444
  127. package/dist/esm/app/middleware/cluster_app_mock.d.ts +0 -3
  128. package/dist/esm/app/middleware/cluster_app_mock.js +0 -99
  129. package/dist/esm/app.d.ts +0 -6
  130. package/dist/esm/app.js +0 -17
  131. package/dist/esm/bootstrap.d.ts +0 -5
  132. package/dist/esm/bootstrap.js +0 -15
  133. package/dist/esm/index.d.ts +0 -77
  134. package/dist/esm/index.js +0 -91
  135. package/dist/esm/lib/agent_handler.d.ts +0 -3
  136. package/dist/esm/lib/agent_handler.js +0 -24
  137. package/dist/esm/lib/app.d.ts +0 -3
  138. package/dist/esm/lib/app.js +0 -295
  139. package/dist/esm/lib/app_handler.d.ts +0 -5
  140. package/dist/esm/lib/app_handler.js +0 -65
  141. package/dist/esm/lib/cluster.d.ts +0 -114
  142. package/dist/esm/lib/cluster.js +0 -328
  143. package/dist/esm/lib/context.d.ts +0 -1
  144. package/dist/esm/lib/context.js +0 -13
  145. package/dist/esm/lib/format_options.d.ts +0 -5
  146. package/dist/esm/lib/format_options.js +0 -94
  147. package/dist/esm/lib/inject_context.d.ts +0 -6
  148. package/dist/esm/lib/inject_context.js +0 -126
  149. package/dist/esm/lib/mock_agent.d.ts +0 -5
  150. package/dist/esm/lib/mock_agent.js +0 -45
  151. package/dist/esm/lib/mock_custom_loader.d.ts +0 -1
  152. package/dist/esm/lib/mock_custom_loader.js +0 -34
  153. package/dist/esm/lib/mock_http_server.d.ts +0 -2
  154. package/dist/esm/lib/mock_http_server.js +0 -18
  155. package/dist/esm/lib/mock_httpclient.d.ts +0 -36
  156. package/dist/esm/lib/mock_httpclient.js +0 -144
  157. package/dist/esm/lib/parallel/agent.d.ts +0 -20
  158. package/dist/esm/lib/parallel/agent.js +0 -117
  159. package/dist/esm/lib/parallel/app.d.ts +0 -20
  160. package/dist/esm/lib/parallel/app.js +0 -110
  161. package/dist/esm/lib/parallel/util.d.ts +0 -3
  162. package/dist/esm/lib/parallel/util.js +0 -73
  163. package/dist/esm/lib/prerequire.d.ts +0 -1
  164. package/dist/esm/lib/prerequire.js +0 -25
  165. package/dist/esm/lib/request_call_function.d.ts +0 -1
  166. package/dist/esm/lib/request_call_function.js +0 -47
  167. package/dist/esm/lib/restore.d.ts +0 -1
  168. package/dist/esm/lib/restore.js +0 -13
  169. package/dist/esm/lib/start-cluster.d.ts +0 -2
  170. package/dist/esm/lib/start-cluster.js +0 -18
  171. package/dist/esm/lib/supertest.d.ts +0 -11
  172. package/dist/esm/lib/supertest.js +0 -40
  173. package/dist/esm/lib/tmp/empty.d.ts +0 -1
  174. package/dist/esm/lib/tmp/empty.js +0 -2
  175. package/dist/esm/lib/types.d.ts +0 -68
  176. package/dist/esm/lib/types.js +0 -2
  177. package/dist/esm/lib/utils.d.ts +0 -9
  178. package/dist/esm/lib/utils.js +0 -69
  179. package/dist/esm/package.json +0 -3
  180. package/dist/esm/register.d.ts +0 -8
  181. package/dist/esm/register.js +0 -75
  182. package/dist/package.json +0 -4
  183. package/src/app/extend/agent.ts +0 -57
  184. package/src/app/extend/application.ts +0 -512
  185. package/src/app/middleware/cluster_app_mock.ts +0 -102
  186. package/src/app.ts +0 -18
  187. package/src/bootstrap.ts +0 -25
  188. package/src/index.ts +0 -112
  189. package/src/lib/agent_handler.ts +0 -28
  190. package/src/lib/app.ts +0 -314
  191. package/src/lib/app_handler.ts +0 -77
  192. package/src/lib/cluster.ts +0 -363
  193. package/src/lib/context.ts +0 -14
  194. package/src/lib/format_options.ts +0 -103
  195. package/src/lib/inject_context.ts +0 -134
  196. package/src/lib/mock_agent.ts +0 -57
  197. package/src/lib/mock_custom_loader.ts +0 -36
  198. package/src/lib/mock_http_server.ts +0 -19
  199. package/src/lib/mock_httpclient.ts +0 -183
  200. package/src/lib/parallel/agent.ts +0 -128
  201. package/src/lib/parallel/app.ts +0 -123
  202. package/src/lib/parallel/util.ts +0 -66
  203. package/src/lib/prerequire.ts +0 -25
  204. package/src/lib/request_call_function.ts +0 -49
  205. package/src/lib/restore.ts +0 -14
  206. package/src/lib/start-cluster.ts +0 -23
  207. package/src/lib/supertest.ts +0 -45
  208. package/src/lib/tmp/.gitkeep +0 -0
  209. package/src/lib/tmp/empty.ts +0 -0
  210. package/src/lib/utils.ts +0 -82
  211. package/src/register.ts +0 -80
  212. package/src/typings/index.d.ts +0 -4
@@ -0,0 +1,283 @@
1
+ import { rimrafSync, sleep } from "./utils.js";
2
+ import { request } from "./supertest.js";
3
+ import { formatOptions } from "./format_options.js";
4
+ import path from "node:path";
5
+ import { debuglog } from "node:util";
6
+ import os from "node:os";
7
+ import childProcess from "node:child_process";
8
+ import { once } from "node:events";
9
+ import { existsSync } from "node:fs";
10
+ import { Coffee } from "coffee";
11
+ import { Ready } from "get-ready";
12
+
13
+ //#region src/lib/cluster.ts
14
+ const debug = debuglog("egg/mock/lib/cluster");
15
+ const clusters = /* @__PURE__ */ new Map();
16
+ globalThis.eggMockMasterPort = 17e3 + process.pid % 1e3;
17
+ let serverBin = path.join(import.meta.dirname, "start-cluster.js");
18
+ if (!existsSync(serverBin)) serverBin = path.join(import.meta.dirname, "start-cluster.ts");
19
+ let requestCallFunctionFile = path.join(import.meta.dirname, "request_call_function.js");
20
+ if (!existsSync(requestCallFunctionFile)) requestCallFunctionFile = path.join(import.meta.dirname, "request_call_function.ts");
21
+ /**
22
+ * A cluster version of egg.Application, you can test with supertest
23
+ * @example
24
+ * ```js
25
+ * const mm = require('mm');
26
+ * const request = require('supertest');
27
+ *
28
+ * describe('ClusterApplication', () => {
29
+ * let app;
30
+ * before(function (done) {
31
+ * app = mm.cluster({ baseDir });
32
+ * app.ready(done);
33
+ * });
34
+ *
35
+ * after(function () {
36
+ * app.close();
37
+ * });
38
+ *
39
+ * it('should 200', function (done) {
40
+ * request(app.callback())
41
+ * .get('/')
42
+ * .expect(200, done);
43
+ * });
44
+ * });
45
+ */
46
+ var ClusterApplication = class extends Coffee {
47
+ options;
48
+ port;
49
+ baseDir;
50
+ closed;
51
+ _address;
52
+ /**
53
+ * @class
54
+ * @param {Object} options
55
+ * - {String} baseDir - The directory of the application
56
+ * - {Object} plugins - Custom you plugins
57
+ * - {String} framework - The directory of the egg framework
58
+ * - {Boolean} [cache=true] - Cache application based on baseDir
59
+ * - {Boolean} [coverage=true] - Switch on process coverage, but it'll be slower
60
+ * - {Boolean} [clean=true] - Remove $baseDir/logs
61
+ * - {Object} [opt] - opt pass to coffee, such as { execArgv: ['--debug'] }
62
+ * ```
63
+ */
64
+ constructor(options) {
65
+ const opt = options.opt;
66
+ delete options.opt;
67
+ options.port = options.port ?? ++globalThis.eggMockMasterPort;
68
+ if (!options.workers) options.workers = 1;
69
+ const args = [JSON.stringify(options)];
70
+ debug("fork %s, args: %s, opt: %j", serverBin, args.join(" "), opt);
71
+ super({
72
+ method: "fork",
73
+ cmd: serverBin,
74
+ args,
75
+ opt
76
+ });
77
+ Ready.mixin(this);
78
+ this.port = options.port;
79
+ this.baseDir = options.baseDir;
80
+ this.debug(process.env.DEBUG ? 0 : 2);
81
+ if (options.coverage === false) this.coverage(false);
82
+ process.nextTick(() => {
83
+ this.proc.on("message", (msg) => {
84
+ switch (msg && msg.action ? msg.action : msg) {
85
+ case "egg-ready":
86
+ debug("on message egg-ready %o", msg);
87
+ this._address = msg.data.address;
88
+ this.emit("close", 0);
89
+ break;
90
+ case "app-worker-died":
91
+ case "agent-worker-died":
92
+ this.emit("close", 1);
93
+ break;
94
+ default: break;
95
+ }
96
+ });
97
+ });
98
+ this.end(() => this.ready(true));
99
+ }
100
+ /**
101
+ * the process that forked
102
+ * @member {ChildProcess}
103
+ */
104
+ get process() {
105
+ return this.proc;
106
+ }
107
+ /**
108
+ * Compatible API for supertest
109
+ */
110
+ callback() {
111
+ return this;
112
+ }
113
+ /**
114
+ * Compatible API for supertest
115
+ * @member {String} url
116
+ * @private
117
+ */
118
+ get url() {
119
+ if (this._address) return this._address;
120
+ return "http://127.0.0.1:" + this.port;
121
+ }
122
+ /**
123
+ * Compatible API for supertest
124
+ */
125
+ address() {
126
+ return {
127
+ port: this.port,
128
+ address: this._address
129
+ };
130
+ }
131
+ /**
132
+ * Compatible API for supertest
133
+ */
134
+ listen() {
135
+ return this;
136
+ }
137
+ /**
138
+ * kill the process
139
+ */
140
+ async close() {
141
+ this.closed = true;
142
+ const proc = this.proc;
143
+ const baseDir = this.baseDir;
144
+ if (proc?.connected) {
145
+ proc.kill("SIGTERM");
146
+ await once(proc, "exit");
147
+ }
148
+ clusters.delete(baseDir);
149
+ debug("delete cluster cache %s, remain %s", baseDir, [...clusters.keys()]);
150
+ if (os.platform() === "win32") await sleep(1e3);
151
+ }
152
+ get isClosed() {
153
+ return this.closed;
154
+ }
155
+ get router() {
156
+ const self = this;
157
+ return { pathFor(url) {
158
+ return self._callFunctionOnAppWorker("pathFor", [url], "router", true);
159
+ } };
160
+ }
161
+ /**
162
+ * get app[property] value in app worker
163
+ */
164
+ getAppInstanceProperty(property) {
165
+ return this._callFunctionOnAppWorker("__getter__", [], property, true);
166
+ }
167
+ /**
168
+ * collection logger message, then can be use on `expectLog()`
169
+ * it's different from `app.expectLog()`, only support string params.
170
+ *
171
+ * @param {String} [logger] - logger instance name, default is `logger`
172
+ * @function ClusterApplication#expectLog
173
+ */
174
+ mockLog(logger) {
175
+ logger = logger ?? "logger";
176
+ this._callFunctionOnAppWorker("mockLog", [logger], null, true);
177
+ }
178
+ /**
179
+ * expect str in the logger
180
+ * it's different from `app.expectLog()`, only support string params.
181
+ *
182
+ * @param {String} str - test str
183
+ * @param {String} [logger] - logger instance name, default is `logger`
184
+ * @function ClusterApplication#expectLog
185
+ */
186
+ expectLog(str, logger) {
187
+ logger = logger ?? "logger";
188
+ this._callFunctionOnAppWorker("expectLog", [str, logger], null, true);
189
+ }
190
+ /**
191
+ * not expect str in the logger
192
+ * it's different from `app.notExpectLog()`, only support string params.
193
+ *
194
+ * @param {String} str - test str
195
+ * @param {String} [logger] - logger instance name, default is `logger`
196
+ * @function ClusterApplication#notExpectLog
197
+ */
198
+ notExpectLog(str, logger) {
199
+ logger = logger ?? "logger";
200
+ this._callFunctionOnAppWorker("notExpectLog", [str, logger], null, true);
201
+ }
202
+ httpRequest() {
203
+ return request(this);
204
+ }
205
+ _callFunctionOnAppWorker(method, args = [], property = void 0, needResult = false) {
206
+ for (let i = 0; i < args.length; i++) {
207
+ const arg = args[i];
208
+ if (typeof arg === "function") args[i] = {
209
+ __egg_mock_type: "function",
210
+ value: arg.toString()
211
+ };
212
+ else if (arg instanceof Error) {
213
+ const errObject = {
214
+ __egg_mock_type: "error",
215
+ name: arg.name,
216
+ message: arg.message,
217
+ stack: arg.stack
218
+ };
219
+ for (const key in arg) if (key !== "name" && key !== "message" && key !== "stack") errObject[key] = arg[key];
220
+ args[i] = errObject;
221
+ }
222
+ }
223
+ const data = {
224
+ port: this.port,
225
+ method,
226
+ args,
227
+ property,
228
+ needResult
229
+ };
230
+ const child = childProcess.spawnSync(process.execPath, [requestCallFunctionFile, JSON.stringify(data)], { stdio: "pipe" });
231
+ let result;
232
+ if (child.stdout && child.stdout.length > 0) if (needResult) result = JSON.parse(child.stdout.toString());
233
+ else console.error(child.stdout.toString());
234
+ if (child.status !== 0) throw new Error(child.stderr.toString());
235
+ if (child.error) throw child.error;
236
+ return result;
237
+ }
238
+ };
239
+ function createCluster(initOptions) {
240
+ const options = formatOptions(initOptions);
241
+ if (options.cache && clusters.has(options.baseDir)) {
242
+ const clusterApp$1 = clusters.get(options.baseDir);
243
+ if (!clusterApp$1.isClosed) return clusterApp$1;
244
+ clusters.delete(options.baseDir);
245
+ }
246
+ if (options.clean !== false) {
247
+ const logDir = path.join(options.baseDir, "logs");
248
+ try {
249
+ rimrafSync(logDir);
250
+ } catch (err) {
251
+ console.error(`remove log dir ${logDir} failed: ${err.stack}`);
252
+ }
253
+ const runDir = path.join(options.baseDir, "run");
254
+ try {
255
+ rimrafSync(runDir);
256
+ } catch (err) {
257
+ console.error(`remove run dir ${runDir} failed: ${err.stack}`);
258
+ }
259
+ }
260
+ let clusterApp = new ClusterApplication(options);
261
+ clusterApp = new Proxy(clusterApp, { get(target, prop) {
262
+ debug("proxy handler.get %s", prop);
263
+ const method = prop;
264
+ if (typeof method === "string" && /^mock\w+$/.test(method) && target[method] === void 0) return function mockProxy(...args) {
265
+ return target._callFunctionOnAppWorker(method, args, null, true);
266
+ };
267
+ return target[prop];
268
+ } });
269
+ clusters.set(options.baseDir, clusterApp);
270
+ return clusterApp;
271
+ }
272
+ async function restore() {
273
+ for (const clusterApp of clusters.values()) await clusterApp.mockRestore();
274
+ }
275
+ process.on("exit", () => {
276
+ for (const clusterApp of clusters.values()) {
277
+ debug("on exit close clusterApp, port: %s", clusterApp.port);
278
+ clusterApp.close();
279
+ }
280
+ });
281
+
282
+ //#endregion
283
+ export { ClusterApplication, createCluster, restore };
@@ -0,0 +1,4 @@
1
+ //#region src/lib/context.d.ts
2
+ declare const context: any;
3
+ //#endregion
4
+ export { context };
@@ -0,0 +1,13 @@
1
+ import { utils } from "@eggjs/core";
2
+
3
+ //#region src/lib/context.ts
4
+ const context = { runInBackground(scope) {
5
+ /* istanbul ignore next */
6
+ const taskName = scope._name || scope.name || utils.getCalleeFromStack(true);
7
+ if (taskName) scope._name = taskName;
8
+ const promise = this._runInBackground(scope);
9
+ this.app._backgroundTasks.push(promise);
10
+ } };
11
+
12
+ //#endregion
13
+ export { context };
@@ -0,0 +1,10 @@
1
+ import { MockApplicationOptions, MockOptions } from "./types.js";
2
+
3
+ //#region src/lib/format_options.d.ts
4
+
5
+ /**
6
+ * format the options
7
+ */
8
+ declare function formatOptions(initOptions?: MockOptions): MockApplicationOptions;
9
+ //#endregion
10
+ export { formatOptions };
@@ -0,0 +1,65 @@
1
+ import { getSourceDirname } from "./utils.js";
2
+ import path from "node:path";
3
+ import { readJSONSync } from "utility";
4
+ import { isMocked, mm } from "mm";
5
+ import { debuglog } from "node:util";
6
+ import { getFrameworkPath } from "@eggjs/utils";
7
+
8
+ //#region src/lib/format_options.ts
9
+ const debug = debuglog("egg/mock/lib/format_options");
10
+ /**
11
+ * format the options
12
+ */
13
+ function formatOptions(initOptions) {
14
+ const options = {
15
+ baseDir: process.cwd(),
16
+ cache: true,
17
+ coverage: true,
18
+ clean: true,
19
+ ...initOptions
20
+ };
21
+ if (!path.isAbsolute(options.baseDir)) options.baseDir = path.join(process.cwd(), "test/fixtures", options.baseDir);
22
+ let framework = initOptions?.framework ?? initOptions?.customEgg;
23
+ if (framework === true) {
24
+ framework = process.cwd();
25
+ options.plugin = false;
26
+ } else {
27
+ if (!framework) framework = "";
28
+ framework = getFrameworkPath({
29
+ framework,
30
+ baseDir: options.baseDir
31
+ });
32
+ }
33
+ options.framework = options.customEgg = framework;
34
+ const plugins = options.plugins = options.plugins || {};
35
+ let pluginPath = path.join(getSourceDirname(), "..");
36
+ if (pluginPath.endsWith("/dist") || pluginPath.endsWith("\\dist")) pluginPath = path.join(pluginPath, "..");
37
+ plugins["egg-mock"] = {
38
+ enable: true,
39
+ path: pluginPath
40
+ };
41
+ if (options.plugin !== false) {
42
+ const pluginPath$1 = process.cwd();
43
+ const pkgPath = path.join(pluginPath$1, "package.json");
44
+ const pluginName = getPluginName(pkgPath);
45
+ if (options.plugin && !pluginName) throw new Error(`should set "eggPlugin" property in ${pkgPath}`);
46
+ if (pluginName) plugins[pluginName] = {
47
+ enable: true,
48
+ path: pluginPath$1
49
+ };
50
+ }
51
+ const env = process.env.EGG_SERVER_ENV;
52
+ if (!isMocked(process.env, "HOME") && (env === "default" || env === "test" || env === "prod")) mm(process.env, "HOME", options.baseDir);
53
+ if (process.env.EGG_MOCK_SERVER_ENV) options.cache = false;
54
+ debug("[formatOptions] options: %j", options);
55
+ return options;
56
+ }
57
+ function getPluginName(pkgPath) {
58
+ try {
59
+ const pkg = readJSONSync(pkgPath);
60
+ if (pkg.eggPlugin?.name) return pkg.eggPlugin.name;
61
+ } catch {}
62
+ }
63
+
64
+ //#endregion
65
+ export { formatOptions };
@@ -0,0 +1,9 @@
1
+ //#region src/lib/inject_context.d.ts
2
+ /**
3
+ * Monkey patch the mocha instance with egg context.
4
+ *
5
+ * @param {Function} mocha - the module of mocha
6
+ */
7
+ declare function injectContext(mocha: any): void;
8
+ //#endregion
9
+ export { injectContext };
@@ -0,0 +1,106 @@
1
+ import { getApp } from "./app_handler.js";
2
+ import assert from "node:assert";
3
+ import { debuglog } from "node:util";
4
+
5
+ //#region src/lib/inject_context.ts
6
+ const debug = debuglog("egg/mock/lib/inject_context");
7
+ const MOCHA_SUITE_APP = Symbol.for("mocha#suite#app");
8
+ /**
9
+ * Monkey patch the mocha instance with egg context.
10
+ *
11
+ * @param {Function} mocha - the module of mocha
12
+ */
13
+ function injectContext(mocha) {
14
+ if (mocha._injectContextLoaded) {
15
+ debug("mocha already injected context, skip it");
16
+ return;
17
+ }
18
+ const { Runner } = mocha;
19
+ const runSuite = Runner.prototype.runSuite;
20
+ const runTests = Runner.prototype.runTests;
21
+ function getTestTitle(suite, test) {
22
+ const suiteTitle = suite.root ? "root suite" : suite.title;
23
+ if (!test) return `"${suiteTitle}"`;
24
+ return `"${suiteTitle} - ${test.title}"`;
25
+ }
26
+ Runner.prototype.runSuite = async function(suite, fn) {
27
+ debug("run suite: %s", suite.title);
28
+ let app;
29
+ const self = this;
30
+ try {
31
+ app = await getApp(suite);
32
+ debug("get app: %s", !!app);
33
+ await app.ready();
34
+ } catch {
35
+ app = null;
36
+ }
37
+ if (!app) return runSuite.call(self, suite, fn);
38
+ let errSuite;
39
+ try {
40
+ suite.ctx[MOCHA_SUITE_APP] = app;
41
+ await (app.mockModuleContextScope || app.mockContextScope).call(app, async function() {
42
+ await new Promise((resolve) => {
43
+ runSuite.call(self, suite, (aErrSuite) => {
44
+ errSuite = aErrSuite;
45
+ resolve();
46
+ });
47
+ });
48
+ });
49
+ } catch (err) {
50
+ suite.beforeAll("egg-mock-mock-ctx-failed", async () => {
51
+ throw err;
52
+ });
53
+ return runSuite.call(self, suite, (aErrSuite) => {
54
+ return fn(aErrSuite);
55
+ });
56
+ }
57
+ return fn(errSuite);
58
+ };
59
+ Runner.prototype.runTests = async function(suite, fn) {
60
+ const tests = suite.tests.slice();
61
+ if (!tests.length) return runTests.call(this, suite, fn);
62
+ const app = suite.ctx[MOCHA_SUITE_APP];
63
+ const self = this;
64
+ if (!app) return runTests.call(self, suite, fn);
65
+ function done(errSuite) {
66
+ suite.tests = tests;
67
+ return fn(errSuite);
68
+ }
69
+ async function next(i) {
70
+ const test = tests[i];
71
+ if (!test) return done();
72
+ suite.tests = [test];
73
+ let app$1;
74
+ try {
75
+ app$1 = await getApp(suite, test);
76
+ assert(app$1, `not found app for test ${getTestTitle(suite, test)}`);
77
+ await app$1.ready();
78
+ } catch (err) {
79
+ self.fail(test, err);
80
+ return next(i + 1);
81
+ }
82
+ try {
83
+ await (app$1.mockModuleContextScope || app$1.mockContextScope).call(app$1, async function() {
84
+ return await new Promise((resolve) => {
85
+ runTests.call(self, suite, () => {
86
+ return resolve();
87
+ });
88
+ });
89
+ });
90
+ } catch (err) {
91
+ self.fail(test, err);
92
+ return next(i + 1);
93
+ }
94
+ return next(i + 1);
95
+ }
96
+ next(0).catch((err) => {
97
+ self.fail(suite, err);
98
+ done(suite);
99
+ });
100
+ };
101
+ mocha._injectContextLoaded = true;
102
+ debug("inject context success");
103
+ }
104
+
105
+ //#endregion
106
+ export { injectContext };
@@ -0,0 +1,9 @@
1
+ import { HttpClient, MockAgent } from "urllib";
2
+
3
+ //#region src/lib/mock_agent.d.ts
4
+ declare function getMockAgent(app?: {
5
+ httpClient?: HttpClient;
6
+ }): MockAgent<MockAgent.Options>;
7
+ declare function restoreMockAgent(): Promise<void>;
8
+ //#endregion
9
+ export { getMockAgent, restoreMockAgent };
@@ -0,0 +1,45 @@
1
+ import { debuglog } from "node:util";
2
+ import { Dispatcher, HttpClient, MockAgent, getGlobalDispatcher, setGlobalDispatcher } from "urllib";
3
+
4
+ //#region src/lib/mock_agent.ts
5
+ const debug = debuglog("egg/mock/lib/mock_agent");
6
+ globalThis.__mockAgent = null;
7
+ globalThis.__httpClientDispatchers = /* @__PURE__ */ new Map();
8
+ function getMockAgent(app) {
9
+ debug("getMockAgent");
10
+ if (!globalThis.__globalDispatcher) {
11
+ globalThis.__globalDispatcher = getGlobalDispatcher();
12
+ debug("create global dispatcher");
13
+ }
14
+ if (app?.httpClient && !globalThis.__httpClientDispatchers.has(app.httpClient)) {
15
+ globalThis.__httpClientDispatchers.set(app.httpClient, app.httpClient.getDispatcher());
16
+ debug("add new httpClient, size: %d", globalThis.__httpClientDispatchers.size);
17
+ }
18
+ if (!globalThis.__mockAgent) {
19
+ globalThis.__mockAgent = new MockAgent();
20
+ setGlobalDispatcher(globalThis.__mockAgent);
21
+ if (typeof app?.httpClient?.setDispatcher === "function") app.httpClient.setDispatcher(globalThis.__mockAgent);
22
+ debug("create new mockAgent");
23
+ }
24
+ return globalThis.__mockAgent;
25
+ }
26
+ async function restoreMockAgent() {
27
+ debug("restoreMockAgent start");
28
+ if (globalThis.__globalDispatcher) {
29
+ setGlobalDispatcher(globalThis.__globalDispatcher);
30
+ debug("restore global dispatcher");
31
+ }
32
+ debug("restore httpClient, size: %d", globalThis.__httpClientDispatchers.size);
33
+ for (const [httpClient$1, dispatcher] of globalThis.__httpClientDispatchers) httpClient$1.setDispatcher(dispatcher);
34
+ globalThis.__httpClientDispatchers.clear();
35
+ if (globalThis.__mockAgent) {
36
+ const agent = globalThis.__mockAgent;
37
+ globalThis.__mockAgent = null;
38
+ await agent.close();
39
+ debug("close mockAgent");
40
+ }
41
+ debug("restoreMockAgent end");
42
+ }
43
+
44
+ //#endregion
45
+ export { getMockAgent, restoreMockAgent };
@@ -0,0 +1,4 @@
1
+ //#region src/lib/mock_custom_loader.d.ts
2
+ declare function setCustomLoader(app: any): void;
3
+ //#endregion
4
+ export { setCustomLoader };
@@ -0,0 +1,35 @@
1
+ import { debuglog } from "node:util";
2
+
3
+ //#region src/lib/mock_custom_loader.ts
4
+ const debug = debuglog("egg/mock/lib/mock_custom_loader");
5
+ function setCustomLoader(app) {
6
+ const customLoader = app.config.customLoader;
7
+ if (!customLoader) return;
8
+ for (const field of Object.keys(customLoader)) {
9
+ const loaderConfig = Object.assign({}, customLoader[field]);
10
+ loaderConfig.field = field;
11
+ addMethod(loaderConfig);
12
+ }
13
+ function addMethod(loaderConfig) {
14
+ const field = loaderConfig.field;
15
+ const appMethodName = "mock" + field.replace(/^[a-z]/i, (s) => s.toUpperCase());
16
+ if (app[appMethodName]) {
17
+ app.coreLogger.warn("Can't override app.%s", appMethodName);
18
+ return;
19
+ }
20
+ debug("[addMethod] %s => %j", appMethodName, loaderConfig);
21
+ app[appMethodName] = function(service, methodName, fn) {
22
+ if (typeof service === "string") {
23
+ const arr = service.split(".");
24
+ service = loaderConfig.inject === "ctx" ? this[field + "Classes"] : this[field];
25
+ for (const key of arr) service = service[key];
26
+ service = service.prototype || service;
27
+ }
28
+ this._mockFn(service, methodName, fn);
29
+ return this;
30
+ };
31
+ }
32
+ }
33
+
34
+ //#endregion
35
+ export { setCustomLoader };
@@ -0,0 +1,6 @@
1
+ import { Server } from "node:http";
2
+
3
+ //#region src/lib/mock_http_server.d.ts
4
+ declare function createServer(app: any): Server;
5
+ //#endregion
6
+ export { createServer };
@@ -0,0 +1,17 @@
1
+ import http, { Server } from "node:http";
2
+
3
+ //#region src/lib/mock_http_server.ts
4
+ const SERVER = Symbol("http_server");
5
+ function createServer(app) {
6
+ let server = app[SERVER] || app.callback();
7
+ if (typeof server === "function") {
8
+ server = http.createServer(server);
9
+ app[SERVER] = server;
10
+ if (!app.server) app.server = server;
11
+ app.emit("server", server);
12
+ }
13
+ return server;
14
+ }
15
+
16
+ //#endregion
17
+ export { createServer };
@@ -0,0 +1,40 @@
1
+ import { BodyInit, Dispatcher, Headers } from "urllib";
2
+
3
+ //#region src/lib/mock_httpclient.d.ts
4
+ interface MockResultOptions {
5
+ data: string | Buffer | Record<string, any>;
6
+ /**
7
+ * http status
8
+ */
9
+ status?: number;
10
+ /**
11
+ * response header
12
+ */
13
+ headers?: Record<string, string>;
14
+ /**
15
+ * delay the associated reply by a set amount in ms
16
+ */
17
+ delay?: number;
18
+ /**
19
+ * any matching request will always reply with the defined response indefinitely
20
+ */
21
+ persist?: boolean;
22
+ /**
23
+ * any matching request will reply with the defined response a fixed amount of times
24
+ */
25
+ repeats?: number;
26
+ }
27
+ type ResultObject = MockResultOptions;
28
+ interface MockResponseCallbackOptions {
29
+ path: string;
30
+ method: string;
31
+ headers?: Headers | Record<string, string>;
32
+ origin?: string;
33
+ body?: BodyInit | Dispatcher.DispatchOptions['body'] | null;
34
+ maxRedirections?: number;
35
+ }
36
+ type MockResultFunction = (url: string, options: MockResponseCallbackOptions) => MockResultOptions | string;
37
+ declare function createMockHttpClient(app: any): (mockUrl: string | RegExp, mockMethod: string | string[] | MockResultOptions | MockResultFunction, mockResult?: MockResultOptions | MockResultFunction | string) => void;
38
+ type MockHttpClientMethod = ReturnType<typeof createMockHttpClient>;
39
+ //#endregion
40
+ export { MockHttpClientMethod, MockResponseCallbackOptions, MockResultFunction, MockResultOptions, ResultObject, createMockHttpClient };