@adobe/acc-js-sdk 1.0.9 → 1.1.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.
@@ -51,7 +51,7 @@ describe('Application', () => {
51
51
  <element name='recipient' label='Recipients2'/>
52
52
  </schema>`);
53
53
  newSchema(xml);
54
- }).toThrow("there's a already a node");
54
+ }).toThrow("Failed to add element 'recipient' to ArrayMap. There's already an item with the same name");
55
55
  });
56
56
 
57
57
  it("Should find root node", () => {
@@ -108,7 +108,7 @@ describe('Application', () => {
108
108
  </schema>`);
109
109
  var schema = newSchema(xml);
110
110
  var root = schema.root;
111
- expect(root.hasChild("@email")).toBe(true);
111
+ expect(!!root.children.get("@email")).toBe(true);
112
112
  var email = root.children["@email"];
113
113
  expect(email).not.toBeNull();
114
114
  expect(email.name).toBe("@email");
@@ -124,8 +124,8 @@ describe('Application', () => {
124
124
  </schema>`);
125
125
  var schema = newSchema(xml);
126
126
  var root = schema.root;
127
- expect(root.hasChild("email")).toBe(false);
128
- expect(root.hasChild("@dummy")).toBe(false);
127
+ expect(!!root.children.get("email")).toBe(false);
128
+ expect(!!root.children.get("@dummy")).toBe(false);
129
129
  });
130
130
 
131
131
  it("Should not find inexistant attribute (@-syntax)", () => {
@@ -136,8 +136,8 @@ describe('Application', () => {
136
136
  </schema>`);
137
137
  var schema = newSchema(xml);
138
138
  var root = schema.root;
139
- expect(root.hasChild("@email")).toBe(true);
140
- expect(root.hasChild("email")).toBe(false);
139
+ expect(!!root.children.get("@email")).toBe(true);
140
+ expect(!!root.children.get("email")).toBe(false);
141
141
  });
142
142
  });
143
143
 
