@skyramp/skyramp 1.0.0-sha.b2dfe11 → 1.2.2

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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -17
  3. package/package.json +14 -5
  4. package/scripts/download-binary.js +189 -0
  5. package/src/classes/Asserts.d.ts +16 -0
  6. package/src/classes/Asserts.js +41 -0
  7. package/src/classes/AsyncScenario.d.ts +133 -0
  8. package/src/classes/AsyncScenario.js +324 -0
  9. package/src/classes/AsyncTestStatus.d.ts +172 -0
  10. package/src/classes/AsyncTestStatus.js +488 -0
  11. package/src/classes/DelayConfig.d.ts +4 -0
  12. package/src/classes/DelayConfig.js +25 -0
  13. package/src/classes/Endpoint.d.ts +2 -2
  14. package/src/classes/Endpoint.js +81 -43
  15. package/src/classes/GrpcEndpoint.d.ts +1 -1
  16. package/src/classes/GrpcEndpoint.js +24 -3
  17. package/src/classes/LoadTestConfig.d.ts +131 -0
  18. package/src/classes/LoadTestConfig.js +186 -0
  19. package/src/classes/Protocol.d.ts +5 -0
  20. package/src/classes/Protocol.js +8 -0
  21. package/src/classes/RequestV2.d.ts +30 -0
  22. package/src/classes/RequestV2.js +181 -0
  23. package/src/classes/RequestValue.d.ts +24 -0
  24. package/src/classes/RequestValue.js +113 -0
  25. package/src/classes/ResponseV2.d.ts +24 -0
  26. package/src/classes/ResponseV2.js +96 -0
  27. package/src/classes/ResponseValue.d.ts +21 -0
  28. package/src/classes/ResponseValue.js +93 -0
  29. package/src/classes/RestEndpoint.d.ts +11 -2
  30. package/src/classes/RestEndpoint.js +90 -5
  31. package/src/classes/RestParam.d.ts +4 -0
  32. package/src/classes/RestParam.js +32 -0
  33. package/src/classes/Scenario.d.ts +48 -0
  34. package/src/classes/Scenario.js +208 -0
  35. package/src/classes/SkyrampClient.d.ts +184 -4
  36. package/src/classes/SkyrampClient.js +774 -40
  37. package/src/classes/Step.d.ts +28 -0
  38. package/src/classes/Step.js +113 -0
  39. package/src/classes/TrafficConfig.d.ts +6 -0
  40. package/src/classes/TrafficConfig.js +28 -0
  41. package/src/function.js +46 -0
  42. package/src/index.d.ts +14 -1
  43. package/src/index.js +36 -3
  44. package/src/lib.js +6 -6
  45. package/src/utils.js +180 -20
  46. package/src/utils.d.ts +0 -5
