@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.
Files changed (59) hide show
  1. package/package.json +2 -2
  2. package/src/conf/defaults.ts +0 -25
  3. package/src/conf/extrema.ts +0 -36
  4. package/src/conf/index.ts +0 -95
  5. package/src/conf/notifications.ts +0 -17
  6. package/src/conf/types.ts +0 -100
  7. package/src/conf/validate.ts +0 -559
  8. package/src/distributed-logger-reporter.ts +0 -19
  9. package/src/echo/firehose.ts +0 -64
  10. package/src/echo/index.ts +0 -4
  11. package/src/echo/stats.ts +0 -84
  12. package/src/har/index.ts +0 -81
  13. package/src/multipart-form-data/form-data-utils.ts +0 -81
  14. package/src/multipart-form-data/is-binary-file.ts +0 -206
  15. package/src/multipart-form-data/multipart-text-to-post-form-data.ts +0 -149
  16. package/src/parameters/extractions.ts +0 -53
  17. package/src/parameters/extractors/cheerio-extractor.ts +0 -57
  18. package/src/parameters/extractors/expression-extractor.ts +0 -13
  19. package/src/parameters/extractors/extractor.ts +0 -3
  20. package/src/parameters/extractors/header-extractor.ts +0 -24
  21. package/src/parameters/extractors/index.ts +0 -10
  22. package/src/parameters/extractors/json-path-extractor.ts +0 -63
  23. package/src/parameters/extractors/parametrized-extractor.ts +0 -27
  24. package/src/parameters/extractors/regex-extractor.ts +0 -18
  25. package/src/parameters/extractors/regex-matcher.ts +0 -17
  26. package/src/parameters/extractors/ws-extractor.ts +0 -91
  27. package/src/parameters/generate-random.ts +0 -114
  28. package/src/parameters/index.ts +0 -624
  29. package/src/parameters/json-path-utils.ts +0 -20
  30. package/src/parameters/operators/binary-operator.ts +0 -23
  31. package/src/parameters/operators/index.ts +0 -39
  32. package/src/parameters/parameter-functions/boolean-parameter-functions.ts +0 -24
  33. package/src/parameters/parameter-functions/crypto.ts +0 -55
  34. package/src/parameters/parameter-functions/json-schema.ts +0 -29
  35. package/src/parameters/parameter-functions/numeric-input-parameter-functions.ts +0 -22
  36. package/src/parameters/parameter-functions/numeric-parameter-functions.ts +0 -37
  37. package/src/parameters/parameter-functions/parameter-function-utils.ts +0 -55
  38. package/src/parameters/parameter-functions/parameter-function.ts +0 -7
  39. package/src/parameters/parameter-functions/parameter-functions.ts +0 -54
  40. package/src/parameters/parameter-functions/random-parameter-functions.ts +0 -22
  41. package/src/parameters/parameter-functions/textual-parameter-functions.ts +0 -464
  42. package/src/parameters/parameter-regex-providers.ts +0 -78
  43. package/src/parameters/resolvers/random-parameters-resolver.ts +0 -8
  44. package/src/parameters/type.ts +0 -7
  45. package/src/parameters/value-utils.ts +0 -47
  46. package/src/request/index.ts +0 -526
  47. package/src/schema/json-schema-generator.ts +0 -76
  48. package/test/conf/validate.spec.js +0 -141
  49. package/test/har/is-har.spec.js +0 -33
  50. package/test/multipart-form-data/form-data-utils.spec.ts +0 -142
  51. package/test/multipart-form-data/resources/multipart-form-data-file-text-content.json +0 -5
  52. package/test/parameters/builtin-functions.spec.js +0 -85
  53. package/test/parameters/json-path-utils.spec.ts +0 -50
  54. package/test/parameters/parameter-functions.spec.js +0 -48
  55. package/test/parameters/parameter-utils.spec.js +0 -185
  56. package/test/parameters/regex-functions.spec.ts +0 -57
  57. package/test/parameters/value-utils.spec.js +0 -73
  58. package/test/schema/json-schema-generator.spec.js +0 -227
  59. package/tsconfig.json +0 -9
