Skip to content

Commit 208cfd7

Browse files
committed
Support delay mock
1 parent 80312ed commit 208cfd7

File tree

8 files changed

+80
-19
lines changed

8 files changed

+80
-19
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ So, I create one by myself.
1414
- [x] Combined with Mock.js
1515
- [x] Support exclude for some other path
1616
- [x] Proxy for other api server
17+
- [x] Delay for global and specific path
1718
- [ ] Support RAP system
1819

1920
## Usage
@@ -61,6 +62,7 @@ import FetchMock from 'react-native-fetch-mock';
6162
6263
if (__dev__) {
6364
global.fetch = new FetchMock(require('path/to/mocks/directory'), {
65+
delay: 200, // 200ms
6466
fetch: global.fetch,
6567
exclude: [
6668
'http://www.google.com',
@@ -79,6 +81,7 @@ if (__dev__) {
7981
// if __dev__ is true, it will back the data you defined in mock directory
8082
fetch('/api/path', options);
8183
fetch('/api/path', {
84+
delay: 2000, // /api/path will delayed after 2000ms. Most of suitation, this won't be used usually.
8285
method: 'POST',
8386
headers: {
8487
'Content-Type': 'application/json',

dist/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,7 @@ Object.defineProperty(exports,"__esModule",{value:true});exports.Mock=undefined;
142142

143143

144144

145-
default;}});var _pathToRegexp=require('path-to-regexp');var _pathToRegexp2=_interopRequireDefault(_pathToRegexp);var _util=require('./util');var _response=require('./response');var _response2=_interopRequireDefault(_response);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}var FetchMock=function(){function FetchMock(required){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{fetch:function fetch(){},exclude:[],proxy:[]};_classCallCheck(this,FetchMock);if('object'!==typeof required){throw new Error('There is no required defined.');}this.urls=[];this.raw=options.fetch;this.exclude=options.exclude||[];this.proxy=options.proxy||[];this.loadMocks=this.loadMocks.bind(this);this.loadMock=this.loadMock.bind(this);this.matchReqUrl=this.matchReqUrl.bind(this);this.isExclude=this.isExclude.bind(this);this.isProxied=this.isProxied.bind(this);this.fetch=this.fetch.bind(this);this.loadMocks(required);}_createClass(FetchMock,[{key:'loadMocks',value:function loadMocks(required){var _this=this;var __mocks__=required.default||required;var mocks=Object.keys(__mocks__);mocks.forEach(function(key){_this.loadMock(key,__mocks__[key]);});}},{key:'loadMock',value:function loadMock(key,mock){var _this2=this;if('object'!==typeof mock){if('function'===typeof mock){var items=key.split(' ');var method=items.length===2?items[0]:'GET';var url=items.length===2?items[1]:key;this.urls.push({method:method,url:url,func:mock});}return;}var keys=Object.keys(mock);keys.map(function(key){_this2.loadMock(key,mock[key]);});}},{key:'matchReqUrl',value:function matchReqUrl(request){var insideParams=void 0;var filters=this.urls.filter(function(uri){var obj=(0,_util.matchUrl)(uri.url,request.url);if(obj.result&&uri.method.toUpperCase()===request.method.toUpperCase()){insideParams=obj.params;return true;}return false;});if(!filters||filters.length==0)throw new Error('No url '+request.url+' is defined.');request.urlparams=insideParams;return{request:request,mock:filters[0]};}},{key:'isExclude',value:function isExclude(url){for(var i=0;i<this.exclude.length;i++){var excludeUrl=this.exclude[i];if(excludeUrl===url||(0,_pathToRegexp2.default)(''+excludeUrl).exec(url)!==null){return true;}}return false;}},{key:'isProxied',value:function isProxied(url){if(this.proxy.length===0)return false;var proxied=this.proxy.filter(function(item){return(0,_pathToRegexp2.default)(''+item.path).exec(url)!==null;});if(proxied.length>1)throw new Error(url+' proxied has two proxies, you should specific only one');return proxied[0];}},{key:'proxied',value:function proxied(url){var matches=void 0,proxied=void 0;this.proxy.forEach(function(item){var tmp=(0,_pathToRegexp2.default)(item.path).exec(url);if(tmp.length>1){matches=tmp;proxied=item;return false;}});return proxied.process?proxied.process(proxied,matches):proxied.target+'/'+matches[1];}},{key:'fetch',value:function fetch(url,options){if(this.isProxied(url)){url=this.proxied(url);}if(this.isExclude(url)){return this.raw(url,options);}var _matchReqUrl=this.matchReqUrl((0,_util.parseRequest)(url,options)),request=_matchReqUrl.request,mock=_matchReqUrl.mock;if('function'!==typeof mock.func){throw new Error('There is no url defined in __mocks__');}var obj=mock.func(request);if((0,_util.isNull)(obj)){throw'response data should not be undefined or null, it will be an object or an array at least';}if((0,_util.isNull)(obj.status)){obj={status:200,data:obj};}var response=new _response2.default(obj);return Promise.resolve(response);}}]);return FetchMock;}();exports.default=FetchMock;
145+
146+
147+
148+
default;}});var _pathToRegexp=require('path-to-regexp');var _pathToRegexp2=_interopRequireDefault(_pathToRegexp);var _util=require('./util');var _response=require('./response');var _response2=_interopRequireDefault(_response);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}var FetchMock=function(){function FetchMock(required){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{fetch:function fetch(){},exclude:[],proxy:[],delay:2000};_classCallCheck(this,FetchMock);if('object'!==typeof required){throw new Error('There is no required defined.');}this.urls=[];this.raw=options.fetch;this.exclude=options.exclude||[];this.proxy=options.proxy||[];this.delayTime=options.delay;this.loadMocks=this.loadMocks.bind(this);this.loadMock=this.loadMock.bind(this);this.matchReqUrl=this.matchReqUrl.bind(this);this.isExclude=this.isExclude.bind(this);this.isProxied=this.isProxied.bind(this);this.fetch=this.fetch.bind(this);this.loadMocks(required);}_createClass(FetchMock,[{key:'loadMocks',value:function loadMocks(required){var _this=this;var __mocks__=required.default||required;var mocks=Object.keys(__mocks__);mocks.forEach(function(key){_this.loadMock(key,__mocks__[key]);});}},{key:'loadMock',value:function loadMock(key,mock){var _this2=this;if('object'!==typeof mock){if('function'===typeof mock){var items=key.split(' ');var method=items.length===2?items[0]:'GET';var url=items.length===2?items[1]:key;this.urls.push({method:method,url:url,func:mock});}return;}var keys=Object.keys(mock);keys.map(function(key){_this2.loadMock(key,mock[key]);});}},{key:'matchReqUrl',value:function matchReqUrl(request){var insideParams=void 0;var filters=this.urls.filter(function(uri){var obj=(0,_util.matchUrl)(uri.url,request.url);if(obj.result&&uri.method.toUpperCase()===request.method.toUpperCase()){insideParams=obj.params;return true;}return false;});if(!filters||filters.length==0)throw new Error('No url '+request.url+' is defined.');request.urlparams=insideParams;return{request:request,mock:filters[0]};}},{key:'isExclude',value:function isExclude(url){for(var i=0;i<this.exclude.length;i++){var excludeUrl=this.exclude[i];if(excludeUrl===url||(0,_pathToRegexp2.default)(''+excludeUrl).exec(url)!==null){return true;}}return false;}},{key:'isProxied',value:function isProxied(url){if(this.proxy.length===0)return false;var proxied=this.proxy.filter(function(item){return(0,_pathToRegexp2.default)(''+item.path).exec(url)!==null;});if(proxied.length>1)throw new Error(url+' proxied has two proxies, you should specific only one');return proxied[0];}},{key:'proxied',value:function proxied(url){var matches=void 0,proxied=void 0;this.proxy.forEach(function(item){var tmp=(0,_pathToRegexp2.default)(item.path).exec(url);if(tmp.length>1){matches=tmp;proxied=item;return false;}});return proxied.process?proxied.process(proxied,matches):proxied.target+'/'+matches[1];}},{key:'fetch',value:function fetch(url){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};if(this.isProxied(url)){url=this.proxied(url);}if(this.isExclude(url)){return this.raw(url,options);}var _matchReqUrl=this.matchReqUrl((0,_util.parseRequest)(url,options)),request=_matchReqUrl.request,mock=_matchReqUrl.mock;if('function'!==typeof mock.func){throw new Error('There is no url defined in __mocks__');}var obj=mock.func(request);if((0,_util.isNull)(obj)){throw'response data should not be undefined or null, it will be an object or an array at least';}if((0,_util.isNull)(obj.status)){obj={status:200,data:obj};}var response=new _response2.default(obj);var delayTime=options.delay||this.delayTime||0;return(0,_util.delay)(delayTime).then(function(){return Promise.resolve(response);});}}]);return FetchMock;}();exports.default=FetchMock;