@@ -159,7 +159,7 @@ describe('Application', () => {
159
159
 
160
160
  describe("Find node", () => {
161
161
 
162
- it("Should find nodes", () => {
162
+ it("Should find nodes", async () => {
163
163
  var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
164
164
  <element name='recipient' label='Recipients'>
165
165
  <attribute name='email' label="Email" type='string' length='3'/>
@@ -174,68 +174,50 @@ describe('Application', () => {
174
174
  var root = schema.root;
175
175
 
176
176
  // Relative path
177
- expect(root.findNode("@email").label).toBe("Email");
178
- expect(root.findNode("country").label).toBe("Country");
179
- expect(root.findNode("country/@isoA3").label).toBe("Country name");
180
- expect(root.findNode("country/@country-id").label).toBe("Country id");
181
-
182
- // Not found (defaut behavior throws)
183
- expect(() => { root.findNode("@dummy"); }).toThrow("Unknown attribute 'dummy'");
184
- expect(() => { root.findNode("dummy"); }).toThrow("Unknown element 'dummy'");
185
- expect(() => { root.findNode("dummy/@dummy"); }).toThrow("Unknown element 'dummy'");
186
- expect(() => { root.findNode("country/@dummy"); }).toThrow("Unknown attribute 'dummy'");
187
- expect(() => { root.findNode("country/dummy/@dummy"); }).toThrow("Unknown element 'dummy'");
188
-
189
- // Not found (mustExists=false)
190
- expect(root.findNode("@dummy", true, false)).toBeNull();
191
- expect(root.findNode("dummy", true, false)).toBeNull();
192
- expect(root.findNode("dummy/@dummy", true, false)).toBeNull();
193
- expect(root.findNode("country/@dummy", true, false)).toBeNull();
194
-
177
+ await expect(root.findNode("@email")).resolves.toMatchObject({ label: "Email" });
178
+ await expect(root.findNode("country")).resolves.toMatchObject({ label: "Country" });
179
+ await expect(root.findNode("country/@isoA3")).resolves.toMatchObject({ label: "Country name" });
180
+ await expect(root.findNode("country/@country-id")).resolves.toMatchObject({ label: "Country id" });
181
+
182
+ await expect(root.findNode("@dummy")).resolves.toBeFalsy();
183
+ await expect(root.findNode("dummy")).resolves.toBeFalsy();
184
+ await expect(root.findNode("dummy/@dummy")).resolves.toBeFalsy();
185
+ await expect(root.findNode("country/@dummy")).resolves.toBeFalsy();
186
+ await expect(root.findNode("country/dummy/@dummy")).resolves.toBeFalsy();
187
+
195
188
  // Starting from schema
196
- expect(schema.findNode("recipient").label).toBe('Recipients');
197
-
198
- // Absolute path
199
- expect(root.findNode("/@email").label).toBe("Email");
200
- const country = root.findNode("country");
201
- expect(country.findNode("/@email").label).toBe("Email");
202
- expect(country.findNode("/country").label).toBe("Country");
203
-
189
+ await expect(schema.findNode("recipient")).resolves.toMatchObject({ label: 'Recipients' });
190
+
191
+ // Absolute path (/ means schema root node, not schema node)
192
+ await expect(root.findNode("/@email")).resolves.toMatchObject({ label: "Email" });
193
+ const country = await root.findNode("country");
194
+ await expect(country.findNode("/@email")).resolves.toMatchObject({ label: "Email" });
195
+ await expect(country.findNode("/country")).resolves.toMatchObject({ label: "Country" });
196
+
204
197
  // Self and parent
205
- expect(country.findNode("./@isoA3").label).toBe("Country name");
206
- expect(country.findNode("../@email").label).toBe("Email");
207
- expect(country.findNode(".././@email").label).toBe("Email");
208
- expect(country.findNode("./../@email").label).toBe("Email");
209
- expect(root.findNode("./country/..").label).toBe("Recipients");
210
-
198
+ await expect(country.findNode("./@isoA3")).resolves.toMatchObject({ label: "Country name" });
199
+ await expect(country.findNode("../@email")).resolves.toMatchObject({ label: "Email" });
200
+ await expect(country.findNode(".././@email")).resolves.toMatchObject({ label: "Email" });
201
+ await expect(country.findNode("./../@email")).resolves.toMatchObject({ label: "Email" });
202
+ await expect(root.findNode("./country/..")).resolves.toMatchObject({ label: "Recipients" });
203
+
211
204
  // Special cases
212
- expect(root.findNode("").label).toBe("Recipients");
213
- expect(root.findNode(".").label).toBe("Recipients");
214
-
205
+ await expect(root.findNode("")).resolves.toMatchObject({ label: "Recipients" });
206
+ await expect(root.findNode(".")).resolves.toMatchObject({ label: "Recipients" });
207
+
215
208
  // Non strict
216
- expect(root.findNode("country/@isoA3", false, false).label).toBe("Country name");
217
- expect(root.findNode("country/isoA3", false, false).label).toBe("Country name");
218
- expect(country.findNode("@isoA3", false, false).label).toBe("Country name");
219
- expect(country.findNode("isoA3", false, false).label).toBe("Country name");
220
- expect(country.findNode("@terminal", false, false).label).toBe("Terminal");
221
- expect(country.findNode("terminal", false, false).label).toBe("Terminal");
222
- expect(country.findNode("@notFound", false, false)).toBeNull();
223
- expect(country.findNode("notFound", false, false)).toBeNull();
224
-
225
- // strict
226
- expect(root.findNode("country/@isoA3", true, false).label).toBe("Country name");
227
- expect(root.findNode("country/isoA3", true, false)).toBeNull();
228
- expect(country.findNode("@isoA3", true, false).label).toBe("Country name");
229
- expect(country.findNode("isoA3", true, false)).toBeNull();
230
- expect(country.findNode("@terminal", true, false)).toBeNull();
231
- expect(country.findNode("terminal", true, false).label).toBe("Terminal");
232
- expect(country.findNode("@notFound", true, false)).toBeNull();
233
- expect(country.findNode("notFound", true, false)).toBeNull();
209
+ await expect(root.findNode("country/@isoA3", false, false)).resolves.toMatchObject({ label: "Country name" });
210
+ await expect(root.findNode("country/isoA3", false, false)).resolves.toBeFalsy();
211
+ await expect(country.findNode("@isoA3", false, false)).resolves.toMatchObject({ label: "Country name" });
212
+ await expect(country.findNode("isoA3", false, false)).resolves.toBeFalsy();
213
+ await expect(country.findNode("@terminal", false, false)).resolves.toBeFalsy();
214
+ await expect(country.findNode("terminal", false, false)).resolves.toMatchObject({ label: "Terminal" });
215
+ await expect(country.findNode("@notFound", false, false)).resolves.toBeFalsy();
216
+ await expect(country.findNode("notFound", false, false)).resolves.toBeFalsy();
234
217
  });
235
218
 
236
-
237
- it("Empty or absolute path requires a schema and root node", () => {
238
-
219
+ it("Empty or absolute path requires a schema and root node", async () => {
220
+
239
221
  var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
240
222
  <element name='profile' label='Recipients'>
241
223
  <attribute name='email' label="Email" type='string' length='3'/>
@@ -248,17 +230,17 @@ describe('Application', () => {
248
230
  var schemaNoRoot = newSchema(xml);
249
231
  var root = schemaNoRoot.root;
250
232
  expect(root).toBeUndefined();
251
- expect(() => { schemaNoRoot.findNode("") }).toThrow("does not have a root node");
252
- expect(() => { schemaNoRoot.findNode("/") }).toThrow("does not have a root node");
253
-
254
- var profile = schemaNoRoot.findNode("profile");
233
+ await expect(schemaNoRoot.findNode("")).resolves.toBeFalsy();
234
+ await expect(schemaNoRoot.findNode("/")).resolves.toBeFalsy();
235
+
236
+ var profile = await schemaNoRoot.findNode("profile");
255
237
  expect(profile).toBeTruthy();
256
- expect(profile.findNode("country/@isoA3").label).toBe("Country name");
257
- expect(() => { profile.findNode("/country/@isoA3") }).toThrow("does not have a root node");
258
- expect(() => { profile.findNode("") }).toThrow("does not have a root node");
238
+ await expect(profile.findNode("country/@isoA3")).resolves.toMatchObject({ label: "Country name" });
239
+ await expect(profile.findNode("/country/@isoA3")).resolves.toBeFalsy();
240
+ await expect(profile.findNode("")).resolves.toBeFalsy();
259
241
  });
260
242
 
261
- it("Should find node by xpath", () => {
243
+ it("Should find node by xpath", async () => {
262
244
  var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
263
245
  <element name='recipient' label='Recipients'>
264
246
  <attribute name='email' label="Email" type='string' length='3'/>
@@ -271,7 +253,7 @@ describe('Application', () => {
271
253
  var schema = newSchema(xml);
272
254
  var root = schema.root;
273
255
 
274
- expect(root.findNode(new XPath("@email")).label).toBe("Email");
256
+ await expect(root.findNode(new XPath("@email"))).resolves.toMatchObject({ label: "Email" });
275
257
  });
276
258
  });
277
259
 
@@ -285,10 +267,53 @@ describe('Application', () => {
285
267
  var schema = newSchema(xml);
286
268
  var enumerations = schema.enumerations;
287
269
  expect(enumerations.gender.dummy).toBeFalsy();
288
- expect(enumerations.gender.name).toBe("gender");
289
- expect(enumerations.status.name).toBe("status");
270
+ expect(enumerations.gender.shortName).toBe("gender");
271
+ expect(enumerations.status.shortName).toBe("status");
272
+ expect(enumerations.gender.name).toBe("nms:recipient:gender");
273
+ expect(enumerations.status.name).toBe("nms:recipient:status");
290
274
  });
291
275
 
276
+ it("Should support forEach and map", () => {
277
+ const xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
278
+ <enumeration name="gender" basetype="byte"/>
279
+ <enumeration name="status" basetype="byte"/>
280
+ <element name='recipient' label='Recipients'></element>
281
+ </schema>`);
282
+ const schema = newSchema(xml);
283
+ const enumerations = schema.enumerations;
284
+
285
+ // Use forEach to concatenate enumeration names
286
+ let cat = "";
287
+ enumerations.forEach(e => cat = cat + e.name);
288
+ expect(cat).toBe("nms:recipient:gendernms:recipient:status");
289
+
290
+ // Use map to get get an array of enumeration names
291
+ expect(enumerations.map(e => e.name).join(',')).toBe("nms:recipient:gender,nms:recipient:status");
292
+ });
293
+
294
+ it("Should support index based access", () => {
295
+ const xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
296
+ <enumeration name="gender" basetype="byte"/>
297
+ <enumeration name="status" basetype="byte"/>
298
+ <element name='recipient' label='Recipients'></element>
299
+ </schema>`);
300
+ const schema = newSchema(xml);
301
+ const enumerations = schema.enumerations;
302
+ expect(enumerations[0].name).toBe("nms:recipient:gender");
303
+ expect(enumerations[1].name).toBe("nms:recipient:status");
304
+
305
+ // Use a for-loop
306
+ let cat = "";
307
+ for (let i=0; i<enumerations.length; i++)
308
+ cat = cat + enumerations[i].name;
309
+ expect(cat).toBe("nms:recipient:gendernms:recipient:status");
310
+
311
+ // Use the for ... of iterator
312
+ cat = "";
313
+ for (const enumeration of enumerations)
314
+ cat = cat + enumeration.name;
315
+ });
316
+
292
317
  it("Should set default label", () => {
293
318
  const xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
294
319
  <enumeration name="gender" basetype="byte"/>
@@ -297,8 +322,8 @@ describe('Application', () => {
297
322
  </schema>`);
298
323
  const schema = newSchema(xml);
299
324
  const enumerations = schema.enumerations;
300
- expect(enumerations.gender.label).toBe("Gender");
301
- expect(enumerations.status.label).toBe("Status code");
325
+ expect(enumerations[0].label).toBe("Gender");
326
+ expect(enumerations[1].label).toBe("Status code");
302
327
  });
303
328
 
304
329
  it("Should test images", () => {
@@ -323,13 +348,13 @@ describe('Application', () => {
323
348
  var schema = newSchema(xml);
324
349
  var enumerations = schema.enumerations;
325
350
  // no img attribute
326
- expect(enumerations.gender.name).toBe("gender");
351
+ expect(enumerations.gender.name).toBe("nms:recipient:gender");
327
352
  expect(enumerations.gender.hasImage).toBe(false);
328
353
  // at least one img attribute
329
- expect(enumerations.status.name).toBe("status");
354
+ expect(enumerations.status.name).toBe("nms:recipient:status");
330
355
  expect(enumerations.status.hasImage).toBe(true);
331
356
  // at least one img attribute
332
- expect(enumerations.status2.name).toBe("status2");
357
+ expect(enumerations.status2.name).toBe("nms:recipient:status2");
333
358
  expect(enumerations.status2.hasImage).toBe(false);
334
359
  expect(schema.root.children["@gender"].enum).toBe("nms:recipient:gender");
335
360
  })
@@ -349,6 +374,46 @@ describe('Application', () => {
349
374
  expect(enumerations.status.values.customer.label).toBe("Client");
350
375
  })
351
376
 
377
+ it("Should support forEach and map on enumeration values", () => {
378
+ const xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
379
+ <enumeration name="gender" basetype="byte"/>
380
+ <enumeration name="status" basetype="byte">
381
+ <value name="prospect" label="Prospect" value="0"/>
382
+ <value name="customer" label="Client" value="1"/>
383
+ </enumeration>
384
+ <element name='recipient' label='Recipients'></element>
385
+ </schema>`);
386
+ const schema = newSchema(xml);
387
+ const enumerations = schema.enumerations;
388
+ const status = enumerations.status.values;
389
+
390
+
391
+ // Use forEach to concatenate enumeration names
392
+ let cat = "";
393
+ status.forEach(e => cat = cat + e.name);
394
+ expect(cat).toBe("prospectcustomer");
395
+
396
+ // Use map to get get an array of enumeration names
397
+ expect(status.map(e => e.name).join(',')).toBe("prospect,customer");
398
+ });
399
+
400
+
401
+ it("Should support index based access", () => {
402
+ const xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
403
+ <enumeration name="gender" basetype="byte"/>
404
+ <enumeration name="status" basetype="byte">
405
+ <value name="prospect" label="Prospect" value="0"/>
406
+ <value name="customer" label="Client" value="1"/>
407
+ </enumeration>
408
+ <element name='recipient' label='Recipients'></element>
409
+ </schema>`);
410
+ const schema = newSchema(xml);
411
+ const enumerations = schema.enumerations;
412
+ const status = enumerations.status.values;
413
+ expect(status[0].name).toBe("prospect");
414
+ expect(status[1].name).toBe("customer");
415
+ });
416
+
352
417
  it("Should set default label", () => {
353
418
  const xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
354
419
  <enumeration name="gender" basetype="byte"/>
@@ -361,8 +426,8 @@ describe('Application', () => {
361
426
  const schema = newSchema(xml);
362
427
  const enumerations = schema.enumerations;
363
428
  const status = enumerations.status.values;
364
- expect(status.prospect.label).toBe("Prospect");
365
- expect(status.customer.label).toBe("Client");
429
+ expect(status[0].label).toBe("Prospect");
430
+ expect(status[1].label).toBe("Client");
366
431
  });
367
432
 
368
433
  it("Byte enumerations", () => {
@@ -395,6 +460,227 @@ describe('Application', () => {
395
460
  var enumerations = schema.enumerations;
396
461
  expect(enumerations.instanceType.default.value).toBe(1);
397
462
  });
463
+
464
+ describe("Using application.getSysEnum", () => {
465
+
466
+ it("Should find simple enumeration (from schema id)", async () => {
467
+ const client = await Mock.makeClient();
468
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
469
+ await client.NLWS.xtkSession.logon();
470
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
471
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
472
+ <SOAP-ENV:Body>
473
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
474
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
475
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
476
+ <enumeration basetype="byte" name="instanceType" default="1" label="Instance type">
477
+ <value label="One-off event" name="single" value="0"/>
478
+ <value label="Reference recurrence" name="master" value="1"/>
479
+ <value label="Instance of a recurrence" name="instance" value="2"/>
480
+ <value label="Exception to a recurrence" name="exception" value="3"/>
481
+ </enumeration>
482
+ </schema>
483
+ </pdomDoc>
484
+ </GetEntityIfMoreRecentResponse>
485
+ </SOAP-ENV:Body>
486
+ </SOAP-ENV:Envelope>`));
487
+ const enumeration = await client.application.getSysEnum("instanceType", "nms:profile");
488
+ expect(enumeration.label).toBe("Instance type");
489
+ });
490
+
491
+ it("Should find node enumeration", async () => {
492
+ const client = await Mock.makeClient();
493
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
494
+ await client.NLWS.xtkSession.logon();
495
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
496
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
497
+ <SOAP-ENV:Body>
498
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
499
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
500
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
501
+ <enumeration basetype="byte" name="instanceType" default="1" label="Instance type">
502
+ <value label="One-off event" name="single" value="0"/>
503
+ <value label="Reference recurrence" name="master" value="1"/>
504
+ <value label="Instance of a recurrence" name="instance" value="2"/>
505
+ <value label="Exception to a recurrence" name="exception" value="3"/>
506
+ </enumeration>
507
+ <element name="profile">
508
+ <attribute name="e" enum="instanceType"/>
509
+ <attribute name="a"/>
510
+ </element>
511
+ </schema>
512
+ </pdomDoc>
513
+ </GetEntityIfMoreRecentResponse>
514
+ </SOAP-ENV:Body>
515
+ </SOAP-ENV:Envelope>`));
516
+ const schema = await client.application.getSchema("nms:profile");
517
+ const e = await schema.findNode('/@e');
518
+ expect(e.enum).toBe("instanceType");
519
+ let enumeration = await e.enumeration();
520
+ expect(enumeration.name).toBe("nms:profile:instanceType");
521
+ // It's possible to pass the name
522
+ enumeration = await e.enumeration("instanceType");
523
+ expect(enumeration.name).toBe("nms:profile:instanceType");
524
+ // Should support the case when attirbute is not an enumeration
525
+ const a = await schema.findNode('/@a');
526
+ enumeration = await a.enumeration("instanceType");
527
+ expect(enumeration.name).toBe("nms:profile:instanceType");
528
+ enumeration = await a.enumeration();
529
+ expect(enumeration).toBeUndefined();
530
+ });
531
+
532
+ it("Should find simple enumeration (from schema)", async () => {
533
+ const client = await Mock.makeClient();
534
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
535
+ await client.NLWS.xtkSession.logon();
536
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
537
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
538
+ <SOAP-ENV:Body>
539
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
540
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
541
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
542
+ <enumeration basetype="byte" name="instanceType" default="1" label="Instance type">
543
+ <value label="One-off event" name="single" value="0"/>
544
+ <value label="Reference recurrence" name="master" value="1"/>
545
+ <value label="Instance of a recurrence" name="instance" value="2"/>
546
+ <value label="Exception to a recurrence" name="exception" value="3"/>
547
+ </enumeration>
548
+ </schema>
549
+ </pdomDoc>
550
+ </GetEntityIfMoreRecentResponse>
551
+ </SOAP-ENV:Body>
552
+ </SOAP-ENV:Envelope>`));
553
+ const schema = await client.application.getSchema("nms:profile");
554
+ const enumeration = await client.application.getSysEnum("instanceType", schema);
555
+ expect(enumeration.label).toBe("Instance type");
556
+ });
557
+
558
+ it("Should find fully qualified enumeration (in the same schema)", async () => {
559
+ const client = await Mock.makeClient();
560
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
561
+ await client.NLWS.xtkSession.logon();
562
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
563
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
564
+ <SOAP-ENV:Body>
565
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
566
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
567
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
568
+ <enumeration basetype="byte" name="instanceType" default="1" label="Instance type">
569
+ <value label="One-off event" name="single" value="0"/>
570
+ <value label="Reference recurrence" name="master" value="1"/>
571
+ <value label="Instance of a recurrence" name="instance" value="2"/>
572
+ <value label="Exception to a recurrence" name="exception" value="3"/>
573
+ </enumeration>
574
+ </schema>
575
+ </pdomDoc>
576
+ </GetEntityIfMoreRecentResponse>
577
+ </SOAP-ENV:Body>
578
+ </SOAP-ENV:Envelope>`));
579
+ const schema = await client.application.getSchema("nms:profile");
580
+ const enumeration = await client.application.getSysEnum("nms:profile:instanceType", schema);
581
+ expect(enumeration.label).toBe("Instance type");
582
+ });
583
+
584
+ it("Should find fully qualified enumeration (in a different schema)", async () => {
585
+ const client = await Mock.makeClient();
586
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
587
+ await client.NLWS.xtkSession.logon();
588
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
589
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
590
+ <SOAP-ENV:Body>
591
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
592
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
593
+ <schema name="recipient" namespace="nms" xtkschema="xtk:schema">
594
+ <element name="recipient">
595
+ <attribute name="status" enum="nms:profile:instanceType"/>
596
+ </element>
597
+ </schema>
598
+ </pdomDoc>
599
+ </GetEntityIfMoreRecentResponse>
600
+ </SOAP-ENV:Body>
601
+ </SOAP-ENV:Envelope>`));
602
+ const schema = await client.application.getSchema("nms:recipient");
603
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
604
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
605
+ <SOAP-ENV:Body>
606
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
607
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
608
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
609
+ <enumeration basetype="byte" name="instanceType" default="1" label="Instance type">
610
+ <value label="One-off event" name="single" value="0"/>
611
+ <value label="Reference recurrence" name="master" value="1"/>
612
+ <value label="Instance of a recurrence" name="instance" value="2"/>
613
+ <value label="Exception to a recurrence" name="exception" value="3"/>
614
+ </enumeration>
615
+ </schema>
616
+ </pdomDoc>
617
+ </GetEntityIfMoreRecentResponse>
618
+ </SOAP-ENV:Body>
619
+ </SOAP-ENV:Envelope>`));
620
+ const node = await schema.root.findNode("@status");
621
+ const enumeration = await client.application.getSysEnum(node.enum, schema);
622
+ expect(enumeration.label).toBe("Instance type");
623
+ });
624
+
625
+ it("Should fail if malformed enumeration name", async () => {
626
+ const client = await Mock.makeClient();
627
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
628
+ await client.NLWS.xtkSession.logon();
629
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
630
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
631
+ <SOAP-ENV:Body>
632
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
633
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
634
+ <schema name="recipient" namespace="nms" xtkschema="xtk:schema">
635
+ <element name="recipient">
636
+ <attribute name="status" enum="nms:profile:instanceType"/>
637
+ </element>
638
+ </schema>
639
+ </pdomDoc>
640
+ </GetEntityIfMoreRecentResponse>
641
+ </SOAP-ENV:Body>
642
+ </SOAP-ENV:Envelope>`));
643
+ const schema = await client.application.getSchema("nms:recipient");
644
+ await expect(client.application.getSysEnum("nms:profile", schema)).rejects.toMatchObject({ message: "Invalid enumeration name 'nms:profile': expecting {name} or {schemaId}:{name}" });
645
+ });
646
+
647
+ it("Should not find enumeration if schema is missing", async () => {
648
+ const client = await Mock.makeClient();
649
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
650
+ await client.NLWS.xtkSession.logon();
651
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
652
+ const enumeration = await client.application.getSysEnum("instanceType", "nms:profile");
653
+ expect(enumeration).toBeFalsy();
654
+ });
655
+
656
+ it("Should not find enumeration if no schema", async () => {
657
+ const client = await Mock.makeClient();
658
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
659
+ await client.NLWS.xtkSession.logon();
660
+ let enumeration = await client.application.getSysEnum("instanceType", undefined);
661
+ expect(enumeration).toBeFalsy();
662
+ enumeration = await client.application.getSysEnum("instanceType", null);
663
+ expect(enumeration).toBeFalsy();
664
+ });
665
+
666
+ it("Should not find enumeration if schema is missing (local enum)", async () => {
667
+ const client = await Mock.makeClient();
668
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
669
+ await client.NLWS.xtkSession.logon();
670
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
671
+ const enumeration = await client.application.getSysEnum("instanceType", "nms:profile");
672
+ expect(enumeration).toBeFalsy();
673
+ });
674
+
675
+ it("Should not find enumeration if schema is missing (fully qualified enum)", async () => {
676
+ const client = await Mock.makeClient();
677
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
678
+ await client.NLWS.xtkSession.logon();
679
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
680
+ const enumeration = await client.application.getSysEnum("nms:recipient:instanceType", "nms:profile");
681
+ expect(enumeration).toBeFalsy();
682
+ });
683
+ });
398
684
  });
399
685
 
400
686
  describe("Keys", () => {
@@ -425,6 +711,60 @@ describe('Application', () => {
425
711
  </schema>`);
426
712
  expect(() => { newSchema(xml) }).toThrow("keyfield does not have an xpath attribute");
427
713
  });
714
+
715
+ it("Should ignore missing xpaths", () => {
716
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
717
+ <element name='recipient' label='Recipients'>
718
+ <key name="test">
719
+ <keyfield xpath="@nontFound"/>
720
+ </key>
721
+ </element>
722
+ </schema>`);
723
+ var schema = newSchema(xml);
724
+ var root = schema.root;
725
+ expect(root.keys.test).toBeTruthy();
726
+ expect(root.keys.test.fields["nontFound"]).toBeFalsy();
727
+ });
728
+
729
+ it("Should get first key (internal & external)", () => {
730
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
731
+ <element name='recipient' label='Recipients'>
732
+ <key name="key1">
733
+ <keyfield xpath="@email"/>
734
+ </key>
735
+ <key name="key2" internal="true">
736
+ <keyfield xpath="@id"/>
737
+ </key>
738
+ <attribute name='id' type='string'/>
739
+ <attribute name='email' type='string'/>
740
+ </element>
741
+ </schema>`);
742
+ var schema = newSchema(xml);
743
+ var root = schema.root;
744
+ expect(root.firstInternalKeyDef()).toMatchObject({ name: 'key2', isInternal: true });
745
+ expect(root.firstExternalKeyDef()).toMatchObject({ name: 'key1', isInternal: false });
746
+ expect(root.firstKeyDef()).toMatchObject({ name: 'key2', isInternal: true });
747
+ });
748
+
749
+ it("Should get first key (external only)", () => {
750
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
751
+ <element name='recipient' label='Recipients'>
752
+ <key name="key1">
753
+ <keyfield xpath="@email"/>
754
+ </key>
755
+ <key name="key2">
756
+ <keyfield xpath="@id"/>
757
+ </key>
758
+ <attribute name='id' type='string'/>
759
+ <attribute name='email' type='string'/>
760
+ </element>
761
+ </schema>`);
762
+ var schema = newSchema(xml);
763
+ var root = schema.root;
764
+ expect(root.firstInternalKeyDef()).toBeUndefined();
765
+ expect(root.firstExternalKeyDef()).toMatchObject({ name: 'key1', isInternal: false });
766
+ expect(root.firstKeyDef()).toMatchObject({ name: 'key1', isInternal: false });
767
+ });
428
768
  });
