@loadmill/core 0.3.51 → 0.3.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/conf/defaults.ts +0 -25
- package/src/conf/extrema.ts +0 -36
- package/src/conf/index.ts +0 -95
- package/src/conf/notifications.ts +0 -17
- package/src/conf/types.ts +0 -100
- package/src/conf/validate.ts +0 -559
- package/src/distributed-logger-reporter.ts +0 -19
- package/src/echo/firehose.ts +0 -64
- package/src/echo/index.ts +0 -4
- package/src/echo/stats.ts +0 -84
- package/src/har/index.ts +0 -81
- package/src/multipart-form-data/form-data-utils.ts +0 -81
- package/src/multipart-form-data/is-binary-file.ts +0 -206
- package/src/multipart-form-data/multipart-text-to-post-form-data.ts +0 -149
- package/src/parameters/extractions.ts +0 -53
- package/src/parameters/extractors/cheerio-extractor.ts +0 -57
- package/src/parameters/extractors/expression-extractor.ts +0 -13
- package/src/parameters/extractors/extractor.ts +0 -3
- package/src/parameters/extractors/header-extractor.ts +0 -24
- package/src/parameters/extractors/index.ts +0 -10
- package/src/parameters/extractors/json-path-extractor.ts +0 -63
- package/src/parameters/extractors/parametrized-extractor.ts +0 -27
- package/src/parameters/extractors/regex-extractor.ts +0 -18
- package/src/parameters/extractors/regex-matcher.ts +0 -17
- package/src/parameters/extractors/ws-extractor.ts +0 -91
- package/src/parameters/generate-random.ts +0 -114
- package/src/parameters/index.ts +0 -624
- package/src/parameters/json-path-utils.ts +0 -20
- package/src/parameters/operators/binary-operator.ts +0 -23
- package/src/parameters/operators/index.ts +0 -39
- package/src/parameters/parameter-functions/boolean-parameter-functions.ts +0 -24
- package/src/parameters/parameter-functions/crypto.ts +0 -55
- package/src/parameters/parameter-functions/json-schema.ts +0 -29
- package/src/parameters/parameter-functions/numeric-input-parameter-functions.ts +0 -22
- package/src/parameters/parameter-functions/numeric-parameter-functions.ts +0 -37
- package/src/parameters/parameter-functions/parameter-function-utils.ts +0 -55
- package/src/parameters/parameter-functions/parameter-function.ts +0 -7
- package/src/parameters/parameter-functions/parameter-functions.ts +0 -54
- package/src/parameters/parameter-functions/random-parameter-functions.ts +0 -22
- package/src/parameters/parameter-functions/textual-parameter-functions.ts +0 -464
- package/src/parameters/parameter-regex-providers.ts +0 -78
- package/src/parameters/resolvers/random-parameters-resolver.ts +0 -8
- package/src/parameters/type.ts +0 -7
- package/src/parameters/value-utils.ts +0 -47
- package/src/request/index.ts +0 -526
- package/src/schema/json-schema-generator.ts +0 -76
- package/test/conf/validate.spec.js +0 -141
- package/test/har/is-har.spec.js +0 -33
- package/test/multipart-form-data/form-data-utils.spec.ts +0 -142
- package/test/multipart-form-data/resources/multipart-form-data-file-text-content.json +0 -5
- package/test/parameters/builtin-functions.spec.js +0 -85
- package/test/parameters/json-path-utils.spec.ts +0 -50
- package/test/parameters/parameter-functions.spec.js +0 -48
- package/test/parameters/parameter-utils.spec.js +0 -185
- package/test/parameters/regex-functions.spec.ts +0 -57
- package/test/parameters/value-utils.spec.js +0 -73
- package/test/schema/json-schema-generator.spec.js +0 -227
- package/tsconfig.json +0 -9
package/src/request/index.ts
DELETED
|
@@ -1,526 +0,0 @@
|
|
|
1
|
-
import flatMap = require('lodash/flatMap');
|
|
2
|
-
import * as uriUtils from '@loadmill/universal/dist/uri-utils';
|
|
3
|
-
import { Parameters, parameterUtils } from '../parameters';
|
|
4
|
-
|
|
5
|
-
export const DEFAULT_REQUEST_TIMEOUT = 25000;
|
|
6
|
-
export const supportedMethods = {
|
|
7
|
-
GET: 'GET',
|
|
8
|
-
POST: 'POST',
|
|
9
|
-
PUT: 'PUT',
|
|
10
|
-
DELETE: 'DELETE',
|
|
11
|
-
PATCH: 'PATCH',
|
|
12
|
-
};
|
|
13
|
-
export const ALLOWED_RESPONSE_STATUSES = { SUCCESS: 'SUCCESS', ERROR: 'ERROR', ANY: 'ANY' };
|
|
14
|
-
|
|
15
|
-
export type HttpMethod = keyof typeof supportedMethods;
|
|
16
|
-
export type HttpResponseStatus = keyof typeof ALLOWED_RESPONSE_STATUSES;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* This class represents an HTTP request to be performed in the course of a load test.
|
|
20
|
-
*
|
|
21
|
-
* @property url The URL of the request (parameterizable).
|
|
22
|
-
* @property method The HTTP method.
|
|
23
|
-
* @property headers An array of headers to add to the request (values parameterizable).
|
|
24
|
-
* @property postData The content of the request (text parameterizable).
|
|
25
|
-
* @property delay The delay between this request and the previous one in milliseconds. This property is ignored for the first request.
|
|
26
|
-
* @property timeout The time to wait for the request to finish in milliseconds.
|
|
27
|
-
* @property extract A dictionary of parameter extractions.
|
|
28
|
-
* @property assert An array or dictionary of assertions.
|
|
29
|
-
* @property expectedStatus The expected status of the http response SUCCESS for 2XX-3XX, ERROR for 4XX-5XX.
|
|
30
|
-
*/
|
|
31
|
-
export class LoadmillRequest implements RequestLike {
|
|
32
|
-
auth?: AuthConf;
|
|
33
|
-
stopBefore?: string;
|
|
34
|
-
skipBefore?: SkipConf;
|
|
35
|
-
loop?: LoopConf;
|
|
36
|
-
|
|
37
|
-
useCookies?: boolean;
|
|
38
|
-
description?: string;
|
|
39
|
-
delay?: number | string;
|
|
40
|
-
postData?: RequestPostData;
|
|
41
|
-
postFormData?: PostFormData;
|
|
42
|
-
file?: RequestRawFileData;
|
|
43
|
-
cachePenetration?: CachePenetration;
|
|
44
|
-
|
|
45
|
-
method: HttpMethod = 'GET';
|
|
46
|
-
headers?: LoadmillHeaders[];
|
|
47
|
-
|
|
48
|
-
assert?: Assertions;
|
|
49
|
-
extract?: Extractions[];
|
|
50
|
-
postScript?: string;
|
|
51
|
-
disabled?: boolean;
|
|
52
|
-
timeout?: number;
|
|
53
|
-
expectedStatus?: HttpResponseStatus;
|
|
54
|
-
noRedirects?: boolean;
|
|
55
|
-
|
|
56
|
-
constructor(public url: string) { }
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function resolveUrl(
|
|
60
|
-
url: string,
|
|
61
|
-
parameters: Parameters | Parameters[],
|
|
62
|
-
onError?
|
|
63
|
-
) {
|
|
64
|
-
return uriUtils.withProtocol(
|
|
65
|
-
parameterUtils.resolveExpression(url, parameters, onError)
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* This function should be able to take any object/json and either make a VALID LoadmillRequest out of it
|
|
71
|
-
* or fail with a meaningful error message.
|
|
72
|
-
*/
|
|
73
|
-
export function createRequest(from: RequestLike): LoadmillRequest {
|
|
74
|
-
const {
|
|
75
|
-
url,
|
|
76
|
-
delay,
|
|
77
|
-
assert,
|
|
78
|
-
method,
|
|
79
|
-
timeout,
|
|
80
|
-
extract,
|
|
81
|
-
headers,
|
|
82
|
-
postData,
|
|
83
|
-
postFormData,
|
|
84
|
-
file,
|
|
85
|
-
stopBefore,
|
|
86
|
-
skipBefore,
|
|
87
|
-
loop,
|
|
88
|
-
description,
|
|
89
|
-
expectedStatus,
|
|
90
|
-
postScript,
|
|
91
|
-
disabled,
|
|
92
|
-
noRedirects,
|
|
93
|
-
} = from;
|
|
94
|
-
|
|
95
|
-
const request = new LoadmillRequest(url);
|
|
96
|
-
|
|
97
|
-
if (method) {
|
|
98
|
-
request.method = method;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (description) {
|
|
102
|
-
request.description = description;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (headers) {
|
|
106
|
-
request.headers = toHeaders(headers);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (postData) {
|
|
110
|
-
const text = postData.text;
|
|
111
|
-
const mimeType = postData.mimeType;
|
|
112
|
-
request.postData = { text, mimeType };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (postFormData) {
|
|
116
|
-
request.postFormData = postFormData;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (file) {
|
|
120
|
-
request.file = file;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (delay !== null && delay !== undefined) {
|
|
124
|
-
request.delay = delay;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (stopBefore !== undefined) {
|
|
128
|
-
request.stopBefore = stopBefore;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (skipBefore != null) {
|
|
132
|
-
const { goTo, negate, condition } = skipBefore;
|
|
133
|
-
|
|
134
|
-
request.skipBefore = {
|
|
135
|
-
goTo,
|
|
136
|
-
condition,
|
|
137
|
-
negate: !!negate,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (loop != null) {
|
|
142
|
-
const { iterations, assert } = loop;
|
|
143
|
-
|
|
144
|
-
const [converted] = toAssertions([assert]);
|
|
145
|
-
request.loop = {
|
|
146
|
-
assert: converted,
|
|
147
|
-
iterations
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (timeout != null) {
|
|
152
|
-
request.timeout = timeout;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (extract) {
|
|
156
|
-
request.extract = toExtractions(extract);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (assert) {
|
|
160
|
-
request.assert = toAssertions(assert);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (expectedStatus) {
|
|
164
|
-
request.expectedStatus = expectedStatus;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (postScript !== undefined) {
|
|
168
|
-
request.postScript = postScript;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (disabled !== undefined) {
|
|
172
|
-
request.disabled = disabled;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (noRedirects !== undefined) {
|
|
176
|
-
request.noRedirects = noRedirects;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return request;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export function toHeaders(headers: LoadmillHeaders | LoadmillHeaders[]) {
|
|
183
|
-
return flatMap<LoadmillHeaders | string, LoadmillHeaders>(
|
|
184
|
-
headers as any,
|
|
185
|
-
(value: LoadmillHeaders | any, key: number | string) => {
|
|
186
|
-
const res = [];
|
|
187
|
-
if (typeof key === 'string') {
|
|
188
|
-
pushHeader(value, key, res);
|
|
189
|
-
} else {
|
|
190
|
-
Object.keys(value).map((innerKey: string) => {
|
|
191
|
-
const innerValue = value[innerKey];
|
|
192
|
-
pushHeader(innerValue, innerKey!, res);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return res;
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function toExtractions(extractions: Extractions | Extractions[]) {
|
|
202
|
-
if (!Array.isArray(extractions)) {
|
|
203
|
-
extractions = [extractions];
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return extractions.map(toSingleExtractions);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function toSingleExtractions(extractions: Extractions): Extractions {
|
|
210
|
-
const result = {};
|
|
211
|
-
|
|
212
|
-
// Arrgh: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/12449
|
|
213
|
-
Object.keys(extractions).forEach((name: string) => {
|
|
214
|
-
const extraction = extractions[name];
|
|
215
|
-
let newExtraction: Extraction = extractions[name];
|
|
216
|
-
|
|
217
|
-
if (typeof extraction !== 'string') {
|
|
218
|
-
newExtraction = {};
|
|
219
|
-
const { header, jQuery, jsonPath, edn, regex, ws } = extraction;
|
|
220
|
-
|
|
221
|
-
if (header != null) {
|
|
222
|
-
newExtraction.header = header;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (jQuery != null) {
|
|
226
|
-
newExtraction.jQuery =
|
|
227
|
-
typeof jQuery === 'string'
|
|
228
|
-
? jQuery
|
|
229
|
-
: { query: jQuery.query, attr: jQuery.attr };
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (jsonPath != null) {
|
|
233
|
-
newExtraction.jsonPath = jsonPath;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (edn != null) {
|
|
237
|
-
newExtraction.edn = edn;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (regex != null) {
|
|
241
|
-
newExtraction.regex = regex;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (ws != null) {
|
|
245
|
-
newExtraction.ws = ws;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
result[name] = newExtraction;
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
return result;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function toAssertions(assertions: Assertions) {
|
|
256
|
-
const result: Assertions = [];
|
|
257
|
-
|
|
258
|
-
assertions.forEach((assertion: Assertion, key: number) => {
|
|
259
|
-
const {
|
|
260
|
-
check,
|
|
261
|
-
equals,
|
|
262
|
-
notEquals,
|
|
263
|
-
contains,
|
|
264
|
-
notContains,
|
|
265
|
-
matches,
|
|
266
|
-
falsy,
|
|
267
|
-
greater,
|
|
268
|
-
lesser,
|
|
269
|
-
JSONSchema
|
|
270
|
-
} = assertion;
|
|
271
|
-
|
|
272
|
-
const converted: Assertion = {
|
|
273
|
-
check,
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
if (equals != null) {
|
|
277
|
-
converted.equals = equals;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (notEquals != null) {
|
|
281
|
-
converted.notEquals = notEquals;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (contains != null) {
|
|
285
|
-
converted.contains = contains;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (notContains != null) {
|
|
289
|
-
converted.notContains = notContains;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (matches != null) {
|
|
293
|
-
converted.matches = matches;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (greater != null) {
|
|
297
|
-
converted.greater = greater;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (lesser != null) {
|
|
301
|
-
converted.lesser = lesser;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (falsy != null && (falsy === 'true' || falsy === true)) {
|
|
305
|
-
converted.falsy = true;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (JSONSchema != null) {
|
|
309
|
-
converted.JSONSchema = JSONSchema;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
result[key] = converted;
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
return result;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
export function findRequestIndex(requests: RequestLike[], desc: string) {
|
|
319
|
-
return requests.findIndex(({ description }) => description === desc);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
export function isReservedHeader(lowerName: string) {
|
|
323
|
-
return (
|
|
324
|
-
lowerName.startsWith('proxy-') ||
|
|
325
|
-
(lowerName.startsWith('sec-') && !lowerName.startsWith('sec-websocket')) ||
|
|
326
|
-
lowerName === 'accept-charset' ||
|
|
327
|
-
lowerName === 'accept-encoding' ||
|
|
328
|
-
lowerName === 'access-control-request-headers' ||
|
|
329
|
-
lowerName === 'access-control-request-method' ||
|
|
330
|
-
lowerName === 'connection' ||
|
|
331
|
-
lowerName === 'content-length' ||
|
|
332
|
-
lowerName === 'cookie2' ||
|
|
333
|
-
lowerName === 'date' ||
|
|
334
|
-
lowerName === 'dnt' ||
|
|
335
|
-
lowerName === 'expect' ||
|
|
336
|
-
lowerName === 'keep-alive' ||
|
|
337
|
-
lowerName === 'te' ||
|
|
338
|
-
lowerName === 'trailer' ||
|
|
339
|
-
lowerName === 'transfer-encoding' ||
|
|
340
|
-
lowerName === 'upgrade'
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function pushHeader(value, name: string, to: object[]) {
|
|
345
|
-
to.push(singleton(value, name));
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
function singleton(value: string, name: string) {
|
|
349
|
-
return { [name]: value };
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
export interface RequestLike {
|
|
353
|
-
url: string;
|
|
354
|
-
|
|
355
|
-
// currently ignored:
|
|
356
|
-
auth?: AuthConf;
|
|
357
|
-
|
|
358
|
-
stopBefore?: string;
|
|
359
|
-
skipBefore?: SkipConf;
|
|
360
|
-
loop?: LoopConf;
|
|
361
|
-
|
|
362
|
-
timeout?: number;
|
|
363
|
-
assert?: Assertions;
|
|
364
|
-
method?: HttpMethod;
|
|
365
|
-
description?: string;
|
|
366
|
-
delay?: number | string;
|
|
367
|
-
postData?: RequestPostData;
|
|
368
|
-
postFormData?: PostFormData;
|
|
369
|
-
file?: RequestRawFileData;
|
|
370
|
-
extract?: Extractions | Extractions[];
|
|
371
|
-
headers?: LoadmillHeaders | LoadmillHeaders[];
|
|
372
|
-
expectedStatus?: HttpResponseStatus;
|
|
373
|
-
parameters?;
|
|
374
|
-
postScript?: string;
|
|
375
|
-
disabled?: boolean;
|
|
376
|
-
noRedirects?: boolean;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
export type SkipConf = {
|
|
380
|
-
condition: string;
|
|
381
|
-
negate?: boolean;
|
|
382
|
-
goTo?: string;
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
export type LoopConf = {
|
|
386
|
-
assert: Assertion;
|
|
387
|
-
iterations: number;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
export type RequestPostData = {
|
|
391
|
-
mimeType?: string;
|
|
392
|
-
text: string;
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
export type PostFormData = PostFormDataEntry[];
|
|
396
|
-
|
|
397
|
-
export type PostFormDataEntry = {
|
|
398
|
-
name: string;
|
|
399
|
-
value: string;
|
|
400
|
-
fileName?: string;
|
|
401
|
-
contentType?: string;
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
export type RequestRawFileData = {
|
|
405
|
-
name: string;
|
|
406
|
-
key: string;
|
|
407
|
-
signedUrl?: string; // created by aws
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
export enum BodyTypes {
|
|
411
|
-
POST_DATA = 'postData',
|
|
412
|
-
FORM_DATA = 'postFormData',
|
|
413
|
-
RAW_FILE = 'rawFile',
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
export type LoadmillHeaders = { [headerName: string]: string };
|
|
417
|
-
|
|
418
|
-
export type Extractions = { [parameter: string]: Extraction };
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* This object represents a parameter extraction.
|
|
422
|
-
*
|
|
423
|
-
* The jQuary expression is evaluated against the response body text using Cheerio.
|
|
424
|
-
* The jsonPath expression is evaluated against a superagent-like response object.
|
|
425
|
-
* The edn expression is evaluated against a superagent-like response object converted to JSON and then treated like jsonPath.
|
|
426
|
-
* If a regular expression is specified as well as a header, jQuery or jsonPath then the expression will be matched against the
|
|
427
|
-
* query result, otherwise it is evaluated against the response body text.
|
|
428
|
-
*
|
|
429
|
-
* It is invalid to submit an empty extraction or one with more than one non-regex query. If the extraction yields a
|
|
430
|
-
* `null` result, then the original parameter value will be retained, defaulting to an empty string.
|
|
431
|
-
*
|
|
432
|
-
* @property header A name of a header whose value will be extracted.
|
|
433
|
-
* @property jQuery A jQuery expression to be matched against the response body text.
|
|
434
|
-
* @property jsonPath A jsonPath expression to be matched against the response object.
|
|
435
|
-
* @property edn A jsonPath expression (yes - jsonPath) to be matched against the EDN response object converted to JSON.
|
|
436
|
-
* @property regex A JavaScript regular expression with a capture term, to be matched against the response body text.
|
|
437
|
-
*/
|
|
438
|
-
export type Extraction = string | ExtractionObj;
|
|
439
|
-
|
|
440
|
-
export type ExtractionObj = {
|
|
441
|
-
regex?: string;
|
|
442
|
-
header?: string;
|
|
443
|
-
jsonPath?: string;
|
|
444
|
-
edn?: string;
|
|
445
|
-
|
|
446
|
-
jQuery?:
|
|
447
|
-
| string
|
|
448
|
-
| {
|
|
449
|
-
query: string;
|
|
450
|
-
attr?: string;
|
|
451
|
-
};
|
|
452
|
-
ws?: string;
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
export type Assertions = Assertion[];
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* This object represents an assertion.
|
|
459
|
-
*
|
|
460
|
-
* Assertions are made once the request has been fulfilled and all parameters have been extracted.
|
|
461
|
-
* All assertions are evaluated, even if some fail.
|
|
462
|
-
* If an assertion contains more then one conditions then the conditions are or-ed.
|
|
463
|
-
*
|
|
464
|
-
* @property check A parameter name to assert the given conditions on.
|
|
465
|
-
* @property equals A parametrized expression that asserts to true if its value is equal to `check`.
|
|
466
|
-
* @property contains A parametrized expression that asserts to true if its value is contained in `check`.
|
|
467
|
-
* @property matches A JavaScript regular expression that asserts to true if `check` matches it.
|
|
468
|
-
* @property falsy if true then A parametrized expression that asserts to true if the value of `check` equales false.
|
|
469
|
-
* @property greater A parametrized expression that asserts to true if its value is less to `check`.
|
|
470
|
-
* @property lesser A parametrized expression that asserts to true if its value is greater to `check`.
|
|
471
|
-
*/
|
|
472
|
-
export interface Assertion {
|
|
473
|
-
check: string;
|
|
474
|
-
equals?: string;
|
|
475
|
-
notEquals?: string;
|
|
476
|
-
contains?: string;
|
|
477
|
-
notContains?: string;
|
|
478
|
-
matches?: string;
|
|
479
|
-
falsy?: string | boolean;
|
|
480
|
-
greater?: string;
|
|
481
|
-
lesser?: string;
|
|
482
|
-
JSONSchema?: string;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
export interface AuthConf {
|
|
486
|
-
user?: string;
|
|
487
|
-
password?: string;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
export interface CachePenetration {
|
|
491
|
-
cacheControl?: string;
|
|
492
|
-
mode?: CachePenetrationModes;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
export enum CachePenetrationModes {
|
|
496
|
-
none = 'none',
|
|
497
|
-
def = 'default',
|
|
498
|
-
alwaysQuery = 'always-query',
|
|
499
|
-
alwaysHeader = 'always-header',
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// list of fields in our object we must not change
|
|
503
|
-
export const EXCLUDES = [
|
|
504
|
-
'url',
|
|
505
|
-
'method',
|
|
506
|
-
'headers',
|
|
507
|
-
'timeout',
|
|
508
|
-
'postData',
|
|
509
|
-
'text',
|
|
510
|
-
'mimeType',
|
|
511
|
-
'extract',
|
|
512
|
-
'jsonPath',
|
|
513
|
-
'jQuery',
|
|
514
|
-
'regex',
|
|
515
|
-
'header',
|
|
516
|
-
'assert',
|
|
517
|
-
'check',
|
|
518
|
-
'equals',
|
|
519
|
-
'contains',
|
|
520
|
-
'matches',
|
|
521
|
-
'falsy',
|
|
522
|
-
'greater',
|
|
523
|
-
'lesser',
|
|
524
|
-
];
|
|
525
|
-
|
|
526
|
-
export const isWSRequest = (url: string) => url.startsWith('ws://') || url.startsWith('wss://');
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import find = require('lodash/find');
|
|
2
|
-
import log from '@loadmill/universal/dist/log';
|
|
3
|
-
import isEmpty = require('lodash/isEmpty');
|
|
4
|
-
|
|
5
|
-
export const generateJSONSchema = (jsObj: any, ignoreKeys: string[] = [], shouldAddNullable: boolean = false): PrimitiveSchema | Schema => {
|
|
6
|
-
try {
|
|
7
|
-
const schema = _getSchema(jsObj, ignoreKeys, shouldAddNullable);
|
|
8
|
-
return schema;
|
|
9
|
-
} catch (err) {
|
|
10
|
-
_handleError('Error generating JSON Schema', err, jsObj);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return {};
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const _getSchema = (obj, ignoreKeys: string[] = [], shouldAddNullable: boolean = false) => {
|
|
17
|
-
if (obj == null) {
|
|
18
|
-
return shouldAddNullable ? { type: 'object', nullable: true } :{};
|
|
19
|
-
}
|
|
20
|
-
else if (_isPrimitive(obj)) {
|
|
21
|
-
return {
|
|
22
|
-
'type': typeof obj
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
else if (Array.isArray(obj)) {
|
|
26
|
-
const items: any[] = [];
|
|
27
|
-
for (const [, value] of Object.entries(obj)) {
|
|
28
|
-
const elementSchema = _getSchema(value, ignoreKeys);
|
|
29
|
-
if (!find(items, elementSchema)) {
|
|
30
|
-
items.push(elementSchema);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
// The use of 'oneOf' creates a schema that validates the existence of the items but not their order in the array
|
|
34
|
-
return {
|
|
35
|
-
'type': 'array',
|
|
36
|
-
'items': isEmpty(items) ? {} : { 'anyOf': items }
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
const properties = {};
|
|
41
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
42
|
-
if (!ignoreKeys.includes(key)) {
|
|
43
|
-
properties[key] = _getSchema(value, ignoreKeys);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
'type': 'object',
|
|
48
|
-
properties
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const _isPrimitive = (obj) => Object(obj) !== obj;
|
|
54
|
-
|
|
55
|
-
const _handleError = (err, msg, json) => {
|
|
56
|
-
log.error(msg, err, json);
|
|
57
|
-
throw new Error(msg);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export type Schema = BaseSchema & {
|
|
61
|
-
properties?: {
|
|
62
|
-
[name: string]: Schema | PrimitiveSchema
|
|
63
|
-
}
|
|
64
|
-
items?: Schema[] | PrimitiveSchema[]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export type PrimitiveSchema = BaseSchema & {
|
|
68
|
-
const?: Primitive
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
type BaseSchema = {
|
|
72
|
-
type?: string
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
type Primitive = string | number | boolean;
|
|
76
|
-
|