dist/util.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,20 @@ return{
121121
result:true,
122122
params:params};
123123

124+
};
125+
126+
var delay=function delay(duration){
127+
return new Promise(function(resolve){
128+
setTimeout(function(){
129+
resolve();
130+
},duration);
131+
});
124132
};exports.
125133

126134

127135
isNull=isNull;exports.
128136
prueUrl=prueUrl;exports.
129137
parseUrl=parseUrl;exports.
130138
parseRequest=parseRequest;exports.
131-
matchUrl=matchUrl;
139+
matchUrl=matchUrl;exports.
140+
delay=delay;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-fetch-mock",
3-
"version": "0.5.3",
3+
"version": "0.6.0",
44
"description": "fetch mock for react-native",
55
"main": "index.js",
66
"scripts": {

src/index.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import pathToRegexp from 'path-to-regexp';
2-
import { parseRequest, matchUrl, isNull } from './util';
2+
import { parseRequest, matchUrl, isNull, delay } from './util';
33
import Response from './response';
44

55
class FetchMock {
66
constructor(required, options = {
77
fetch: () => {},
88
exclude: [],
99
proxy: [],
10+
delay: 2000, // ms
1011
}) {
1112
if ('object' !== typeof required) {
1213
throw new Error('There is no required defined.');
@@ -16,6 +17,7 @@ class FetchMock {
1617
this.raw = options.fetch;
1718
this.exclude = options.exclude || [];
1819
this.proxy = options.proxy || [];
20+
this.delayTime = options.delay;
1921

2022
this.loadMocks = this.loadMocks.bind(this);
2123
this.loadMock = this.loadMock.bind(this);
@@ -106,7 +108,7 @@ class FetchMock {
106108
return proxied.process ? proxied.process(proxied, matches) : `${proxied.target}/${matches[1]}`;
107109
}
108110

109-
fetch(url, options) {
111+
fetch(url, options = {}) {
110112
// using proxy
111113
if (this.isProxied(url)) {
112114
url = this.proxied(url);
@@ -137,7 +139,8 @@ class FetchMock {
137139
}
138140

139141
const response = new Response(obj);
140-
return Promise.resolve(response);
142+
const delayTime = options.delay || this.delayTime || 0;
143+
return delay(delayTime).then(() => Promise.resolve(response));
141144
}
142145
}
143146

src/util.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const matchUrl = (sourceUrl, targetUrl) => {
8787
const targetUrlWithoutProctol = removeProctol(targetUrl);
8888
const sourceUrlSplits = sourceUrlWithoutProctol.split('/');
8989
const targetUrlSplits = targetUrlWithoutProctol.split('/');
90-
90+
9191
if (sourceUrlSplits.length !== targetUrlSplits.length) {
9292
return {
9393
result: false,
@@ -103,7 +103,7 @@ const matchUrl = (sourceUrl, targetUrl) => {
103103
}
104104

105105
if (sourceUrlSplit.startsWith('{') && sourceUrlSplit.endsWith('}')) {
106-
if (sourceUrlSplit.replace(/[^{]/g,'').length > 1 || sourceUrlSplit.replace(/[^}]/g,'').length > 1) {
106+
if (sourceUrlSplit.replace(/[^{]/g, '').length > 1 || sourceUrlSplit.replace(/[^}]/g, '').length > 1) {
107107
return {
108108
result: false,
109109
};
@@ -123,10 +123,19 @@ const matchUrl = (sourceUrl, targetUrl) => {
123123
};
124124
};
125125

126+
const delay = (duration) => {
127+
return new Promise(resolve => {
128+
setTimeout(() => {
129+
resolve();
130+
}, duration);
131+
});
132+
};
133+
126134
export {
127135
isNull,
128136
prueUrl,
129137
parseUrl,
130138
parseRequest,
131139
matchUrl,
140+
delay,
132141
};

test/index.test.js

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import expect from 'expect.js';
33
import FetchMock, { Mock } from '../src';
44

55
const fetch = new FetchMock(require('../__mocks__'), {
6+
delay: 2000, // delay 5s
67
fetch: require('isomorphic-fetch'),
78
exclude: [
89
'https://www.amazon.com',
@@ -28,7 +29,7 @@ describe('test fetch mock', () => {
2829
expect(data).not.to.be.empty();
2930
expect(data).to.be.an('array');
3031
expect(data).to.have.length(2);
31-
});
32+
}).timeout(20000);
3233

3334
it('fetch /api/users?a=b', async () => {
3435
const response = await fetch('/api/users');
@@ -39,7 +40,7 @@ describe('test fetch mock', () => {
3940
expect(data).not.to.be.empty();
4041
expect(data).to.be.an('array');
4142
expect(data).to.have.length(2);
42-
});
43+
}).timeout(20000);
4344

4445
it('fetch /api/users with url parameters', async () => {
4546
const response = await fetch('/api/users?name=John');
@@ -50,7 +51,7 @@ describe('test fetch mock', () => {
5051
expect(data).not.to.be.empty();
5152
expect(data).to.be.an('array');
5253
expect(data).to.have.length(1);
53-
});
54+
}).timeout(20000);
5455

5556
it('fetch /api/users with post parameters', async () => {
5657
const response = await fetch('/api/users', {
@@ -69,7 +70,7 @@ describe('test fetch mock', () => {
6970
expect(data).not.to.be.empty();
7071
expect(data).to.be.an('array');
7172
expect(data).to.have.length(1);
72-
});
73+
}).timeout(20000);
7374

7475
it('fetch /api/users/{userId}', async () => {
7576
const response = await fetch('/api/users/123');
@@ -79,7 +80,7 @@ describe('test fetch mock', () => {
7980
expect(data).not.to.be(undefined);
8081
expect(data).not.to.be.empty();
8182
expect(data).to.be.property('userId', '123');
82-
});
83+
}).timeout(20000);
8384

8485
it('fetch /api/users/mockjs with mockjs', async () => {
8586
const response = await fetch('/api/users/mockjs');
@@ -90,7 +91,7 @@ describe('test fetch mock', () => {
9091
expect(data).not.to.be.empty();
9192
expect(data).to.be.an('array');
9293
expect(data).to.have.length(2);
93-
});
94+
}).timeout(20000);
9495

9596
it('fetch /api/users/mockjs with mockjs', async () => {
9697
const response = await fetch('/api/users/mockjs');
@@ -101,7 +102,7 @@ describe('test fetch mock', () => {
101102
expect(data).not.to.be.empty();
102103
expect(data).to.be.an('array');
103104
expect(data).to.have.length(2);
104-
});
105+
}).timeout(20000);
105106

106107
it('fetch /api/users/{userid} with prue data response', async () => {
107108
const response = await fetch('/api/users/pru/121');
@@ -112,7 +113,7 @@ describe('test fetch mock', () => {
112113
expect(data).not.to.be.empty();
113114
expect(data).to.be.an('object');
114115
expect(data).to.be.property('userId', '121');
115-
});
116+
}).timeout(20000);
116117

117118
it('fetch exclude path', async () => {
118119
const response = await fetch('https://www.amazon.com');
@@ -135,7 +136,7 @@ describe('test fetch mock', () => {
135136
}),
136137
});
137138
expect(status).to.be.eql(201);
138-
});
139+
}).timeout(20000);
139140

140141
it('put /api/users/123', async () => {
141142
const response = await fetch('/api/users/123', {
@@ -154,7 +155,7 @@ describe('test fetch mock', () => {
154155
expect(data).not.to.be.empty();
155156
expect(data).to.be.an('object');
156157
expect(data.userId).to.be.eql(123);
157-
});
158+
}).timeout(20000);
158159

159160
it('proxy other api server', async () => {
160161
const response = await fetch('/ip/?format=json');
@@ -165,5 +166,32 @@ describe('test fetch mock', () => {
165166
expect(data).not.to.be.empty();
166167
expect(data).to.be.an('object');
167168
expect(data.ip).to.be.an('string');
169+
}).timeout(20000);
170+
171+
describe('test delay mock', () => {
172+
173+
it('global delay', async () => {
174+
const start = new Date().getTime();
175+
await fetch('/api/users');
176+
expect(new Date().getTime() - start).to.greaterThan(2000);
177+
}).timeout(20000);
178+
179+
it('method delay 30ms', async () => {
180+
const start = new Date().getTime();
181+
await fetch('/api/users', {
182+
delay: 30,
183+
});
184+
expect(new Date().getTime() - start).to.greaterThan(30);
185+
}).timeout(20000);
186+
187+
it('method delay 3000ms', async () => {
188+
const start = new Date().getTime();
189+
await fetch('/api/users', {
190+
delay: 3000,
191+
});
192+
expect(new Date().getTime() - start).to.greaterThan(3000);
193+
}).timeout(20000);
194+
168195
});
196+
169197
});

test/util.test.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'babel-polyfill';
22
import expect from 'expect.js';
3-
import { prueUrl, parseUrl, parseRequest, matchUrl } from '../src/util';
3+
import { prueUrl, parseUrl, parseRequest, matchUrl, delay } from '../src/util';
44

55
describe('test util methods', () => {
66
it('get prue url', async () => {
@@ -104,4 +104,10 @@ describe('test util methods', () => {
104104
result: false,
105105
});
106106
});
107+
108+
it('delay 5000ms', async () => {
109+
const start = new Date().getTime();
110+
await delay(5000);
111+
expect(new Date().getTime() - start).to.greaterThan(5000);
112+
}).timeout(20000);
107113
});

0 commit comments

Comments
 (0)