@adobe/acc-js-sdk 1.1.14 → 1.1.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/src/domUtil.js CHANGED
@@ -386,6 +386,7 @@ class DomUtil {
386
386
  static _getTextIfTextNode(xml) {
387
387
  const child = xml.firstChild;
388
388
  if (!child) return null; // no children
389
+ if (xml.hasAttributes()) return null; // no attributes
389
390
  if (child.nextSibling) return null; // more than 1 child
390
391
  if (child.nodeType !== 3 && child.nodeType !== 4) return null;
391
392
  const text = child.nodeValue;
@@ -400,29 +401,37 @@ class DomUtil {
400
401
  * @param {Element} xml the DOM element to convert to JSON
401
402
  * @param {Object} json the object literal to write to
402
403
  * @param {string} flavor the JSON flavor: "SimpleJson" or "BadgerFish"
404
+ * @param {Object} parentJson parent JSON node during recursion. Is undefined for first call
405
+ * @param {boolean} forceTextAs is set during recursion (SimpleJson format) to force serialization of text nodes using "$: value" syntax
406
+ * instead of "$name: value" syntax. This is necessary to process collections and arrays of elements which only
407
+ * contain text nodes.
403
408
  */
404
- static _toJSON(xml, json, flavor) {
405
- if (xml.hasAttributes()) {
406
- var attributes = xml.attributes;
407
- for (var i=0; i<attributes.length; i++) {
408
- var att = attributes[i];
409
- var attName = (flavor == "BadgerFish" ? "@" : "") + att.name;
410
- json[attName] = att.value;
411
- }
412
- }
409
+ static _toJSON(xml, json, flavor, parentJson, forceTextAs$) {
413
410
 
414
411
  // Heuristic to determine if element is an object or an array
415
412
  const isCollection = xml.tagName.length > 11 && xml.tagName.substr(xml.tagName.length-11) == '-collection';
416
413
 
414
+ // Figure out which elements are arrays. Keep a count of elements for each tag name.
415
+ // When count >1 we consider this tag name to be an array
416
+ var hasChildElements = false; // Will be set if there is at least one child element
417
+ const countByTag = {};
417
418
  var child = xml.firstChild;
418
419
  while (child) {
419
- var childName = child.nodeName;
420
- if (isCollection && (json[childName] === null || json[childName] === undefined))
421
- json[childName] = [ ];
422
- var isArray = !!json[childName];
423
- if (isArray && !Util.isArray(json[childName]))
424
- json[childName] = [ json[childName] ];
425
- if (child.nodeType == 1) { // element
420
+ if (child.nodeType == 1) {
421
+ const childName = child.nodeName;
422
+ if (countByTag[childName] === undefined) countByTag[childName] = 1;
423
+ else countByTag[childName] = countByTag[childName] + 1;
424
+ hasChildElements = true;
425
+ }
426
+ child = child.nextSibling;
427
+ }
428
+
429
+ child = xml.firstChild;
430
+ while (child) {
431
+ if (child.nodeType == 1) {
432
+ const childName = child.nodeName;
433
+ const isArray = isCollection || countByTag[childName] > 1;
434
+ if (isArray && !json[childName]) json[childName] = [];
426
435
  // In SimpleJson representation, ensure we have proper transformation
427
436
  // of text and CDATA nodes. For instance, the following
428
437
  // <workflow><desc>Hello</desc></workflow>
@@ -434,12 +443,12 @@ class DomUtil {
434
443
  // from the schema, we cannot know if <desc></desc> should be
435
444
  // transformed into "$desc": "" or into "desc": {}
436
445
  const text = this._getTextIfTextNode(child);
437
- if (text !== null && flavor == "SimpleJson") {
446
+ if (!isArray && text !== null && flavor == "SimpleJson") {
438
447
  json[`$${childName}`] = text;
439
448
  }
440
449
  else {
441
450
  const jsonChild = flavor == "BadgerFish" ? new BadgerFishObject() : {};
442
- this._toJSON(child, jsonChild, flavor);
451
+ this._toJSON(child, jsonChild, flavor, json, isArray);
443
452
  if (isArray)
444
453
  json[childName].push(jsonChild);
445
454
  else
@@ -457,6 +466,46 @@ class DomUtil {
457
466
  }
458
467
  child = child.nextSibling;
459
468
  }
469
+
470
+ // Proceed with text nodes in SimpleJson format.
471
+ if (flavor === "SimpleJson") {
472
+ var text = "";
473
+ child = xml.firstChild;
474
+ while (child) {
475
+ if (child.nodeType === 3) { // text
476
+ var nodeText = child.nodeValue;
477
+ // Whitespace trimming rule: always trim for the root node, and trim for non-root nodes
478
+ // which actually have children elements
479
+ // Never trim CDATA nodes (nodeType 4)
480
+ if (!parentJson || hasChildElements)
481
+ nodeText = nodeText.trim();
482
+ if (nodeText) text = text + nodeText;
483
+ }
484
+ else if (child.nodeType === 4) { // CDATA
485
+ const cdataText = child.nodeValue;
486
+ if (cdataText) text = text + cdataText;
487
+ }
488
+ child = child.nextSibling;
489
+ }
490
+ if (text) {
491
+ json.$ = text;
492
+ }
493
+ }
494
+
495
+ // Finally proceed with attributes. They are processed last so that we get a chance to prefix
496
+ // the attribute name with "@" in SimpleJson format if there's already an element with the
497
+ // same name
498
+ if (xml.hasAttributes()) {
499
+ const attributes = xml.attributes;
500
+ for (var i=0; i<attributes.length; i++) {
501
+ const att = attributes[i];
502
+ var attName = (flavor == "BadgerFish" ? "@" : "") + att.name;
503
+ if (json[attName] !== undefined && flavor === "SimpleJson")
504
+ // There's already an element with the same name as the attribute
505
+ attName = "@" + attName;
506
+ json[attName] = att.value;
507
+ }
508
+ }
460
509
  }
461
510
 
462
511
  /**
package/src/index.js CHANGED
@@ -112,15 +112,15 @@ class SDK {
112
112
  * There are 2 alternate signatures for this function
113
113
  * <ul>
114
114
  * <li> the first one takes one single parameter which is a string and returns the escaped, quoted string
115
- * <li> the second one takes 2 array of strings and is called when using the function in tagged string litterals. The first array is the constant parts
116
- * of the string litteral, and the second array contains the variable parts. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
115
+ * <li> the second one takes 2 array of strings and is called when using the function in tagged string literals. The first array is the constant parts
116
+ * of the string literal, and the second array contains the variable parts. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
117
117
  * </ul>
118
118
  * <p>
119
- * The function can be used in a tagged string litterals like this: "var expr = escapeXtk`@name=${hello}`"
119
+ * The function can be used in a tagged string literals like this: "var expr = escapeXtk`@name=${hello}`"
120
120
  * <p>
121
121
  * @memberof Campaign
122
- * @param {string|string[]} p1 is the text to escape. If the text is null or undefined, it will be handled as an empty string. when using the escapeXtk for a tagged string litteral, this parameter is the array of constant values in the template.
123
- * @param {undefined|string[]} p2 when using the escapeXtk for a tagged string litteral, this parameter is the array of expression values in the template.
122
+ * @param {string|string[]} p1 is the text to escape. If the text is null or undefined, it will be handled as an empty string. when using the escapeXtk for a tagged string literal, this parameter is the array of constant values in the template.
123
+ * @param {undefined|string[]} p2 when using the escapeXtk for a tagged string literal, this parameter is the array of expression values in the template.
124
124
  * @returns {string} the escaped and quoted (simple quotes) text.
125
125
  *
126
126
  * @example
@@ -138,7 +138,7 @@ class SDK {
138
138
  return "'" + String(p1).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
139
139
  }
140
140
 
141
- // Second syntax: for use in tagged template litterals
141
+ // Second syntax: for use in tagged template literals
142
142
  // instead of writing: { expr: "@name = " + escapeXtk(userName) }
143
143
  // you write { expr: escapeXtk`@name = {userName}` }
144
144
  if (p1.length == 0) return "''";
package/src/soap.js CHANGED
@@ -85,7 +85,7 @@ const NS_XSD = "http://www.w3.org/2001/XMLSchema";
85
85
  class SoapMethodCall {
86
86
 
87
87
  constructor(transport, urn, methodName, sessionToken, securityToken, userAgentString, pushDownOptions, extraHttpHeaders) {
88
- this.request = undefined; // The HTTP request (object litteral passed to the transport layer)
88
+ this.request = undefined; // The HTTP request (object literal passed to the transport layer)
89
89
  this.requestOptions = undefined;
90
90
  this.response = undefined; // The HTTP response object (in case of success)
91
91
 
package/src/transport.js CHANGED
@@ -114,7 +114,6 @@ if (!Util.isBrowser()) {
114
114
  method: options.method,
115
115
  headers: headers,
116
116
  body: options.data,
117
- credentials: options.credentials || 'same-origin'
118
117
  });
119
118
 
120
119
  const p = fetch(r).then(async (response) => {
package/src/util.js CHANGED
@@ -55,7 +55,7 @@ class Util {
55
55
  // JavaScript arrays are objects
56
56
  if (typeof obj != "object") return false;
57
57
  // They also have a length property. But checking the length is not enough
58
- // since, it can also be an object litteral with a "length" property. Campaign
58
+ // since, it can also be an object literal with a "length" property. Campaign
59
59
  // schema attributes typically have a "length" attribute and are not arrays
60
60
  if (obj.length === undefined || obj.length === null) return false;
61
61
  // So check for a "push" function
@@ -133,6 +133,24 @@ class Util {
133
133
  }
134
134
  return obj;
135
135
  }
136
+
137
+ /**
138
+ * Get Schema id from namespace (find first upper case letter)
139
+ * @param {string} namespace a SDK namespace, i.e. xtkWorkflow, nmsDelivery, etc.
140
+ * @return {string} the corresponding schema id, i.e. xtk:workflow, nms:delivery, etc.
141
+ */
142
+ static schemaIdFromNamespace(namespace) {
143
+ var schemaId = "";
144
+ for (var i=0; i<namespace.length; i++) {
145
+ const c = namespace[i];
146
+ if (c >='A' && c<='Z') {
147
+ schemaId = schemaId + ":" + c.toLowerCase() + namespace.substr(i+1);
148
+ break;
149
+ }
150
+ schemaId = schemaId + c;
151
+ }
152
+ return schemaId;
153
+ }
136
154
  }
137
155
 
138
156
  /**
package/src/xtkJob.js ADDED
@@ -0,0 +1,337 @@
1
+ /*
2
+ Copyright 2022 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+ (function() {
13
+ "use strict";
14
+
15
+ const { CampaignException } = require("./campaign.js");
16
+ const { DomUtil } = require("./domUtil.js");
17
+ const { XtkCaster } = require("./xtkCaster.js");
18
+
19
+ /**
20
+ * @namespace Campaign
21
+ *
22
+ * @typedef {DOMElement} SoapMethodDefinition
23
+ * @memberof Campaign
24
+ */
25
+
26
+
27
+
28
+ /**
29
+ * The complete Triforce, or one or more components of the Triforce.
30
+ * @typedef {Object} XtkSoapCallSpec
31
+ * @property {string} method - the Soap method name (without any schema information)
32
+ * @property {string} xtkschema - the method schema id. It can be ommited if the object has a xtkschema property
33
+ * @property {any} object - the object ("this") to call the method with, possibly null for static methods. Should implement the xtk:job interface
34
+ * @property {Array} args - the list of arguments to the SOAP call
35
+ * @memberOf Campaign
36
+ */
37
+
38
+ /**
39
+ * @typedef {Object} XtkJobLog
40
+ * @property {number} id - the job log id, which can be used for subsequent calls to getStatus
41
+ * @property {number} iRc - the job return code (0 = ok)
42
+ * @property {Date} logDate - the timestamp of the log
43
+ * @property {number} logType - the level of the log message according
44
+ * @property {string} message - the log message
45
+ * @property {string} object - the log object
46
+ * @property {string} errorCode - the log error code if any
47
+ * @memberOf Campaign
48
+ */
49
+
50
+
51
+ /**
52
+ * @typedef {Object} XtkJobStatus
53
+ * @property {number} status - the job status code, as defined in the xtk:job:jobStatus enumeration
54
+ * @property {XtkJobLog[]} logs - the job log messages
55
+ * @property {{key: string, value: string}} properties - job properties
56
+ * @memberOf Campaign
57
+ */
58
+
59
+ /**********************************************************************************
60
+ *
61
+ * Job Interface
62
+ * Wraps the xtk:jobInterface interface into convenient JavaScript class
63
+ *
64
+ *********************************************************************************/
65
+ /**
66
+ * @private
67
+ * @class
68
+ * @constructor
69
+ * @memberof Campaign
70
+ */
71
+ class XtkJobInterface {
72
+
73
+ /**
74
+ * Create a job interface from a client and a SOAP call definition. This method is not meant to be called directly,
75
+ * use client.jobInterface instead
76
+ * @param {Campaign.Client} client the Client object to call Campaign API
77
+ * @param {Campaign.XtkSoapCallSpec} soapCallSpec the definition of the SOAP call
78
+ */
79
+ constructor(client, soapCallSpec) {
80
+ this._client = client;
81
+ this._soapCall = soapCallSpec;
82
+ this._maxLogCount = 100; // default fetch size
83
+ this._reset();
84
+ }
85
+
86
+ // Reset state before executing or submitting a job
87
+ _reset() {
88
+ this.jobId = undefined;
89
+ this.status = undefined;
90
+ this.result = undefined;
91
+ this.lastLogId = 0;
92
+ this.iRc = 0;
93
+ this.lastErrorCode = undefined;
94
+ this.firstErrorCode = undefined;
95
+ }
96
+
97
+ /**
98
+ * Execute job synchronously (xtk:jobInterface#Execute). Expects the job to have been built with an object implementing the xtk:job interface,
99
+ * for instance a delivery, and with the method to call (for instance "Prepare")
100
+ * Static methods are not supported
101
+ * @returns {string} a job id
102
+ */
103
+ async execute() {
104
+ this._reset();
105
+ const methodName = this._soapCall.method;
106
+ const entitySchemaId = this._soapCall.xtkschema ? this._soapCall.xtkschema : (this._soapCall.object ? this._soapCall.object.xtkschema : undefined);
107
+ if (!entitySchemaId)
108
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `No schema was provided in soap call or object`);
109
+ const callContext = {
110
+ client: this._client,
111
+ object: this._soapCall.object,
112
+ schemaId: 'xtk:jobInterface',
113
+ entitySchemaId: entitySchemaId
114
+ };
115
+ var jobId = await callContext.client._callMethod("Execute", callContext, [ methodName ]);
116
+ this.jobId = jobId;
117
+ return jobId;
118
+ }
119
+
120
+ /**
121
+ * Execute job asynchronously (xtk:jobInterface#Execute). Expects the job to have been built with an object implementing the xtk:job interface,
122
+ * for instance a delivery, and with the method to call (for instance "Prepare")
123
+ * Static methods are not supported
124
+ * @returns {string} a job id
125
+ */
126
+ async submit() {
127
+ this._reset();
128
+ const methodName = this._soapCall.method;
129
+ const entitySchemaId = this._soapCall.xtkschema ? this._soapCall.xtkschema : (this._soapCall.object ? this._soapCall.object.xtkschema : undefined);
130
+ if (!entitySchemaId)
131
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `No schema was provided in soap call or object`);
132
+ const callContext = {
133
+ client: this._client,
134
+ object: this._soapCall.object,
135
+ schemaId: 'xtk:jobInterface',
136
+ entitySchemaId: entitySchemaId
137
+ };
138
+ var jobId = await callContext.client._callMethod("Submit", callContext, [ this._soapCall.method ]);
139
+ this.jobId = jobId;
140
+ return jobId;
141
+ }
142
+
143
+ /**
144
+ * Execute a SOAP call asynchronously (xtk:jobInterface#Execute). Expects the job to have been built with an object implementing the xtk:job interface,
145
+ * for instance a delivery, and with the method to call (for instance "Prepare"). Can optionally pass parameters to the job.
146
+ * Static methods are not supported
147
+ * @returns {string} a job id
148
+ */
149
+ async submitSoapCall() {
150
+ this._reset();
151
+ const entitySchemaId = this._soapCall.xtkschema ? this._soapCall.xtkschema : (this._soapCall.object ? this._soapCall.object.xtkschema : undefined);
152
+ const callContext = {
153
+ client: this._client,
154
+ object: this._soapCall.object,
155
+ schemaId: 'xtk:jobInterface',
156
+ entitySchemaId: entitySchemaId,
157
+ };
158
+
159
+ const methodName = this._soapCall.method;
160
+ var schema = await this._client.getSchema(entitySchemaId, "xml", true);
161
+ if (!schema)
162
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `Schema '${entitySchemaId}' not found`);
163
+ var method = this._client._methodCache.get(entitySchemaId, methodName);
164
+ if (!method)
165
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `Method '${methodName}' of schema '${entitySchemaId}' not found`);
166
+ // SubmitSoapCall does not support
167
+ const isStatic = DomUtil.getAttributeAsBoolean(method, "static");
168
+ if (isStatic)
169
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `Method '${methodName}' of schema '${entitySchemaId}' is static`);
170
+
171
+
172
+ var jobId = await callContext.client._callMethod("SubmitSoapCall", callContext, [ {
173
+ name: this._soapCall.method,
174
+ service: this._soapCall.xtkschema,
175
+ param: [
176
+ { name:"this", type:"DOMDocument", value: this._soapCall.object },
177
+ { name:"bStart", type:"boolean", value:"false" },
178
+ ]
179
+ } ]);
180
+ this.jobId = jobId;
181
+ return jobId;
182
+ }
183
+
184
+ /**
185
+ * Poll the status of a job previously submitted with Execute, Submit, or SubmitSoapCall. The status is made of 3 objects: the status code,
186
+ * logs, and job properties. Job Properties are arbitrary key value pairs set by the job, but also contains progress information.
187
+ * This call will fetch the most recent status and logs and aggregate it with previously fetched statuses
188
+ * @param {number|undefined} lastLogId the log id fetch logs from. If unspecified, this function will return the next batch of logs. If set to 0, will return logs from the beginning
189
+ * @param {number|undefined} maxLogCount the max number of logs to fetch. Defaults to 100
190
+ * @returns {Campaign.XtkJobStatus} an object containing the job status, all logs fetched so for, and job properties
191
+ */
192
+ async getStatus(lastLogId, maxLogCount) {
193
+ if (lastLogId === undefined) lastLogId = this.lastLogId;
194
+ if (maxLogCount === null || maxLogCount === undefined) maxLogCount = this._maxLogCount;
195
+ var status = await this._client.NLWS.xtkJob.getStatus(this.jobId, lastLogId, maxLogCount);
196
+ if (this._client._representation === "xml") {
197
+ status[1] = this._client._toRepresentation(status[1], "SimpleJson");
198
+ status[2] = this._client._toRepresentation(status[2], "SimpleJson");
199
+ }
200
+ status = this._makeJobStatus(status);
201
+ this._updateStatus(status);
202
+ return status;
203
+ }
204
+
205
+ // Aggregate new status with previously fetched status
206
+ _updateStatus(status) {
207
+ for (var i=0; i<status.logs.length; i++) {
208
+ if (status.logs[i].id > this.lastLogId)
209
+ this.lastLogId = status.logs[i].id;
210
+ }
211
+ if (this.status === undefined) {
212
+ this.status = status;
213
+ }
214
+ else {
215
+ const oldLogs = this.status.logs;
216
+ this.status = status;
217
+ this.status.logs = oldLogs.concat(this.status.logs);
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Returns current progress of the job as a percentage (value between 0 and 1). This requires getStatus to have been called before
223
+ * @returns {number} the current job progress as a percentage value
224
+ */
225
+ getProgress() {
226
+ if (!this.status || !this.status.properties || !this.status.properties.progress) return 0;
227
+ if (!this.status.properties.progress.max) return 0;
228
+ return this.status.properties.progress.current / this.status.properties.progress.max;
229
+ }
230
+
231
+ /**
232
+ * Get the result of a job, i.e. the value returned by the underlying SOAP call if it had been called directlty.
233
+ * Assumes that the job is successful. If not, this call will throw an exception
234
+ * @returns {*} the job result
235
+ */
236
+ async getResult() {
237
+ var result = await this._client.NLWS.xtkJob.getResult(this.jobId);
238
+ result = this._makeJobResult(result);
239
+ this.result = result;
240
+ return result;
241
+ }
242
+
243
+ // Convert the job result into a typed object
244
+ _makeJobResult(rawResult) {
245
+ return rawResult;
246
+ }
247
+
248
+ // Convert job logs into a type object
249
+ _makeLogs(rawLogs) {
250
+ const logs = [];
251
+ rawLogs = rawLogs || {};
252
+ rawLogs = XtkCaster.asArray(rawLogs.log);
253
+ for (var i=0; i<rawLogs.length; i++) {
254
+ const rawLog = rawLogs[i];
255
+ var message = XtkCaster.asString(rawLog.message);
256
+ const match = message.match(/(\w{3}-\d{6})(.*)/);
257
+ var errorCode = undefined;
258
+ if (match && match.length >= 2) {
259
+ errorCode = match[1];
260
+ message = match[2] || "";
261
+ message = message.trim();
262
+ }
263
+ rawLog.id = XtkCaster.asLong(rawLog.id);
264
+ rawLog.iRc = XtkCaster.asLong(rawLog.iRc);
265
+ rawLog.logDate = XtkCaster.asDatetime(rawLog.logDate);
266
+ rawLog.logType = XtkCaster.asLong(rawLog.logType);
267
+ rawLog.message = message;
268
+ rawLog.object = XtkCaster.asString(rawLog.object);
269
+ rawLog.errorCode = errorCode;
270
+ logs.push(rawLog);
271
+
272
+ if (errorCode)
273
+ this.lastErrorCode = errorCode;
274
+ if (errorCode && !this.firstErrorCode)
275
+ this.firstErrorCode = errorCode;
276
+ if (rawLog.iRc != 0)
277
+ this.iRc = rawLog.iRc;
278
+ }
279
+ return logs;
280
+ }
281
+
282
+ // Convert job properties into a typed object
283
+ _makeProperties(rawProperties) {
284
+ rawProperties = rawProperties || {};
285
+ rawProperties.warning = XtkCaster.asBoolean(rawProperties.warning);
286
+ if (!rawProperties.progress) rawProperties.progress = {};
287
+ rawProperties.progress.current = XtkCaster.asLong(rawProperties.progress.current);
288
+ rawProperties.progress.max = XtkCaster.asLong(rawProperties.progress.max);
289
+ return rawProperties;
290
+ }
291
+
292
+ // Parse the result of GetStatus API. The result is an array of 3 object. The first is the status code,
293
+ // followed by the the logs, and finally the properties
294
+ _makeJobStatus(rawStatus) {
295
+ if (!rawStatus) rawStatus = [];
296
+ return {
297
+ status: XtkCaster.asLong(rawStatus[0]),
298
+ logs: this._makeLogs(rawStatus[1]),
299
+ properties: this._makeProperties(rawStatus[2])
300
+ };
301
+ }
302
+
303
+ /**
304
+ * Cancel a preciously submitted job
305
+ */
306
+ async cancel() {
307
+ await this._client.NLWS.xtkJob.cancel(this.jobId);
308
+ }
309
+
310
+ /**
311
+ * Pause a preciously submitted job
312
+ */
313
+ async pause() {
314
+ await this._client.NLWS.xtkJob.pause(this.jobId);
315
+ }
316
+
317
+ /**
318
+ * Waits until a job is actually cancelled
319
+ * @param {number} timeoutSeconds in seconds
320
+ */
321
+ async waitJobCancelled(timeoutSeconds) {
322
+ await this._client.NLWS.xtkJob.waitJobCancelled(this.jobId, timeoutSeconds);
323
+ }
324
+
325
+ /**
326
+ * Queries if warnings or errors have been generated for this job
327
+ * @return {boolean} Returns 'true' if there has been at least one warning or error message
328
+ */
329
+ async hasWarning() {
330
+ return XtkCaster.asBoolean(await this._client.NLWS.xtkJob.hasWarning(this.jobId));
331
+ }
332
+ }
333
+
334
+ // Public exports
335
+ exports.XtkJobInterface = XtkJobInterface;
336
+
337
+ })();
@@ -40,14 +40,14 @@ describe('ACC Client', function () {
40
40
  it('Create client with invalid parameters', () => {
41
41
  // No 4th parameter should be ok
42
42
  expect(new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin"))).not.toBeFalsy();
43
- // Object litteral is ok too
43
+ // Object literal is ok too
44
44
  expect(new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin"), {})).not.toBeFalsy();
45
45
  expect(new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin"), { representation: "BadgerFish" })).not.toBeFalsy();
46
46
  expect(new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin"), { dummy: 1 })).not.toBeFalsy();
47
47
  // Boolean is not ok
48
- expect(() => { new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", true)); }).toThrow("An object litteral is expected");
49
- expect(() => { new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", false)); }).toThrow("An object litteral is expected");
50
- expect(() => { new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", "BadgerFish")); }).toThrow("An object litteral is expected");
48
+ expect(() => { new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", true)); }).toThrow("An object literal is expected");
49
+ expect(() => { new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", false)); }).toThrow("An object literal is expected");
50
+ expect(() => { new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", "BadgerFish")); }).toThrow("An object literal is expected");
51
51
  // Invalid representation is not ok
52
52
  expect(() => { new Client(sdk, ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", { representation: "Hello" })); }).toThrow("Invalid representation");
53
53
  });
@@ -2614,7 +2614,7 @@ describe('ACC Client', function () {
2614
2614
  </extAccount-collection>`);
2615
2615
  });
2616
2616
 
2617
- it("Should force an json representation", async () => {
2617
+ it("Should force a json representation", async () => {
2618
2618
  const client = await Mock.makeClient();
2619
2619
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2620
2620
  await client.NLWS.xtkSession.logon();
@@ -2633,7 +2633,7 @@ describe('ACC Client', function () {
2633
2633
  const query = client.NLWS.json.xtkQueryDef.create(queryDef);
2634
2634
  const result = await query.executeQuery();
2635
2635
  const json = JSON.stringify(result);
2636
- expect(json).toBe('{"#text":[],"extAccount":[{"id":"1816","name":"defaultPopAccount"},{"id":"1818","name":"defaultOther"},{"id":"1849","name":"billingReport"},{"id":"12070","name":"TST_EXT_ACCOUNT_POSTGRESQL"},{"id":"1817","name":"defaultEmailBulk"},{"id":"2087","name":"ffda"},{"id":"2088","name":"defaultEmailMid"}]}');
2636
+ expect(json).toBe('{"extAccount":[{"id":"1816","name":"defaultPopAccount"},{"id":"1818","name":"defaultOther"},{"id":"1849","name":"billingReport"},{"id":"12070","name":"TST_EXT_ACCOUNT_POSTGRESQL"},{"id":"1817","name":"defaultEmailBulk"},{"id":"2087","name":"ffda"},{"id":"2088","name":"defaultEmailMid"}]}');
2637
2637
  });
2638
2638
  });
2639
2639
 
@@ -3252,8 +3252,10 @@ describe('ACC Client', function () {
3252
3252
  url: expect.any(String),
3253
3253
  method: 'POST',
3254
3254
  processData: false,
3255
- credentials: 'include',
3256
- headers: expect.anything(),
3255
+ headers: expect.objectContaining({
3256
+ 'X-Security-Token': expect.any(String),
3257
+ 'X-Session-Token': expect.any(String),
3258
+ }),
3257
3259
  })
3258
3260
  );
3259
3261
 
@@ -3514,6 +3516,18 @@ describe('ACC Client', function () {
3514
3516
  schema: "nms:delivery",
3515
3517
  formData: {ctx: {}}
3516
3518
  });
3519
+ expect(client._transport).toHaveBeenLastCalledWith(
3520
+ expect.objectContaining({
3521
+ data: expect.anything(),
3522
+ url: expect.any(String),
3523
+ method: 'POST',
3524
+ headers: expect.objectContaining({
3525
+ 'X-Security-Token': expect.any(String),
3526
+ 'X-Session-Token': expect.any(String),
3527
+ "Content-Type": "application/x-www-form-urlencoded",
3528
+ }),
3529
+ })
3530
+ );
3517
3531
  expect(report._reportContext).toBe("throughput");
3518
3532
  expect(report._selection).toBe("12133");
3519
3533
  expect(report.vars.$period).toBe("604800");