diff --git a/.github/workflows/pkg.pr.new.yml b/.github/workflows/pkg.pr.new.yml
new file mode 100644
index 0000000..bac3fac
--- /dev/null
+++ b/.github/workflows/pkg.pr.new.yml
@@ -0,0 +1,23 @@
+name: Publish Any Commit
+on: [push, pull_request]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - run: corepack enable
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Build
+ run: npm run prepublishOnly --if-present
+
+ - run: npx pkg-pr-new publish
diff --git a/README.md b/README.md
index 6e259a3..928acbd 100644
--- a/README.md
+++ b/README.md
@@ -523,6 +523,7 @@ it('should work', function() {
```
### env for custom bootstrap
+
EGG_BASE_DIR: the base dir of egg app
EGG_FRAMEWORK: the framework of egg app
@@ -534,16 +535,8 @@ Please open an issue [here](https://github.com/eggjs/egg/issues).
[MIT](LICENSE)
-
-
## Contributors
-|[
popomore](https://github.com/popomore)
|[
fengmk2](https://github.com/fengmk2)
|[
atian25](https://github.com/atian25)
|[
dead-horse](https://github.com/dead-horse)
|[
shepherdwind](https://github.com/shepherdwind)
|[
shaoshuai0102](https://github.com/shaoshuai0102)
|
-| :---: | :---: | :---: | :---: | :---: | :---: |
-|[
mansonchor](https://github.com/mansonchor)
|[
whxaxes](https://github.com/whxaxes)
|[
brickyang](https://github.com/brickyang)
|[
zbinlin](https://github.com/zbinlin)
|[
GoodMeowing](https://github.com/GoodMeowing)
|[
ngot](https://github.com/ngot)
|
-|[
geekdada](https://github.com/geekdada)
|[
shinux](https://github.com/shinux)
|[
zhang740](https://github.com/zhang740)
|[
caoer](https://github.com/caoer)
|[
lidianhao123](https://github.com/lidianhao123)
|[
limerickgds](https://github.com/limerickgds)
|
-[
paranoidjk](https://github.com/paranoidjk)
|[
gxcsoccer](https://github.com/gxcsoccer)
|[
okoala](https://github.com/okoala)
|[
ImHype](https://github.com/ImHype)
|[
linjiajian999](https://github.com/linjiajian999)
-
-This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Fri Apr 29 2022 22:49:14 GMT+0800`.
+[![Contributors](https://contrib.rocks/image?repo=eggjs/egg-mock)](https://github.com/eggjs/egg-mock/graphs/contributors)
-
+Made with [contributors-img](https://contrib.rocks).
diff --git a/README.zh_CN.md b/README.zh_CN.md
index dc2c9c2..013d573 100644
--- a/README.zh_CN.md
+++ b/README.zh_CN.md
@@ -494,6 +494,7 @@ describe('test ctx', () => {
```
### env for custom bootstrap
+
EGG_BASE_DIR: the base dir of egg app
EGG_FRAMEWORK: the framework of egg app
@@ -505,16 +506,8 @@ Please open an issue [here](https://github.com/eggjs/egg/issues).
[MIT](LICENSE)
-
-
## Contributors
-|[
popomore](https://github.com/popomore)
|[
fengmk2](https://github.com/fengmk2)
|[
atian25](https://github.com/atian25)
|[
dead-horse](https://github.com/dead-horse)
|[
shepherdwind](https://github.com/shepherdwind)
|[
shaoshuai0102](https://github.com/shaoshuai0102)
|
-| :---: | :---: | :---: | :---: | :---: | :---: |
-|[
mansonchor](https://github.com/mansonchor)
|[
whxaxes](https://github.com/whxaxes)
|[
brickyang](https://github.com/brickyang)
|[
zbinlin](https://github.com/zbinlin)
|[
GoodMeowing](https://github.com/GoodMeowing)
|[
ngot](https://github.com/ngot)
|
-|[
geekdada](https://github.com/geekdada)
|[
shinux](https://github.com/shinux)
|[
zhang740](https://github.com/zhang740)
|[
caoer](https://github.com/caoer)
|[
lidianhao123](https://github.com/lidianhao123)
|[
limerickgds](https://github.com/limerickgds)
|
-[
paranoidjk](https://github.com/paranoidjk)
|[
gxcsoccer](https://github.com/gxcsoccer)
|[
okoala](https://github.com/okoala)
|[
ImHype](https://github.com/ImHype)
|[
linjiajian999](https://github.com/linjiajian999)
-
-This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Fri Apr 29 2022 22:49:14 GMT+0800`.
+[![Contributors](https://contrib.rocks/image?repo=eggjs/egg-mock)](https://github.com/eggjs/egg-mock/graphs/contributors)
-
+Made with [contributors-img](https://contrib.rocks).
diff --git a/app/extend/agent.js b/app/extend/agent.js
index f211783..d85a5f7 100644
--- a/app/extend/agent.js
+++ b/app/extend/agent.js
@@ -22,11 +22,11 @@ module.exports = {
* @return {MockAgent} agent
*/
mockAgent() {
- return mockAgent.getAgent();
+ return mockAgent.getAgent(this);
},
mockAgentRestore() {
- return mockAgent.restore();
+ return mockAgent.restore(this);
},
/**
diff --git a/app/extend/application.js b/app/extend/application.js
index 251c9ef..020f14a 100644
--- a/app/extend/application.js
+++ b/app/extend/application.js
@@ -303,11 +303,11 @@ module.exports = {
* @return {MockAgent} agent
*/
mockAgent() {
- return mockAgent.getAgent();
+ return mockAgent.getAgent(this);
},
mockAgentRestore() {
- return mockAgent.restore();
+ return mockAgent.restore(this);
},
/**
diff --git a/index.js b/index.js
index a79b4b8..6382895 100644
--- a/index.js
+++ b/index.js
@@ -4,7 +4,9 @@ const app = require('./lib/app');
const mockAgent = require('./lib/mock_agent');
// egg-bin will set this flag to require files for instrument
-if (process.env.EGG_BIN_PREREQUIRE) require('./lib/prerequire');
+if (process.env.EGG_BIN_PREREQUIRE) {
+ require('./lib/prerequire');
+}
/**
* @namespace mm
@@ -22,7 +24,7 @@ Object.assign(mock, mm, {
cluster.restore();
mm.restore();
// return promise
- return mockAgent.restore();
+ return mockAgent.restore(app);
},
/**
diff --git a/lib/mock_agent.js b/lib/mock_agent.js
index f5e6858..9eeba0d 100644
--- a/lib/mock_agent.js
+++ b/lib/mock_agent.js
@@ -2,21 +2,36 @@ const { MockAgent, setGlobalDispatcher, getGlobalDispatcher } = require('urllib'
let _mockAgent;
let _global;
+const APP_HTTPCLIENT_AGENT = Symbol('app.httpclient.agent');
module.exports = {
- getAgent() {
+ getAgent(app) {
if (!_global) {
_global = getGlobalDispatcher();
+ if (typeof app?.httpclient?.getDispatcher === 'function') {
+ if (!app[APP_HTTPCLIENT_AGENT]) {
+ // save the raw dispatcher
+ app[APP_HTTPCLIENT_AGENT] = app.httpclient.getDispatcher();
+ }
+ }
}
if (!_mockAgent) {
_mockAgent = new MockAgent();
setGlobalDispatcher(_mockAgent);
+ if (typeof app?.httpclient?.setDispatcher === 'function') {
+ app.httpclient.setDispatcher(_mockAgent);
+ }
}
return _mockAgent;
},
- async restore() {
+ async restore(app) {
if (!_mockAgent) return;
- if (_global) setGlobalDispatcher(_global);
+ if (_global) {
+ setGlobalDispatcher(_global);
+ if (app?.[APP_HTTPCLIENT_AGENT]) {
+ app.httpclient.setDispatcher(app[APP_HTTPCLIENT_AGENT]);
+ }
+ }
const agent = _mockAgent;
_mockAgent = null;
await agent.close();
diff --git a/lib/mock_httpclient.js b/lib/mock_httpclient.js
index d488f12..57515cf 100644
--- a/lib/mock_httpclient.js
+++ b/lib/mock_httpclient.js
@@ -114,7 +114,7 @@ module.exports = app => {
mockConfigIndex = mockConfigs.length;
mockConfigs.push({ mockUrl, mockResult, mockConfigIndex });
}
- const mockPool = mockAgent.getAgent().get(origin);
+ const mockPool = mockAgent.getAgent(app).get(origin);
// persist default is true
const persist = typeof mockResult?.persist === 'boolean' ? mockResult?.persist : true;
mockMethod.forEach(function(method) {
diff --git a/package.json b/package.json
index 90a6574..286d34c 100644
--- a/package.json
+++ b/package.json
@@ -23,8 +23,7 @@
"test": "npm run lint && npm run tsd && npm run test-local",
"test-local": "egg-bin test -r ./register.js --ts false",
"cov": "egg-bin cov -r ./register.js --ts false",
- "ci": "npm run lint && npm run tsd && npm run cov",
- "contributors": "git-contributor"
+ "ci": "npm run lint && npm run tsd && npm run cov"
},
"dependencies": {
"@types/supertest": "^2.0.7",
@@ -63,7 +62,6 @@
"egg-tracer": "^2.0.0",
"eslint": "^8.24.0",
"eslint-config-egg": "^12.0.0",
- "git-contributor": "^2.0.0",
"mocha": "^10.1.0",
"pedding": "^1.1.0",
"tsd": "^0.31.0",
diff --git a/test/fixtures/demo_next_h2/app.js b/test/fixtures/demo_next_h2/app.js
new file mode 100644
index 0000000..0c134c2
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = function() {
+
+};
diff --git a/test/fixtures/demo_next_h2/app/context.js b/test/fixtures/demo_next_h2/app/context.js
new file mode 100644
index 0000000..8422a63
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/context.js
@@ -0,0 +1,9 @@
+'use strict';
+
+module.exports = {
+ getResult(result) {
+ return {
+ body: result,
+ };
+ },
+};
diff --git a/test/fixtures/demo_next_h2/app/controller/file.js b/test/fixtures/demo_next_h2/app/controller/file.js
new file mode 100644
index 0000000..e98c443
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/controller/file.js
@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = function* () {
+ const stream = yield this.getFileStream();
+ const fields = stream.fields;
+ this.body = {
+ fields,
+ filename: stream.filename,
+ user: this.user,
+ };
+};
diff --git a/test/fixtures/demo_next_h2/app/controller/home.js b/test/fixtures/demo_next_h2/app/controller/home.js
new file mode 100644
index 0000000..395021b
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/controller/home.js
@@ -0,0 +1,104 @@
+'use strict';
+
+exports.get = function* () {
+ this.body = {
+ cookieValue: this.getCookie('foo') || undefined,
+ cookiesValue: this.cookies.get('foo') || undefined,
+ sessionValue: this.session.foo,
+ };
+};
+
+exports.post = function* () {
+ this.body = 'done';
+};
+
+exports.hello = function* () {
+ this.body = 'hi';
+};
+
+exports.service = function* () {
+ this.body = {
+ foo1: yield this.service.foo.get(),
+ foo2: yield this.service.bar.foo.get(),
+ foo3: this.service.foo.getSync(),
+ thirdService: yield this.service.third.bar.foo.get(),
+ };
+};
+
+exports.serviceOld = function* () {
+ this.body = yield this.service.old.test();
+};
+
+exports.header = function* () {
+ this.body = {
+ header: this.get('customheader'),
+ };
+};
+
+exports.urllib = function* () {
+ const url = 'http://' + this.host;
+ const method = this.query.method || 'request';
+ const data = this.query.data ? JSON.parse(this.query.data) : undefined;
+ const dataType = this.query.dataType;
+ const foo = this.query.foo;
+ let requestUrl = url + (this.query.mock_url || '/mock_url');
+ if (foo) {
+ requestUrl = `${requestUrl}?foo=${foo}`;
+ }
+ let r = this.app.httpclient[method](requestUrl, {
+ dataType,
+ data,
+ });
+ if (method === 'request') r = r.then(d => d);
+ const r1 = yield r;
+ const r2 = yield this.app.httpclient[method](requestUrl, {
+ method: 'POST',
+ dataType,
+ data,
+ headers: {
+ 'x-custom': 'custom',
+ },
+ });
+ this.body = {
+ get: Buffer.isBuffer(r1.data) ? r1.data.toString() : r1.data,
+ post: Buffer.isBuffer(r2.data) ? r2.data.toString() : r2.data,
+ };
+};
+
+exports.streaming = async ctx => {
+ const url = 'http://' + ctx.host;
+ const response = await ctx.httpclient.request(url + '/mock_url', {
+ method: 'GET',
+ streaming: true,
+ });
+ ctx.status = response.status;
+ ctx.body = response.res;
+};
+
+exports.mockUrlGet = function* () {
+ const foo = this.query.foo;
+ if (foo) {
+ this.body = `url get with foo: ${foo}`;
+ return;
+ }
+ this.body = 'url get';
+};
+
+exports.mockUrlPost = function* () {
+ this.body = 'url post';
+};
+
+exports.mockUrllibHeaders = function* () {
+ const url = 'http://' + this.host;
+ const method = this.query.method || 'request';
+ const res = yield this.app.httpclient[method](url + '/mock_url');
+ this.body = res.headers;
+};
+
+exports.dataType = function* () {
+ const url = 'http://' + this.host;
+ const res = yield this.app.httpclient.request(url + '/mock_url', {
+ dataType: 'json',
+ });
+ this.body = res.data;
+};
diff --git a/test/fixtures/demo_next_h2/app/controller/session.js b/test/fixtures/demo_next_h2/app/controller/session.js
new file mode 100644
index 0000000..5e9e198
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/controller/session.js
@@ -0,0 +1,6 @@
+'use strict';
+
+module.exports = function* () {
+ this.session.save();
+ this.body = this.session;
+};
diff --git a/test/fixtures/demo_next_h2/app/controller/user.js b/test/fixtures/demo_next_h2/app/controller/user.js
new file mode 100644
index 0000000..b789ef2
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/controller/user.js
@@ -0,0 +1,12 @@
+'use strict';
+
+exports.get = function* () {
+ this.body = this.user;
+};
+
+exports.post = function* () {
+ this.body = {
+ user: this.user,
+ params: this.request.body,
+ };
+};
diff --git a/test/fixtures/demo_next_h2/app/extend/application.js b/test/fixtures/demo_next_h2/app/extend/application.js
new file mode 100644
index 0000000..2810f72
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/extend/application.js
@@ -0,0 +1,18 @@
+'use strict';
+
+module.exports = {
+ mockDevice(obj) {
+ obj.mock = true;
+ return obj;
+ },
+
+ * mockGenerator(obj) {
+ obj.mock = true;
+ return obj;
+ },
+
+ mockPromise(obj) {
+ obj.mock = true;
+ return Promise.resolve(obj);
+ },
+};
diff --git a/test/fixtures/demo_next_h2/app/router.js b/test/fixtures/demo_next_h2/app/router.js
new file mode 100644
index 0000000..0af9e43
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/router.js
@@ -0,0 +1,23 @@
+module.exports = app => {
+ app.get('home', '/', app.controller.home.get);
+ app.get('/hello', app.controller.home.hello);
+ app.get('/service', app.controller.home.service);
+ app.get('/service/old', app.controller.home.serviceOld);
+ app.get('/header', app.controller.home.header);
+ app.get('/urllib', app.controller.home.urllib);
+ app.get('/mock_url', app.controller.home.mockUrlGet);
+ app.get('/mock_url2', app.controller.home.mockUrlGet);
+ app.post('/mock_url', app.controller.home.mockUrlPost);
+ app.post('/mock_url2', app.controller.home.mockUrlPost);
+ app.get('/mock_urllib', app.controller.home.mockUrllibHeaders);
+ app.get('/data_type', app.controller.home.dataType);
+ app.get('session', '/session', app.controller.session);
+
+ app.post('/', app.controller.home.post);
+
+ app.get('/user', app.controller.user.get);
+ app.post('/user', app.controller.user.post);
+ app.post('/file', app.controller.file);
+
+ app.get('/streaming', 'home.streaming');
+};
diff --git a/test/fixtures/demo_next_h2/app/service/bar/foo.js b/test/fixtures/demo_next_h2/app/service/bar/foo.js
new file mode 100644
index 0000000..8070a93
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/service/bar/foo.js
@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = function(app) {
+ class Foo extends app.Service {
+ * get() {
+ return 'bar';
+ }
+ }
+
+ return Foo;
+};
diff --git a/test/fixtures/demo_next_h2/app/service/foo.js b/test/fixtures/demo_next_h2/app/service/foo.js
new file mode 100644
index 0000000..467c747
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/service/foo.js
@@ -0,0 +1,15 @@
+'use strict';
+
+module.exports = function(app) {
+ class Foo extends app.Service {
+ * get() {
+ return 'bar';
+ }
+
+ getSync() {
+ return 'bar';
+ }
+ }
+
+ return Foo;
+};
diff --git a/test/fixtures/demo_next_h2/app/service/old.js b/test/fixtures/demo_next_h2/app/service/old.js
new file mode 100644
index 0000000..29ea81e
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/service/old.js
@@ -0,0 +1,9 @@
+'use strict';
+
+module.exports = () => {
+ exports.test = function* () {
+ return 'hello';
+ };
+
+ return exports;
+};
diff --git a/test/fixtures/demo_next_h2/app/service/third/bar/foo.js b/test/fixtures/demo_next_h2/app/service/third/bar/foo.js
new file mode 100644
index 0000000..21c1807
--- /dev/null
+++ b/test/fixtures/demo_next_h2/app/service/third/bar/foo.js
@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = function(app) {
+ class Main extends app.Service {
+ * get() {
+ return 'third';
+ }
+ }
+
+ return Main;
+};
diff --git a/test/fixtures/demo_next_h2/config/config.js b/test/fixtures/demo_next_h2/config/config.js
new file mode 100644
index 0000000..05cad3f
--- /dev/null
+++ b/test/fixtures/demo_next_h2/config/config.js
@@ -0,0 +1,13 @@
+module.exports = {
+ httpclient: {
+ useHttpClientNext: true,
+ allowH2: true,
+ request: {
+ timing: true,
+ },
+ },
+ logger: {
+ consoleLevel: 'NONE',
+ },
+ keys: '123',
+};
diff --git a/test/fixtures/demo_next_h2/mocks_data/service/bar/foo/get/foobar.js b/test/fixtures/demo_next_h2/mocks_data/service/bar/foo/get/foobar.js
new file mode 100644
index 0000000..af79a2f
--- /dev/null
+++ b/test/fixtures/demo_next_h2/mocks_data/service/bar/foo/get/foobar.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = 'foobar';
diff --git a/test/fixtures/demo_next_h2/mocks_data/service/foo/get/foobar.js b/test/fixtures/demo_next_h2/mocks_data/service/foo/get/foobar.js
new file mode 100644
index 0000000..af79a2f
--- /dev/null
+++ b/test/fixtures/demo_next_h2/mocks_data/service/foo/get/foobar.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = 'foobar';
diff --git a/test/fixtures/demo_next_h2/package.json b/test/fixtures/demo_next_h2/package.json
new file mode 100644
index 0000000..e38ae2e
--- /dev/null
+++ b/test/fixtures/demo_next_h2/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "demo"
+}
diff --git a/test/mock_httpclient_next_h2.test.js b/test/mock_httpclient_next_h2.test.js
new file mode 100644
index 0000000..ab7b97c
--- /dev/null
+++ b/test/mock_httpclient_next_h2.test.js
@@ -0,0 +1,525 @@
+const pedding = require('pedding');
+const path = require('path');
+const fs = require('fs');
+const request = require('supertest');
+const assert = require('assert');
+const mm = require('..');
+
+const fixtures = path.join(__dirname, 'fixtures');
+
+describe('test/mock_httpclient_next_h2.test.js', () => {
+ let app;
+ let server;
+ let url;
+ let url2;
+ before(() => {
+ app = mm.app({
+ baseDir: path.join(fixtures, 'demo_next_h2'),
+ });
+ return app.ready();
+ });
+ before(() => {
+ server = app.listen();
+ url = `http://127.0.0.1:${server.address().port}/mock_url`;
+ url2 = `http://127.0.0.1:${server.address().port}/mock_url2`;
+ });
+ after(() => app.close());
+ afterEach(mm.restore);
+
+ it('should mock url and get response event on urllib', done => {
+ done = pedding(2, done);
+ app.mockCsrf();
+ app.mockHttpclient(url, {
+ data: Buffer.from('mock all response'),
+ });
+
+ request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock all response',
+ post: 'mock all response',
+ })
+ .expect(200, done);
+
+ app.httpclient.once('response', result => {
+ assert('url' in result.req);
+ // assert('size' in result.req);
+ assert('options' in result.req);
+
+ assert(result.res.status === 200);
+ assert(result.res.statusCode === 200);
+ assert.deepEqual(result.res.headers, {});
+ assert(result.res.rt);
+ done();
+ });
+
+ let count = 0;
+ app.httpclient.on('response', result => {
+ if (count === 0) {
+ const options = result.req.options;
+ assert(options.method === 'GET');
+ } else if (count === 1) {
+ const options = result.req.options;
+ assert(options.method === 'POST');
+ assert(options.headers['x-custom'] === 'custom');
+ }
+ count++;
+ });
+ });
+
+ it('should mock url using app.mockAgent().intercept()', async () => {
+ app.mockCsrf();
+ app.mockAgent()
+ .get(new URL(url).origin)
+ .intercept({
+ path: '/mock_url',
+ method: 'GET',
+ })
+ .reply(200, 'mock GET response');
+ app.mockAgent()
+ .get(new URL(url).origin)
+ .intercept({
+ path: '/mock_url',
+ method: 'POST',
+ })
+ .reply(200, 'mock POST response');
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock GET response',
+ post: 'mock POST response',
+ })
+ .expect(200);
+ });
+
+ it('should support on streaming', async () => {
+ app.mockHttpclient(url, 'get', {
+ data: fs.readFileSync(__filename),
+ });
+
+ const res = await request(server)
+ .get('/streaming')
+ .expect(200);
+ assert.match(res.body.toString(), /should support on streaming/);
+ assert.equal(res.body.toString(), fs.readFileSync(__filename, 'utf8'));
+ });
+
+ it('should mock url support multi method', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, [ 'get', 'post' ], {
+ data: Buffer.from('mock response'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock response',
+ post: 'mock response',
+ })
+ .expect(200);
+ });
+
+ it('should mockHttpclient call multi times work with Regex', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(/\/not\/match\//, {
+ data: Buffer.from('mock not match response'),
+ });
+ app.mockHttpclient(/\/mock_url/, {
+ data: Buffer.from('mock 1 match response'),
+ });
+ app.mockHttpclient(/\/mock_url/, {
+ data: Buffer.from('mock 2 match response'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock 1 match response',
+ post: 'mock 1 match response',
+ })
+ .expect(200);
+ });
+
+ it('should mockHttpclient call multi times work with url string', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(`${url}-not-match`, {
+ data: Buffer.from('mock not match response'),
+ });
+ app.mockHttpclient(url, {
+ data: Buffer.from('mock 1 match response'),
+ });
+ app.mockHttpclient(url, {
+ data: Buffer.from('mock 2 match response'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock 1 match response',
+ post: 'mock 1 match response',
+ })
+ .expect(200);
+ });
+
+ it('should mock url method support *', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, '*', {
+ data: Buffer.from('mock * response'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock * response',
+ post: 'mock * response',
+ })
+ .expect(200);
+ });
+
+ it('should mock url post', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'post', {
+ data: Buffer.from('mock url post'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'url get',
+ post: 'mock url post',
+ })
+ .expect(200);
+ });
+
+ it('should use first mock data on duplicate url mock', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'post', {
+ data: Buffer.from('mock url1 first post'),
+ });
+ // should ignore this same url mock data, use the first mock data
+ app.mockHttpclient(url, 'post', {
+ data: Buffer.from('mock url1 second post'),
+ });
+ app.mockHttpclient(url2, 'post', {
+ data: Buffer.from('mock url2 post'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'url get',
+ post: 'mock url1 first post',
+ })
+ .expect(200);
+ await request(server)
+ .get('/urllib')
+ .query({
+ mock_url: '/mock_url2',
+ })
+ .expect({
+ get: 'url get',
+ post: 'mock url2 post',
+ })
+ .expect(200);
+ });
+
+ it('should mock work on query', async () => {
+ app.mockCsrf();
+ // mockHttpclient not support query, should use mockAgent instead
+ app.mockHttpclient(`${url}?foo=foo1`, 'get', {
+ data: Buffer.from('mock foo1'),
+ });
+ app.mockHttpclient(`${url}?foo=foo2`, 'get', {
+ data: Buffer.from('mock foo1'),
+ });
+ await request(server)
+ .get('/urllib')
+ .query({ foo: 'foo1' })
+ .expect({
+ get: 'mock foo1',
+ post: 'url post',
+ })
+ .expect(200);
+ await request(server)
+ .get('/urllib')
+ .query({ foo: 'foo2' })
+ .expect({
+ get: 'mock foo1',
+ post: 'url post',
+ })
+ .expect(200);
+ await app.mockAgentRestore();
+
+ app.mockAgent().get(new URL(url).origin)
+ .intercept({
+ path: '/mock_url?foo=foo1',
+ method: 'GET',
+ })
+ .reply(200, 'mock new foo1');
+ app.mockAgent().get(new URL(url).origin)
+ .intercept({
+ path: '/mock_url?foo=foo2',
+ method: 'GET',
+ })
+ .reply(200, 'mock new foo2');
+ await request(server)
+ .get('/urllib')
+ .query({ foo: 'foo1' })
+ .expect({
+ get: 'mock new foo1',
+ post: 'url post',
+ })
+ .expect(200);
+ await request(server)
+ .get('/urllib')
+ .query({ foo: 'foo2' })
+ .expect({
+ get: 'mock new foo2',
+ post: 'url post',
+ })
+ .expect(200);
+ });
+
+ it('should mock url get and post', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'post', {
+ data: 'mock url post',
+ });
+ app.mockHttpclient(url, {
+ data: 'mock url get',
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock url get',
+ post: 'mock url post',
+ })
+ .expect(200);
+ });
+
+ it('should support request', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'post', {
+ data: 'mock url post',
+ });
+ app.mockHttpclient(url, {
+ data: 'mock url get',
+ });
+
+ await request(server)
+ .get('/urllib?method=request')
+ .expect({
+ get: 'mock url get',
+ post: 'mock url post',
+ })
+ .expect(200);
+ });
+
+ it('should support persist = false', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, {
+ data: 'mock url',
+ persist: false,
+ });
+
+ await request(server)
+ .get('/urllib?method=request')
+ .expect({
+ get: 'mock url',
+ post: 'url post',
+ })
+ .expect(200);
+ });
+
+ it('should support persist = true and ignore repeats = 1', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, {
+ data: 'mock url',
+ persist: true,
+ repeats: 1,
+ });
+
+ await request(server)
+ .get('/urllib?method=request')
+ .expect({
+ get: 'mock url',
+ post: 'mock url',
+ })
+ .expect(200);
+ });
+
+ it('should support persist = false and repeats = 2', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, {
+ data: 'mock url',
+ delay: 100,
+ persist: false,
+ repeats: 2,
+ });
+
+ await request(server)
+ .get('/urllib?method=request')
+ .expect({
+ get: 'mock url',
+ post: 'mock url',
+ })
+ .expect(200);
+
+ await request(server)
+ .get('/urllib?method=request')
+ .expect({
+ get: 'url get',
+ post: 'url post',
+ })
+ .expect(200);
+ });
+
+ it('should support curl', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'post', {
+ data: 'mock url post',
+ });
+ app.mockHttpclient(url, {
+ data: 'mock url get',
+ });
+
+ await request(server)
+ .get('/urllib?method=curl')
+ .expect({
+ get: 'mock url get',
+ post: 'mock url post',
+ })
+ .expect(200);
+ });
+
+ it('should support json', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'get', {
+ data: { method: 'get' },
+ });
+ app.mockHttpclient(url, 'post', {
+ data: { method: 'post' },
+ });
+
+ await request(server)
+ .get('/urllib?dataType=json')
+ .expect({
+ get: { method: 'get' },
+ post: { method: 'post' },
+ })
+ .expect(200);
+ });
+
+ it('should support text', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'post', {
+ data: 'mock url post',
+ });
+ app.mockHttpclient(url, {
+ data: 'mock url get',
+ });
+
+ await request(server)
+ .get('/urllib?dataType=text')
+ .expect({
+ get: 'mock url get',
+ post: 'mock url post',
+ })
+ .expect(200);
+ });
+
+ it('should exits req headers', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, {
+ data: 'mock url test',
+ });
+ await request(server)
+ .get('/mock_urllib')
+ .expect({})
+ .expect(200);
+ });
+
+ it('should mock url path support RegExp', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(/\/mock_url$/, {
+ data: Buffer.from('mock response'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock response',
+ post: 'mock response',
+ })
+ .expect(200);
+ });
+
+ it('should mock full url support RegExp', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(/http:\/\/127\.0\.0\.1:\d+\/mock_url$/, [ 'get', 'post' ], {
+ data: Buffer.from('mock full 127 url response'),
+ });
+
+ await request(server)
+ .get('/urllib')
+ .expect({
+ get: 'mock full 127 url response',
+ post: 'mock full 127 url response',
+ })
+ .expect(200);
+ });
+
+ it('should use copy of mock data', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(/\/mock_url$/, {
+ data: { a: 1 },
+ });
+
+ await request(server)
+ .get('/data_type')
+ .expect({
+ a: 1,
+ })
+ .expect(200);
+
+ await request(server)
+ .get('/data_type')
+ .expect({
+ a: 1,
+ })
+ .expect(200);
+ });
+
+ it('should support fn', async () => {
+ app.mockCsrf();
+ app.mockHttpclient(url, 'get', (url, opt) => {
+ return `mock ${url} with ${opt.path}`;
+ });
+ app.mockHttpclient(url, 'post', 'mock url post');
+
+ await request(server)
+ .get('/urllib')
+ .query({ data: JSON.stringify({ a: 'b' }) })
+ .expect({
+ get: `mock ${url}?a=b with /mock_url?a=b`,
+ post: 'mock url post',
+ })
+ .expect(200);
+ });
+
+ it('should mock fn with multi-request without error', async () => {
+ app.mockCsrf();
+ let i = 0;
+ app.mockHttpclient(url, 'post', () => {
+ i++;
+ return {};
+ });
+
+ await request(server).get('/urllib').expect(200);
+ await request(server).get('/urllib').expect(200);
+ await request(server).get('/urllib').expect(200);
+ assert(i === 3);
+ });
+});