@@ -0,0 +1,324 @@
1
+ const RequestV2 = require('./RequestV2');
2
+
3
+ /**
4
+ * Generates a REST path name from path and method
5
+ * @param {string} path - The REST path
6
+ * @param {string} method - The HTTP method
7
+ * @returns {string} The generated path name
8
+ */
9
+ function getRestPathName(path, method) {
10
+ if (!path || !method) return '';
11
+
12
+ // Remove leading slash and replace special characters
13
+ const cleanPath = path.replace(/^\//, '').replace(/[{}/]/g, '_');
14
+ return `${cleanPath}_${method.toLowerCase()}`;
15
+ }
16
+
17
+ /**
18
+ * Wrapper class for RequestV2 object in async scenarios
19
+ */
20
+ class AsyncRequest {
21
+ /**
22
+ * Creates an AsyncRequest instance
23
+ * @param {AsyncScenario} scenario - The parent scenario
24
+ * @param {RequestV2} request - The request object
25
+ * @param {number} stepIndex - The step index in the scenario
26
+ */
27
+ constructor(scenario, request, stepIndex) {
28
+ this.scenario = scenario;
29
+ this.request = request;
30
+ this.stepIndex = stepIndex;
31
+ }
32
+
33
+ /**
34
+ * Returns request's response value construct for asynchronous backend
35
+ * @param {string|null} path - The path to the value
36
+ * @returns {string} The async request value reference
37
+ */
38
+ getAsyncRequestValue(path) {
39
+ if (path === null || path === undefined) {
40
+ return `requests.${this.request.name}.res`;
41
+ }
42
+ return `requests.${this.request.name}.res.${path}`;
43
+ }
44
+
45
+ /**
46
+ * Returns request's status check construct for asynchronous backend
47
+ * @param {string|number} code - The expected status code
48
+ * @returns {string} The status check expression
49
+ */
50
+ requestStatusCheck(code) {
51
+ return `requests.${this.request.name}.code == ${code}`;
52
+ }
53
+
54
+ /**
55
+ * Adds an assert to the request
56
+ * @param {string} jsonPath - The JSON path to the value
57
+ * @param {*} expectedValue - The expected value
58
+ */
59
+ assertEqual(jsonPath, expectedValue) {
60
+ this.scenario.steps[this.stepIndex].asyncAsserts.push(
61
+ `${this.getAsyncRequestValue(jsonPath)} == ${expectedValue}`
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Adds a not equal assert to the request
67
+ * @param {string} jsonPath - The JSON path to the value
68
+ * @param {*} value - The value to compare against
69
+ */
70
+ assertNotEqual(jsonPath, value) {
71
+ this.scenario.steps[this.stepIndex].asyncAsserts.push(
72
+ `${this.getAsyncRequestValue(jsonPath)} != ${value}`
73
+ );
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Represents a testing scenario for asynchronous operations
79
+ */
80
+ class AsyncScenario {
81
+ /**
82
+ * Creates an AsyncScenario instance
83
+ * @param {Object} options - The scenario options
84
+ * @param {string} options.name - The name of the scenario
85
+ * @param {boolean} [options.ignoreFailure=false] - Whether to ignore failures
86
+ */
87
+ constructor(options) {
88
+ if (typeof options === 'string') {
89
+ // Backward compatibility: if a string is passed, treat it as the name
90
+ console.warn('Deprecated: AsyncScenario constructor now expects an object. Please use new AsyncScenario({name: "scenarioName"})');
91
+ options = { name: options, ignoreFailure: arguments[1] || false };
92
+ }
93
+
94
+ const { name, ignoreFailure = false } = options;
95
+
96
+ this.name = name;
97
+ this.steps = [];
98
+ this.vars = {};
99
+ this.until = "";
100
+ this.maxRetries = 5;
101
+ this.retryInterval = 1;
102
+ this.ignoreFailure = ignoreFailure;
103
+ }
104
+
105
+ /**
106
+ * Adds an asynchronous request to this scenario
107
+ * @param {Object} [options={}] - The request options
108
+ * @param {string} [options.name] - The name of the request
109
+ * @param {string} [options.url] - The URL of the request
110
+ * @param {string} [options.path] - The path of the request
111
+ * @param {string} [options.method] - The HTTP method of the request (e.g., GET, POST)
112
+ * @param {string} [options.body] - The body of the request
113
+ * @param {Object} [options.headers] - The headers of the request
114
+ * @param {Object} [options.pathParams] - The path parameters of the request
115
+ * @param {Object} [options.queryParams] - The query parameters of the request
116
+ * @param {Object} [options.formParams] - The form parameters of the request
117
+ * @param {Array} [options.multipartParams] - The multipart parameters of the request
118
+ * @param {Object} [options.dataOverride] - The data override for the request
119
+ * @param {string} [options.description] - The description of the request
120
+ * @param {string} [options.expectedCode] - The expected HTTP status code of the request
121
+ * @param {string} [options.if_=""] - The condition to execute the request
122
+ * @param {string} [options.until] - The condition to stop retrying
123
+ * @param {number} [options.maxRetries] - The maximum number of retries
124
+ * @param {number} [options.retryInterval] - The interval between retries
125
+ * @returns {AsyncRequest} The created async request object
126
+ */
127
+ addAsyncRequest(options = {}) {
128
+ const {
129
+ name,
130
+ url,
131
+ path,
132
+ method,
133
+ body,
134
+ headers,
135
+ pathParams,
136
+ queryParams,
137
+ formParams,
138
+ multipartParams,
139
+ dataOverride,
140
+ description,
141
+ expectedCode,
142
+ if_ = "",
143
+ until,
144
+ maxRetries,
145
+ retryInterval
146
+ } = options;
147
+
148
+ const request = new RequestV2({
149
+ name,
150
+ url,
151
+ path,
152
+ method,
153
+ body,
154
+ headers,
155
+ pathParams,
156
+ queryParams,
157
+ formParams,
158
+ multipartParams,
159
+ dataOverride,
160
+ description
161
+ });
162
+
163
+ if (!name && path && method) {
164
+ request.name = getRestPathName(path, method);
165
+ }
166
+
167
+ const stepRequest = request.asRequestDict();
168
+ if (if_ !== "") {
169
+ stepRequest.if = if_;
170
+ }
171
+ if (until !== "") {
172
+ stepRequest.repeat = {
173
+ until: until,
174
+ maxRetries: maxRetries,
175
+ interval: retryInterval
176
+ };
177
+ }
178
+ stepRequest.type = "request";
179
+ stepRequest.varOverride = {};
180
+ stepRequest.varExport = {};
181
+ stepRequest.asyncAsserts = [];
182
+
183
+ if (expectedCode) {
184
+ stepRequest.asyncAsserts.push(
185
+ `requests.${request.name}.code == ${expectedCode}`
186
+ );
187
+ }
188
+
189
+ this.steps.push(stepRequest);
190
+ const stepIndex = this.steps.length - 1;
191
+ return new AsyncRequest(this, request, stepIndex);
192
+ }
193
+
194
+ /**
195
+ * Adds an asynchronous nested scenario to this scenario
196
+ * @param {AsyncScenario} nestedScenario - The nested scenario to add
197
+ * @param {string} [until=""] - The condition to stop retrying
198
+ * @param {number} [maxRetries=5] - The maximum number of retries
199
+ * @param {number} [retryInterval=1] - The interval between retries
200
+ */
201
+ addAsyncScenario(nestedScenario, until = "", maxRetries = 5, retryInterval = 1) {
202
+ const stepScenario = {
203
+ type: "scenario",
204
+ scenario: nestedScenario
205
+ };
206
+ this.until = until;
207
+ if (this.until !== "") {
208
+ this.maxRetries = maxRetries;
209
+ this.retryInterval = retryInterval;
210
+ }
211
+ this.steps.push(stepScenario);
212
+ }
213
+
214
+ /**
215
+ * Sets a scenario level variable
216
+ * @param {string} varName - The name of the variable
217
+ * @param {*} value - The value of the variable
218
+ */
219
+ setAsyncVar(varName, value) {
220
+ if (this.vars === null || this.vars === undefined) {
221
+ this.vars = {};
222
+ }
223
+ this.vars[varName] = value;
224
+ }
225
+
226
+ /**
227
+ * Returns scenario's variable construct for asynchronous backend
228
+ * @param {string} varName - The name of the variable
229
+ * @returns {string} The variable reference
230
+ */
231
+ getAsyncVar(varName) {
232
+ return `vars.${varName}`;
233
+ }
234
+
235
+ /**
236
+ * Returns scenario's response value construct for asynchronous backend
237
+ * @param {string} varName - The name of the variable
238
+ * @returns {string} The scenario value reference
239
+ */
240
+ getAsyncScenarioValue(varName) {
241
+ return `scenarios.${this.name}.${varName}`;
242
+ }
243
+
244
+ /**
245
+ * Sets a scenario level variable for export
246
+ * @param {string} varName - The name of the variable
247
+ * @param {*} value - The value of the variable
248
+ */
249
+ exportAsyncVar(varName, value) {
250
+ this.steps.push({
251
+ type: "varExport",
252
+ name: varName,
253
+ value: value
254
+ });
255
+ }
256
+
257
+ /**
258
+ * Adds an assert to the scenario
259
+ * @param {string} value - The value to assert
260
+ */
261
+ addAssert(value) {
262
+ this.steps.push({
263
+ type: "assert",
264
+ assert: value
265
+ });
266
+ }
267
+
268
+ /**
269
+ * Converts this scenario to JSON
270
+ * @returns {Object} The JSON representation of the scenario
271
+ */
272
+ toJson() {
273
+ const steps = [];
274
+ for (const step of this.steps) {
275
+ if (step.type === "request") {
276
+ // Extract the request-specific fields and wrap them properly
277
+ const { varOverride, varExport, asyncAsserts, ...requestFields } = step;
278
+
279
+ // Convert requestName back to name for proper format
280
+ if (requestFields.requestName) {
281
+ requestFields.name = requestFields.requestName;
282
+ delete requestFields.requestName;
283
+ }
284
+
285
+ // Create the request object with varOverride and varExport
286
+ const requestObj = {
287
+ ...requestFields,
288
+ varOverride: varOverride || {},
289
+ varExport: varExport || {}
290
+ };
291
+
292
+ // Add asyncAsserts if present
293
+ if (asyncAsserts && asyncAsserts.length > 0) {
294
+ requestObj.asyncAsserts = asyncAsserts;
295
+ }
296
+
297
+ steps.push({ request: requestObj });
298
+ } else if (step.type === "scenario") {
299
+ if (step.scenario instanceof AsyncScenario) {
300
+ steps.push({ scenario: step.scenario.toJson() });
301
+ }
302
+ } else if (step.type === "varExport") {
303
+ const exportObj = {};
304
+ exportObj[step.name] = step.value;
305
+ steps.push({ varExport: exportObj });
306
+ }
307
+ }
308
+
309
+ return {
310
+ name: this.name,
311
+ steps: steps,
312
+ vars: this.vars,
313
+ until: this.until,
314
+ maxRetries: this.maxRetries,
315
+ interval: this.retryInterval,
316
+ ignoreFailure: this.ignoreFailure
317
+ };
318
+ }
319
+ }
320
+
321
+ module.exports = {
322
+ AsyncScenario,
323
+ AsyncRequest
324
+ };
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Unified AsyncTestStatus class for handling all test status operations
3
+ */
4
+ declare class AsyncTestStatus {
5
+ testStatus: Record<string, object>;
6
+ testId: string;
7
+ testType: string;
8
+ scenarioDict: Record<string, AsyncTestStatus.AsyncScenarioStatus>;
9
+
10
+ /**
11
+ * Creates an AsyncTestStatus instance
12
+ * @param options The test status options
13
+ */
14
+ constructor(options: Record<string, object>);
15
+
16
+ /**
17
+ * Returns the test id
18
+ */
19
+ getTestId(): string;
20
+
21
+ /**
22
+ * Returns the test type
23
+ */
24
+ getTestType(): string;
25
+
26
+ /**
27
+ * Get the scenario by name
28
+ * @param scenarioName The scenario name
29
+ */
30
+ getScenario(scenarioName: string): AsyncTestStatus.AsyncScenarioStatus;
31
+
32
+ /**
33
+ * Get scenarios, optionally filtered by name
34
+ * @param scenarioName Optional scenario name filter
35
+ */
36
+ getScenarios(scenarioName?: string): AsyncTestStatus.AsyncScenarioStatus[];
37
+
38
+ /**
39
+ * Get request by scenario and request name
40
+ * @param scenarioName The scenario name
41
+ * @param requestName The request name
42
+ */
43
+ getRequest(scenarioName: string, requestName: string): AsyncTestStatus.AsyncRequestStatus;
44
+
45
+ /**
46
+ * Get the overall status
47
+ */
48
+ getOverallStatus(): Promise<string>;
49
+
50
+ /**
51
+ * Create the appropriate TestStatus object based on the options
52
+ * @param options The test status options
53
+ */
54
+ static create(options: Record<string, object>): AsyncTestStatus;
55
+
56
+ /**
57
+ * Sorts entries based on their ID structure
58
+ * @param entry1 First entry to compare
59
+ * @param entry2 Second entry to compare
60
+ */
61
+ static sortKeys(entry1: object, entry2: object): number;
62
+ }
63
+
64
+ declare namespace AsyncTestStatus {
65
+ /**
66
+ * AsyncScenarioStatus inner class
67
+ */
68
+ class AsyncScenarioStatus {
69
+ testType: string;
70
+ result: object;
71
+ name: string;
72
+ id: string;
73
+ overallStatus: Record<string, object>;
74
+ timeseries: Record<string, object>;
75
+ subScenarios: AsyncScenarioStatus[];
76
+ requests: AsyncRequestStatus[];
77
+ stats?: object;
78
+ status?: object;
79
+ error?: object;
80
+ stepDescription?: object;
81
+ stepName?: string;
82
+
83
+ /**
84
+ * Creates an AsyncScenarioStatus instance
85
+ * @param dataObject The data object containing scenario information
86
+ * @param testType The type of test (load or integration)
87
+ */
88
+ constructor(dataObject: object, testType: string);
89
+
90
+ /**
91
+ * Returns string representation of the scenario status
92
+ */
93
+ toString(): string;
94
+
95
+ /**
96
+ * Get sub scenarios
97
+ */
98
+ getSubScenarios(): AsyncScenarioStatus[];
99
+
100
+ /**
101
+ * Get request by name from this scenario
102
+ * @param requestName The request name to find
103
+ */
104
+ getRequest(requestName: string): AsyncRequestStatus;
105
+
106
+ /**
107
+ * Get all requests
108
+ */
109
+ getRequests(): AsyncRequestStatus[];
110
+
111
+ /**
112
+ * Get overall status of the scenario
113
+ */
114
+ getOverallStatus(): Promise<string>;
115
+
116
+ /**
117
+ * Assert status (for integration tests)
118
+ */
119
+ assertStatus(): object;
120
+ }
121
+
122
+ /**
123
+ * AsyncRequestStatus inner class
124
+ */
125
+ class AsyncRequestStatus {
126
+ testType: string;
127
+ name: string;
128
+ id: string;
129
+ resultObject: object;
130
+ jsonObject: string;
131
+ asserts: object[];
132
+ testStatus?: object;
133
+
134
+ /**
135
+ * Creates an AsyncRequestStatus instance
136
+ * @param resultObject The result object containing request data
137
+ * @param testType The type of test (load or integration)
138
+ */
139
+ constructor(resultObject: object, testType: string);
140
+
141
+ /**
142
+ * Returns string representation of the request status
143
+ */
144
+ toString(): string;
145
+
146
+ /**
147
+ * Converts the object to JSON
148
+ */
149
+ toJson(): Record<string, object>;
150
+
151
+ /**
152
+ * Get the response of the load test for a specific status code
153
+ * @param statusCode The HTTP status code
154
+ * @param jsonPath Optional JSON path to extract specific data
155
+ */
156
+ getLoadTestResponse(statusCode: string, jsonPath?: string | null): string | null;
157
+
158
+ /**
159
+ * Get the response of the request
160
+ * @param jsonPath Optional JSON path
161
+ */
162
+ getResponse(jsonPath?: string | null): string | null;
163
+
164
+ /**
165
+ * Get the value of the variable
166
+ * @param key The variable key
167
+ */
168
+ getVarValue(key: string): string;
169
+ }
170
+ }
171
+
172
+ export = AsyncTestStatus;