@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.
@@ -0,0 +1,713 @@
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
+
13
+
14
+ /**********************************************************************************
15
+ *
16
+ * Unit tests for the ACC client
17
+ *
18
+ *********************************************************************************/
19
+
20
+ const DomUtil = require('../src/domUtil.js').DomUtil;
21
+ const Mock = require('./mock.js').Mock;
22
+ const { XtkJobInterface } = require('../src/xtkJob.js');
23
+
24
+
25
+ const MOCK_SUBMIT_JOB_RESPONSE = (jobId) => Promise.resolve(`<?xml version='1.0'?>
26
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema'
27
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
28
+ xmlns:ns='urn:nms:delivery'
29
+ xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
30
+ <SOAP-ENV:Body>
31
+ <SubmitResponse xmlns='urn:nms:delivery' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
32
+ <pstrId xsi:type='xsd:string'>${jobId}</pstrId>
33
+ </SubmitResponse>
34
+ </SOAP-ENV:Body>
35
+ </SOAP-ENV:Envelope>`);
36
+
37
+ const MOCK_GETSTATUS1_RESPONSE = (status, current, max, warning, logs) => Promise.resolve(`<?xml version='1.0'?>
38
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema'
39
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
40
+ xmlns:ns='urn:xtk:job'
41
+ xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
42
+ <SOAP-ENV:Body>
43
+ <GetStatusResponse xmlns='urn:xtk:job' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
44
+ <psStatus xsi:type='xsd:short'>${status}</psStatus>
45
+ <pelemReturnLogs xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
46
+ ${logs ? "<elemReturnLogs>" + logs + "</elemReturnLogs>" : "<elemReturnLogs/>"}
47
+ </pelemReturnLogs>
48
+ <pelemProperties xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
49
+ <elemProperties warning="${warning ? 1 : 0}">
50
+ <progress current="${current}" max="${max}"/>
51
+ </elemProperties>
52
+ </pelemProperties>
53
+ </GetStatusResponse>
54
+ </SOAP-ENV:Body>
55
+ </SOAP-ENV:Envelope>`);
56
+
57
+
58
+ describe('XRK Jobs', function () {
59
+
60
+ describe("Job parsing", () => {
61
+ it("Should parse job status", () => {
62
+ expect(new XtkJobInterface()._makeJobStatus()).toEqual({ status:0, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
63
+ expect(new XtkJobInterface()._makeJobStatus({ })).toEqual({ status:0, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
64
+ expect(new XtkJobInterface()._makeJobStatus([ 3 ])).toEqual({ status:3, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
65
+ });
66
+
67
+ it("Should parse logs", () => {
68
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: null } ])).toEqual({ status:1, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
69
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: [] } ])).toEqual({ status:1, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
70
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: { iRc: "3"} } ])).toEqual({ status:1, logs:[ { iRc:3, id:0, logDate:null, logType:0, message:"", object:"" } ], properties: { warning:false, progress: { current:0, max:0} } });
71
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: { id:"1234", iRc:"3", logType:"2", message:"Hello", object:"test" } } ])).toEqual({ status:1, logs:[ { iRc:3, id:1234, logDate:null, logType:2, message:"Hello", object:"test" } ], properties: { warning:false, progress: { current:0, max:0} } });
72
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: [{ id:"1234", iRc:"3", logType:"2", message:"Hello", object:"test" }] } ])).toEqual({ status:1, logs:[ { iRc:3, id:1234, logDate:null, logType:2, message:"Hello", object:"test" } ], properties: { warning:false, progress: { current:0, max:0} } });
73
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: [{ id:"1234", iRc:"3", logType:"2", message:"Hello", object:"test" }, { id:"1244", iRc:"-53", logType:"2", message:"World" }] } ])).toEqual(
74
+ { status:1,
75
+ logs:[ { iRc:3, id:1234, logDate:null, logType:2, message:"Hello", object:"test" },
76
+ { iRc:-53, id:1244, logDate:null, logType:2, message:"World", object:"" } ],
77
+ properties: { warning:false, progress: { current:0, max:0} }
78
+ });
79
+ });
80
+
81
+ it("Should extract error code", () => {
82
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: { id:"1234", iRc:"3", logType:"2", message:"DLV-490009 Hello", object:"test" } } ])).toEqual({ status:1, logs:[ { iRc:3, id:1234, logDate:null, logType:2, errorCode:"DLV-490009", message:"Hello", object:"test" } ], properties: { warning:false, progress: { current:0, max:0} } });
83
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: { id:"1234", iRc:"3", logType:"2", message:"DLV-49000 Hello", object:"test" } } ])).toEqual({ status:1, logs:[ { iRc:3, id:1234, logDate:null, logType:2, message:"DLV-49000 Hello", object:"test" } ], properties: { warning:false, progress: { current:0, max:0} } });
84
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: { id:"1234", iRc:"3", logType:"2", message:"DLV-490009", object:"test" } } ])).toEqual({ status:1, logs:[ { iRc:3, id:1234, logDate:null, logType:2, errorCode:"DLV-490009", message:"", object:"test" } ], properties: { warning:false, progress: { current:0, max:0} } });
85
+ });
86
+
87
+ it("Should parse log date", () => {
88
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: { logDate:"" } } ])).toEqual({ status:1, logs:[ { iRc:0, id:0, logDate:null, logType:0, message:"", object:"" } ], properties: { warning:false, progress: { current:0, max:0} } });
89
+ expect(new XtkJobInterface()._makeJobStatus([ 1, { log: { logDate:"2022-11-19 16:30:19.140Z" } } ])).toEqual({ status:1, logs:[ { iRc:0, id:0, logDate:new Date(1668875419140), logType:0, message:"", object:"" } ], properties: { warning:false, progress: { current:0, max:0} } });
90
+ });
91
+
92
+ it("Should parse progress", () => {
93
+ expect(new XtkJobInterface()._makeJobStatus([ 1, undefined, {} ])).toEqual({ status:1, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
94
+ expect(new XtkJobInterface()._makeJobStatus([ 1, undefined, { progress:{} } ])).toEqual({ status:1, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
95
+ expect(new XtkJobInterface()._makeJobStatus([ 1, undefined, { progress:{ current:10 } } ])).toEqual({ status:1, logs:[], properties: { warning:false, progress: { current:10, max:0} } });
96
+ expect(new XtkJobInterface()._makeJobStatus([ 1, undefined, { progress:{ current:10, max:100 } } ])).toEqual({ status:1, logs:[], properties: { warning:false, progress: { current:10, max:100} } });
97
+ });
98
+
99
+ it("Should return progress as a percentage", () => {
100
+ const progress = (getStatusResponse) => {
101
+ const job = new XtkJobInterface();
102
+ const status = job._makeJobStatus(getStatusResponse);
103
+ job._updateStatus(status);
104
+ return job.getProgress();
105
+ };
106
+ expect(progress([ 1 ])).toBe(0);
107
+ expect(progress([ 1, undefined, {} ])).toBe(0);
108
+ expect(progress([ 1, undefined, { progress:{} } ])).toBe(0);
109
+ expect(progress([ 1, undefined, { progress:{ current:10 } } ])).toBe(0);
110
+ expect(progress([ 1, undefined, { progress:{ current:10, max:100 } } ])).toBe(0.1);
111
+ });
112
+
113
+ it("Should return progress as a percentage (edge cases)", () => {
114
+ const job = new XtkJobInterface();
115
+ expect(job.getProgress()).toBe(0);
116
+ });
117
+ });
118
+
119
+ describe("Result parsing", () => {
120
+ it("Should parse job result", () => {
121
+ expect(new XtkJobInterface()._makeJobResult()).toEqual(undefined);
122
+ expect(new XtkJobInterface()._makeJobResult("Hello")).toEqual("Hello");
123
+ expect(new XtkJobInterface()._makeJobResult({ hello: 'world' })).toEqual({ hello: 'world' });
124
+ });
125
+ });
126
+
127
+ describe("Job update", () => {
128
+ it("Should set empty status", () => {
129
+ const job = new XtkJobInterface();
130
+ expect(job.status).toBeUndefined();
131
+ job._updateStatus(job._makeJobStatus());
132
+ expect(job.status).toEqual({ status: 0, properties: { progress: { current:0, max: 0 }, warning:false }, logs: [] });
133
+ });
134
+
135
+ it("Should set initial status", () => {
136
+ const job = new XtkJobInterface();
137
+ expect(job.status).toBeUndefined();
138
+ job._updateStatus(job._makeJobStatus([ 1, { log: [{ id:"1234", iRc:"3", logType:"2", message:"Hello", object:"test" }, { id:"1244", iRc:"-53", logType:"2", message:"World" }] } ]) );
139
+ expect(job.status).toEqual({ status:1,
140
+ logs:[ { iRc:3, id:1234, logDate:null, logType:2, message:"Hello", object:"test" },
141
+ { iRc:-53, id:1244, logDate:null, logType:2, message:"World", object:"" } ],
142
+ properties: { warning:false, progress: { current:0, max:0} }
143
+ });
144
+ });
145
+
146
+ it("Should update status", () => {
147
+ const job = new XtkJobInterface();
148
+ expect(job.status).toBeUndefined();
149
+ expect(job.lastLogId).toBe(0);
150
+ job._updateStatus(job._makeJobStatus([ 1, { log: [{ id:"1234", iRc:"3", logType:"2", message:"Hello", object:"test" }, { id:"1244", iRc:"-53", logType:"2", message:"World" }] } ]) );
151
+ expect(job.status).toEqual({ status:1,
152
+ logs:[ { iRc:3, id:1234, logDate:null, logType:2, message:"Hello", object:"test" },
153
+ { iRc:-53, id:1244, logDate:null, logType:2, message:"World", object:"" } ],
154
+ properties: { warning:false, progress: { current:0, max:0} }
155
+ });
156
+ expect(job.lastLogId).toBe(1244);
157
+ job._updateStatus(job._makeJobStatus([ 1, { log: [{ id:"1245", iRc:"3", logType:"2", message:"Hello World" }] } ]) );
158
+ expect(job.status).toEqual({ status:1,
159
+ logs:[ { iRc:3, id:1234, logDate:null, logType:2, message:"Hello", object:"test" },
160
+ { iRc:-53, id:1244, logDate:null, logType:2, message:"World", object:"" } ,
161
+ { iRc:3, id:1245, logDate:null, logType:2, message:"Hello World", object:"" } ],
162
+ properties: { warning:false, progress: { current:0, max:0} }
163
+ });
164
+ expect(job.lastLogId).toBe(1245);
165
+ });
166
+
167
+ it("Should ignore old logs when computing lastLogId", () => {
168
+ const job = new XtkJobInterface();
169
+ job._updateStatus(job._makeJobStatus([ 1, { log: [{ id:"1234", iRc:"3", logType:"2", message:"Hello", object:"test" }, { id:"1244", iRc:"-53", logType:"2", message:"World" }] } ]) );
170
+ expect(job.lastLogId).toBe(1244);
171
+ job._updateStatus(job._makeJobStatus([ 1, { log: [{ id:"1200", iRc:"3", logType:"2", message:"Hello World" }] } ]) ); // 1200 < 1234
172
+ expect(job.lastLogId).toBe(1244);
173
+ });
174
+ });
175
+
176
+
177
+ describe("Execute", () => {
178
+ it("Execute with success", async () => {
179
+ const client = { _callMethod: jest.fn() };
180
+ const job = new XtkJobInterface(client, { xtkschema: "nms:delivery", object: "Hello World", method: "Prepare" });
181
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
182
+ const jobId = await job.execute();
183
+ expect(jobId).toBe("9876");
184
+ expect(client._callMethod.mock.calls.length).toBe(1);
185
+ expect(client._callMethod.mock.calls[0][0]).toBe("Execute");
186
+ expect(client._callMethod.mock.calls[0][1]).toMatchObject({
187
+ entitySchemaId: "nms:delivery",
188
+ schemaId: "xtk:jobInterface",
189
+ object: "Hello World"
190
+ });
191
+ expect(client._callMethod.mock.calls[0][2]).toEqual([ "Prepare" ]);
192
+ });
193
+
194
+ it("Infer schema from objects", async () => {
195
+ const client = { _callMethod: jest.fn() };
196
+ const job = new XtkJobInterface(client, { object: { xtkschema: "nms:delivery", name: "Hello World" }, method: "Prepare" });
197
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
198
+ const jobId = await job.execute();
199
+ expect(jobId).toBe("9876");
200
+ expect(client._callMethod.mock.calls.length).toBe(1);
201
+ expect(client._callMethod.mock.calls[0][0]).toBe("Execute");
202
+ expect(client._callMethod.mock.calls[0][1]).toMatchObject({
203
+ entitySchemaId: "nms:delivery",
204
+ schemaId: "xtk:jobInterface",
205
+ object: { xtkschema: "nms:delivery", name: "Hello World" }
206
+ });
207
+ expect(client._callMethod.mock.calls[0][2]).toEqual([ "Prepare" ]);
208
+ });
209
+
210
+ it("Should fail if missing entity schema (with object)", async () => {
211
+ const client = { _callMethod: jest.fn() };
212
+ const job = new XtkJobInterface(client, { object: { name: "Hello World" }, method: "Prepare" });
213
+ await expect(job.execute()).rejects.toMatchObject({
214
+ "detail": "No schema was provided in soap call or object",
215
+ "errorCode": "SDK-000009",
216
+ "faultCode": 16384,
217
+ "faultString": "Unknown method 'Prepare' of schema 'undefined'",
218
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'Prepare' of schema 'undefined'. No schema was provided in soap call or object",
219
+ "name": "CampaignException",
220
+ "statusCode": 400,
221
+ });
222
+ });
223
+
224
+ it("Should fail if missing entity schema (without object)", async () => {
225
+ const client = { _callMethod: jest.fn() };
226
+ const job = new XtkJobInterface(client, { method: "Prepare" });
227
+ await expect(job.execute()).rejects.toMatchObject({
228
+ "detail": "No schema was provided in soap call or object",
229
+ "errorCode": "SDK-000009",
230
+ "faultCode": 16384,
231
+ "faultString": "Unknown method 'Prepare' of schema 'undefined'",
232
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'Prepare' of schema 'undefined'. No schema was provided in soap call or object",
233
+ "name": "CampaignException",
234
+ "statusCode": 400,
235
+ });
236
+ });
237
+ });
238
+
239
+ describe("Submit", () => {
240
+ it("Submit with success", async () => {
241
+ const client = { _callMethod: jest.fn() };
242
+ const job = new XtkJobInterface(client, { xtkschema: "nms:delivery", object: "Hello World", method: "Prepare" });
243
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
244
+ const jobId = await job.submit();
245
+ expect(jobId).toBe("9876");
246
+ expect(client._callMethod.mock.calls.length).toBe(1);
247
+ expect(client._callMethod.mock.calls[0][0]).toBe("Submit");
248
+ expect(client._callMethod.mock.calls[0][1]).toMatchObject({
249
+ entitySchemaId: "nms:delivery",
250
+ schemaId: "xtk:jobInterface",
251
+ object: "Hello World"
252
+ });
253
+ expect(client._callMethod.mock.calls[0][2]).toEqual([ "Prepare" ]);
254
+ });
255
+
256
+ it("Infer schema from objects", async () => {
257
+ const client = { _callMethod: jest.fn() };
258
+ const job = new XtkJobInterface(client, { object: { xtkschema: "nms:delivery", name: "Hello World" }, method: "Prepare" });
259
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
260
+ const jobId = await job.submit();
261
+ expect(jobId).toBe("9876");
262
+ expect(client._callMethod.mock.calls.length).toBe(1);
263
+ expect(client._callMethod.mock.calls[0][0]).toBe("Submit");
264
+ expect(client._callMethod.mock.calls[0][1]).toMatchObject({
265
+ entitySchemaId: "nms:delivery",
266
+ schemaId: "xtk:jobInterface",
267
+ object: { xtkschema: "nms:delivery", name: "Hello World" }
268
+ });
269
+ expect(client._callMethod.mock.calls[0][2]).toEqual([ "Prepare" ]);
270
+ });
271
+
272
+
273
+ it("Should fail if missing entity schema (with object)", async () => {
274
+ const client = { _callMethod: jest.fn() };
275
+ const job = new XtkJobInterface(client, { object: { name: "Hello World" }, method: "Prepare" });
276
+ await expect(job.submit()).rejects.toMatchObject({
277
+ "detail": "No schema was provided in soap call or object",
278
+ "errorCode": "SDK-000009",
279
+ "faultCode": 16384,
280
+ "faultString": "Unknown method 'Prepare' of schema 'undefined'",
281
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'Prepare' of schema 'undefined'. No schema was provided in soap call or object",
282
+ "name": "CampaignException",
283
+ "statusCode": 400,
284
+ });
285
+ });
286
+
287
+ it("Should fail if missing entity schema (without object)", async () => {
288
+ const client = { _callMethod: jest.fn() };
289
+ const job = new XtkJobInterface(client, { method: "Prepare" });
290
+ await expect(job.submit()).rejects.toMatchObject({
291
+ "detail": "No schema was provided in soap call or object",
292
+ "errorCode": "SDK-000009",
293
+ "faultCode": 16384,
294
+ "faultString": "Unknown method 'Prepare' of schema 'undefined'",
295
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'Prepare' of schema 'undefined'. No schema was provided in soap call or object",
296
+ "name": "CampaignException",
297
+ "statusCode": 400,
298
+ });
299
+ });
300
+ });
301
+
302
+ describe("SubmitSoapCall", () => {
303
+ it("SubmitSoapCall with success", async () => {
304
+ const client = { _callMethod: jest.fn(), getSchema: jest.fn(), _methodCache: { get: jest.fn()} };
305
+ const job = new XtkJobInterface(client, { xtkschema: "nms:delivery", object: "Hello World", method: "Prepare" });
306
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
307
+ client.getSchema.mockReturnValueOnce(Promise.resolve(true));
308
+ client._methodCache.get.mockReturnValueOnce(DomUtil.parse("<method></method>").documentElement);
309
+ const jobId = await job.submitSoapCall();
310
+ expect(jobId).toBe("9876");
311
+ expect(client._callMethod.mock.calls.length).toBe(1);
312
+ expect(client._callMethod.mock.calls[0][0]).toBe("SubmitSoapCall");
313
+ expect(client._callMethod.mock.calls[0][1]).toMatchObject({
314
+ entitySchemaId: "nms:delivery",
315
+ schemaId: "xtk:jobInterface",
316
+ object: "Hello World",
317
+ });
318
+ expect(client._callMethod.mock.calls[0][2]).toEqual([ {
319
+ name: "Prepare",
320
+ service: "nms:delivery",
321
+ param: [
322
+ { name:"this", type:"DOMDocument", value: "Hello World", },
323
+ { name:"bStart", type:"boolean", value:"false" },
324
+ ]
325
+ } ]);
326
+ });
327
+
328
+ it("Infer schema from objects", async () => {
329
+ const client = { _callMethod: jest.fn(), getSchema: jest.fn(), _methodCache: { get: jest.fn()} };
330
+ const job = new XtkJobInterface(client, { object: { xtkschema: "nms:delivery", name: "Hello World" }, method: "Prepare" });
331
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
332
+ client.getSchema.mockReturnValueOnce(Promise.resolve(true));
333
+ client._methodCache.get.mockReturnValueOnce(DomUtil.parse("<method></method>").documentElement);
334
+ const jobId = await job.submitSoapCall();
335
+ expect(jobId).toBe("9876");
336
+ expect(client._callMethod.mock.calls[0][1]).toMatchObject({
337
+ entitySchemaId: "nms:delivery",
338
+ schemaId: "xtk:jobInterface",
339
+ object: { xtkschema: "nms:delivery", name: "Hello World" }
340
+ });
341
+ });
342
+
343
+ it("Should fail on missing schema", async () => {
344
+ const client = { _callMethod: jest.fn(), getSchema: jest.fn(), _methodCache: { get: jest.fn()} };
345
+ const job = new XtkJobInterface(client, { method: "Prepare" });
346
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
347
+ client.getSchema.mockReturnValueOnce(Promise.resolve(false));
348
+ client._methodCache.get.mockReturnValueOnce(DomUtil.parse("<method></method>").documentElement);
349
+ await expect(job.submitSoapCall()).rejects.toMatchObject({
350
+ "detail": "Schema 'undefined' not found",
351
+ "errorCode": "SDK-000009",
352
+ "faultCode": 16384,
353
+ "faultString": "Unknown method 'Prepare' of schema 'undefined'",
354
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'Prepare' of schema 'undefined'. Schema 'undefined' not found",
355
+ "name": "CampaignException",
356
+ "statusCode": 400,
357
+ });
358
+ });
359
+
360
+ it("Should fail on invalid schema", async () => {
361
+ const client = { _callMethod: jest.fn(), getSchema: jest.fn(), _methodCache: { get: jest.fn()} };
362
+ const job = new XtkJobInterface(client, { object: { xtkschema: "nms:notFound", name: "Hello World" }, method: "Prepare" });
363
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
364
+ client.getSchema.mockReturnValueOnce(Promise.resolve(false));
365
+ client._methodCache.get.mockReturnValueOnce(DomUtil.parse("<method></method>").documentElement);
366
+ await expect(job.submitSoapCall()).rejects.toMatchObject({
367
+ "detail": "Schema 'nms:notFound' not found",
368
+ "errorCode": "SDK-000009",
369
+ "faultCode": 16384,
370
+ "faultString": "Unknown method 'Prepare' of schema 'nms:notFound'",
371
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'Prepare' of schema 'nms:notFound'. Schema 'nms:notFound' not found",
372
+ "name": "CampaignException",
373
+ "statusCode": 400,
374
+ });
375
+ });
376
+
377
+ it("Should fail on method not found", async () => {
378
+ const client = { _callMethod: jest.fn(), getSchema: jest.fn(), _methodCache: { get: jest.fn()} };
379
+ const job = new XtkJobInterface(client, { object: { xtkschema: "nms:delivery", name: "Hello World" }, method: "NotFound" });
380
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
381
+ client.getSchema.mockReturnValueOnce(Promise.resolve(true));
382
+ client._methodCache.get.mockReturnValueOnce(undefined);
383
+ await expect(job.submitSoapCall()).rejects.toMatchObject({
384
+ "detail": "Method 'NotFound' of schema 'nms:delivery' not found",
385
+ "errorCode": "SDK-000009",
386
+ "faultCode": 16384,
387
+ "faultString": "Unknown method 'NotFound' of schema 'nms:delivery'",
388
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'NotFound' of schema 'nms:delivery'. Method 'NotFound' of schema 'nms:delivery' not found",
389
+ "name": "CampaignException",
390
+ "statusCode": 400,
391
+ });
392
+ });
393
+
394
+ it("Should fail on static methods", async () => {
395
+ const client = { _callMethod: jest.fn(), getSchema: jest.fn(), _methodCache: { get: jest.fn()} };
396
+ const job = new XtkJobInterface(client, { object: { xtkschema: "nms:delivery", name: "Hello World" }, method: "StaticMethod" });
397
+ client._callMethod.mockReturnValueOnce(Promise.resolve("9876"));
398
+ client.getSchema.mockReturnValueOnce(Promise.resolve(true));
399
+ client._methodCache.get.mockReturnValueOnce(DomUtil.parse('<method static="true"></method>').documentElement);
400
+ await expect(job.submitSoapCall()).rejects.toMatchObject({
401
+ "detail": "Method 'StaticMethod' of schema 'nms:delivery' is static",
402
+ "errorCode": "SDK-000009",
403
+ "faultCode": 16384,
404
+ "faultString": "Unknown method 'StaticMethod' of schema 'nms:delivery'",
405
+ "message": "400 - Error 16384: SDK-000009 Unknown method 'StaticMethod' of schema 'nms:delivery'. Method 'StaticMethod' of schema 'nms:delivery' is static",
406
+ "name": "CampaignException",
407
+ "statusCode": 400,
408
+ });
409
+ });
410
+ });
411
+
412
+ describe("Get Status", () => {
413
+ it("Should get status", async () => {
414
+ const client = { NLWS: { xtkJob: { getStatus: jest.fn() } } };
415
+ const job = new XtkJobInterface(client);
416
+ job.jobId = "ABC";
417
+ client.NLWS.xtkJob.getStatus.mockReturnValueOnce(Promise.resolve({ }));
418
+ const status = await job.getStatus();
419
+ expect(status).toEqual({ status:0, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
420
+ expect(job.status).toEqual({ status:0, logs:[], properties: { warning:false, progress: { current:0, max:0} } });
421
+ expect(client.NLWS.xtkJob.getStatus.mock.calls.length).toBe(1);
422
+ expect(client.NLWS.xtkJob.getStatus.mock.calls[0]).toEqual(["ABC", 0, 100]);
423
+ });
424
+
425
+ it("Should get next logs", async() => {
426
+ const client = { NLWS: { xtkJob: { getStatus: jest.fn() } } };
427
+ const job = new XtkJobInterface(client);
428
+ job.jobId = "ABC";
429
+ client.NLWS.xtkJob.getStatus.mockReturnValueOnce(Promise.resolve([ 1, { log: [ { id: 1 } ] } ]));
430
+ var status = await job.getStatus();
431
+ expect(status).toEqual({ status:1, logs:[
432
+ { iRc:0, id:1, logDate:null, logType:0, message:"", object:"" }
433
+ ], properties: { warning:false, progress: { current:0, max:0} } });
434
+ expect(job.status).toEqual({ status:1, logs:[
435
+ { iRc:0, id:1, logDate:null, logType:0, message:"", object:"" }
436
+ ], properties: { warning:false, progress: { current:0, max:0} } });
437
+ expect(client.NLWS.xtkJob.getStatus.mock.calls.length).toBe(1);
438
+ expect(client.NLWS.xtkJob.getStatus.mock.calls[0]).toEqual(["ABC", 0, 100]);
439
+
440
+ client.NLWS.xtkJob.getStatus.mockReturnValueOnce(Promise.resolve([ 1, { log: [ { id: 2 }, { id: 3 } ] } ]));
441
+ status = await job.getStatus();
442
+ expect(status).toEqual({ status:1, logs:[
443
+ { iRc:0, id:1, logDate:null, logType:0, message:"", object:"" },
444
+ { iRc:0, id:2, logDate:null, logType:0, message:"", object:"" },
445
+ { iRc:0, id:3, logDate:null, logType:0, message:"", object:"" }
446
+ ], properties: { warning:false, progress: { current:0, max:0} } });
447
+ expect(job.status).toEqual({ status:1, logs:[
448
+ { iRc:0, id:1, logDate:null, logType:0, message:"", object:"" },
449
+ { iRc:0, id:2, logDate:null, logType:0, message:"", object:"" },
450
+ { iRc:0, id:3, logDate:null, logType:0, message:"", object:"" }
451
+ ], properties: { warning:false, progress: { current:0, max:0} } });
452
+ expect(client.NLWS.xtkJob.getStatus.mock.calls.length).toBe(2);
453
+ expect(client.NLWS.xtkJob.getStatus.mock.calls[1]).toEqual(["ABC", 1, 100]);
454
+ });
455
+
456
+ it("Should get status from id", async () => {
457
+ const client = { NLWS: { xtkJob: { getStatus: jest.fn() } } };
458
+ const job = new XtkJobInterface(client);
459
+ job.jobId = "ABC";
460
+ client.NLWS.xtkJob.getStatus.mockReturnValueOnce(Promise.resolve({ }));
461
+ const status = await job.getStatus(12, 500);
462
+ expect(client.NLWS.xtkJob.getStatus.mock.calls.length).toBe(1);
463
+ expect(client.NLWS.xtkJob.getStatus.mock.calls[0]).toEqual(["ABC", 12, 500]);
464
+ });
465
+ });
466
+
467
+ describe("Get Result", () => {
468
+ it("Should get result", async () => {
469
+ const client = { NLWS: { xtkJob: { getResult: jest.fn() } } };
470
+ const job = new XtkJobInterface(client);
471
+ job.jobId = "ABC";
472
+ client.NLWS.xtkJob.getResult.mockReturnValueOnce(Promise.resolve("Hello"));
473
+ const result = await job.getResult();
474
+ expect(result).toEqual("Hello");
475
+ expect(client.NLWS.xtkJob.getResult.mock.calls.length).toBe(1);
476
+ expect(client.NLWS.xtkJob.getResult.mock.calls[0][0]).toBe("ABC");
477
+ });
478
+ });
479
+
480
+ describe("Asynchronous jobs", () => {
481
+
482
+ it("Should submit an delivery preparation", async () => {
483
+ const client = await Mock.makeClient();
484
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
485
+ await client.NLWS.xtkSession.logon();
486
+ const job = client.jobInterface({
487
+ xtkschema: 'nms:delivery',
488
+ method: 'Prepare',
489
+ object: { }, // In reality should be an actual delivery object. Not passed here to simplify the test
490
+ });
491
+
492
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_JOB_SCHEMA_RESPONSE);
493
+ client._transport.mockReturnValueOnce(MOCK_SUBMIT_JOB_RESPONSE("4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM="));
494
+ var jobId = await job.submit();
495
+ expect(client._transport).toHaveBeenCalledTimes(3); // Logon, GetSchema(xtk:job), Submit
496
+ expect(client._transport.mock.calls[1][0].data).toContain('<pk xsi:type="xsd:string">xtk:schema|xtk:job</pk><md5 xsi:type="xsd:string"/><mustExist xsi:type="xsd:boolean">false</mustExist></m:GetEntityIfMoreRecent>');
497
+ expect(client._transport.mock.calls[2][0].data).toContain('<m:Submit xmlns:m="urn:xtk:jobInterface|nms:delivery"');
498
+ expect(client._transport.mock.calls[2][0].data).toContain('<delivery xtkschema="nms:delivery"/></document><methodName xsi:type="xsd:string">Prepare</methodName>');
499
+ expect(jobId).toBe("4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=");
500
+
501
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
502
+ await client.NLWS.xtkSession.logoff();
503
+ });
504
+
505
+ it("Should submit an delivery preparation and get status", async () => {
506
+ const client = await Mock.makeClient();
507
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
508
+ await client.NLWS.xtkSession.logon();
509
+ const job = client.jobInterface({
510
+ xtkschema: 'nms:delivery',
511
+ method: 'Prepare',
512
+ object: { }, // In reality should be an actual delivery object. Not passed here to simplify the test
513
+ });
514
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_JOB_SCHEMA_RESPONSE);
515
+ client._transport.mockReturnValueOnce(MOCK_SUBMIT_JOB_RESPONSE("4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM="));
516
+ jobId = await job.submit();
517
+
518
+ // First call to get status returns the status and a no logs
519
+ client._transport.mockReturnValueOnce(MOCK_GETSTATUS1_RESPONSE(2, 0, 0, true));
520
+ var status = await job.getStatus();
521
+ expect(client._transport).toHaveBeenCalledTimes(4); // Logon, GetSchema(xtk:job), Submit, GetStatus
522
+ expect(client._transport.mock.calls[3][0].data).toContain('<id xsi:type=\"xsd:string\">4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=</id><lastLogId xsi:type=\"xsd:int\">0</lastLogId><maxLogCount xsi:type=\"xsd:int\">100</maxLogCount></m:GetStatus>');
523
+ expect(job).toMatchObject({
524
+ jobId: "4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=",
525
+ lastLogId: 0,
526
+ iRc: 0
527
+ })
528
+ expect(status).toMatchObject({
529
+ status: 2,
530
+ logs: [],
531
+ properties: { warning: true, progress: { current: 0, max: 0 } }
532
+ });
533
+
534
+ // Call GetStatus again, adding some logs and making some progress
535
+ client._transport.mockReturnValueOnce(MOCK_GETSTATUS1_RESPONSE(2, 50, 231, true, '<log iRc="0" id="1511" logDate="2022-11-19 16:30:19.140Z" logType="2" message="Target preparation in progress..." object=""/>'));
536
+ var status = await job.getStatus();
537
+ expect(client._transport).toHaveBeenCalledTimes(5); // Logon, GetSchema(xtk:job), Submit, GetStatus, GetStatus
538
+ expect(client._transport.mock.calls[4][0].data).toContain('<id xsi:type=\"xsd:string\">4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=</id><lastLogId xsi:type=\"xsd:int\">0</lastLogId><maxLogCount xsi:type=\"xsd:int\">100</maxLogCount></m:GetStatus>');
539
+ expect(job).toMatchObject({
540
+ jobId: "4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=",
541
+ lastLogId: 1511,
542
+ iRc: 0
543
+ })
544
+ expect(status).toMatchObject({
545
+ status: 2,
546
+ logs: [
547
+ { iRc: 0, id: 1511, logDate: new Date(1668875419140), logType: 2, message: "Target preparation in progress...", object: "" }
548
+ ],
549
+ properties: { warning: true, progress: { current: 50, max: 231 } }
550
+ });
551
+
552
+ // Call GetStatus again, adding some logs and making some progress and change status
553
+ client._transport.mockReturnValueOnce(MOCK_GETSTATUS1_RESPONSE(3, 231, 231, true, '<log iRc="16384" id="1513" logDate="2022-11-19 16:30:19.820Z" logType="0" message="DLV-490009 You have not defined the target population of the delivery action." object="test"/>'));
554
+ var status = await job.getStatus();
555
+ expect(client._transport).toHaveBeenCalledTimes(6); // Logon, GetSchema(xtk:job), Submit, GetStatus, GetStatus
556
+ expect(client._transport.mock.calls[5][0].data).toContain('<id xsi:type=\"xsd:string\">4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=</id><lastLogId xsi:type=\"xsd:int\">1511</lastLogId><maxLogCount xsi:type=\"xsd:int\">100</maxLogCount></m:GetStatus>');
557
+ expect(job).toMatchObject({
558
+ jobId: "4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=",
559
+ lastLogId: 1513,
560
+ iRc: 16384,
561
+ lastErrorCode: "DLV-490009",
562
+ firstErrorCode: "DLV-490009"
563
+ })
564
+ expect(status).toMatchObject({
565
+ status: 3,
566
+ logs: [
567
+ { iRc: 0, id: 1511, logDate: new Date(1668875419140), logType: 2, message: "Target preparation in progress...", object: "" },
568
+ { iRc: 16384, id: 1513, logDate: new Date(1668875419820), logType: 0, errorCode: "DLV-490009", message: "You have not defined the target population of the delivery action.", object: "test" },
569
+ ],
570
+ properties: { warning: true, progress: { current: 231, max: 231 } }
571
+ });
572
+ expect(job.status).toMatchObject({
573
+ status: 3,
574
+ logs: [
575
+ { iRc: 0, id: 1511, logDate: new Date(1668875419140), logType: 2, message: "Target preparation in progress...", object: "" },
576
+ { iRc: 16384, id: 1513, logDate: new Date(1668875419820), logType: 0, errorCode: "DLV-490009", message: "You have not defined the target population of the delivery action.", object: "test" },
577
+ ],
578
+ properties: { warning: true, progress: { current: 231, max: 231 } }
579
+ });
580
+
581
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
582
+ await client.NLWS.xtkSession.logoff();
583
+
584
+ });
585
+
586
+ });
587
+
588
+ describe("Pausing anc Cancelling", () => {
589
+ it("Should pause job", async () => {
590
+ const client = { NLWS: { xtkJob: { pause: jest.fn() } } };
591
+ const job = new XtkJobInterface(client);
592
+ job.jobId = "ABC";
593
+ await job.pause();
594
+ expect(client.NLWS.xtkJob.pause.mock.calls.length).toBe(1);
595
+ expect(client.NLWS.xtkJob.pause.mock.calls[0]).toEqual(["ABC"]);
596
+ });
597
+
598
+ it("Should cancel job", async () => {
599
+ const client = { NLWS: { xtkJob: { cancel: jest.fn() } } };
600
+ const job = new XtkJobInterface(client);
601
+ job.jobId = "ABC";
602
+ await job.cancel();
603
+ expect(client.NLWS.xtkJob.cancel.mock.calls.length).toBe(1);
604
+ expect(client.NLWS.xtkJob.cancel.mock.calls[0]).toEqual(["ABC"]);
605
+ });
606
+
607
+ it("Should waitJobCancelled job", async () => {
608
+ const client = { NLWS: { xtkJob: { waitJobCancelled: jest.fn() } } };
609
+ const job = new XtkJobInterface(client);
610
+ job.jobId = "ABC";
611
+ await job.waitJobCancelled(7);
612
+ expect(client.NLWS.xtkJob.waitJobCancelled.mock.calls.length).toBe(1);
613
+ expect(client.NLWS.xtkJob.waitJobCancelled.mock.calls[0]).toEqual(["ABC", 7]);
614
+ });
615
+
616
+ it("Should test if job has warnings", async () => {
617
+ const client = { NLWS: { xtkJob: { hasWarning: jest.fn() } } };
618
+ const job = new XtkJobInterface(client);
619
+ job.jobId = "ABC";
620
+ client.NLWS.xtkJob.hasWarning.mockReturnValueOnce(1);
621
+ const hasWarning = await job.hasWarning();
622
+ expect(hasWarning).toBe(true);
623
+ expect(client.NLWS.xtkJob.hasWarning.mock.calls.length).toBe(1);
624
+ expect(client.NLWS.xtkJob.hasWarning.mock.calls[0]).toEqual(["ABC"]);
625
+ });
626
+ });
627
+
628
+
629
+ describe("XML Representation", () => {
630
+ it("Should submit an delivery preparation and get status", async () => {
631
+ const client = await Mock.makeClient({ representation: "xml" });
632
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
633
+ await client.NLWS.xtkSession.logon();
634
+ const job = client.jobInterface({
635
+ xtkschema: 'nms:delivery',
636
+ method: 'Prepare',
637
+ object: DomUtil.parse('<delivery></delivery>'), // In reality should be an actual delivery object. Not passed here to simplify the test
638
+ });
639
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_JOB_SCHEMA_RESPONSE);
640
+ client._transport.mockReturnValueOnce(MOCK_SUBMIT_JOB_RESPONSE("4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM="));
641
+ jobId = await job.submit();
642
+
643
+ // First call to get status returns the status and a no logs
644
+ client._transport.mockReturnValueOnce(MOCK_GETSTATUS1_RESPONSE(2, 0, 0, true));
645
+ var status = await job.getStatus();
646
+ expect(client._transport).toHaveBeenCalledTimes(4); // Logon, GetSchema(xtk:job), Submit, GetStatus
647
+ expect(client._transport.mock.calls[3][0].data).toContain('<id xsi:type=\"xsd:string\">4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=</id><lastLogId xsi:type=\"xsd:int\">0</lastLogId><maxLogCount xsi:type=\"xsd:int\">100</maxLogCount></m:GetStatus>');
648
+ expect(job).toMatchObject({
649
+ jobId: "4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=",
650
+ lastLogId: 0,
651
+ iRc: 0
652
+ })
653
+ expect(status).toMatchObject({
654
+ status: 2,
655
+ logs: [],
656
+ properties: { warning: true, progress: { current: 0, max: 0 } }
657
+ });
658
+
659
+ // Call GetStatus again, adding some logs and making some progress
660
+ client._transport.mockReturnValueOnce(MOCK_GETSTATUS1_RESPONSE(2, 50, 231, true, '<log iRc="0" id="1511" logDate="2022-11-19 16:30:19.140Z" logType="2" message="Target preparation in progress..." object=""/>'));
661
+ var status = await job.getStatus();
662
+ expect(client._transport).toHaveBeenCalledTimes(5); // Logon, GetSchema(xtk:job), Submit, GetStatus, GetStatus
663
+ expect(client._transport.mock.calls[4][0].data).toContain('<id xsi:type=\"xsd:string\">4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=</id><lastLogId xsi:type=\"xsd:int\">0</lastLogId><maxLogCount xsi:type=\"xsd:int\">100</maxLogCount></m:GetStatus>');
664
+ expect(job).toMatchObject({
665
+ jobId: "4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=",
666
+ lastLogId: 1511,
667
+ iRc: 0
668
+ })
669
+ expect(status).toMatchObject({
670
+ status: 2,
671
+ logs: [
672
+ { iRc: 0, id: 1511, logDate: new Date(1668875419140), logType: 2, message: "Target preparation in progress...", object: "" }
673
+ ],
674
+ properties: { warning: true, progress: { current: 50, max: 231 } }
675
+ });
676
+
677
+ // Call GetStatus again, adding some logs and making some progress and change status
678
+ client._transport.mockReturnValueOnce(MOCK_GETSTATUS1_RESPONSE(3, 231, 231, true, '<log iRc="16384" id="1513" logDate="2022-11-19 16:30:19.820Z" logType="0" message="DLV-490009 You have not defined the target population of the delivery action." object="test"/>'));
679
+ var status = await job.getStatus();
680
+ expect(client._transport).toHaveBeenCalledTimes(6); // Logon, GetSchema(xtk:job), Submit, GetStatus, GetStatus
681
+ expect(client._transport.mock.calls[5][0].data).toContain('<id xsi:type=\"xsd:string\">4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=</id><lastLogId xsi:type=\"xsd:int\">1511</lastLogId><maxLogCount xsi:type=\"xsd:int\">100</maxLogCount></m:GetStatus>');
682
+ expect(job).toMatchObject({
683
+ jobId: "4210/nms:delivery@@B/C1boHl4jx1AEnDTI4nI137QkcFiiIZf4v++eFsPdM=",
684
+ lastLogId: 1513,
685
+ iRc: 16384,
686
+ lastErrorCode: "DLV-490009",
687
+ firstErrorCode: "DLV-490009"
688
+ })
689
+ expect(status).toMatchObject({
690
+ status: 3,
691
+ logs: [
692
+ { iRc: 0, id: 1511, logDate: new Date(1668875419140), logType: 2, message: "Target preparation in progress...", object: "" },
693
+ { iRc: 16384, id: 1513, logDate: new Date(1668875419820), logType: 0, errorCode: "DLV-490009", message: "You have not defined the target population of the delivery action.", object: "test" },
694
+ ],
695
+ properties: { warning: true, progress: { current: 231, max: 231 } }
696
+ });
697
+ expect(job.status).toMatchObject({
698
+ status: 3,
699
+ logs: [
700
+ { iRc: 0, id: 1511, logDate: new Date(1668875419140), logType: 2, message: "Target preparation in progress...", object: "" },
701
+ { iRc: 16384, id: 1513, logDate: new Date(1668875419820), logType: 0, errorCode: "DLV-490009", message: "You have not defined the target population of the delivery action.", object: "test" },
702
+ ],
703
+ properties: { warning: true, progress: { current: 231, max: 231 } }
704
+ });
705
+
706
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
707
+ await client.NLWS.xtkSession.logoff();
708
+
709
+ });
710
+ });
711
+
712
+
713
+ });