429
769
 
430
770
  describe("Link", () => {
@@ -460,6 +800,369 @@ describe('Application', () => {
460
800
  link = schema.root.children["emailInfo"];
461
801
  expect(link.isUnbound()).toBe(false);
462
802
  });
803
+
804
+ it("Should get target", async() => {
805
+ const client = await Mock.makeClient();
806
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
807
+ await client.NLWS.xtkSession.logon();
808
+
809
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
810
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
811
+ <SOAP-ENV:Body>
812
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
813
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
814
+ <schema namespace='nms' name='recipient'>
815
+ <element name='recipient' label='Recipients'>
816
+ <element name="country" type="link" target="nms:country"/>
817
+ </element>
818
+ </schema>
819
+ </pdomDoc>
820
+ </GetEntityIfMoreRecentResponse>
821
+ </SOAP-ENV:Body>
822
+ </SOAP-ENV:Envelope>`));
823
+ const recipient = await client.application.getSchema('nms:recipient');
824
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
825
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
826
+ <SOAP-ENV:Body>
827
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
828
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
829
+ <schema namespace='nms' name='country'>
830
+ <element name='country' label="The Country">
831
+ <attribute name="isoA3" label="Country code"/>
832
+ </element>
833
+ </schema>
834
+ </pdomDoc>
835
+ </GetEntityIfMoreRecentResponse>
836
+ </SOAP-ENV:Body>
837
+ </SOAP-ENV:Envelope>`));
838
+ const country = await recipient.root.findNode("country");
839
+ expect(country.target).toBe("nms:country");
840
+ const target = await country.linkTarget();
841
+ expect(target.label).toBe("The Country");
842
+ })
843
+ });
844
+
845
+ describe("Joins", () => {
846
+
847
+ it("Should find join nodes", async () => {
848
+ // The schema in the ref does not exist
849
+ const client = await Mock.makeClient();
850
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
851
+ await client.NLWS.xtkSession.logon();
852
+
853
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
854
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
855
+ <SOAP-ENV:Body>
856
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
857
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
858
+ <schema namespace='nms' name='recipient'>
859
+ <element name='recipient'>
860
+ <element integrity="neutral" label="Info on the email" name="emailInfo" target="nms:address" type="link" unbound="true">
861
+ <join xpath-dst="@address" xpath-src="@email"/>
862
+ <join xpath-dst="@dst" xpath-src="@source"/>
863
+ </element>
864
+ <attribute name="email"/>
865
+ <attribute name="source"/>
866
+ </element>
867
+ </schema>
868
+ </pdomDoc>
869
+ </GetEntityIfMoreRecentResponse>
870
+ </SOAP-ENV:Body>
871
+ </SOAP-ENV:Envelope>`));
872
+ const recipient = await client.application.getSchema('nms:recipient');
873
+ expect(recipient).toBeTruthy();
874
+
875
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
876
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
877
+ <SOAP-ENV:Body>
878
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
879
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
880
+ <schema namespace='nms' name='address'>
881
+ <element name='address'>
882
+ <attribute name="dst"/>
883
+ <attribute name="address"/>
884
+ </element>
885
+ </schema>
886
+ </pdomDoc>
887
+ </GetEntityIfMoreRecentResponse>
888
+ </SOAP-ENV:Body>
889
+ </SOAP-ENV:Envelope>`));
890
+ const address = await client.application.getSchema('nms:address');
891
+ expect(address).toBeTruthy();
892
+
893
+ // Check link attributes
894
+ const link = await recipient.root.findNode("emailInfo");
895
+ expect(link.isExternalJoin).toBe(false);
896
+
897
+ // "joins" gives a description of the link source and destination xpaths
898
+ expect(link.joins.length).toBe(2);
899
+ expect(link.joins).toMatchObject([ { src: "@email", dst: "@address" }, { src: "@source", dst: "@dst" } ]);
900
+
901
+ // "joinNodes" will lookup the corresponding nodes in the source and target schemas
902
+ const nodes = await link.joinNodes();
903
+ expect(nodes.length).toBe(2);
904
+ expect(nodes[0].source).toMatchObject({ name:"@email", label: "Email" });
905
+ expect(nodes[0].destination).toMatchObject({ name:"@address", label: "Address" });
906
+ expect(nodes[1].source).toMatchObject({ name:"@source", label: "Source" });
907
+ expect(nodes[1].destination).toMatchObject({ name:"@dst", label: "Dst" });
908
+ });
909
+
910
+ it("Should find join nodes with paths", async () => {
911
+ // The schema in the ref does not exist
912
+ const client = await Mock.makeClient();
913
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
914
+ await client.NLWS.xtkSession.logon();
915
+
916
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
917
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
918
+ <SOAP-ENV:Body>
919
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
920
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
921
+ <schema namespace='nms' name='recipient'>
922
+ <element name='recipient'>
923
+ <element name="countryLink" type="link" externalJoin="true" target="nms:country" revLink="operator" revIntegrity="normal">
924
+ <join xpath-dst="@isoA2" xpath-src="location/@countryCode"/>
925
+ </element>
926
+ <element name="location">
927
+ <attribute name="countryCode" label="Country Code"/>
928
+ </element>
929
+ </element>
930
+ </schema>
931
+ </pdomDoc>
932
+ </GetEntityIfMoreRecentResponse>
933
+ </SOAP-ENV:Body>
934
+ </SOAP-ENV:Envelope>`));
935
+ const recipient = await client.application.getSchema('nms:recipient');
936
+ expect(recipient).toBeTruthy();
937
+
938
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
939
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
940
+ <SOAP-ENV:Body>
941
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
942
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
943
+ <schema namespace='nms' name='country'>
944
+ <element name='country'>
945
+ <attribute name="isoA2"/>
946
+ </element>
947
+ </schema>
948
+ </pdomDoc>
949
+ </GetEntityIfMoreRecentResponse>
950
+ </SOAP-ENV:Body>
951
+ </SOAP-ENV:Envelope>`));
952
+ const country = await client.application.getSchema('nms:country');
953
+ expect(country).toBeTruthy();
954
+
955
+ // Check link attributes
956
+ const link = await recipient.root.findNode("countryLink");
957
+ expect(link.isExternalJoin).toBe(true);
958
+
959
+ // "joins" gives a description of the link source and destination xpaths
960
+ expect(link.joins.length).toBe(1);
961
+ expect(link.joins).toMatchObject([ { src: "location/@countryCode", dst: "@isoA2" } ]);
962
+
963
+ // "joinNodes" will lookup the corresponding nodes in the source and target schemas
964
+ const nodes = await link.joinNodes();
965
+ expect(nodes.length).toBe(1);
966
+ expect(nodes[0].source).toMatchObject({ name:"@countryCode", label: "Country Code" });
967
+ expect(nodes[0].destination).toMatchObject({ name:"@isoA2", label: "IsoA2" });
968
+ });
969
+
970
+ it("Should support empty joins", async () => {
971
+ const client = await Mock.makeClient();
972
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
973
+ await client.NLWS.xtkSession.logon();
974
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
975
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
976
+ <SOAP-ENV:Body>
977
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
978
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
979
+ <schema namespace='nms' name='recipient'>
980
+ <element name='recipient'>
981
+ <element name="countryLink" type="link" target="nms:country">
982
+ </element>
983
+ </element>
984
+ </schema>
985
+ </pdomDoc>
986
+ </GetEntityIfMoreRecentResponse>
987
+ </SOAP-ENV:Body>
988
+ </SOAP-ENV:Envelope>`));
989
+ const recipient = await client.application.getSchema('nms:recipient');
990
+ expect(recipient).toBeTruthy();
991
+ const link = await recipient.root.findNode("countryLink");
992
+ expect(link.joins).toMatchObject([]);
993
+ const nodes = await link.joinNodes();
994
+ expect(nodes).toMatchObject([]);
995
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
996
+ const reverseLink = await link.reverseLink();
997
+ expect(reverseLink).toBeFalsy();
998
+ });
999
+
1000
+ it("Should support non-links", async () => {
1001
+ const client = await Mock.makeClient();
1002
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1003
+ await client.NLWS.xtkSession.logon();
1004
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1005
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1006
+ <SOAP-ENV:Body>
1007
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1008
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1009
+ <schema namespace='nms' name='recipient'>
1010
+ <element name='recipient'>
1011
+ <element name="countryName" type="string">
1012
+ </element>
1013
+ </element>
1014
+ </schema>
1015
+ </pdomDoc>
1016
+ </GetEntityIfMoreRecentResponse>
1017
+ </SOAP-ENV:Body>
1018
+ </SOAP-ENV:Envelope>`));
1019
+ const recipient = await client.application.getSchema('nms:recipient');
1020
+ expect(recipient).toBeTruthy();
1021
+ const link = await recipient.root.findNode("countryName");
1022
+ expect(link.joins).toMatchObject([]);
1023
+ const nodes = await link.joinNodes();
1024
+ expect(nodes).toBeFalsy();
1025
+ const reverseLink = await link.reverseLink();
1026
+ expect(reverseLink).toBeFalsy();
1027
+ });
1028
+
1029
+ it("Should support missing target schema", async () => {
1030
+ const client = await Mock.makeClient();
1031
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1032
+ await client.NLWS.xtkSession.logon();
1033
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1034
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1035
+ <SOAP-ENV:Body>
1036
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1037
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1038
+ <schema namespace='nms' name='recipient'>
1039
+ <element name='recipient'>
1040
+ <element name="countryLink" type="link" target="cus:missing">
1041
+ </element>
1042
+ </element>
1043
+ </schema>
1044
+ </pdomDoc>
1045
+ </GetEntityIfMoreRecentResponse>
1046
+ </SOAP-ENV:Body>
1047
+ </SOAP-ENV:Envelope>`));
1048
+ const recipient = await client.application.getSchema('nms:recipient');
1049
+ expect(recipient).toBeTruthy();
1050
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
1051
+ const link = await recipient.root.findNode("countryLink");
1052
+ expect(link.joins).toMatchObject([]);
1053
+ const nodes = await link.joinNodes();
1054
+ expect(nodes).toMatchObject([]);
1055
+ const reverseLink = await link.reverseLink();
1056
+ expect(reverseLink).toBeFalsy();
1057
+ });
1058
+
1059
+ it("Should support missing destination", async () => {
1060
+ const client = await Mock.makeClient();
1061
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1062
+ await client.NLWS.xtkSession.logon();
1063
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1064
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1065
+ <SOAP-ENV:Body>
1066
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1067
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1068
+ <schema namespace='nms' name='recipient'>
1069
+ <element name='recipient'>
1070
+ <element name="countryLink" type="link" target="nms:country">
1071
+ <join xpath-dst="@notFound" xpath-src="@countryCode"/>
1072
+ </element>
1073
+ <attribute name="countryCode"/>
1074
+ </element>
1075
+ </schema>
1076
+ </pdomDoc>
1077
+ </GetEntityIfMoreRecentResponse>
1078
+ </SOAP-ENV:Body>
1079
+ </SOAP-ENV:Envelope>`));
1080
+ const recipient = await client.application.getSchema('nms:recipient');
1081
+ expect(recipient).toBeTruthy();
1082
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
1083
+ const link = await recipient.root.findNode("countryLink");
1084
+ expect(link.joins).toMatchObject([ { src:"@countryCode", dst:"@notFound" }]);
1085
+
1086
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1087
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1088
+ <SOAP-ENV:Body>
1089
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1090
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1091
+ <schema namespace='nms' name='country'>
1092
+ <element name='country'>
1093
+ <attribute name="isoA2"/>
1094
+ </element>
1095
+ </schema>
1096
+ </pdomDoc>
1097
+ </GetEntityIfMoreRecentResponse>
1098
+ </SOAP-ENV:Body>
1099
+ </SOAP-ENV:Envelope>`));
1100
+
1101
+ const nodes = await link.joinNodes();
1102
+ expect(nodes).toMatchObject([]);
1103
+ const reverseLink = await link.reverseLink();
1104
+ expect(reverseLink).toBeFalsy();
1105
+ });
1106
+
1107
+ it("Should find the reverse link", async () => {
1108
+ // The schema in the ref does not exist
1109
+ const client = await Mock.makeClient();
1110
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1111
+ await client.NLWS.xtkSession.logon();
1112
+
1113
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1114
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1115
+ <SOAP-ENV:Body>
1116
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1117
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1118
+ <schema namespace='nms' name='recipient'>
1119
+ <element name='recipient'>
1120
+ <element advanced="true" externalJoin="true" label="Info on the email" name="emailInfo" revLink="recipient" target="nms:address" type="link" unbound="false">
1121
+ <join xpath-dst="@address" xpath-src="@email"/>
1122
+ </element>
1123
+ <attribute name="email"/>
1124
+ </element>
1125
+ </schema>
1126
+ </pdomDoc>
1127
+ </GetEntityIfMoreRecentResponse>
1128
+ </SOAP-ENV:Body>
1129
+ </SOAP-ENV:Envelope>`));
1130
+ const recipient = await client.application.getSchema('nms:recipient');
1131
+ expect(recipient).toBeTruthy();
1132
+
1133
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1134
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1135
+ <SOAP-ENV:Body>
1136
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1137
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1138
+ <schema namespace='nms' name='address'>
1139
+ <element name='address'>
1140
+ <element advanced="false" externalJoin="false" label="Recipients" name="recipient" revLink="emailInfo" target="nms:recipient" type="link" unbound="true">
1141
+ <join xpath-dst="@email" xpath-src="@address"/>
1142
+ </element>
1143
+ </element>
1144
+ </schema>
1145
+ </pdomDoc>
1146
+ </GetEntityIfMoreRecentResponse>
1147
+ </SOAP-ENV:Body>
1148
+ </SOAP-ENV:Envelope>`));
1149
+ const address = await client.application.getSchema('nms:address');
1150
+ expect(address).toBeTruthy();
1151
+
1152
+ // Check link attributes
1153
+ const link = await recipient.root.findNode("emailInfo");
1154
+ expect(link.isExternalJoin).toBe(true);
1155
+ expect(link.revLink).toBe("recipient");
1156
+
1157
+ // Check revlink
1158
+ const revLink = await link.reverseLink();
1159
+ expect(revLink).toMatchObject({
1160
+ isExternalJoin: false,
1161
+ revLink: "emailInfo",
1162
+ name: "recipient",
1163
+ joins: [ { src:"@address", dst:"@email" }]
1164
+ });
1165
+ });
463
1166
  });
464
1167
 
465
1168
  describe("getnodepath", () => {
@@ -472,13 +1175,13 @@ describe('Application', () => {
472
1175
  </element>
473
1176
  </element>
474
1177
  </schema>`);