package/src/echo/stats.ts DELETED
@@ -1,84 +0,0 @@
1
- import isUUID from 'validator/lib/isUUID';
2
-
3
- const isNumber = s => /^[0-9]+$/.test(s);
4
-
5
- const standardizePath = path => {
6
- const parts = path.slice(1).split('/');
7
- let newPath = '';
8
-
9
- parts.forEach(part => {
10
- newPath += (isUUID(part) || isNumber(part)) ? '/{param}' : `/${part}`;
11
- });
12
-
13
- return newPath;
14
- };
15
-
16
- const updateKey = (obj, key, shouldIncr, value) => {
17
- obj[key] = shouldIncr ? (obj[key] || 0) + value : value;
18
- };
19
-
20
- export class Stats {
21
-
22
- stats;
23
-
24
- constructor() {
25
- this.stats = {
26
- lmCode: -1,
27
- totalRequests: 0,
28
- totalResponseTime: 0,
29
- requestsCounter: {},
30
- requestsResponseTime: {},
31
- isNewSession: false,
32
- totalNewSessions: 0
33
- };
34
- }
35
-
36
- updateStats(key, shouldIncr, value:any = 0, subKey = '') {
37
- if (key && value) {
38
- if (subKey) {
39
- updateKey(this.stats[key], subKey, shouldIncr, value);
40
- } else {
41
- updateKey(this.stats, key, shouldIncr, value);
42
- }
43
- }
44
- }
45
-
46
- addRequest(request, responseTime) {
47
- const convertedPath = standardizePath(new URL(request.url).pathname);
48
-
49
- this.updateStats('totalRequests', true, 1);
50
- this.updateStats('totalResponseTime', true, parseInt(responseTime, 10));
51
- this.updateStats('requestsCounter', true, 1, `${request.method}:${convertedPath}`);
52
- this.updateStats('requestsResponseTime', true, parseInt(responseTime, 10), `${request.method}:${convertedPath}`);
53
- }
54
-
55
- clearStats() {
56
- this.stats.totalRequests = 0;
57
- this.stats.totalResponseTime = 0;
58
- this.stats.requestsCounter = {};
59
- this.stats.requestsResponseTime = {};
60
- this.stats.isNewSession = false;
61
- this.stats.totalNewSessions = 0;
62
- }
63
-
64
- async push(url) {
65
- let isPushed = false;
66
- if (this.stats.totalRequests > 0) {
67
- // eslint-disable-next-line no-undef
68
- const res = await fetch(`${url}/stats`, {
69
- method: 'POST',
70
- body: JSON.stringify(this.stats),
71
- headers: {
72
- 'Content-Type': 'application/json',
73
- Accept: 'application/json'
74
- }
75
- });
76
- if (res.ok) {
77
- this.clearStats();
78
- isPushed = true;
79
- }
80
- }
81
-
82
- return isPushed;
83
- }
84
- }
package/src/har/index.ts DELETED
@@ -1,81 +0,0 @@
1
- export interface Har {
2
- log: HarLog;
3
- }
4
-
5
- export interface HarLog {
6
- version: string;
7
- entries: HarEntry[];
8
- }
9
-
10
- export interface HarEntry {
11
- time: number;
12
- request: HarRequest;
13
- response: HarResponse;
14
- startedDateTime: string;
15
- _resourceType?: ResourceType;
16
- _webSocketMessages?: WebSocketMessage[];
17
- }
18
-
19
- type ResourceType = 'main_frame' | 'sub_frame' | 'stylesheet' | 'script' | 'image' | 'font' |
20
- 'object' | 'xmlhttprequest' | 'ping' | 'csp_report' | 'media' | 'websocket' | 'other';
21
-
22
- export type WebSocketMessage = {
23
- type: WebSocketMessageType,
24
- time: number,
25
- opcode: number,
26
- data: string,
27
- };
28
-
29
- export type WebSocketMessageType = 'send' | 'receive';
30
-
31
- export interface HarRequest {
32
- url: string;
33
- method: string;
34
- headers: HarHeaders;
35
- bodySize: number;
36
- postData?: HarPostData;
37
- cookies: Cookie[]
38
- queryString: { name: string, value: string }[];
39
- }
40
-
41
- export type HarHeaders = HarHeader[];
42
-
43
- export type HarHeader = {
44
- name: string;
45
- value: string;
46
- };
47
-
48
- export interface HarResponse {
49
- status: number;
50
- headers: HarHeaders;
51
- statusText: string;
52
-
53
- content: {
54
- mimeType: string;
55
- text?: string;
56
- encoding?: string;
57
- };
58
- }
59
-
60
- export type Cookie = {
61
- name: string;
62
- value: string;
63
- }
64
-
65
- export type HarPostData = {
66
- mimeType: string;
67
- text?: string;
68
- params?: HarParam[];
69
- }
70
-
71
- export type HarParam = {
72
- name: string;
73
- value?: string;
74
- fileName?: string;
75
- contentType?: string;
76
- }
77
-
78
- export const isHar = (obj: any) => Boolean(obj.log) &&
79
- typeof obj.log.version === 'string' &&
80
- obj.log.version.startsWith('1.') &&
81
- Array.isArray(obj.log.entries);
@@ -1,81 +0,0 @@
1
- import { HarParam } from '../har';
2
- import { PostFormData, PostFormDataEntry } from '../request';
3
- import { getBinaryOrTextValue, multipartFormDataTextToPostFormData } from './multipart-text-to-post-form-data';
4
-
5
- export class Form {
6
- entries: HarParam[];
7
- boundary: string;
8
- constructor(entries?: HarParam[], boundary?: string) {
9
- this.entries = entries || [];
10
- this.boundary = boundary || this.generateBoundary();
11
- }
12
-
13
- generateBoundary = (): string => {
14
- let boundary = '-'.repeat(26);
15
- for (let i = 0; i < 24; i++) {
16
- boundary += Math.floor(Math.random() * 10).toString(16);
17
- }
18
- return boundary;
19
- };
20
-
21
- append = (name: string, value: string, fileName?: string) => {
22
- const entry: HarParam = { name, value };
23
- fileName && (entry.fileName = fileName);
24
- this.entries.push(entry);
25
- };
26
-
27
- toString = (): string => {
28
- let result = '';
29
- for (const { name, value, fileName, contentType } of this.entries) {
30
- result += '--' + this.boundary + '\r\n';
31
- result += `Content-Disposition: form-data; name="${name}"${this.addFileName(fileName)}${this.addContentType(contentType)}\r\n\r\n${value || ''}\r\n`;
32
- }
33
- result += '--' + this.boundary + '--\r\n';
34
-
35
- return result;
36
- };
37
-
38
- private addFileName(fileName: string = '') {
39
- let formattedFileName = '';
40
- if (fileName) {
41
- formattedFileName = `; filename="${fileName}"`;
42
- }
43
- return formattedFileName;
44
- }
45
-
46
- private addContentType = (contentType: string = ''): string => {
47
- let formattedContentType = '';
48
- if (contentType) {
49
- formattedContentType = `\r\ncontent-type: ${contentType}`;
50
- }
51
- return formattedContentType;
52
- }
53
- }
54
-
55
- export type FormEntry = { name: string, value: string, [other: string]: string };
56
-
57
- export function mapToMultipartFormData(request) {
58
- const { postData: { params, text } } = request;
59
- if (text) {
60
- request.postFormData = multipartFormDataTextToPostFormData(text);
61
- } else if (params) {
62
- request.postFormData = multipartParamsToPostFormData(params);
63
- }
64
- delete request.postData;
65
- }
66
-
67
- const multipartParamsToPostFormData = (params: HarParam[] = []) => {
68
- const postFormData: PostFormData = [];
69
- for (const p of params) {
70
- const { name, value = '', fileName, contentType } = p;
71
- const entry: PostFormDataEntry = { name, value };
72
- if (fileName) {
73
- entry.fileName = fileName;
74
- entry.value = getBinaryOrTextValue({ value, fileName, contentType });
75
- }
76
- postFormData.push(entry);
77
- }
78
- return postFormData;
79
- };
80
-
81
- export { multipartFormDataTextToPostFormData };
@@ -1,206 +0,0 @@
1
- const MAX_BYTES = 512;
2
-
3
- // A very basic non-exception raising reader. Read bytes and
4
- // at the end use hasError() to check whether this worked.
5
- class Reader {
6
- public fileBuffer: Buffer;
7
- public size: number;
8
- public offset: number;
9
- public error: boolean;
10
-
11
- constructor(fileBuffer: Buffer, size: number) {
12
- this.fileBuffer = fileBuffer;
13
- this.size = size;
14
- this.offset = 0;
15
- this.error = false;
16
- }
17
-
18
- public hasError(): boolean {
19
- return this.error;
20
- }
21
-
22
- public nextByte(): number {
23
- if (this.offset === this.size || this.hasError()) {
24
- this.error = true;
25
- return 0xff;
26
- }
27
- return this.fileBuffer[this.offset++];
28
- }
29
-
30
- public next(len: number): number[] {
31
- const n = new Array();
32
- for (let i = 0; i < len; i++) {
33
- n[i] = this.nextByte();
34
- }
35
- return n;
36
- }
37
- }
38
-
39
- // Read a Google Protobuf var(iable)int from the buffer.
40
- function readProtoVarInt(reader: Reader): number {
41
- let idx = 0;
42
- let varInt = 0;
43
-
44
- while (!reader.hasError()) {
45
- const b = reader.nextByte();
46
- varInt = varInt | ((b & 0x7f) << (7 * idx));
47
- if ((b & 0x80) === 0) {
48
- break;
49
- }
50
- idx++;
51
- }
52
-
53
- return varInt;
54
- }
55
-
56
- // Attempt to taste a full Google Protobuf message.
57
- function readProtoMessage(reader: Reader): boolean {
58
- const varInt = readProtoVarInt(reader);
59
- const wireType = varInt & 0x7;
60
-
61
- switch (wireType) {
62
- case 0:
63
- readProtoVarInt(reader);
64
- return true;
65
- case 1:
66
- reader.next(8);
67
- return true;
68
- case 2: {
69
- const len = readProtoVarInt(reader);
70
- reader.next(len);
71
- return true;
72
- }
73
- case 5:
74
- reader.next(4);
75
- return true;
76
- }
77
- return false;
78
- }
79
-
80
- // Check whether this seems to be a valid protobuf file.
81
- function isBinaryProto(fileBuffer: Buffer, totalBytes: number): boolean {
82
- const reader = new Reader(fileBuffer, totalBytes);
83
- let numMessages = 0;
84
-
85
- // eslint-disable-next-line no-constant-condition
86
- while (true) {
87
- // Definitely not a valid protobuf
88
- if (!readProtoMessage(reader) && !reader.hasError()) {
89
- return false;
90
- }
91
- // Short read?
92
- if (reader.hasError()) {
93
- break;
94
- }
95
- numMessages++;
96
- }
97
-
98
- return numMessages > 0;
99
- }
100
-
101
- export function isBinaryFile(file: Buffer, size?: number): boolean {
102
- if (size === undefined) {
103
- size = file.length;
104
- }
105
- return isBinaryCheck(file, size);
106
- }
107
-
108
- function isBinaryCheck(fileBuffer: Buffer, bytesRead: number): boolean {
109
- // empty file. no clue what it is.
110
- if (bytesRead === 0) {
111
- return false;
112
- }
113
-
114
- let suspiciousBytes = 0;
115
- const totalBytes = Math.min(bytesRead, MAX_BYTES);
116
-
117
- // UTF-8 BOM
118
- if (bytesRead >= 3 && fileBuffer[0] === 0xef && fileBuffer[1] === 0xbb && fileBuffer[2] === 0xbf) {
119
- return false;
120
- }
121
-
122
- // UTF-32 BOM
123
- if (
124
- bytesRead >= 4 &&
125
- fileBuffer[0] === 0x00 &&
126
- fileBuffer[1] === 0x00 &&
127
- fileBuffer[2] === 0xfe &&
128
- fileBuffer[3] === 0xff
129
- ) {
130
- return false;
131
- }
132
-
133
- // UTF-32 LE BOM
134
- if (
135
- bytesRead >= 4 &&
136
- fileBuffer[0] === 0xff &&
137
- fileBuffer[1] === 0xfe &&
138
- fileBuffer[2] === 0x00 &&
139
- fileBuffer[3] === 0x00
140
- ) {
141
- return false;
142
- }
143
-
144
- // GB BOM
145
- if (
146
- bytesRead >= 4 &&
147
- fileBuffer[0] === 0x84 &&
148
- fileBuffer[1] === 0x31 &&
149
- fileBuffer[2] === 0x95 &&
150
- fileBuffer[3] === 0x33
151
- ) {
152
- return false;
153
- }
154
-
155
- if (totalBytes >= 5 && fileBuffer.slice(0, 5).toString() === '%PDF-') {
156
- /* PDF. This is binary. */
157
- return true;
158
- }
159
-
160
- // UTF-16 BE BOM
161
- if (bytesRead >= 2 && fileBuffer[0] === 0xfe && fileBuffer[1] === 0xff) {
162
- return false;
163
- }
164
-
165
- // UTF-16 LE BOM
166
- if (bytesRead >= 2 && fileBuffer[0] === 0xff && fileBuffer[1] === 0xfe) {
167
- return false;
168
- }
169
-
170
- for (let i = 0; i < totalBytes; i++) {
171
- if (fileBuffer[i] === 0) {
172
- // NULL byte--it's binary!
173
- return true;
174
- } else if ((fileBuffer[i] < 7 || fileBuffer[i] > 14) && (fileBuffer[i] < 32 || fileBuffer[i] > 127)) {
175
- // UTF-8 detection
176
- if (fileBuffer[i] > 193 && fileBuffer[i] < 224 && i + 1 < totalBytes) {
177
- i++;
178
- if (fileBuffer[i] > 127 && fileBuffer[i] < 192) {
179
- continue;
180
- }
181
- } else if (fileBuffer[i] > 223 && fileBuffer[i] < 240 && i + 2 < totalBytes) {
182
- i++;
183
- if (fileBuffer[i] > 127 && fileBuffer[i] < 192 && fileBuffer[i + 1] > 127 && fileBuffer[i + 1] < 192) {
184
- i++;
185
- continue;
186
- }
187
- }
188
-
189
- suspiciousBytes++;
190
- // Read at least 32 fileBuffer before making a decision
191
- if (i >= 32 && (suspiciousBytes * 100) / totalBytes > 10) {
192
- return true;
193
- }
194
- }
195
- }
196
-
197
- if ((suspiciousBytes * 100) / totalBytes > 10) {
198
- return true;
199
- }
200
-
201
- if (suspiciousBytes > 1 && isBinaryProto(fileBuffer, totalBytes)) {
202
- return true;
203
- }
204
-
205
- return false;
206
- }
@@ -1,149 +0,0 @@
1
- import { extension } from 'mime-types';
2
- import { isBase64 } from 'validator';
3
-
4
- import { HarParam } from '../har';
5
- import { PostFormData, PostFormDataEntry } from '../request';
6
- import { isBinaryFile } from './is-binary-file';
7
-
8
- export const multipartFormDataTextToPostFormData = (multipartFormDataText: string = ''): PostFormData =>
9
- getLines(multipartFormDataText)
10
- .map(line => extractPostFormDataEntry(line));
11
-
12
- const getLines = (multipartFormDataText: string = ''): string[] =>
13
- removeEmptyLines(
14
- multipartFormDataText.split(
15
- splitByBoundaryRegex(
16
- getBoundary(multipartFormDataText)
17
- )
18
- )
19
- );
20
-
21
- const getBoundary = (multipartFormDataText: string): string =>
22
- multipartFormDataText.substring(0, multipartFormDataText.indexOf('\r\n'));
23
-
24
- const splitByBoundaryRegex = (boundary: string) => {
25
- const normalBoundary = boundary + '\r\n';
26
- const lastBoundary = boundary + '--\r\n';
27
- return new RegExp(`${normalBoundary}|${lastBoundary}`);
28
- };
29
-
30
- const removeEmptyLines = (lines: string[] = []): string[] => lines.filter(Boolean);
31
-
32
- const extractPostFormDataEntry = (line: string): PostFormDataEntry => {
33
- const indexOfFirst2Newlines = line.indexOf('\r\n\r\n');
34
-
35
- const fields = extractFields(line, indexOfFirst2Newlines);
36
- const value = calculateValue(fields, line, indexOfFirst2Newlines);
37
-
38
- const postFormDataEntry: PostFormDataEntry = { name: fields.name, value };
39
- fields.fileName && (postFormDataEntry.fileName = fields.fileName);
40
- fields.contentType && (postFormDataEntry.contentType = fields.contentType);
41
-
42
- return postFormDataEntry;
43
- };
44
-
45
- type Fields = HarParam;
46
-
47
- const extractFields = (line: string, indexOfFirst2Newlines: number): Fields => {
48
- const rawFields = extractRawFields(line, indexOfFirst2Newlines);
49
- const res: Fields = { name: '' };
50
- const fieldsLines = rawFields.split('\r\n');
51
- addNameFields(fieldsLines[0], res);
52
- fieldsLines.length > 1 && addContentType(fieldsLines[1], res);
53
- return res;
54
- };
55
-
56
- const extractRawFields = (line: string, indexOfFieldsValueSeperator: number): string =>
57
- line.substring(0, indexOfFieldsValueSeperator);
58
-
59
- const removeDoubleQuotes = (v: string): string =>
60
- v.replace(/"/g, '');
61
-
62
- const calculateValue = ({ fileName, contentType }: Fields, line: string, indexOfFirst2Newlines: number): string | '' => {
63
- const value = extractValue(line, indexOfFirst2Newlines);
64
- return getBinaryOrTextValue({ value, fileName, contentType });
65
- };
66
-
67
- export const getBinaryOrTextValue = (fields: Omit<Fields, 'name'>): string => {
68
- const { value = '', fileName } = fields;
69
- if (fileName) {
70
- const isBass64 = isBase64(value);
71
- const toBinary = isToBinary(fields);
72
- if (isBass64 || toBinary) {
73
- return myAtob(value, isBass64, toBinary);
74
- }
75
- }
76
- return value;
77
- };
78
-
79
- const myAtob = (target = '', fromBase64?: boolean, toBinary?: boolean) => {
80
- const defaultEncoding = 'utf8';
81
- const encodingFrom = fromBase64 ? 'base64' : defaultEncoding;
82
- const encodingTo = toBinary ? 'binary' : defaultEncoding;
83
- return Buffer.from(target, encodingFrom).toString(encodingTo);
84
- };
85
-
86
- const isToBinary = (fields: Omit<Fields, 'name'>): boolean => {
87
- const { value = '', fileName, contentType } = fields;
88
- if (isAlreadyBinary(value)) {
89
- return false;
90
- }
91
- if (fileName) {
92
- const ext = getExtension(fileName);
93
- if (ext) {
94
- return isBinaryFileExtension(ext);
95
- }
96
- }
97
- if (contentType) {
98
- return isBinaryContentType(contentType);
99
- }
100
- return false;
101
- };
102
-
103
- const isAlreadyBinary = (target = '') => {
104
- const bytes = Buffer.from(target);
105
- const size = target.length;
106
- return isBinaryFile(bytes, size);
107
- };
108
-
109
- const getExtension = (fileName: string): string | undefined =>
110
- fileName.split('.').pop();
111
-
112
- const isBinaryFileExtension = (ext: string): boolean =>
113
- ['docx', 'pdf', 'doc', 'jpg', 'jpeg', 'png'].includes(ext);
114
-
115
- const isBinaryContentType = (contentType: string): boolean =>
116
- ['docx', 'pdf', 'bin'].includes(extension(contentType) || '');
117
-
118
- const extractValue = (line: string, indexOfFieldsValueSeperator: number): string =>
119
- removeEndingNewline(
120
- line.substring(indexOfFieldsValueSeperator + 4)
121
- );
122
-
123
- const removeEndingNewline = (s: string): string =>
124
- s.endsWith('\r\n') ? removeLast2Chars(s) : s;
125
-
126
- const removeLast2Chars = (s: string): string =>
127
- s.substring(0, s.length - 2);
128
-
129
- const addNameFields = (nameFieldsLine: string, res: HarParam) => {
130
- const tokens = extractTokens(nameFieldsLine);
131
- for (const token of tokens) {
132
- const [k, v] = token.split('=');
133
- if (k === 'name') {
134
- res.name = removeDoubleQuotes(v);
135
- } else if (k === 'filename') {
136
- res.fileName = removeDoubleQuotes(v);
137
- }
138
- }
139
- };
140
-
141
- const extractTokens = (nameFieldsLine: string): string[] =>
142
- nameFieldsLine.split(';').map(t => t.trim());
143
-
144
- const addContentType = (contentTypeLine: string, res: HarParam) => {
145
- const [k, v] = contentTypeLine.split(': ');
146
- if (k === 'content-type') {
147
- res.contentType = v;
148
- }
149
- };
@@ -1,53 +0,0 @@
1
- import { Extractions } from '../request';
2
- import { parameterUtils } from '.';
3
- const { getParameterName } = parameterUtils;
4
-
5
- /**
6
- * Gets an extractions instance which looks like this: { [paramName]: string }.
7
- *
8
- * If it's an assign extraction, i.e { [paramName]: string }
9
- * OR { [paramName]: { jsonPath/jQuery/...: string } }
10
- * OR { [paramName]: { jQuery: { query: string, attr?: string } } }}}
11
- * And spreads this object into its parts.
12
- *
13
- * Example:
14
- * input ext = { my_ext: { jsonPath: '$["users"][0]["id"]' } }
15
- * output = { name: 'my_ext', value: '$["users"][0]["name"]', type: 'jsonPath' }
16
- *
17
- * @param ext The extraction object to take a part
18
- * @returns The spreaded parts of the given extraction object
19
- */
20
- export function getExtractionParts(ext: Extractions): ExtractionParts {
21
- const name = getParameterName(ext);
22
- const extContent = ext[name];
23
- if (typeof extContent === 'string') {
24
- return { name, value: extContent };
25
- }
26
- const [type] = Object.keys(extContent);
27
- const value = ext[name][type];
28
- return { name, value, type };
29
- }
30
-
31
- export type ExtractionParts = {
32
- name: string;
33
- value: string | {
34
- query: string;
35
- attr?: string;
36
- };
37
- type?: string;
38
- };
39
-
40
- export function requestsExtractionsArr(requests, toIndex: number) {
41
- const extractionParamNames = [] as string[];
42
- for (let i = 0; i <= toIndex; i++) {
43
- if (requests[i].extract) {
44
- for (const param of requests[i].extract) {
45
- const paramName = Object.keys(param)[0];
46
- if (paramName && extractionParamNames.indexOf(paramName) < 0) {
47
- extractionParamNames.push(paramName);
48
- }
49
- }
50
- }
51
- }
52
- return extractionParamNames;
53
- }
@@ -1,57 +0,0 @@
1
- import cheerio from 'cheerio';
2
- import random = require('lodash/random');
3
- import { parameterValueToNumber, RANDOM_SELECT_OPT } from '../value-utils';
4
- import { Parameters } from '../type';
5
- import { ParametrizedExtractor } from './parametrized-extractor';
6
- import { PresentableError } from '@loadmill/universal/dist/errors';
7
-
8
- export class CheerioExtractor extends ParametrizedExtractor {
9
- private $;
10
-
11
- constructor(target, parameters: Parameters) {
12
- super(parameters);
13
- this.$ = cheerio.load(target);
14
- }
15
-
16
- extractResolved = (
17
- resolvedJQuery: string,
18
- selection: string = '0',
19
- resolvedAttrName?: string
20
- ) => {
21
- let jQueryResult;
22
-
23
- const matched = this.$(resolvedJQuery);
24
- const numMatched = matched.length;
25
-
26
- if (numMatched === 0) {
27
- jQueryResult = null;
28
- } else {
29
- const index = getIndex(selection, numMatched);
30
- const element = matched.eq(index);
31
-
32
- if (resolvedAttrName) {
33
- const attr = element.attr(resolvedAttrName);
34
- jQueryResult = attr != null ? attr.toString() : null;
35
- } else {
36
- jQueryResult = element.html();
37
- }
38
- }
39
-
40
- // log.debug('jQuery extraction:', { resolvedJQuery, jQueryResult });
41
-
42
- return jQueryResult;
43
- };
44
- }
45
-
46
- function getIndex(selection: string, len) {
47
- let index: number | null;
48
- if (selection === RANDOM_SELECT_OPT) {
49
- index = random(0, len - 1);
50
- } else {
51
- index = parameterValueToNumber(selection, { integer: true });
52
- if (index == null) {
53
- throw new PresentableError('Invalid index: ' + selection);
54
- }
55
- }
56
- return index;
57
- }