@opentap/runner-client 2.0.0-alpha.2.18 → 2.0.0-alpha.2.19

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.
@@ -65,7 +65,7 @@ export declare class BaseClient {
65
65
  * @param options (optional)
66
66
  * @returns Promise of an object
67
67
  */
68
- protected requestChunked<T>(subject: string, options?: RequestOptions, isFullSubject?: boolean): Promise<T>;
68
+ protected requestChunked<T>(subject: string, replySubject: string, payload: any, options?: RequestOptions, isFullSubject?: boolean): Promise<T>;
69
69
  /**
70
70
  * Check if the the response is an error from the server.
71
71
  * @param {any} response
package/lib/BaseClient.js CHANGED
@@ -56,7 +56,6 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
56
56
  };
57
57
  import { ComponentSettingsBase, ComponentSettingsIdentifier, ComponentSettingsListItem, DataGridControl, ErrorResponse, FileDescriptor, ListItemType, ProfileGroup, } from './DTOs';
58
58
  import { Empty, ErrorCode, JSONCodec, StringCodec, connect, headers, } from 'nats.ws';
59
- import { v4 as uuidv4 } from 'uuid';
60
59
  var DEFAULT_TIMEOUT = 6000;
61
60
  var BaseClient = /** @class */ (function () {
62
61
  function BaseClient(baseSubject, options) {
@@ -199,7 +198,8 @@ var BaseClient = /** @class */ (function () {
199
198
  */
200
199
  BaseClient.prototype.sendChunked = function (subject, payload, options) {
201
200
  return __awaiter(this, void 0, void 0, function () {
202
- var stringCodec, data, headers, opts, fileDescriptor, getChunk, dataSubject, message, i, response, jsonCodec;
201
+ var stringCodec, data, headers, opts, fileDescriptor, getChunk, dataSubject, i;
202
+ var _this = this;
203
203
  return __generator(this, function (_a) {
204
204
  switch (_a.label) {
205
205
  case 0:
@@ -218,28 +218,36 @@ var BaseClient = /** @class */ (function () {
218
218
  var offset = chunk * fileDescriptor.chunkSize;
219
219
  return data.slice(offset, offset + fileDescriptor.chunkSize);
220
220
  };
221
- return [4 /*yield*/, this.request(subject, fileDescriptor)];
221
+ return [4 /*yield*/, this.request(subject, fileDescriptor, opts)];
222
222
  case 1:
223
223
  dataSubject = _a.sent();
224
- i = 0;
225
- _a.label = 2;
226
- case 2:
227
- if (!(i < fileDescriptor.numberOfChunks)) return [3 /*break*/, 5];
228
- return [4 /*yield*/, this.connection.request(dataSubject, getChunk(i), opts)];
229
- case 3:
230
- // The main response will be received after the last chunk is sent, the intermediate ones
231
- // are empty acknowledgement messages
232
- message = _a.sent();
233
- _a.label = 4;
234
- case 4:
235
- i++;
236
- return [3 /*break*/, 2];
237
- case 5:
238
- if (message && message.data.length !== 0) {
239
- jsonCodec = JSONCodec();
240
- response = jsonCodec.decode(message.data);
224
+ for (i = 0; i < fileDescriptor.numberOfChunks; i++) {
225
+ this.connection.publish(dataSubject, getChunk(i), opts);
241
226
  }
242
- return [2 /*return*/, this.isErrorResponse(response) ? Promise.reject(ErrorResponse.fromJS(response)) : Promise.resolve(response)];
227
+ return [2 /*return*/, new Promise(function (resolve, reject) {
228
+ var combinedResult = new Uint8Array([]);
229
+ // Subscribe to dataSubject before sending the terminating message to ensure we are listening before the server starts responding
230
+ var subscription = _this.connection.subscribe(dataSubject);
231
+ // Publish an empty message to indicate that we are ready to listen
232
+ _this.connection.publish(dataSubject, Empty, opts);
233
+ var first = true;
234
+ subscription.callback = function (error, message) {
235
+ if (error) {
236
+ reject(error);
237
+ }
238
+ combinedResult = new Uint8Array(__spreadArray(__spreadArray([], Array.from(combinedResult), true), Array.from(message === null || message === void 0 ? void 0 : message.data), true));
239
+ // We shouldn't resolve after the first message since this is going to be the empty message we just sent
240
+ // We should resolve after the server terminates the message with an empty message
241
+ if (first === false && (message === null || message === void 0 ? void 0 : message.data.length) === 0) {
242
+ resolve(combinedResult);
243
+ }
244
+ first = false;
245
+ };
246
+ }).then(function (byteArray) {
247
+ var jsonCodec = JSONCodec();
248
+ var response = jsonCodec.decode(byteArray);
249
+ return _this.isErrorResponse(response) ? Promise.reject(ErrorResponse.fromJS(response)) : Promise.resolve(response);
250
+ })];
243
251
  }
244
252
  });
245
253
  });
@@ -251,49 +259,49 @@ var BaseClient = /** @class */ (function () {
251
259
  * @param options (optional)
252
260
  * @returns Promise of an object
253
261
  */
254
- BaseClient.prototype.requestChunked = function (subject, options, isFullSubject) {
262
+ BaseClient.prototype.requestChunked = function (subject, replySubject, payload, options, isFullSubject) {
255
263
  return __awaiter(this, void 0, void 0, function () {
264
+ var fileSize;
256
265
  var _this = this;
257
266
  return __generator(this, function (_a) {
258
267
  if (!this.connection)
259
268
  return [2 /*return*/, Promise.reject("".concat(subject, ": Connection is down! Please try again!"))];
260
269
  if (this.connection.isClosed())
261
270
  return [2 /*return*/, Promise.reject("".concat(subject, ": Connection has been closed! Please reconnect!"))];
271
+ fileSize = -1;
262
272
  return [2 /*return*/, new Promise(function (resolve, reject) {
263
- var numberOfChunks = -1;
264
- var received = 0;
265
273
  var combinedResult = new Uint8Array([]);
266
- // Resolves the promise if the all of the chunks are received
267
- var resolveIfComplete = function () {
268
- if (received === numberOfChunks) {
274
+ // Subscribe to the subject before starting the process
275
+ var subscription = _this.connection.subscribe(replySubject);
276
+ var resolveIfCompleted = function () {
277
+ if (combinedResult.length === fileSize) {
278
+ subscription.unsubscribe();
269
279
  resolve(combinedResult);
270
280
  }
271
281
  };
272
- // Generate a unique subject where the Runner will publish the chunks
273
- var replySubject = "_INBOX.".concat(uuidv4());
274
- // Subscribe to the subject before starting the process
275
- var subscription = _this.connection.subscribe(replySubject);
276
282
  subscription.callback = function (error, message) {
277
283
  if (error) {
278
284
  reject(error);
279
285
  }
280
- // Combine each chunk
281
286
  combinedResult = new Uint8Array(__spreadArray(__spreadArray([], Array.from(combinedResult), true), Array.from(message === null || message === void 0 ? void 0 : message.data), true));
282
- received++;
283
- message.respond(Empty); // Respond acknowledgement
284
- resolveIfComplete();
287
+ resolveIfCompleted();
285
288
  };
286
289
  var headers = _this.buildHeaders();
287
290
  var opts = __assign(__assign({}, options), { timeout: _this.timeout, headers: headers });
288
291
  // Request the file descriptor from the runner by posting the reply subject
289
- return _this.request(subject, replySubject, opts, isFullSubject)
292
+ return _this.request(subject, payload, opts, isFullSubject)
290
293
  .then(function (fileDescriptor) { return FileDescriptor.fromJS(fileDescriptor); })
291
294
  .then(function (fileDescriptor) {
292
- numberOfChunks = fileDescriptor.numberOfChunks;
293
- // Check if the chunks are already received
294
- resolveIfComplete();
295
+ fileSize = fileDescriptor.fileSize;
296
+ resolveIfCompleted();
297
+ })
298
+ .catch(function (error) {
299
+ subscription.unsubscribe();
300
+ throw error;
295
301
  });
296
302
  }).then(function (byteArray) {
303
+ if (byteArray.length !== fileSize)
304
+ return Promise.reject("Unexpected response size. Expected ".concat(fileSize, " bytes, but got ").concat(byteArray.length, "."));
297
305
  var jsonCodec = JSONCodec();
298
306
  var response = jsonCodec.decode(byteArray);
299
307
  return _this.isErrorResponse(response) ? Promise.reject(ErrorResponse.fromJS(response)) : Promise.resolve(response);
package/lib/DTOs.d.ts CHANGED
@@ -418,6 +418,14 @@ export declare class PasswordControl extends Setting implements IPasswordControl
418
418
  export interface IPasswordControl extends ISetting {
419
419
  password?: string | undefined;
420
420
  }
421
+ export declare class TestPlanRequest implements ITestPlanRequest {
422
+ properties?: string[] | null | undefined;
423
+ subject?: string | undefined;
424
+ }
425
+ export interface ITestPlanRequest {
426
+ properties?: string[] | null | undefined;
427
+ subject?: string | undefined;
428
+ }
421
429
  export declare class FileDescriptor implements IFileDescriptor {
422
430
  numberOfChunks: number;
423
431
  fileSize: number;
package/lib/DTOs.js CHANGED
@@ -1238,6 +1238,12 @@ var PasswordControl = /** @class */ (function (_super) {
1238
1238
  return PasswordControl;
1239
1239
  }(Setting));
1240
1240
  export { PasswordControl };
1241
+ var TestPlanRequest = /** @class */ (function () {
1242
+ function TestPlanRequest() {
1243
+ }
1244
+ return TestPlanRequest;
1245
+ }());
1246
+ export { TestPlanRequest };
1241
1247
  var FileDescriptor = /** @class */ (function () {
1242
1248
  function FileDescriptor(fileSize, chunkSize) {
1243
1249
  var _a;
@@ -27,6 +27,7 @@ var __assign = (this && this.__assign) || function () {
27
27
  import { BreakPoints, CommonContext, CommonSettings, DataGridControl, Image, Interaction, ListItemType, LogList, Result, RunStatus, SessionEvent, Setting, TestPlan, TestRun, TestStepType, TestStepValidationError, WatchDog, } from './DTOs';
28
28
  import { JSONCodec } from 'nats.ws';
29
29
  import { BaseClient } from './BaseClient';
30
+ import { v4 as uuidv4 } from 'uuid';
30
31
  var SessionClient = /** @class */ (function (_super) {
31
32
  __extends(SessionClient, _super);
32
33
  function SessionClient(baseSubject, options) {
@@ -204,7 +205,9 @@ var SessionClient = /** @class */ (function (_super) {
204
205
  * @return Test plan retrieved
205
206
  */
206
207
  SessionClient.prototype.getTestPlanXML = function () {
207
- return this.requestChunked('GetTestPlanXML').then(this.success()).catch(this.error());
208
+ // Generate a unique subject where the Runner will publish the chunks
209
+ var replySubject = "_INBOX.".concat(uuidv4());
210
+ return this.requestChunked('GetTestPlanXML', replySubject, replySubject).then(this.success()).catch(this.error());
208
211
  };
209
212
  /**
210
213
  * Load test plan using a test plan TapPackage from a repository
@@ -227,7 +230,8 @@ var SessionClient = /** @class */ (function (_super) {
227
230
  * @return Test plan resources opened.
228
231
  */
229
232
  SessionClient.prototype.resourcesOpen = function () {
230
- return this.request('ResourcesOpen')
233
+ var replySubject = "_INBOX.".concat(uuidv4());
234
+ return this.requestChunked('ResourcesOpen', replySubject, replySubject)
231
235
  .then(function (testPlanJs) { return TestPlan.fromJS(testPlanJs); })
232
236
  .then(this.success())
233
237
  .catch(this.error());
@@ -237,7 +241,8 @@ var SessionClient = /** @class */ (function (_super) {
237
241
  * @return Test plan resources closed.
238
242
  */
239
243
  SessionClient.prototype.resourcesClose = function () {
240
- return this.request('ResourcesClose')
244
+ var replySubject = "_INBOX.".concat(uuidv4());
245
+ return this.requestChunked('ResourcesClose', replySubject, replySubject)
241
246
  .then(function (testPlanJs) { return TestPlan.fromJS(testPlanJs); })
242
247
  .then(this.success())
243
248
  .catch(this.error());
@@ -272,7 +277,12 @@ var SessionClient = /** @class */ (function (_super) {
272
277
  * @return Test plan retrieved
273
278
  */
274
279
  SessionClient.prototype.getTestPlan = function (properties) {
275
- return this.request('GetTestPlan', properties)
280
+ var replySubject = "_INBOX.".concat(uuidv4());
281
+ var payload = {
282
+ subject: replySubject,
283
+ properties: properties,
284
+ };
285
+ return this.requestChunked('GetTestPlan', replySubject, payload)
276
286
  .then(function (testPlanJs) { return TestPlan.fromJS(testPlanJs); })
277
287
  .then(this.success())
278
288
  .catch(this.error());
@@ -283,7 +293,7 @@ var SessionClient = /** @class */ (function (_super) {
283
293
  * @return Test plan changed
284
294
  */
285
295
  SessionClient.prototype.setTestPlan = function (plan) {
286
- return this.request('SetTestPlan', plan)
296
+ return this.sendChunked('SetTestPlan', plan)
287
297
  .then(function (testPlanJs) { return TestPlan.fromJS(testPlanJs); })
288
298
  .then(this.success())
289
299
  .catch(this.error());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentap/runner-client",
3
- "version": "2.0.0-alpha.2.18",
3
+ "version": "2.0.0-alpha.2.19",
4
4
  "description": "This is the web client for the OpenTAP Runner.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",