475
- var schema = newSchema(xml);
476
- var root = schema.root;
477
- var email = root.findNode("@email");
478
- var country = root.findNode("country");
479
- var name = country.findNode("@name");
480
-
481
- it("Should support nodePath property", () => {
1178
+
1179
+ it("Should support nodePath property", async () => {
1180
+ var schema = newSchema(xml);
1181
+ var root = schema.root;
1182
+ var email = await root.findNode("@email");
1183
+ var country = await root.findNode("country");
1184
+ var name = await country.findNode("@name");
482
1185
  expect(schema.nodePath).toBe("/recipient");
483
1186
  expect(root.nodePath).toBe("/");
484
1187
  expect(email.nodePath).toBe("/@email");
@@ -486,7 +1189,13 @@ describe('Application', () => {
486
1189
  expect(name.nodePath).toBe("/country/@name");
487
1190
  });
488
1191
 
489
- it("_getNodePath", () => {
1192
+ it("_getNodePath", async () => {
1193
+ var schema = newSchema(xml);
1194
+ var root = schema.root;
1195
+ var email = await root.findNode("@email");
1196
+ var country = await root.findNode("country");
1197
+ var name = await country.findNode("@name");
1198
+
490
1199
  // No parameters => absolute
491
1200
  expect(schema._getNodePath()._path).toBe("/recipient");
492
1201
  expect(root._getNodePath()._path).toBe("/");
@@ -510,6 +1219,641 @@ describe('Application', () => {
510
1219
  });
511
1220
  });
512
1221
 
1222
+ describe("Ref target", () => {
1223
+
1224
+ it("Should follow ref", async () => {
1225
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1226
+ <element name='recipient' label='Recipients'>
1227
+ <element name="myAddress" ref="address"/>
1228
+ </element>
1229
+ <element name='address'>
1230
+ <element name="country">
1231
+ <attribute name='name' label="Country Name"/>
1232
+ </element>
1233
+ </element>
1234
+ </schema>`);
1235
+ var schema = newSchema(xml);
1236
+ // Pointing to the node with ref itself => return it
1237
+ var node = await schema.root.findNode("myAddress");
1238
+ expect(node).toMatchObject({ name:"myAddress", ref:"address", childrenCount:0 });
1239
+ // Follow ref
1240
+ let target = await node.refTarget();
1241
+ expect(target).toMatchObject({ name:"address", ref:"", childrenCount:1 });
1242
+ });
1243
+
1244
+ it("Should support nodes with no ref", async () => {
1245
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1246
+ <element name='address'>
1247
+ <element name="country">
1248
+ <attribute name='name' label="Country Name"/>
1249
+ </element>
1250
+ </element>
1251
+ </schema>`);
1252
+ var schema = newSchema(xml);
1253
+ var node = await schema.findNode("address");
1254
+ var target = await node.refTarget();
1255
+ expect(target).toBeFalsy();
1256
+ });
1257
+ });
1258
+
1259
+ describe("Links", () => {
1260
+ it("Should find link node", async () => {
1261
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1262
+ <element name='recipient' label='Recipients'>
1263
+ <element name="country" type="link" target="nms:country"/>
1264
+ </element>
1265
+ </schema>`);
1266
+ var schema = newSchema(xml);
1267
+ var node = await schema.root.findNode("country");
1268
+ expect(node).toMatchObject({ name:"country", type:"link", childrenCount:0, target:"nms:country" });
1269
+ });
1270
+
1271
+ it("Should fail on invalid link target", async () => {
1272
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1273
+ <element name='recipient' label='Recipients'>
1274
+ <element name="country" type="link" target="country"/>
1275
+ </element>
1276
+ </schema>`);
1277
+ var schema = newSchema(xml);
1278
+ await expect(schema.root.findNode("country/@name")).rejects.toMatchObject({ message: "Cannot find target of link 'country': target is not a valid link target (missing schema id)" });
1279
+ });
1280
+
1281
+ it("Should fail if link target has multiple schemas (like the owner link in nms:operation)", async () => {
1282
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1283
+ <element name='recipient' label='Recipients'>
1284
+ <element name="owner" type="link" target="xtk:opsecurity, xtk:operator"/>
1285
+ </element>
1286
+ </schema>`);
1287
+ var schema = newSchema(xml);
1288
+ await expect(schema.root.findNode("owner/@name")).rejects.toMatchObject({ message: "Cannot find target of link 'xtk:opsecurity, xtk:operator': target has multiple schemas" });
1289
+ });
1290
+
1291
+ it("Should follow link", async () => {
1292
+ // The schema in the ref does not exist
1293
+ const client = await Mock.makeClient();
1294
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1295
+ await client.NLWS.xtkSession.logon();
1296
+
1297
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1298
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1299
+ <SOAP-ENV:Body>
1300
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1301
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1302
+ <schema namespace='nms' name='recipient'>
1303
+ <element name='recipient' label='Recipients'>
1304
+ <element name="country" type="link" target="nms:country"/>
1305
+ </element>
1306
+ </schema>
1307
+ </pdomDoc>
1308
+ </GetEntityIfMoreRecentResponse>
1309
+ </SOAP-ENV:Body>
1310
+ </SOAP-ENV:Envelope>`));
1311
+ const recipient = await client.application.getSchema('nms:recipient');
1312
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1313
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1314
+ <SOAP-ENV:Body>
1315
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1316
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1317
+ <schema namespace='nms' name='country'>
1318
+ <element name='country'>
1319
+ <attribute name="isoA3" label="Country code"/>
1320
+ </element>
1321
+ </schema>
1322
+ </pdomDoc>
1323
+ </GetEntityIfMoreRecentResponse>
1324
+ </SOAP-ENV:Body>
1325
+ </SOAP-ENV:Envelope>`));
1326
+ const isoA3 = await recipient.root.findNode("country/@isoA3");
1327
+ expect(isoA3).toMatchObject({ name:"@isoA3", type:"string", label:"Country code", isAttribute:true, childrenCount:0, target:"" });
1328
+ });
1329
+
1330
+ it("Should follow link pointing to a sub-element", async () => {
1331
+ // The schema in the ref does not exist
1332
+ const client = await Mock.makeClient();
1333
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1334
+ await client.NLWS.xtkSession.logon();
1335
+
1336
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1337
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1338
+ <SOAP-ENV:Body>
1339
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1340
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1341
+ <schema namespace='nms' name='recipient'>
1342
+ <element name='recipient' label='Recipients'>
1343
+ <element name="country" type="link" target="nms:country/test"/>
1344
+ </element>
1345
+ </schema>
1346
+ </pdomDoc>
1347
+ </GetEntityIfMoreRecentResponse>
1348
+ </SOAP-ENV:Body>
1349
+ </SOAP-ENV:Envelope>`));
1350
+ const recipient = await client.application.getSchema('nms:recipient');
1351
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1352
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1353
+ <SOAP-ENV:Body>
1354
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1355
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1356
+ <schema namespace='nms' name='country'>
1357
+ <element name='country'>
1358
+ <attribute name="isoA3" label="Country code"/>
1359
+ <element name="test">
1360
+ <attribute name="isoA3" label="Country code 2"/>
1361
+ </element>
1362
+ </element>
1363
+ </schema>
1364
+ </pdomDoc>
1365
+ </GetEntityIfMoreRecentResponse>
1366
+ </SOAP-ENV:Body>
1367
+ </SOAP-ENV:Envelope>`));
1368
+ const isoA3 = await recipient.root.findNode("country/@isoA3");
1369
+ expect(isoA3).toMatchObject({ name:"@isoA3", type:"string", label:"Country code 2", isAttribute:true, childrenCount:0, target:"" });
1370
+ });
1371
+
1372
+ it("Should find target of non-links", async () => {
1373
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1374
+ <element name='recipient' label='Recipients'>
1375
+ <element name="country"/>
1376
+ </element>
1377
+ </schema>`);
1378
+ var schema = newSchema(xml);
1379
+ var node = await schema.root.findNode("country");
1380
+ node = await node.linkTarget();
1381
+ expect(node).toMatchObject({ name:"recipient" });
1382
+ });
1383
+
1384
+ it("Should support link target schema not found", async () => {
1385
+ // The schema in the ref does not exist
1386
+ const client = await Mock.makeClient();
1387
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1388
+ await client.NLWS.xtkSession.logon();
1389
+
1390
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1391
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1392
+ <SOAP-ENV:Body>
1393
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1394
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1395
+ <schema namespace='nms' name='recipient'>
1396
+ <element name='recipient' label='Recipients'>
1397
+ <element name="country" type="link" target="nms:country"/>
1398
+ </element>
1399
+ </schema>
1400
+ </pdomDoc>
1401
+ </GetEntityIfMoreRecentResponse>
1402
+ </SOAP-ENV:Body>
1403
+ </SOAP-ENV:Envelope>`));
1404
+ const recipient = await client.application.getSchema('nms:recipient');
1405
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
1406
+ const isoA3 = await recipient.root.findNode("country/@isoA3");
1407
+ expect(isoA3).toBeFalsy();
1408
+ });
1409
+
1410
+
1411
+ it("Should support target schema with no root", async () => {
1412
+ // The schema in the ref does not exist
1413
+ const client = await Mock.makeClient();
1414
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1415
+ await client.NLWS.xtkSession.logon();
1416
+
1417
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1418
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1419
+ <SOAP-ENV:Body>
1420
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1421
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1422
+ <schema namespace='nms' name='recipient'>
1423
+ <element name='recipient' label='Recipients'>
1424
+ <element name="country" type="link" target="nms:country/test"/>
1425
+ </element>
1426
+ </schema>
1427
+ </pdomDoc>
1428
+ </GetEntityIfMoreRecentResponse>
1429
+ </SOAP-ENV:Body>
1430
+ </SOAP-ENV:Envelope>`));
1431
+ const recipient = await client.application.getSchema('nms:recipient');
1432
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1433
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1434
+ <SOAP-ENV:Body>
1435
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1436
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1437
+ <schema namespace='nms' name='country'>
1438
+ </schema>
1439
+ </pdomDoc>
1440
+ </GetEntityIfMoreRecentResponse>
1441
+ </SOAP-ENV:Body>
1442
+ </SOAP-ENV:Envelope>`));
1443
+ const isoA3 = await recipient.root.findNode("country/@isoA3");
1444
+ expect(isoA3).toBeFalsy();
1445
+ });
1446
+ });
1447
+
1448
+ describe("Ref nodes", () => {
1449
+ it("Should follow ref elements in same schema (not qualified)", async () => {
1450
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1451
+ <element name='recipient' label='Recipients'>
1452
+ <element name="myAddress" ref="address"/>
1453
+ </element>
1454
+ <element name='address'>
1455
+ <element name="country">
1456
+ <attribute name='name' label="Country Name"/>
1457
+ </element>
1458
+ </element>
1459
+ </schema>`);
1460
+ var schema = newSchema(xml);
1461
+ // Pointing to the node with ref itself => return it
1462
+ var node = await schema.root.findNode("myAddress");
1463
+ expect(node).toMatchObject({ name:"myAddress", ref:"address", childrenCount:0 });
1464
+ // Accessing nodes following the ref
1465
+ node = await schema.root.findNode("myAddress/country");
1466
+ expect(node).toMatchObject({ name:"country", label:"Country", ref:"", childrenCount:1 });
1467
+ node = await schema.root.findNode("myAddress/country/@name");
1468
+ expect(node).toMatchObject({ name:"@name", label:"Country Name", ref:"", childrenCount:0 });
1469
+ });
1470
+ it("Should follow ref elements in same schema (fully qualified)", async () => {
1471
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1472
+ <element name='recipient' label='Recipients'>
1473
+ <element name="myAddress" ref="nms:recipient:address"/>
1474
+ </element>
1475
+ <element name='address'>
1476
+ <element name="country">
1477
+ <attribute name='name' label="Country Name"/>
1478
+ </element>
1479
+ </element>
1480
+ </schema>`);
1481
+ var schema = newSchema(xml);
1482
+ // Pointing to the node with ref itself => return it
1483
+ var node = await schema.root.findNode("myAddress");
1484
+ expect(node).toMatchObject({ name:"myAddress", ref:"nms:recipient:address", childrenCount:0 });
1485
+ // Accessing nodes following the ref
1486
+ node = await schema.root.findNode("myAddress/country");
1487
+ expect(node).toMatchObject({ name:"country", label:"Country", ref:"", childrenCount:1 });
1488
+ node = await schema.root.findNode("myAddress/country/@name");
1489
+ expect(node).toMatchObject({ name:"@name", label:"Country Name", ref:"", childrenCount:0 });
1490
+ });
1491
+
1492
+ it("Should fail on malformed refs", async () => {
1493
+ // Refs should be {schemaId}:{xpath}, meaning at least two ":"
1494
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1495
+ <element name='recipient' label='Recipients'>
1496
+ <element name="myAddress" ref="nms:recipient"/>
1497
+ <attribute name="firstName"/>
1498
+ </element>
1499
+ </schema>`);
1500
+ var schema = newSchema(xml);
1501
+ await expect(schema.root.findNode("myAddress/@firstName")).rejects.toMatchObject({ message: "Cannot find ref target 'nms:recipient' from node '/myAddress' of schema 'nms:recipient': ref value is not correct (expeted <schemaId>:<path>)" });
1502
+ });
1503
+
1504
+ it("Should support inexisting schemas", async () => {
1505
+ // The schema in the ref does not exist
1506
+ const client = await Mock.makeClient();
1507
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1508
+ await client.NLWS.xtkSession.logon();
1509
+
1510
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1511
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1512
+ <SOAP-ENV:Body>
1513
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1514
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1515
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1516
+ <element name="profile">
1517
+ <element name="address" ref="nms:recipient:address"/>
1518
+ </element>
1519
+ </schema>
1520
+ </pdomDoc>
1521
+ </GetEntityIfMoreRecentResponse>
1522
+ </SOAP-ENV:Body>
1523
+ </SOAP-ENV:Envelope>`));
1524
+ const schema = await client.application.getSchema("nms:profile");
1525
+ const address = await schema.root.findNode("address");
1526
+ expect(address.ref).toBe("nms:recipient:address");
1527
+
1528
+ client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
1529
+ const city = await schema.root.findNode("address/@city");
1530
+ expect(city).toBeFalsy();
1531
+ });
1532
+
1533
+ it("Should follow ref elements in a different scheam", async () => {
1534
+ const client = await Mock.makeClient();
1535
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1536
+ await client.NLWS.xtkSession.logon();
1537
+
1538
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1539
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1540
+ <SOAP-ENV:Body>
1541
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1542
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1543
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1544
+ <element name="profile">
1545
+ <element name="address" ref="nms:recipient:address"/>
1546
+ </element>
1547
+ </schema>
1548
+ </pdomDoc>
1549
+ </GetEntityIfMoreRecentResponse>
1550
+ </SOAP-ENV:Body>
1551
+ </SOAP-ENV:Envelope>`));
1552
+ const schema = await client.application.getSchema("nms:profile");
1553
+ const address = await schema.root.findNode("address");
1554
+ expect(address.ref).toBe("nms:recipient:address");
1555
+
1556
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1557
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1558
+ <SOAP-ENV:Body>
1559
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1560
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1561
+ <schema name="recipient" namespace="nms" xtkschema="xtk:schema">
1562
+ <element name="recipient">
1563
+ </element>
1564
+ <element name="address" ref="nms:recipient:address">
1565
+ <attribute name="city"/>
1566
+ </element>
1567
+ </schema>
1568
+ </pdomDoc>
1569
+ </GetEntityIfMoreRecentResponse>
1570
+ </SOAP-ENV:Body>
1571
+ </SOAP-ENV:Envelope>`));
1572
+ const city = await schema.root.findNode("address/@city");
1573
+ expect(city).toMatchObject({ name: "@city" });
1574
+ });
1575
+
1576
+ it("Should find path from ref node", async () => {
1577
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1578
+ <element name='recipient' label='Recipients'>
1579
+ <element name="myAddress" ref="address"/>
1580
+ </element>
1581
+ <element name='address'>
1582
+ <element name="country">
1583
+ <attribute name='name' label="Country Name"/>
1584
+ </element>
1585
+ </element>
1586
+ </schema>`);
1587
+ var schema = newSchema(xml);
1588
+ // Pointing to the node with ref itself => return it
1589
+ var node = await schema.root.findNode("myAddress");
1590
+ expect(node).toMatchObject({ name:"myAddress", ref:"address", childrenCount:0 });
1591
+ // Follow path
1592
+ let target = await node.findNode("country/@name");
1593
+ expect(target).toMatchObject({ name:"@name", ref:"" });
1594
+ });
1595
+ });
1596
+
1597
+ describe("More tests", () => {
1598
+
1599
+ it("Should set label to name with upper case if no label", async () => {
1600
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1601
+ <element name='recipient' label='Recipients'>
1602
+ <attribute name='email' type='string' length='3'/>
1603
+ <element name="country">
1604
+ <attribute name='name'/>
1605
+ </element>
1606
+ </element>
1607
+ </schema>`);
1608
+ var schema = newSchema(xml);
1609
+ var root = schema.root;
1610
+ var node = await root.findNode("@email");
1611
+ expect(node).toMatchObject({ name: "@email", label: "Email", description: "Email", type:"string", nodePath: "/@email" });
1612
+ });
1613
+
1614
+ it("Should have the right children names", async () => {
1615
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
1616
+ <element name='recipient' label='Recipients'>
1617
+ <attribute name='email' type='string' length='3'/>
1618
+ <element name="email"></element>
1619
+ <element name="country">
1620
+ <attribute name='name'/>
1621
+ </element>
1622
+ <attribute name='firstName'/>
1623
+ </element>
1624
+ </schema>`);
1625
+ var schema = newSchema(xml);
1626
+ const names = schema.root.children.map(e => e.name).join(',');
1627
+ expect(names).toBe("@email,email,country,@firstName");
1628
+ });
1629
+
1630
+ it("Should get compute string", async () => {
1631
+ const client = await Mock.makeClient();
1632
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1633
+ await client.NLWS.xtkSession.logon();
1634
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1635
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1636
+ <SOAP-ENV:Body>
1637
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1638
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1639
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1640
+ <element name="profile">
1641
+ <compute-string expr="@lastName + ' ' + @firstName +' (' + @email + ')'"/>
1642
+ <attribute name="firstName"/>
1643
+ <attribute name="lastName"/>
1644
+ <attribute name="email"/>
1645
+ <attribute name="fullName" expr="@lastName + ' ' + @firstName"/>"
1646
+ </element>
1647
+ </schema>
1648
+ </pdomDoc>
1649
+ </GetEntityIfMoreRecentResponse>
1650
+ </SOAP-ENV:Body>
1651
+ </SOAP-ENV:Envelope>`));
1652
+ const schema = await client.application.getSchema("nms:profile");
1653
+
1654
+ let node = schema;
1655
+ let cs = await node.computeString();
1656
+ expect(cs).toBe("");
1657
+ expect(node.isCalculated).toBe(false);
1658
+
1659
+ node = schema.root;
1660
+ cs = await node.computeString();
1661
+ expect(cs).toBe("@lastName + ' ' + @firstName +' (' + @email + ')'");
1662
+ expect(node.isCalculated).toBe(false);
1663
+
1664
+ node = schema.root.children.get("@fullName");
1665
+ cs = await node.computeString();
1666
+ expect(cs).toBe("@lastName + ' ' + @firstName");
1667
+ expect(node.isCalculated).toBe(true);
1668
+ });
1669
+
1670
+ it("Should get compute string for ref nodes", async () => {
1671
+ const client = await Mock.makeClient();
1672
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1673
+ await client.NLWS.xtkSession.logon();
1674
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1675
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1676
+ <SOAP-ENV:Body>
1677
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1678
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1679
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1680
+ <element name="profile" ref="alternate">
1681
+ </element>
1682
+ <element name="alternate" expr="@lastName + ' ' + @firstName +' (' + @email + ')'">
1683
+ <attribute name="firstName"/>
1684
+ <attribute name="lastName"/>
1685
+ <attribute name="email"/>
1686
+ </element>
1687
+ </schema>
1688
+ </pdomDoc>
1689
+ </GetEntityIfMoreRecentResponse>
1690
+ </SOAP-ENV:Body>
1691
+ </SOAP-ENV:Envelope>`));
1692
+ const schema = await client.application.getSchema("nms:profile");
1693
+ const node = schema.root;
1694
+ const cs = await node.computeString();
1695
+ expect(cs).toBe("@lastName + ' ' + @firstName +' (' + @email + ')'");
1696
+ expect(node.isCalculated).toBe(false);
1697
+ });
1698
+
1699
+ it("Should get compute string for ref nodes (missing target)", async () => {
1700
+ const client = await Mock.makeClient();
1701
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1702
+ await client.NLWS.xtkSession.logon();
1703
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1704
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1705
+ <SOAP-ENV:Body>
1706
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1707
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1708
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1709
+ <element name="profile" ref="missing">
1710
+ </element>
1711
+ </schema>
1712
+ </pdomDoc>
1713
+ </GetEntityIfMoreRecentResponse>
1714
+ </SOAP-ENV:Body>
1715
+ </SOAP-ENV:Envelope>`));
1716
+ const schema = await client.application.getSchema("nms:profile");
1717
+ const node = schema.root;
1718
+ const cs = await node.computeString();
1719
+ expect(cs).toBe("");
1720
+ expect(node.isCalculated).toBe(false);
1721
+ });
1722
+
1723
+ it("Should get compute string (automatically computed))", async () => {
1724
+ const client = await Mock.makeClient();
1725
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1726
+ await client.NLWS.xtkSession.logon();
1727
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1728
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1729
+ <SOAP-ENV:Body>
1730
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1731
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1732
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1733
+ <element name="profile">
1734
+ <key>
1735
+ <keyfield xpath="@email"/>
1736
+ <keyfield xpath="@lastName"/>
1737
+ </key>
1738
+ <attribute name="firstName"/>
1739
+ <attribute name="lastName"/>
1740
+ <attribute name="email"/>
1741
+ </element>
1742
+ </schema>
1743
+ </pdomDoc>
1744
+ </GetEntityIfMoreRecentResponse>
1745
+ </SOAP-ENV:Body>
1746
+ </SOAP-ENV:Envelope>`));
1747
+ const schema = await client.application.getSchema("nms:profile");
1748
+ const node = schema.root;
1749
+ const cs = await node.computeString();
1750
+ expect(cs).toBe("[/@email]");
1751
+ expect(node.isCalculated).toBe(false);
1752
+ });
1753
+
1754
+ it("Should get compute string (empty)", async () => {
1755
+ const client = await Mock.makeClient();
1756
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1757
+ await client.NLWS.xtkSession.logon();
1758
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1759
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1760
+ <SOAP-ENV:Body>
1761
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1762
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1763
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1764
+ <element name="profile">
1765
+ <attribute name="firstName"/>
1766
+ <attribute name="lastName"/>
1767
+ <attribute name="email"/>
1768
+ </element>
1769
+ </schema>
1770
+ </pdomDoc>
1771
+ </GetEntityIfMoreRecentResponse>
1772
+ </SOAP-ENV:Body>
1773
+ </SOAP-ENV:Envelope>`));
1774
+ const schema = await client.application.getSchema("nms:profile");
1775
+ const node = schema.root;
1776
+ const cs = await node.computeString();
1777
+ expect(cs).toBe("");
1778
+ expect(node.isCalculated).toBe(false);
1779
+ });
1780
+
1781
+ it("Should get compute string (empty key)", async () => {
1782
+ const client = await Mock.makeClient();
1783
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1784
+ await client.NLWS.xtkSession.logon();
1785
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1786
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1787
+ <SOAP-ENV:Body>
1788
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1789
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1790
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1791
+ <element name="profile">
1792
+ <key></key>
1793
+ <attribute name="firstName"/>
1794
+ <attribute name="lastName"/>
1795
+ <attribute name="email"/>
1796
+ </element>
1797
+ </schema>
1798
+ </pdomDoc>
1799
+ </GetEntityIfMoreRecentResponse>
1800
+ </SOAP-ENV:Body>
1801
+ </SOAP-ENV:Envelope>`));
1802
+ const schema = await client.application.getSchema("nms:profile");
1803
+ const node = schema.root;
1804
+ const cs = await node.computeString();
1805
+ expect(cs).toBe("");
1806
+ expect(node.isCalculated).toBe(false);
1807
+ });
1808
+
1809
+ it("Should get compute string (invalid key)", async () => {
1810
+ const client = await Mock.makeClient();
1811
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1812
+ await client.NLWS.xtkSession.logon();
1813
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
1814
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1815
+ <SOAP-ENV:Body>
1816
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1817
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
1818
+ <schema name="profile" namespace="nms" xtkschema="xtk:schema">
1819
+ <element name="profile">
1820
+ <key>
1821
+ <keyfield xpath="@notFound"/>
1822
+ </key>
1823
+ <attribute name="firstName"/>
1824
+ <attribute name="lastName"/>
1825
+ <attribute name="email"/>
1826
+ </element>
1827
+ </schema>
1828
+ </pdomDoc>
1829
+ </GetEntityIfMoreRecentResponse>
1830
+ </SOAP-ENV:Body>
1831
+ </SOAP-ENV:Envelope>`));
1832
+ const schema = await client.application.getSchema("nms:profile");
1833
+ const node = schema.root;
1834
+ const cs = await node.computeString();
1835
+ expect(cs).toBe("");
1836
+ expect(node.isCalculated).toBe(false);
1837
+ });
1838
+ });
1839
+
1840
+ describe("Type ANY", () => {
1841
+ it("Should find ANY node", async () => {
1842
+ var xml = DomUtil.parse(`<schema namespace='nms' name='group'>
1843
+ <element name='group'>
1844
+ <element name="extension" type="ANY" label="Extension data" xml="true" doesNotSupportDiff="true"/>
1845
+ </element>
1846
+ </schema>`);
1847
+ var schema = newSchema(xml);
1848
+ var root = schema.root;
1849
+ var node = await root.findNode("extension");
1850
+ expect(node).toMatchObject({ name: "extension", label: "Extension data", nodePath: "/extension", type: "ANY" });
1851
+
1852
+ // xpath inside ANY node are not supported
1853
+ node = await root.findNode("extension/group");
1854
+ expect(node).toBeFalsy();
1855
+ });
1856
+ });
513
1857
 
514
1858
  describe("toString", () => {
515
1859
  var xml = DomUtil.parse(`<schema namespace='nms' name='recipient' label="Recipients" labelSingular="Recipient">
@@ -524,9 +1868,9 @@ describe('Application', () => {
524
1868
  it("Should stringify schema or schema node", async () => {
525
1869
  var schema = newSchema(xml);
526
1870
  var root = schema.root;
527
- var email = root.findNode("@email");
528
- var country = root.findNode("country");
529
- var name = country.findNode("@name");
1871
+ var email = await root.findNode("@email");
1872
+ var country = await root.findNode("country");
1873
+ var name = await country.findNode("@name");
530
1874
 
531
1875
  expect(schema.toString()).toBe(`Recipients (recipient)
532
1876
  - Recipient (recipient)
@@ -555,9 +1899,40 @@ describe('Application', () => {
555
1899
  </schema>`);
556
1900
  const schema = newSchema(xml);
557
1901
  expect(schema.root.isSQL).toBe(true);
558
- let node = schema.root.findNode("@email");
1902
+ let node = await schema.root.findNode("@email");
559
1903
  expect(node.isSQL).toBe(true);
560
- node = schema.root.findNode("@test");
1904
+ node = await schema.root.findNode("@test");
1905
+ expect(node.isSQL).toBe(false);
1906
+ });
1907
+
1908
+ it("Should have isSQL for link" , async () => {
1909
+ let xml = DomUtil.parse(`<schema namespace='nms' name='recipient' mappingType="sql">
1910
+ <element name='recipient' sqltable="NmsRecipient">
1911
+ <element name='country' type='link'/>
1912
+ </element>
1913
+ </schema>`);
1914
+ let schema = newSchema(xml);
1915
+ let node = await schema.root.findNode("country");
1916
+ expect(node.isSQL).toBe(true);
1917
+
1918
+ // not a sql mapping type
1919
+ xml = DomUtil.parse(`<schema namespace='nms' name='recipient' mappingType="file">
1920
+ <element name='recipient' sqltable="NmsRecipient">
1921
+ <element name='country' type='link'/>
1922
+ </element>
1923
+ </schema>`);
1924
+ schema = newSchema(xml);
1925
+ node = await schema.root.findNode("country");
1926
+ expect(node.isSQL).toBe(false);
1927
+
1928
+ // xml link
1929
+ xml = DomUtil.parse(`<schema namespace='nms' name='recipient' mappingType="sql">
1930
+ <element name='recipient' sqltable="NmsRecipient">
1931
+ <element name='country' type='link' xml="true"/>
1932
+ </element>
1933
+ </schema>`);
1934
+ schema = newSchema(xml);
1935
+ node = await schema.root.findNode("country");
561
1936
  expect(node.isSQL).toBe(false);
562
1937
  });
563
1938
 
@@ -571,16 +1946,16 @@ describe('Application', () => {
571
1946
  </element>
572
1947
  </schema>`);
573
1948
  const schema = newSchema(xml);
574
- let node = schema.root.findNode("@email");
1949
+ let node = await schema.root.findNode("@email");
575
1950
  expect(node.isMemo).toBe(false);
576
1951
  expect(node.isMemoData).toBe(false);
577
- node = schema.root.findNode("@test");
1952
+ node = await schema.root.findNode("@test");
578
1953
  expect(node.isMemo).toBe(false);
579
1954
  expect(node.isMemoData).toBe(false);
580
- node = schema.root.findNode("@memo");
1955
+ node = await schema.root.findNode("@memo");
581
1956
  expect(node.isMemo).toBe(true);
582
1957
  expect(node.isMemoData).toBe(false);
583
- node = schema.root.findNode("data");
1958
+ node = await schema.root.findNode("data");
584
1959
  expect(node.isMemo).toBe(true);
585
1960
  expect(node.isMemoData).toBe(true);
586
1961
  });
@@ -610,25 +1985,25 @@ describe('Application', () => {
610
1985
  </element>
611
1986
  </schema>`);
612
1987
  const schema = newSchema(xml);
613
- let node = schema.root.findNode("@email"); expect(node.isNotNull).toBe(false);
614
- node = schema.root.findNode("@id"); expect(node.isNotNull).toBe(true);
615
- node = schema.root.findNode("@b"); expect(node.isNotNull).toBe(true);
616
- node = schema.root.findNode("@s"); expect(node.isNotNull).toBe(true);
617
- node = schema.root.findNode("@f"); expect(node.isNotNull).toBe(true);
618
- node = schema.root.findNode("@d"); expect(node.isNotNull).toBe(true);
619
- node = schema.root.findNode("@i"); expect(node.isNotNull).toBe(true);
620
- node = schema.root.findNode("@m"); expect(node.isNotNull).toBe(true);
621
- node = schema.root.findNode("@p"); expect(node.isNotNull).toBe(true);
622
- node = schema.root.findNode("@t"); expect(node.isNotNull).toBe(true);
623
- node = schema.root.findNode("@b0"); expect(node.isNotNull).toBe(true);
624
-
625
- node = schema.root.findNode("@snn"); expect(node.isNotNull).toBe(false);
626
- node = schema.root.findNode("@snnt"); expect(node.isNotNull).toBe(true);
627
- node = schema.root.findNode("@snnf"); expect(node.isNotNull).toBe(false);
628
-
629
- node = schema.root.findNode("@lnn"); expect(node.isNotNull).toBe(true);
630
- node = schema.root.findNode("@lnnt"); expect(node.isNotNull).toBe(true);
631
- node = schema.root.findNode("@lnnf"); expect(node.isNotNull).toBe(false);
1988
+ let node = await schema.root.findNode("@email"); expect(node.isNotNull).toBe(false);
1989
+ node = await schema.root.findNode("@id"); expect(node.isNotNull).toBe(true);
1990
+ node = await schema.root.findNode("@b"); expect(node.isNotNull).toBe(true);
1991
+ node = await schema.root.findNode("@s"); expect(node.isNotNull).toBe(true);
1992
+ node = await schema.root.findNode("@f"); expect(node.isNotNull).toBe(true);
1993
+ node = await schema.root.findNode("@d"); expect(node.isNotNull).toBe(true);
1994
+ node = await schema.root.findNode("@i"); expect(node.isNotNull).toBe(true);
1995
+ node = await schema.root.findNode("@m"); expect(node.isNotNull).toBe(true);
1996
+ node = await schema.root.findNode("@p"); expect(node.isNotNull).toBe(true);
1997
+ node = await schema.root.findNode("@t"); expect(node.isNotNull).toBe(true);
1998
+ node = await schema.root.findNode("@b0"); expect(node.isNotNull).toBe(true);
1999
+
2000
+ node = await schema.root.findNode("@snn"); expect(node.isNotNull).toBe(false);
2001
+ node = await schema.root.findNode("@snnt"); expect(node.isNotNull).toBe(true);
2002
+ node = await schema.root.findNode("@snnf"); expect(node.isNotNull).toBe(false);
2003
+
2004
+ node = await schema.root.findNode("@lnn"); expect(node.isNotNull).toBe(true);
2005
+ node = await schema.root.findNode("@lnnt"); expect(node.isNotNull).toBe(true);
2006
+ node = await schema.root.findNode("@lnnf"); expect(node.isNotNull).toBe(false);
632
2007
  });
633
2008
 
634
2009
  it("Should test user description" , async () => {