@skyramp/skyramp 0.4.106 → 0.5.1
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/lib/dev-darwin-amd64.dylib +0 -0
- package/lib/dev-darwin-amd64.h +17 -0
- package/lib/dev-darwin-arm64.dylib +0 -0
- package/lib/dev-darwin-arm64.h +17 -0
- package/lib/dev-linux-386.h +17 -0
- package/lib/dev-linux-386.so +0 -0
- package/lib/dev-linux-amd64.h +17 -0
- package/lib/dev-linux-amd64.so +0 -0
- package/lib/dev-windows-amd64.dll +0 -0
- package/lib/dev-windows-amd64.h +17 -0
- package/package.json +1 -1
- package/src/classes/RequestV2.d.ts +26 -0
- package/src/classes/RequestV2.js +109 -0
- package/src/classes/ResponseV2.d.ts +22 -0
- package/src/classes/ResponseV2.js +90 -0
- package/src/classes/SkyrampClient.d.ts +29 -1
- package/src/classes/SkyrampClient.js +74 -20
- package/src/function.js +58 -0
- package/src/index.d.ts +5 -1
- package/src/index.js +10 -1
- package/src/utils.js +111 -3
|
Binary file
|
package/lib/dev-darwin-amd64.h
CHANGED
|
@@ -40,6 +40,11 @@ struct worker_info {
|
|
|
40
40
|
char *error;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
struct response_wrapper {
|
|
44
|
+
char *response;
|
|
45
|
+
char *error;
|
|
46
|
+
};
|
|
47
|
+
|
|
43
48
|
#line 1 "cgo-generated-wrapper"
|
|
44
49
|
|
|
45
50
|
#line 7 "endpoint.go"
|
|
@@ -127,6 +132,18 @@ extern char* generateUserTokenWrapper(char* provider, char* email, char* oauthTo
|
|
|
127
132
|
extern struct worker_info newStartDockerSkyrampWorkerWrapper(char* image, char* tag, GoInt hostPort, char* targetNetworkName, char* testServiceAlias);
|
|
128
133
|
extern char* newDeleteDockerSkyrampWorkerWrapper(char* containerName);
|
|
129
134
|
extern char* runTesterCurlWrapper(char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* address, char* request);
|
|
135
|
+
extern struct response_wrapper sendRequestWrapper(char* address, char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* request);
|
|
136
|
+
|
|
137
|
+
/* Return type for getJSONValueWrapper */
|
|
138
|
+
struct getJSONValueWrapper_return {
|
|
139
|
+
char* r0;
|
|
140
|
+
char* r1;
|
|
141
|
+
};
|
|
142
|
+
extern struct getJSONValueWrapper_return getJSONValueWrapper(char* jsonS, char* path);
|
|
143
|
+
extern char* checkStatusCodeWrapper(char* response, char* expectedStatus);
|
|
144
|
+
extern char* deployDockerDashboardWrapper(char* networkName);
|
|
145
|
+
extern char* deployK8sDashboardWrapper(char* networkName);
|
|
146
|
+
extern struct response_wrapper checkSchemaWrapper(char* requestBody, char* sampleSchema);
|
|
130
147
|
extern char* newGrpcEndpointWrapper(char* name, char* serviceName, GoInt port, char* inputFile);
|
|
131
148
|
extern char* newRestEndpointWrapper(char* name, char* openApiTag, GoInt port, char* inputFile, char* restPath);
|
|
132
149
|
extern char* getEndpointWrapper(char* service, GoInt port, char* restPath);
|
|
Binary file
|
package/lib/dev-darwin-arm64.h
CHANGED
|
@@ -40,6 +40,11 @@ struct worker_info {
|
|
|
40
40
|
char *error;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
struct response_wrapper {
|
|
44
|
+
char *response;
|
|
45
|
+
char *error;
|
|
46
|
+
};
|
|
47
|
+
|
|
43
48
|
#line 1 "cgo-generated-wrapper"
|
|
44
49
|
|
|
45
50
|
#line 7 "endpoint.go"
|
|
@@ -127,6 +132,18 @@ extern char* generateUserTokenWrapper(char* provider, char* email, char* oauthTo
|
|
|
127
132
|
extern struct worker_info newStartDockerSkyrampWorkerWrapper(char* image, char* tag, GoInt hostPort, char* targetNetworkName, char* testServiceAlias);
|
|
128
133
|
extern char* newDeleteDockerSkyrampWorkerWrapper(char* containerName);
|
|
129
134
|
extern char* runTesterCurlWrapper(char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* address, char* request);
|
|
135
|
+
extern struct response_wrapper sendRequestWrapper(char* address, char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* request);
|
|
136
|
+
|
|
137
|
+
/* Return type for getJSONValueWrapper */
|
|
138
|
+
struct getJSONValueWrapper_return {
|
|
139
|
+
char* r0;
|
|
140
|
+
char* r1;
|
|
141
|
+
};
|
|
142
|
+
extern struct getJSONValueWrapper_return getJSONValueWrapper(char* jsonS, char* path);
|
|
143
|
+
extern char* checkStatusCodeWrapper(char* response, char* expectedStatus);
|
|
144
|
+
extern char* deployDockerDashboardWrapper(char* networkName);
|
|
145
|
+
extern char* deployK8sDashboardWrapper(char* networkName);
|
|
146
|
+
extern struct response_wrapper checkSchemaWrapper(char* requestBody, char* sampleSchema);
|
|
130
147
|
extern char* newGrpcEndpointWrapper(char* name, char* serviceName, GoInt port, char* inputFile);
|
|
131
148
|
extern char* newRestEndpointWrapper(char* name, char* openApiTag, GoInt port, char* inputFile, char* restPath);
|
|
132
149
|
extern char* getEndpointWrapper(char* service, GoInt port, char* restPath);
|
package/lib/dev-linux-386.h
CHANGED
|
@@ -40,6 +40,11 @@ struct worker_info {
|
|
|
40
40
|
char *error;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
struct response_wrapper {
|
|
44
|
+
char *response;
|
|
45
|
+
char *error;
|
|
46
|
+
};
|
|
47
|
+
|
|
43
48
|
#line 1 "cgo-generated-wrapper"
|
|
44
49
|
|
|
45
50
|
#line 7 "endpoint.go"
|
|
@@ -127,6 +132,18 @@ extern char* generateUserTokenWrapper(char* provider, char* email, char* oauthTo
|
|
|
127
132
|
extern struct worker_info newStartDockerSkyrampWorkerWrapper(char* image, char* tag, GoInt hostPort, char* targetNetworkName, char* testServiceAlias);
|
|
128
133
|
extern char* newDeleteDockerSkyrampWorkerWrapper(char* containerName);
|
|
129
134
|
extern char* runTesterCurlWrapper(char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* address, char* request);
|
|
135
|
+
extern struct response_wrapper sendRequestWrapper(char* address, char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* request);
|
|
136
|
+
|
|
137
|
+
/* Return type for getJSONValueWrapper */
|
|
138
|
+
struct getJSONValueWrapper_return {
|
|
139
|
+
char* r0;
|
|
140
|
+
char* r1;
|
|
141
|
+
};
|
|
142
|
+
extern struct getJSONValueWrapper_return getJSONValueWrapper(char* jsonS, char* path);
|
|
143
|
+
extern char* checkStatusCodeWrapper(char* response, char* expectedStatus);
|
|
144
|
+
extern char* deployDockerDashboardWrapper(char* networkName);
|
|
145
|
+
extern char* deployK8sDashboardWrapper(char* networkName);
|
|
146
|
+
extern struct response_wrapper checkSchemaWrapper(char* requestBody, char* sampleSchema);
|
|
130
147
|
extern char* newGrpcEndpointWrapper(char* name, char* serviceName, GoInt port, char* inputFile);
|
|
131
148
|
extern char* newRestEndpointWrapper(char* name, char* openApiTag, GoInt port, char* inputFile, char* restPath);
|
|
132
149
|
extern char* getEndpointWrapper(char* service, GoInt port, char* restPath);
|
package/lib/dev-linux-386.so
CHANGED
|
Binary file
|
package/lib/dev-linux-amd64.h
CHANGED
|
@@ -40,6 +40,11 @@ struct worker_info {
|
|
|
40
40
|
char *error;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
struct response_wrapper {
|
|
44
|
+
char *response;
|
|
45
|
+
char *error;
|
|
46
|
+
};
|
|
47
|
+
|
|
43
48
|
#line 1 "cgo-generated-wrapper"
|
|
44
49
|
|
|
45
50
|
#line 7 "endpoint.go"
|
|
@@ -127,6 +132,18 @@ extern char* generateUserTokenWrapper(char* provider, char* email, char* oauthTo
|
|
|
127
132
|
extern struct worker_info newStartDockerSkyrampWorkerWrapper(char* image, char* tag, GoInt hostPort, char* targetNetworkName, char* testServiceAlias);
|
|
128
133
|
extern char* newDeleteDockerSkyrampWorkerWrapper(char* containerName);
|
|
129
134
|
extern char* runTesterCurlWrapper(char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* address, char* request);
|
|
135
|
+
extern struct response_wrapper sendRequestWrapper(char* address, char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* request);
|
|
136
|
+
|
|
137
|
+
/* Return type for getJSONValueWrapper */
|
|
138
|
+
struct getJSONValueWrapper_return {
|
|
139
|
+
char* r0;
|
|
140
|
+
char* r1;
|
|
141
|
+
};
|
|
142
|
+
extern struct getJSONValueWrapper_return getJSONValueWrapper(char* jsonS, char* path);
|
|
143
|
+
extern char* checkStatusCodeWrapper(char* response, char* expectedStatus);
|
|
144
|
+
extern char* deployDockerDashboardWrapper(char* networkName);
|
|
145
|
+
extern char* deployK8sDashboardWrapper(char* networkName);
|
|
146
|
+
extern struct response_wrapper checkSchemaWrapper(char* requestBody, char* sampleSchema);
|
|
130
147
|
extern char* newGrpcEndpointWrapper(char* name, char* serviceName, GoInt port, char* inputFile);
|
|
131
148
|
extern char* newRestEndpointWrapper(char* name, char* openApiTag, GoInt port, char* inputFile, char* restPath);
|
|
132
149
|
extern char* getEndpointWrapper(char* service, GoInt port, char* restPath);
|
package/lib/dev-linux-amd64.so
CHANGED
|
Binary file
|
|
Binary file
|
package/lib/dev-windows-amd64.h
CHANGED
|
@@ -40,6 +40,11 @@ struct worker_info {
|
|
|
40
40
|
char *error;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
struct response_wrapper {
|
|
44
|
+
char *response;
|
|
45
|
+
char *error;
|
|
46
|
+
};
|
|
47
|
+
|
|
43
48
|
#line 1 "cgo-generated-wrapper"
|
|
44
49
|
|
|
45
50
|
#line 7 "endpoint.go"
|
|
@@ -127,6 +132,18 @@ extern __declspec(dllexport) char* generateUserTokenWrapper(char* provider, char
|
|
|
127
132
|
extern __declspec(dllexport) struct worker_info newStartDockerSkyrampWorkerWrapper(char* image, char* tag, GoInt hostPort, char* targetNetworkName, char* testServiceAlias);
|
|
128
133
|
extern __declspec(dllexport) char* newDeleteDockerSkyrampWorkerWrapper(char* containerName);
|
|
129
134
|
extern __declspec(dllexport) char* runTesterCurlWrapper(char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* address, char* request);
|
|
135
|
+
extern __declspec(dllexport) struct response_wrapper sendRequestWrapper(char* address, char* namespace, char* kubePath, char* kubeContext, char* clusterName, char* request);
|
|
136
|
+
|
|
137
|
+
/* Return type for getJSONValueWrapper */
|
|
138
|
+
struct getJSONValueWrapper_return {
|
|
139
|
+
char* r0;
|
|
140
|
+
char* r1;
|
|
141
|
+
};
|
|
142
|
+
extern __declspec(dllexport) struct getJSONValueWrapper_return getJSONValueWrapper(char* jsonS, char* path);
|
|
143
|
+
extern __declspec(dllexport) char* checkStatusCodeWrapper(char* response, char* expectedStatus);
|
|
144
|
+
extern __declspec(dllexport) char* deployDockerDashboardWrapper(char* networkName);
|
|
145
|
+
extern __declspec(dllexport) char* deployK8sDashboardWrapper(char* networkName);
|
|
146
|
+
extern __declspec(dllexport) struct response_wrapper checkSchemaWrapper(char* requestBody, char* sampleSchema);
|
|
130
147
|
extern __declspec(dllexport) char* newGrpcEndpointWrapper(char* name, char* serviceName, GoInt port, char* inputFile);
|
|
131
148
|
extern __declspec(dllexport) char* newRestEndpointWrapper(char* name, char* openApiTag, GoInt port, char* inputFile, char* restPath);
|
|
132
149
|
extern __declspec(dllexport) char* getEndpointWrapper(char* service, GoInt port, char* restPath);
|
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a REST request.
|
|
3
|
+
*/
|
|
4
|
+
interface RequestV2Options {
|
|
5
|
+
url: string;
|
|
6
|
+
path: string;
|
|
7
|
+
method: string;
|
|
8
|
+
body?: string;
|
|
9
|
+
headers?: {[headerName: string]: string};
|
|
10
|
+
cookies?: {[cookieName: string]: string};
|
|
11
|
+
dataOverride?: {[dataName: string]: string | number | boolean | object};
|
|
12
|
+
pathParams?: {[pathName: string]: string | number | boolean | object};
|
|
13
|
+
queryParams?: {[queryName: string]: string | number | boolean | object};
|
|
14
|
+
formParams?: {[formParamName: string]: string | number | boolean | object};
|
|
15
|
+
expectedCode?: string;
|
|
16
|
+
funcHandler?: string;
|
|
17
|
+
funcHandlerType?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class RequestV2 {
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new instance of RequestV2.
|
|
22
|
+
* @param options - The options for creating the request.
|
|
23
|
+
*/
|
|
24
|
+
constructor(options: RequestV2Options);
|
|
25
|
+
toYaml(): string;
|
|
26
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const yaml = require('js-yaml');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a REST request.
|
|
5
|
+
*/
|
|
6
|
+
class RequestV2 {
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new instance of RequestV2.
|
|
9
|
+
* @param {Object} [options={}] - The options for creating the request.
|
|
10
|
+
* @param {string} [options.url=''] - The URL of the request.
|
|
11
|
+
* @param {string} [options.path=''] - The REST path of the request.
|
|
12
|
+
* @param {string} [options.method=''] - The HTTP method of the request.
|
|
13
|
+
* @param {string} [options.body=''] - The request body in JSON format.
|
|
14
|
+
* @param {Object.<string, string>} [options.headers={}] - The HTTP headers of the request.
|
|
15
|
+
* @param {Object.<string, string>} [options.cookies={}] - The HTTP cookies of the request.
|
|
16
|
+
* @param {Object.<string, *>} [options.dataOverride={}] - The data override for the request.
|
|
17
|
+
* @param {Object.<string, *>} [options.pathParams={}] - The path parameters for the request.
|
|
18
|
+
* @param {Object.<string, *>} [options.queryParams={}] - The query parameters for the request.
|
|
19
|
+
* @param {Object.<string, *>} [options.formParams={}] - The form parameters of the request.
|
|
20
|
+
* @param {string} [options.expectedCode=''] - The expected HTTP status code of the response.
|
|
21
|
+
* @param {string} [options.funcHandler=''] - The dynamic handler function for the request.
|
|
22
|
+
* @param {string} [options.funcHandlerType=''] - The type of the dynamic handler (e.g., 'python', 'javascript').
|
|
23
|
+
*/
|
|
24
|
+
constructor(options = {}) {
|
|
25
|
+
this.url = options.url || '';
|
|
26
|
+
this.path = options.path || '';
|
|
27
|
+
this.method = options.method || '';
|
|
28
|
+
this.body = options.body || '';
|
|
29
|
+
this.headers = options.headers || {};
|
|
30
|
+
this.cookies = options.cookies || {};
|
|
31
|
+
this.dataOverride = options.dataOverride || {};
|
|
32
|
+
this.pathParams = options.pathParams || {};
|
|
33
|
+
this.queryParams = options.queryParams || {};
|
|
34
|
+
this.formParams = options.formParams || {};
|
|
35
|
+
this.expectedCode = options.expectedCode || '';
|
|
36
|
+
this.funcHandler = options.funcHandler || '';
|
|
37
|
+
this.funcHandlerType = options.funcHandlerType || '';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
toYaml() {
|
|
41
|
+
// Map of camelCase to snake_case field names
|
|
42
|
+
const fieldMappings = {
|
|
43
|
+
url: 'url',
|
|
44
|
+
path: 'path',
|
|
45
|
+
method: 'method',
|
|
46
|
+
body: 'body',
|
|
47
|
+
headers: 'headers',
|
|
48
|
+
cookies: 'cookies',
|
|
49
|
+
dataOverride: 'data_override',
|
|
50
|
+
pathParams: 'path_params',
|
|
51
|
+
queryParams: 'query_params',
|
|
52
|
+
formParams: 'form_params',
|
|
53
|
+
expectedCode: 'expected_code',
|
|
54
|
+
funcHandler: 'func_handler',
|
|
55
|
+
funcHandlerType: 'func_handler_type'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const { body, ...rest } = this;
|
|
59
|
+
// Create object with non-empty values and convert to snake_case
|
|
60
|
+
const yamlObject = Object.entries(rest).reduce((acc, [key, value]) => {
|
|
61
|
+
// Include field only if it's not empty (empty string, empty object, or empty array)
|
|
62
|
+
if (value && (typeof value !== 'object' || Object.keys(value).length > 0)) {
|
|
63
|
+
// Use snake_case key if mapping exists, otherwise use original key
|
|
64
|
+
const snakeKey = fieldMappings[key] || key;
|
|
65
|
+
acc[snakeKey] = value;
|
|
66
|
+
}
|
|
67
|
+
return acc;
|
|
68
|
+
}, {});
|
|
69
|
+
|
|
70
|
+
// Add body if it exists
|
|
71
|
+
if (body) {
|
|
72
|
+
yamlObject.body = JSON.stringify(body, null, 2);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return yaml.dump(yamlObject);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
toJson() {
|
|
79
|
+
// Use the same field mappings as toYaml for consistency
|
|
80
|
+
const fieldMappings = {
|
|
81
|
+
url: 'url',
|
|
82
|
+
path: 'path',
|
|
83
|
+
method: 'method',
|
|
84
|
+
body: 'body',
|
|
85
|
+
headers: 'headers',
|
|
86
|
+
cookies: 'cookies',
|
|
87
|
+
dataOverride: 'data_override',
|
|
88
|
+
pathParams: 'path_params',
|
|
89
|
+
queryParams: 'query_params',
|
|
90
|
+
formParams: 'form_params',
|
|
91
|
+
expectedCode: 'expected_code',
|
|
92
|
+
funcHandler: 'func_handler',
|
|
93
|
+
funcHandlerType: 'func_handler_type'
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const { ...rest } = this;
|
|
97
|
+
// Create object with non-empty values and convert to snake_case
|
|
98
|
+
const jsonObject = Object.entries(rest).reduce((acc, [key, value]) => {
|
|
99
|
+
if (value && (typeof value !== 'object' || Object.keys(value).length > 0)) {
|
|
100
|
+
const snakeKey = fieldMappings[key] || key;
|
|
101
|
+
acc[snakeKey] = value;
|
|
102
|
+
}
|
|
103
|
+
return acc;
|
|
104
|
+
}, {});
|
|
105
|
+
return JSON.stringify(jsonObject, null, 2);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = RequestV2;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a REST response.
|
|
3
|
+
*/
|
|
4
|
+
interface ResponseV2Options {
|
|
5
|
+
path?: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
statusCode?: string;
|
|
8
|
+
responseHeaders?: {[headerName: string]: string};
|
|
9
|
+
responseBody?: string;
|
|
10
|
+
requestHeaders?: {[headerName: string]: string};
|
|
11
|
+
requestBody?: string;
|
|
12
|
+
duration?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export declare class ResponseV2 {
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new instance of ResponseV2.
|
|
18
|
+
* @param options - The options for creating the response.
|
|
19
|
+
*/
|
|
20
|
+
constructor(options?: ResponseV2Options);
|
|
21
|
+
toYaml(): string;
|
|
22
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const yaml = require('js-yaml');
|
|
2
|
+
/**
|
|
3
|
+
* Represents a REST response.
|
|
4
|
+
*/
|
|
5
|
+
class ResponseV2 {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new ResponseV2 instance
|
|
9
|
+
* @param {Object} options - The options for creating the response
|
|
10
|
+
* @param {string} [options.path=''] - The request path
|
|
11
|
+
* @param {string} [options.method=''] - The HTTP method used
|
|
12
|
+
* @param {string} [options.status_code=''] - The HTTP status code of the response
|
|
13
|
+
* @param {Object} [options.response_headers={}] - Headers included in the response
|
|
14
|
+
* @param {string} [options.response_body=''] - Body of the response
|
|
15
|
+
* @param {Object} [options.request_headers={}] - Headers included in the request
|
|
16
|
+
* @param {string} [options.request_body=''] - Body of the request
|
|
17
|
+
* @param {string} [options.duration=''] - Duration of the request/response cycle
|
|
18
|
+
*/
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
this.path = options.path || '';
|
|
21
|
+
this.method = options.method || '';
|
|
22
|
+
this.statusCode = options.status_code || '';
|
|
23
|
+
this.responseHeaders = options.response_headers || {};
|
|
24
|
+
this.responseBody = options.response_body || '';
|
|
25
|
+
this.requestHeaders = options.request_headers || {};
|
|
26
|
+
this.requestBody = options.request_body || '';
|
|
27
|
+
this.duration = options.duration || '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
toYaml() {
|
|
31
|
+
// Map of camelCase to snake_case field names
|
|
32
|
+
const fieldMappings = {
|
|
33
|
+
path: 'path',
|
|
34
|
+
method: 'method',
|
|
35
|
+
statusCode: 'status_code',
|
|
36
|
+
responseHeaders: 'response_headers',
|
|
37
|
+
responseBody: 'response_body',
|
|
38
|
+
requestHeaders: 'request_headers',
|
|
39
|
+
requestBody: 'request_body',
|
|
40
|
+
duration: 'duration'
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const { body, ...rest } = this;
|
|
44
|
+
// Create object with non-empty values and convert to snake_case
|
|
45
|
+
const yamlObject = Object.entries(rest).reduce((acc, [key, value]) => {
|
|
46
|
+
// Include field only if it's not empty (empty string, empty object, or empty array)
|
|
47
|
+
if (value && (typeof value !== 'object' || Object.keys(value).length > 0)) {
|
|
48
|
+
// Use snake_case key if mapping exists, otherwise use original key
|
|
49
|
+
const snakeKey = fieldMappings[key] || key;
|
|
50
|
+
acc[snakeKey] = value;
|
|
51
|
+
}
|
|
52
|
+
return acc;
|
|
53
|
+
}, {});
|
|
54
|
+
|
|
55
|
+
// Add body if it exists
|
|
56
|
+
if (body) {
|
|
57
|
+
yamlObject.body = JSON.stringify(body, null, 2);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return yaml.dump(yamlObject);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
toJson() {
|
|
64
|
+
// Use the same field mappings as toYaml for consistency
|
|
65
|
+
const fieldMappings = {
|
|
66
|
+
path: 'path',
|
|
67
|
+
method: 'method',
|
|
68
|
+
statusCode: 'status_code',
|
|
69
|
+
responseHeaders: 'response_headers',
|
|
70
|
+
responseBody: 'response_body',
|
|
71
|
+
requestHeaders: 'request_headers',
|
|
72
|
+
requestBody: 'request_body',
|
|
73
|
+
duration: 'duration'
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const { ...rest } = this;
|
|
77
|
+
// Create object with non-empty values and convert to snake_case
|
|
78
|
+
const jsonObject = Object.entries(rest).reduce((acc, [key, value]) => {
|
|
79
|
+
if (value && (typeof value !== 'object' || Object.keys(value).length > 0)) {
|
|
80
|
+
const snakeKey = fieldMappings[key] || key;
|
|
81
|
+
acc[snakeKey] = value;
|
|
82
|
+
}
|
|
83
|
+
return acc;
|
|
84
|
+
}, {});
|
|
85
|
+
return JSON.stringify(jsonObject, null, 2);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
module.exports = ResponseV2;
|
|
@@ -2,7 +2,7 @@ import { ResponseValue } from '..';
|
|
|
2
2
|
import { Endpoint } from './Endpoint';
|
|
3
3
|
import { Scenario } from './Scenario';
|
|
4
4
|
import {TrafficConfig} from './TrafficConfig';
|
|
5
|
-
|
|
5
|
+
import {oauthResponseType} from './SkyrampClient';
|
|
6
6
|
interface testerStartV1Options {
|
|
7
7
|
namespace?: string;
|
|
8
8
|
kubePath?: string;
|
|
@@ -25,8 +25,35 @@ interface MockerApplyV1Options {
|
|
|
25
25
|
response: ResponseValue | ResponseValue[];
|
|
26
26
|
trafficConfig: TrafficConfig;
|
|
27
27
|
}
|
|
28
|
+
interface SendRequestV2Options {
|
|
29
|
+
url: string;
|
|
30
|
+
path: string;
|
|
31
|
+
method: string;
|
|
32
|
+
body?: string;
|
|
33
|
+
headers?: {[headerName: string]: string};
|
|
34
|
+
cookies?: {[cookieName: string]: string};
|
|
35
|
+
dataOverride?: {[dataName: string]: string | number | boolean | object};
|
|
36
|
+
pathParams?: {[pathName: string]: string | number | boolean | object};
|
|
37
|
+
queryParams?: {[queryName: string]: string | number | boolean | object};
|
|
38
|
+
formParams?: {[formParamName: string]: string | number | boolean | object};
|
|
39
|
+
expectedCode?: string;
|
|
40
|
+
funcHandler?: string;
|
|
41
|
+
funcHandlerType?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface SkyrampClientOptions {
|
|
45
|
+
docker_network?: string;
|
|
46
|
+
docker_skyramp_port?: number;
|
|
47
|
+
kubeconfigPath?: string;
|
|
48
|
+
clusterName?: string;
|
|
49
|
+
context?: string;
|
|
50
|
+
userToken?: string;
|
|
51
|
+
address?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
28
54
|
export declare class SkyrampClient {
|
|
29
55
|
constructor(kubeconfigPath?: string, clusterName?: string, context?: string, userToken?: string);
|
|
56
|
+
constructor(options: SkyrampClientOptions);
|
|
30
57
|
applyLocal(): Promise<void>;
|
|
31
58
|
addKubeconfig(context: string, clusterName: string, kubeconfigPath: string): Promise<void>;
|
|
32
59
|
removeLocal(): Promise<void>;
|
|
@@ -58,4 +85,5 @@ export declare class SkyrampClient {
|
|
|
58
85
|
getOAuthURL(provider: string, port: number): string;
|
|
59
86
|
runOAuthLoopback(provider: string, port: number): Promise<oauthResponseType>;
|
|
60
87
|
registerUser(provider: string, email: string, oauthToken: string): Promise<string>;
|
|
88
|
+
sendRequest(options: SendRequestV2Options): Promise<void>;
|
|
61
89
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const lib = require('../lib');
|
|
2
2
|
const koffi = require('koffi');
|
|
3
3
|
const TrafficConfig = require('./TrafficConfig');
|
|
4
|
-
|
|
4
|
+
const RequestV2 = require('./RequestV2');
|
|
5
|
+
const ResponseV2 = require('./ResponseV2');
|
|
5
6
|
const oauthResponseType = koffi.struct({
|
|
6
7
|
emails: koffi.array('char*', 10),
|
|
7
8
|
num_emails: 'int',
|
|
@@ -26,6 +27,11 @@ const testerInfoType = koffi.struct({
|
|
|
26
27
|
error: 'char*',
|
|
27
28
|
});
|
|
28
29
|
|
|
30
|
+
const contractResponseType = koffi.struct({
|
|
31
|
+
response: 'char*',
|
|
32
|
+
error: 'char*',
|
|
33
|
+
});
|
|
34
|
+
|
|
29
35
|
const WORKER_URL = "public.ecr.aws/j1n2c2p2/rampup/worker";
|
|
30
36
|
const WORKER_TAG = "latest";
|
|
31
37
|
const CONTAINER_PORT = 35142;
|
|
@@ -59,6 +65,9 @@ const registerUserWrapper = lib.func('registerUserWrapper', 'string', ['string',
|
|
|
59
65
|
const getOAuthURL = lib.func('getOAuthURLWrapper', 'string', ['string', 'int']);
|
|
60
66
|
const runOAuthLoopback = lib.func('runOAuthLoopback', oauthResponseType, ['string', 'int']);
|
|
61
67
|
|
|
68
|
+
// contract test
|
|
69
|
+
// func sendRequestWrapper(address, namespace, kubePath, kubeContext, clusterName, request *C.char) *C.char {
|
|
70
|
+
const sendRequestWrapper = lib.func('sendRequestWrapper', contractResponseType, ['string', 'string', 'string', 'string', 'string', 'string']);
|
|
62
71
|
/**
|
|
63
72
|
* The `SkyrampClient` class is the main client that provides methods for interacting with the Skyramp service.
|
|
64
73
|
* It allows users to manage Kubernetes clusters, deploy and delete workers and targets, apply mock descriptions, and start tests.
|
|
@@ -70,18 +79,36 @@ class SkyrampClient {
|
|
|
70
79
|
/**
|
|
71
80
|
* Initializes a new instance of the SkyrampClient class.
|
|
72
81
|
* @constructor
|
|
73
|
-
* @param {string}
|
|
74
|
-
* @param {string}
|
|
75
|
-
* @param {string}
|
|
76
|
-
* @param {string}
|
|
82
|
+
* @param {string|Object} kubeconfigPathOrOptions - Either the path to kubeconfig file or an options object
|
|
83
|
+
* @param {string} [kubeconfigPathOrOptions.kubeconfigPath] - The path to the kubeconfig file
|
|
84
|
+
* @param {string} [kubeconfigPathOrOptions.clusterName] - The name of the cluster
|
|
85
|
+
* @param {string} [kubeconfigPathOrOptions.context] - The context of the cluster
|
|
86
|
+
* @param {string} [kubeconfigPathOrOptions.userToken] - The user token for authentication
|
|
87
|
+
* @param {string} [kubeconfigPathOrOptions.address] - The address of the service
|
|
88
|
+
* @param {string} [clusterName] - The name of the cluster (when using individual parameters)
|
|
89
|
+
* @param {string} [context] - The context of the cluster (when using individual parameters)
|
|
90
|
+
* @param {string} [userToken] - The user token for authentication (when using individual parameters)
|
|
77
91
|
*/
|
|
78
|
-
constructor(
|
|
79
|
-
if (
|
|
80
|
-
|
|
92
|
+
constructor(kubeconfigPathOrOptions, clusterName, context, userToken) {
|
|
93
|
+
if (typeof kubeconfigPathOrOptions === 'object') {
|
|
94
|
+
const options = kubeconfigPathOrOptions;
|
|
95
|
+
if (options.kubeconfigPath || options.clusterName || options.context) {
|
|
96
|
+
this.addKubeconfig(options.clusterName, options.context, options.kubeconfigPath);
|
|
97
|
+
}
|
|
98
|
+
this.workerNamespaces = [];
|
|
99
|
+
this.userToken = options.userToken;
|
|
100
|
+
this.address = options.address;
|
|
101
|
+
if (options.docker_skyramp_port) {
|
|
102
|
+
this.address = `localhost:${options.docker_skyramp_port}`;
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
if (kubeconfigPathOrOptions || clusterName || context) {
|
|
106
|
+
this.addKubeconfig(clusterName, context, kubeconfigPathOrOptions);
|
|
81
107
|
}
|
|
82
108
|
this.workerNamespaces = [];
|
|
83
109
|
this.userToken = userToken;
|
|
84
110
|
}
|
|
111
|
+
}
|
|
85
112
|
|
|
86
113
|
setUserToken(userToken) {
|
|
87
114
|
this.userToken = userToken;
|
|
@@ -168,7 +195,7 @@ class SkyrampClient {
|
|
|
168
195
|
|
|
169
196
|
/**
|
|
170
197
|
* Applies local changes to the Kubernetes cluster configuration.
|
|
171
|
-
*
|
|
198
|
+
*
|
|
172
199
|
* @returns {Promise} A promise that resolves when the local changes are successfully applied, or rejects with an error if any error occurs.
|
|
173
200
|
*/
|
|
174
201
|
async applyLocal() {
|
|
@@ -192,7 +219,7 @@ class SkyrampClient {
|
|
|
192
219
|
|
|
193
220
|
/**
|
|
194
221
|
* Adds a Kubernetes configuration to the SkyrampClient object.
|
|
195
|
-
*
|
|
222
|
+
*
|
|
196
223
|
* @param {string} context - The context of the Kubernetes configuration.
|
|
197
224
|
* @param {string} clusterName - The name of the Kubernetes cluster.
|
|
198
225
|
* @param {string} kubeConfigPath - The path to the kubeconfig file.
|
|
@@ -215,7 +242,7 @@ class SkyrampClient {
|
|
|
215
242
|
|
|
216
243
|
/**
|
|
217
244
|
* Removes the local configuration of the SkyrampClient.
|
|
218
|
-
*
|
|
245
|
+
*
|
|
219
246
|
* @returns {Promise<void>} A promise that resolves when the removal is successful, or rejects with an error if an error occurs during the removal process.
|
|
220
247
|
*/
|
|
221
248
|
async removeLocal() {
|
|
@@ -234,7 +261,7 @@ class SkyrampClient {
|
|
|
234
261
|
|
|
235
262
|
/**
|
|
236
263
|
* Asynchronously removes a cluster from the configuration.
|
|
237
|
-
*
|
|
264
|
+
*
|
|
238
265
|
* @param {string} clusterName - The name of the cluster to be removed from the configuration.
|
|
239
266
|
* @returns {Promise} A Promise that resolves if the cluster is successfully removed, or rejects with an error if the removal fails.
|
|
240
267
|
*/
|
|
@@ -278,7 +305,7 @@ class SkyrampClient {
|
|
|
278
305
|
|
|
279
306
|
/**
|
|
280
307
|
* Deletes a worker from a specified namespace in the SkyrampClient class.
|
|
281
|
-
*
|
|
308
|
+
*
|
|
282
309
|
* @param {string} namespace - The namespace from which the worker should be deleted.
|
|
283
310
|
* @returns {Promise} - A promise that resolves with no value upon successful deletion.
|
|
284
311
|
* @throws {Error} - If there is no cluster to delete the worker from or if there is no worker to delete from the specified namespace.
|
|
@@ -307,7 +334,7 @@ class SkyrampClient {
|
|
|
307
334
|
|
|
308
335
|
/**
|
|
309
336
|
* Asynchronous method that runs a Docker worker using the provided image, tag, port, and network name.
|
|
310
|
-
*
|
|
337
|
+
*
|
|
311
338
|
* @param {string} [workerImage=WORKER_URL] - The URL of the Docker worker image.
|
|
312
339
|
* @param {string} [workerTag=WORKER_TAG] - The tag of the Docker worker image.
|
|
313
340
|
* @param {number} [hostPort=CONTAINER_PORT] - The port on the host machine to expose for the Docker worker.
|
|
@@ -330,7 +357,7 @@ class SkyrampClient {
|
|
|
330
357
|
|
|
331
358
|
/**
|
|
332
359
|
* Asynchronous method that removes a Docker container running the Skyramp worker.
|
|
333
|
-
*
|
|
360
|
+
*
|
|
334
361
|
* @param {string} containerName - The name of the Docker container to be removed.
|
|
335
362
|
* @returns {Promise} A promise that resolves when the container is successfully removed.
|
|
336
363
|
* @throws {Error} If an error occurs during the removal process.
|
|
@@ -357,13 +384,13 @@ class SkyrampClient {
|
|
|
357
384
|
|
|
358
385
|
/**
|
|
359
386
|
* Applies a mock description to a specified namespace and address.
|
|
360
|
-
*
|
|
387
|
+
*
|
|
361
388
|
* @param {string} namespace - The namespace where the mock description will be applied.
|
|
362
389
|
* @param {string} address - The address to which the mock description will be applied.
|
|
363
390
|
* @param {object} response - The details of the mock response.
|
|
364
391
|
* @param {object} trafficConfig - The traffic configuration parameters.
|
|
365
392
|
* @returns {Promise} A Promise that resolves when the mock description is successfully applied.
|
|
366
|
-
*
|
|
393
|
+
*
|
|
367
394
|
*/
|
|
368
395
|
async mockerApplyV1(...args) {
|
|
369
396
|
let namespace, kubeConfig, kubeContext, clusterName, address, response, trafficConfig;
|
|
@@ -385,7 +412,7 @@ class SkyrampClient {
|
|
|
385
412
|
if (trafficConfig instanceof TrafficConfig) {
|
|
386
413
|
mockDescription.mock = { ...mockDescription.mock, ...trafficConfig.toJson() }
|
|
387
414
|
}
|
|
388
|
-
|
|
415
|
+
|
|
389
416
|
const yamlContent = getYamlBytes(mockDescription);
|
|
390
417
|
return this.applyMockDescription(namespace, kubeConfig, kubeContext, clusterName, address, yamlContent);
|
|
391
418
|
}
|
|
@@ -419,7 +446,7 @@ class SkyrampClient {
|
|
|
419
446
|
|
|
420
447
|
/**
|
|
421
448
|
* Starts a test scenario in a specified namespace.
|
|
422
|
-
*
|
|
449
|
+
*
|
|
423
450
|
* @param {string|object} namespaceOrOptions - The namespace in which to start the test scenario or an options object.
|
|
424
451
|
* @param {string} [address] - The address of the target service to test.
|
|
425
452
|
* @param {object} [scenario] - The scenario object that defines the test steps and assertions.
|
|
@@ -427,7 +454,7 @@ class SkyrampClient {
|
|
|
427
454
|
* @param {object} [globalHeaders] - Optional global headers to be included in the test requests.
|
|
428
455
|
* @param {boolean} [generateTestReport] - Optional flag to generate a test report. Default is false.
|
|
429
456
|
* @param {boolean} [isDockerenv] - Optional flag to indicate if the test is running in a Docker environment. Default is false.
|
|
430
|
-
*
|
|
457
|
+
*
|
|
431
458
|
* @returns {Promise} - A promise that resolves when the test scenario is started.
|
|
432
459
|
*/
|
|
433
460
|
async testerStartV1(options = {}) {
|
|
@@ -596,6 +623,33 @@ class SkyrampClient {
|
|
|
596
623
|
|
|
597
624
|
return mockDescription;
|
|
598
625
|
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Sends a request to a Skyramp worker using the V2 API
|
|
629
|
+
* @param {Object} options - The options for sending the request
|
|
630
|
+
* @param {string} [options.address=""] - The address of the worker to send the request to
|
|
631
|
+
* @param {string} [options.namespace=""] - The namespace where the worker is deployed
|
|
632
|
+
* @param {string} [options.kubePath=""] - The path to the kubeconfig file
|
|
633
|
+
* @param {string} [options.kubeContext=""] - The kubernetes context to use
|
|
634
|
+
* @param {string} [options.clusterName=""] - The name of the kubernetes cluster
|
|
635
|
+
* @returns {Promise<string>} A promise that resolves with the response from the worker
|
|
636
|
+
*/
|
|
637
|
+
async sendRequest(options) {
|
|
638
|
+
// FIXME: should be sendRequest
|
|
639
|
+
const req = new RequestV2(options);
|
|
640
|
+
return new Promise((resolve, reject) => {
|
|
641
|
+
const jsonRequest = req.toJson();
|
|
642
|
+
sendRequestWrapper.async(this.address, this.namespace, this.kubePath, this.kubeContext, this.clusterName, jsonRequest, (err, res) => {
|
|
643
|
+
if (err) {
|
|
644
|
+
reject(err);
|
|
645
|
+
} else {
|
|
646
|
+
const jsonResponse = JSON.parse(res.response);
|
|
647
|
+
const response = new ResponseV2(jsonResponse);
|
|
648
|
+
resolve(response);
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
}
|
|
599
653
|
}
|
|
600
654
|
|
|
601
655
|
module.exports = SkyrampClient;
|
package/src/function.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const ResponseV2 = require('./classes/ResponseV2');
|
|
2
|
+
const lib = require('./lib');
|
|
3
|
+
|
|
4
|
+
// func checkStatusCodeWrapper(response *C.char, expectedStatus *C.char) (*C.char, *C.char) {
|
|
5
|
+
const checkStatusCodeWrapper = lib.func('checkStatusCodeWrapper', 'string', ['string', 'string']);
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Checks if the response's status code matches the expected status code (with support for wildcards).
|
|
10
|
+
*
|
|
11
|
+
* The expected status can include 'x' as a wildcard for a single digit.
|
|
12
|
+
* Examples:
|
|
13
|
+
* - "200" matches exactly 200
|
|
14
|
+
* - "20x" matches any status code in the range 200 to 209
|
|
15
|
+
* - "2xx" matches any status code in the range 200 to 299
|
|
16
|
+
*
|
|
17
|
+
* @param {ResponseV2} response - The response object containing a `status_code` attribute.
|
|
18
|
+
* @param {string} expectedStatus - The expected status code as a string with optional 'x' wildcards.
|
|
19
|
+
* @returns {boolean} True if the status code matches, false otherwise.
|
|
20
|
+
* @throws {Error} If the response object lacks a 'status_code' attribute.
|
|
21
|
+
*/
|
|
22
|
+
function checkStatusCode(response, expectedStatus) {
|
|
23
|
+
if (!(response instanceof ResponseV2)) {
|
|
24
|
+
throw new Error('Response must be an instance of ResponseV2');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!expectedStatus || typeof expectedStatus !== 'string') {
|
|
28
|
+
throw new Error('Expected status must be a string');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const responseJson = response.toJson();
|
|
33
|
+
const result = checkStatusCodeWrapper(responseJson, expectedStatus);
|
|
34
|
+
const parsed = JSON.parse(result);
|
|
35
|
+
|
|
36
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
37
|
+
throw new Error('Invalid response format from wrapper');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (Object.prototype.hasOwnProperty.call(parsed, 'error')) {
|
|
41
|
+
throw new Error(parsed.error);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (Object.prototype.hasOwnProperty.call(parsed, 'result')) {
|
|
45
|
+
return parsed.result;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
throw new Error('Response missing both result and error fields');
|
|
49
|
+
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error(`Error in checkStatusCode: ${err.message}`);
|
|
52
|
+
throw err; // Re-throw to allow caller to handle errors
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = {
|
|
57
|
+
checkStatusCode
|
|
58
|
+
};
|
package/src/index.d.ts
CHANGED
|
@@ -8,4 +8,8 @@ export * from './classes/ResponseValue';
|
|
|
8
8
|
export * from './classes/RestParam';
|
|
9
9
|
export * from './classes/TrafficConfig';
|
|
10
10
|
export * from './classes/DelayConfig';
|
|
11
|
-
export * from './classes/Protocol';
|
|
11
|
+
export * from './classes/Protocol';
|
|
12
|
+
export * from './classes/RequestV2';
|
|
13
|
+
export * from './classes/ResponseV2';
|
|
14
|
+
export * from './utils';
|
|
15
|
+
export * from './function';
|
package/src/index.js
CHANGED
|
@@ -10,9 +10,15 @@ const DelayConfig = require('./classes/DelayConfig');
|
|
|
10
10
|
const Protocol = require('./classes/Protocol');
|
|
11
11
|
const Asserts= require('./classes/Asserts');
|
|
12
12
|
const Step = require('./classes/Step');
|
|
13
|
+
const RequestV2 = require('./classes/RequestV2');
|
|
14
|
+
const ResponseV2 = require('./classes/ResponseV2');
|
|
15
|
+
const { getValue, checkSchema } = require('./utils');
|
|
16
|
+
const { checkStatusCode } = require('./function');
|
|
13
17
|
|
|
14
18
|
module.exports = {
|
|
15
19
|
SkyrampClient,
|
|
20
|
+
RequestV2,
|
|
21
|
+
ResponseV2,
|
|
16
22
|
GrpcEndpoint,
|
|
17
23
|
RestEndpoint,
|
|
18
24
|
Scenario,
|
|
@@ -23,5 +29,8 @@ module.exports = {
|
|
|
23
29
|
DelayConfig,
|
|
24
30
|
Protocol,
|
|
25
31
|
Asserts,
|
|
26
|
-
Step
|
|
32
|
+
Step,
|
|
33
|
+
getValue,
|
|
34
|
+
checkStatusCode,
|
|
35
|
+
checkSchema,
|
|
27
36
|
}
|
package/src/utils.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const koffi = require('koffi');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const yaml = require('js-yaml');
|
|
5
|
+
const lib = require('./lib');
|
|
4
6
|
const SKYRAMP_YAML_VERSION = "v1"
|
|
5
7
|
|
|
8
|
+
const responseType = koffi.struct({
|
|
9
|
+
response: 'char*',
|
|
10
|
+
error: 'char*',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const getJSONValueWrapper = lib.func('getJSONValueWrapper', responseType, ['string', 'string']);
|
|
14
|
+
const checkSchemaWrapper = lib.func('checkSchemaWrapper', responseType, ['string', 'string']);
|
|
15
|
+
|
|
6
16
|
function getYamlBytes(jsonObject) {
|
|
7
17
|
try {
|
|
8
|
-
const yamlContent = yaml.dump(jsonObject, {lineWidth: 100});
|
|
18
|
+
const yamlContent = yaml.dump(jsonObject, { lineWidth: 100 });
|
|
9
19
|
return yamlContent;
|
|
10
20
|
} catch (error) {
|
|
11
21
|
throw new Error('Error converting to YAML bytes:', error);
|
|
@@ -25,7 +35,7 @@ function createTestDescriptionFromScenario({ scenario, globalVars }) {
|
|
|
25
35
|
},
|
|
26
36
|
services: services,
|
|
27
37
|
endpoints: endpoints,
|
|
28
|
-
scenarios: scenarios,
|
|
38
|
+
scenarios: scenarios,
|
|
29
39
|
requests: requests
|
|
30
40
|
};
|
|
31
41
|
|
|
@@ -48,14 +58,112 @@ function readDataFromFile(filename) {
|
|
|
48
58
|
throw new Error('Unsupported file format. Only .json, .yaml, and .js files are supported.');
|
|
49
59
|
}
|
|
50
60
|
return [jsonData, false];
|
|
51
|
-
} catch(error) {
|
|
61
|
+
} catch (error) {
|
|
52
62
|
throw new Error('Error reading or parsing file: ', error);
|
|
53
63
|
}
|
|
54
64
|
}
|
|
55
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Extracts and parses a value from a JSON response using a JSON path expression
|
|
68
|
+
* @param {Object} response - The response object containing a body property with JSON data
|
|
69
|
+
* @param {string} path - The JSON path expression to extract the value (e.g. "$.data.id")
|
|
70
|
+
* @returns {*} The extracted value converted to the appropriate JavaScript type:
|
|
71
|
+
* - For primitive types (string, number, boolean), returns the converted value
|
|
72
|
+
* - For null values, returns null
|
|
73
|
+
* - For complex types (arrays, objects) or errors, returns null
|
|
74
|
+
* @example
|
|
75
|
+
* const response = {
|
|
76
|
+
* body: '{"type": "string", "value": "hello"}'
|
|
77
|
+
* };
|
|
78
|
+
* etResponseValue(response, "$.value"); // Returns "hello"
|
|
79
|
+
*/
|
|
80
|
+
function getValue(response, path) {
|
|
81
|
+
const result = getJSONValueWrapper(response.responseBody, path);
|
|
82
|
+
|
|
83
|
+
// 1. If result is null/undefined, return null.
|
|
84
|
+
if (!result || result.error !== null) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
// 2. Parse the returned JSON string.
|
|
90
|
+
const parsed = JSON.parse(result.response);
|
|
91
|
+
|
|
92
|
+
// 3. If parsed is an object of the shape { type, value }, handle typed values:
|
|
93
|
+
// e.g., { "type": "string", "value": "hello" }
|
|
94
|
+
if (
|
|
95
|
+
parsed &&
|
|
96
|
+
typeof parsed === 'object' &&
|
|
97
|
+
!Array.isArray(parsed) &&
|
|
98
|
+
Object.prototype.hasOwnProperty.call(parsed, 'type') &&
|
|
99
|
+
Object.prototype.hasOwnProperty.call(parsed, 'value')
|
|
100
|
+
) {
|
|
101
|
+
const { type: valueType, value } = parsed;
|
|
102
|
+
|
|
103
|
+
// Return null for complex types (arrays and objects)
|
|
104
|
+
if (['array', 'object', '[]interface {}'].includes(valueType)) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Convert to the appropriate JavaScript type
|
|
109
|
+
switch (valueType) {
|
|
110
|
+
case 'string':
|
|
111
|
+
return String(value);
|
|
112
|
+
case "float64", "float32", "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8":
|
|
113
|
+
return value;
|
|
114
|
+
case 'boolean':
|
|
115
|
+
return Boolean(value);
|
|
116
|
+
case 'null':
|
|
117
|
+
return null;
|
|
118
|
+
default:
|
|
119
|
+
// For unrecognized or fallback:
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 4. If the result is not of the form { type, value }, return it directly.
|
|
125
|
+
return parsed;
|
|
126
|
+
} catch (err) {
|
|
127
|
+
// 5. If JSON.parse fails or something else goes wrong, log the error and return null.
|
|
128
|
+
console.error(`Error processing JSONValue: ${err}`);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Validates the response body against the expected schema.
|
|
135
|
+
*
|
|
136
|
+
* @param {Object} response - An object containing a `body` property (JSON string).
|
|
137
|
+
* @param {Object|string} expectedSchema - The JSON schema (object or JSON string) to validate against.
|
|
138
|
+
* @returns {boolean} True if validation succeeds, false otherwise.
|
|
139
|
+
*/
|
|
140
|
+
/**
|
|
141
|
+
* Validates the response body against the expected schema.
|
|
142
|
+
*
|
|
143
|
+
* @param {Object} response - The response object containing the body to validate
|
|
144
|
+
* @param {string} response.body - The response body as a JSON string
|
|
145
|
+
* @param {Object|string} expectedSchema - The JSON schema to validate against. Can be either:
|
|
146
|
+
* - A JSON schema object with type definitions and validation rules
|
|
147
|
+
* - A JSON string containing a schema definition
|
|
148
|
+
* @returns {boolean} True if validation succeeds, false otherwise.
|
|
149
|
+
*/
|
|
150
|
+
function checkSchema(response, expectedSchema) {
|
|
151
|
+
const result = checkSchemaWrapper(response.responseBody, expectedSchema);
|
|
152
|
+
if (result.error) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
if (!result.response) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const parsed = JSON.parse(result.response);
|
|
159
|
+
return parsed.result;
|
|
160
|
+
}
|
|
161
|
+
|
|
56
162
|
module.exports = {
|
|
57
163
|
createTestDescriptionFromScenario,
|
|
58
164
|
getYamlBytes,
|
|
59
165
|
readDataFromFile,
|
|
166
|
+
getValue,
|
|
167
|
+
checkSchema,
|
|
60
168
|
SKYRAMP_YAML_VERSION
|
|
61
169
|
}
|