runner-runtime 1.0.14 → 1.0.16
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/events/api.js +21 -13
- package/events/index.js +11 -5
- package/index.js +20 -16
- package/libs/2har.js +148 -0
- package/package.json +3 -1
- package/test.js +2 -2
- package/tmp/request.js +1 -1
package/events/api.js
CHANGED
|
@@ -10,6 +10,8 @@ const FileType = require("file-type"),
|
|
|
10
10
|
Buffer = require("buffer/").Buffer,
|
|
11
11
|
isImage = require("is-image");
|
|
12
12
|
const { getAPIFromCollection, smartUrlJoin, replace2RegExp, getParentTargetIDs, base64toCacheFile, getInsideVariables, getCaseInsensitive, camelCaseToSnakeCase } = require('../libs/utils'),
|
|
13
|
+
{ generateHarFromRequest } = require('../libs/2har'),
|
|
14
|
+
|
|
13
15
|
_ = require('lodash');
|
|
14
16
|
const sdk = require("postman-collection"),
|
|
15
17
|
Url = sdk.Url,
|
|
@@ -2172,7 +2174,15 @@ module.exports = (event, option, callback, eventRuntimeData, eventResultList) =>
|
|
|
2172
2174
|
}
|
|
2173
2175
|
}
|
|
2174
2176
|
|
|
2175
|
-
|
|
2177
|
+
const requestOptions = convert2EchoRequest(request, requestJson, postmanJSON, history);
|
|
2178
|
+
_.set(eventRuntimeData, [event?.event_id, "request"], requestOptions);
|
|
2179
|
+
|
|
2180
|
+
if (_.includes(['get_parsed_request'], scene)) {
|
|
2181
|
+
resolve(generateHarFromRequest(request));
|
|
2182
|
+
try {
|
|
2183
|
+
run.abort();
|
|
2184
|
+
} catch (e) { }
|
|
2185
|
+
}
|
|
2176
2186
|
},
|
|
2177
2187
|
|
|
2178
2188
|
beforeTest(err, cursor, events, item) {
|
|
@@ -2255,20 +2265,18 @@ module.exports = (event, option, callback, eventRuntimeData, eventResultList) =>
|
|
|
2255
2265
|
|
|
2256
2266
|
// 写入到自动化测试结果
|
|
2257
2267
|
if (scene === 'auto_test' && _.includes(['assert', 'assert_visual', 'api', 'sample'], event?.type)) {
|
|
2258
|
-
eventResultList.push(_.assign(camelCaseToSnakeCase(_.get(eventRuntimeData, event?.event_id)), _.pick(event, ['type', 'event_id', 'test_id'])
|
|
2259
|
-
iteration_id: aTools.snowflakeId()
|
|
2260
|
-
}))
|
|
2268
|
+
eventResultList.push(_.assign(camelCaseToSnakeCase(_.get(eventRuntimeData, event?.event_id)), _.pick(event, ['type', 'event_id', 'test_id', 'iteration_id'])))
|
|
2261
2269
|
}
|
|
2262
|
-
}
|
|
2263
2270
|
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2271
|
+
resolve(_.assign({
|
|
2272
|
+
action: 'request',
|
|
2273
|
+
data: camelCaseToSnakeCase(_.get(eventRuntimeData, event?.event_id)),
|
|
2274
|
+
error: _.get(eventRuntimeData, [event?.event_id, 'error', 'message']) || null,
|
|
2275
|
+
event_id: event?.event_id,
|
|
2276
|
+
iteration_id: _.get(eventRuntimeData, [event?.event_id, 'iteration_id']),
|
|
2277
|
+
type: 'request'
|
|
2278
|
+
}, _.pick(requestJson, ['parent_id', 'project_id', 'test_id', 'target_id'])))
|
|
2279
|
+
}
|
|
2272
2280
|
}
|
|
2273
2281
|
})
|
|
2274
2282
|
}
|
package/events/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const atomicSleep = require("atomic-sleep"),
|
|
2
2
|
jsonpath = require("jsonpath"),
|
|
3
|
+
aTools = require("apipost-tools"),
|
|
3
4
|
JSON5 = require('json5'),
|
|
4
5
|
_ = require('lodash'),
|
|
5
6
|
{ returnBoolean, variableReplace } = require('../libs/utils');
|
|
@@ -196,7 +197,9 @@ const events = {
|
|
|
196
197
|
const executeEvent = (event, option, callback, eventRuntimeData, eventResultList) => {
|
|
197
198
|
return new Promise((resolve, reject) => {
|
|
198
199
|
if (_.isUndefined(_.get(eventRuntimeData, event.event_id))) {
|
|
199
|
-
_.set(eventRuntimeData, event.event_id, {
|
|
200
|
+
_.set(eventRuntimeData, event.event_id, {
|
|
201
|
+
iteration_id: aTools.snowflakeId()
|
|
202
|
+
});
|
|
200
203
|
}
|
|
201
204
|
const eventCall = _.get(events, `${event?.type}`);
|
|
202
205
|
|
|
@@ -208,10 +211,13 @@ const executeEvent = (event, option, callback, eventRuntimeData, eventResultList
|
|
|
208
211
|
const { total, scene } = option;
|
|
209
212
|
if (scene == 'auto_test' && _.isInteger(event?.progress)) {
|
|
210
213
|
callback({
|
|
211
|
-
action: '
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
214
|
+
action: 'process',
|
|
215
|
+
data: {
|
|
216
|
+
processCurrentCount: event?.progress + 1,
|
|
217
|
+
processTotalCount: total,
|
|
218
|
+
event_id: event?.event_id,
|
|
219
|
+
testing_id: event?.test_id,
|
|
220
|
+
}
|
|
215
221
|
})
|
|
216
222
|
}
|
|
217
223
|
})
|
package/index.js
CHANGED
|
@@ -19,21 +19,6 @@ const run = async (events, option, callback) => {
|
|
|
19
19
|
if (scene == 'http_request') {
|
|
20
20
|
const event = _.first(tempEvents);
|
|
21
21
|
|
|
22
|
-
if (_.isObject(event) && _.has(event, 'type')) {
|
|
23
|
-
try {
|
|
24
|
-
const data = await executeEvent(event, _.assign(eventOptions, { iterationData: {} }), callback, eventRuntimeData, eventResultList);
|
|
25
|
-
callback(data)
|
|
26
|
-
} catch (e) {
|
|
27
|
-
callback(e);
|
|
28
|
-
|
|
29
|
-
if (_.includes(ABORT_RECURSION_ERROR, e?.action)) {
|
|
30
|
-
throw new Error(String(e?.message));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
} else if (scene == 'get_parsed_request') {
|
|
35
|
-
const event = _.first(tempEvents);
|
|
36
|
-
|
|
37
22
|
if (_.isObject(event) && _.has(event, 'type')) {
|
|
38
23
|
try {
|
|
39
24
|
const data = await executeEvent(event, _.assign(eventOptions, { iterationData: {} }), callback, eventRuntimeData, eventResultList);
|
|
@@ -72,4 +57,23 @@ const run = async (events, option, callback) => {
|
|
|
72
57
|
})
|
|
73
58
|
}
|
|
74
59
|
}
|
|
75
|
-
|
|
60
|
+
|
|
61
|
+
const getHar = async (events, option) => {
|
|
62
|
+
const eventOptions = _.pick(option, ["scene", "lang", "project", "env", "globals", "cookies", "system_configs", "custom_functions", "collection", "database_configs", "enable_sandbox", "sleep", "name", "testing_id"]);
|
|
63
|
+
const eventRuntimeData = {
|
|
64
|
+
variables: {}
|
|
65
|
+
};
|
|
66
|
+
const eventResultList = [];
|
|
67
|
+
const event = _.first(events);
|
|
68
|
+
|
|
69
|
+
if (_.isObject(event) && _.has(event, 'type')) {
|
|
70
|
+
try {
|
|
71
|
+
return await executeEvent(event, _.assign(eventOptions, { scene: 'get_parsed_request' }), () => { }, eventRuntimeData, eventResultList);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
if (_.includes(ABORT_RECURSION_ERROR, e?.action)) {
|
|
74
|
+
throw new Error(String(e?.message));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
module.exports = { run, getHar }
|
package/libs/2har.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a Postman-style request configuration into HAR format JSON.
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} options - Request options based on Postman format.
|
|
5
|
+
* {
|
|
6
|
+
* url: string,
|
|
7
|
+
* method: string,
|
|
8
|
+
* headers: array,
|
|
9
|
+
* queryParams: array,
|
|
10
|
+
* body: {
|
|
11
|
+
* mode: string, // none | urlencoded | formdata | raw | json
|
|
12
|
+
* [urlencoded]: array, // For urlencoded form data
|
|
13
|
+
* [formdata]: array, // For multipart/form-data
|
|
14
|
+
* [raw]: string, // For raw (text or binary)
|
|
15
|
+
* [json]: object // For JSON body
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* @returns {Object} HAR format JSON object.
|
|
19
|
+
*/
|
|
20
|
+
function generateHarFromRequest(options) {
|
|
21
|
+
const {
|
|
22
|
+
url,
|
|
23
|
+
method = 'GET',
|
|
24
|
+
headers = [], // Array of { key, value }
|
|
25
|
+
queryParams = [], // Array of { key, value }
|
|
26
|
+
body = { mode: 'none' }, // Body in Postman format
|
|
27
|
+
} = options;
|
|
28
|
+
|
|
29
|
+
const har = {
|
|
30
|
+
log: {
|
|
31
|
+
version: '1.2',
|
|
32
|
+
creator: {
|
|
33
|
+
name: 'Custom Node Request to HAR Converter',
|
|
34
|
+
version: '1.0',
|
|
35
|
+
},
|
|
36
|
+
entries: [
|
|
37
|
+
{
|
|
38
|
+
request: {
|
|
39
|
+
method: method.toUpperCase(),
|
|
40
|
+
url: appendQueryParams(url, queryParams),
|
|
41
|
+
headers: processHeaders(headers),
|
|
42
|
+
queryString: processQueryString(queryParams),
|
|
43
|
+
postData: processBody(body),
|
|
44
|
+
headersSize: -1, // Optional, usually auto-calculated
|
|
45
|
+
bodySize: -1, // Optional, usually auto-calculated
|
|
46
|
+
},
|
|
47
|
+
startedDateTime: new Date().toISOString(),
|
|
48
|
+
time: 0, // Mock timing data (replace with actual timing if needed)
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return har;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Appends query parameters to a URL.
|
|
59
|
+
* @param {string} url - The base URL.
|
|
60
|
+
* @param {Array} queryParams - Array of { key: string, value: string }.
|
|
61
|
+
* @returns {string} URL with query parameters appended.
|
|
62
|
+
*/
|
|
63
|
+
function appendQueryParams(url, queryParams) {
|
|
64
|
+
if (!queryParams || queryParams.length === 0) return url;
|
|
65
|
+
|
|
66
|
+
const searchParams = new URLSearchParams();
|
|
67
|
+
queryParams.forEach(({ key, value }) => {
|
|
68
|
+
searchParams.append(key, value);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return `${url}?${searchParams.toString()}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Converts Postman-style headers into HAR format.
|
|
76
|
+
* @param {Array} headers - Array of { key: string, value: string }.
|
|
77
|
+
* @returns {Array} Array of HAR headers.
|
|
78
|
+
*/
|
|
79
|
+
function processHeaders(headers) {
|
|
80
|
+
return (headers || []).map(({ key, value }) => ({
|
|
81
|
+
name: key,
|
|
82
|
+
value: value,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Converts Postman-style query parameters into HAR format.
|
|
88
|
+
* @param {Array} queryParams - Array of { key: string, value: string }.
|
|
89
|
+
* @returns {Array} Array of HAR query parameters.
|
|
90
|
+
*/
|
|
91
|
+
function processQueryString(queryParams) {
|
|
92
|
+
return (queryParams || []).map(({ key, value }) => ({
|
|
93
|
+
name: key,
|
|
94
|
+
value: String(value),
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Processes the body into HAR format based on its mode.
|
|
100
|
+
* @param {Object} body - Postman-style body object with a defined mode.
|
|
101
|
+
* @returns {Object|undefined} HAR postData object.
|
|
102
|
+
*/
|
|
103
|
+
function processBody(body) {
|
|
104
|
+
const { mode } = body;
|
|
105
|
+
|
|
106
|
+
if (mode === 'none') {
|
|
107
|
+
return undefined; // No body
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (mode === 'urlencoded') {
|
|
111
|
+
return {
|
|
112
|
+
mimeType: 'application/x-www-form-urlencoded',
|
|
113
|
+
params: (body.urlencoded || []).map(({ key, value }) => ({
|
|
114
|
+
name: key,
|
|
115
|
+
value: String(value),
|
|
116
|
+
})),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (mode === 'formdata') {
|
|
121
|
+
return {
|
|
122
|
+
mimeType: 'multipart/form-data',
|
|
123
|
+
params: (body.formdata || []).map(({ key, value, type = 'text' }) => {
|
|
124
|
+
const param = { name: key, value: String(value) };
|
|
125
|
+
if (type === 'file') param.fileName = value; // File handling
|
|
126
|
+
return param;
|
|
127
|
+
}),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (mode === 'raw') {
|
|
132
|
+
return {
|
|
133
|
+
mimeType: 'text/plain',
|
|
134
|
+
text: String(body.raw),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (mode === 'json') {
|
|
139
|
+
return {
|
|
140
|
+
mimeType: 'application/json',
|
|
141
|
+
text: JSON.stringify(body.json || {}),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return undefined; // No body
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = { generateHarFromRequest };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runner-runtime",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "Processing data returned by AI.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"apipost-tools": "^0.0.38",
|
|
25
25
|
"atomic-sleep": "^1.0.0",
|
|
26
26
|
"content-disposition": "^0.5.4",
|
|
27
|
+
"database-query": "^1.1.12",
|
|
27
28
|
"exp-mock": "^2.0.15",
|
|
28
29
|
"file-type": "^16.5.4",
|
|
29
30
|
"is-image": "^3.0.0",
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
"net": "^1.0.2",
|
|
40
41
|
"postman-collection": "^5.0.2",
|
|
41
42
|
"postman-runtime-pro": "^7.43.13",
|
|
43
|
+
"request-har": "^1.0.0",
|
|
42
44
|
"strip-json-comments": "^5.0.1",
|
|
43
45
|
"tough": "^0.6.0",
|
|
44
46
|
"tough-cookie": "^5.1.2",
|
package/test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const _ =require('lodash');
|
|
2
|
-
const {
|
|
2
|
+
const { getHar } = require('./index');
|
|
3
3
|
|
|
4
4
|
// 以下为调用示例
|
|
5
5
|
const callback = (res) => {
|
|
@@ -121,4 +121,4 @@ const callback = (res) => {
|
|
|
121
121
|
})();
|
|
122
122
|
//pip end
|
|
123
123
|
const { option, test_events } = require('./tmp/request'); // tmp todo...
|
|
124
|
-
|
|
124
|
+
getHar(test_events, option, callback);
|