@adobe/acc-js-sdk 1.1.4 → 1.1.7

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.
@@ -12,9 +12,9 @@ governing permissions and limitations under the License.
12
12
 
13
13
 
14
14
  /**********************************************************************************
15
- *
15
+ *
16
16
  * Unit tests for the ACC client
17
- *
17
+ *
18
18
  *********************************************************************************/
19
19
 
20
20
  const sdk = require('../src/index.js');
@@ -24,6 +24,8 @@ const Mock = require('./mock.js').Mock;
24
24
  const { HttpError } = require('../src/transport.js');
25
25
  const { Cipher } = require('../src/crypto.js');
26
26
  const { EntityAccessor } = require('../src/entityAccessor.js');
27
+ const { JSDOM } = require('jsdom');
28
+ const dom = new JSDOM();
27
29
 
28
30
  describe('ACC Client', function () {
29
31
 
@@ -64,16 +66,16 @@ describe('ACC Client', function () {
64
66
 
65
67
  it('Should logon and logoff with traces', async () => {
66
68
  const client = await Mock.makeClient();
69
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
70
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
67
71
  const logs = await Mock.withMockConsole(async () => {
68
72
  client.traceAPICalls(true);
69
- client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
70
- client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
71
73
  await client.NLWS.xtkSession.logon();
72
74
  expect(client.isLogged()).toBe(true);
73
75
  var sessionInfoXml = client.getSessionInfo("xml");
74
76
  expect(DomUtil.findElement(sessionInfoXml, "serverInfo", true).getAttribute("buildNumber")).toBe("9219");
75
77
  await client.NLWS.xtkSession.logoff();
76
- expect(client.isLogged()).toBe(false);
78
+ expect(client.isLogged()).toBe(false);
77
79
  })
78
80
  expect(logs.length).toBe(4);
79
81
  expect(logs[0]).toMatch(/SOAP.*request.*Logon/is)
@@ -285,7 +287,7 @@ describe('ACC Client', function () {
285
287
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
286
288
  client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
287
289
  await client.NLWS.xtkSession.logon();
288
-
290
+
289
291
  // Setting an option for the first time will
290
292
  // - try to read the option from the database (as it's not in cache yet): xtk:session#GetOption
291
293
  // - use a writer to write the result to the database
@@ -308,7 +310,7 @@ describe('ACC Client', function () {
308
310
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
309
311
  client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
310
312
  await client.NLWS.xtkSession.logon();
311
-
313
+
312
314
  // Setting an option for the first time will
313
315
  // - try to read the option from the database (as it's not in cache yet): xtk:session#GetOption
314
316
  // - use a writer to write the result to the database
@@ -331,7 +333,7 @@ describe('ACC Client', function () {
331
333
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
332
334
  client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
333
335
  await client.NLWS.xtkSession.logon();
334
-
336
+
335
337
  // Setting an option for the first time will
336
338
  // - try to read the option from the database (as it's not in cache yet): xtk:session#GetOption. In this case, it will return a numeric option
337
339
  // - use a writer to write the result to the database
@@ -416,7 +418,7 @@ describe('ACC Client', function () {
416
418
  expect(schema["@name"]).toBe("extAccount");
417
419
 
418
420
  // Ask with invalid representation
419
- await expect(client.getSchema("nms:extAccount", "invalid")).rejects.toMatchObject({ errorCode: 'SDK-000004' });
421
+ await expect(client.getSchema("nms:extAccount", "invalid")).rejects.toMatchObject({ errorCode: 'SDK-000004' });
420
422
 
421
423
  // Get missing schema
422
424
  client.clearAllCaches();
@@ -474,7 +476,7 @@ describe('ACC Client', function () {
474
476
  await expect(client.getSysEnum("encryptionType", startSchema)).rejects.toMatchObject({ errorCode: "SDK-000006" });
475
477
  client._representation = "xml";
476
478
 
477
- // Get non-cached XML representation
479
+ // Get non-cached XML representation
478
480
  client.clearAllCaches();
479
481
  client._transport.mockReturnValueOnce(Mock.GET_NMS_EXTACCOUNT_SCHEMA_RESPONSE);
480
482
  sysEnum = await client.getSysEnum("nms:extAccount:encryptionType");
@@ -690,7 +692,7 @@ describe('ACC Client', function () {
690
692
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
691
693
  await client.NLWS.xtkSession.logon();
692
694
  const key = Mock.makeKey();
693
-
695
+
694
696
  client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
695
697
  client._transport.mockReturnValueOnce(Mock.GET_SECRET_KEY_OPTION_RESPONSE(key));
696
698
  var cipher = await client._getSecretKeyCipher();
@@ -1008,13 +1010,13 @@ describe('ACC Client', function () {
1008
1010
  });
1009
1011
 
1010
1012
  it("Should support mutable calls", async () => {
1011
- // Some methods can mutate the object on which they apply. This is for instance the case of the xtk:queryDef#SelectAll method.
1012
- // You call it on a queryDef, and it internally returns a new query definition which contain select nodes for all the nodes of the schema.
1013
+ // Some methods can mutate the object on which they apply. This is for instance the case of the xtk:queryDef#SelectAll method.
1014
+ // You call it on a queryDef, and it internally returns a new query definition which contain select nodes for all the nodes of the schema.
1013
1015
  // When such a method is called, the SDK will know how to "mutate" the corresponding object.
1014
1016
  const client = await Mock.makeClient();
1015
1017
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1016
1018
  await client.NLWS.xtkSession.logon();
1017
-
1019
+
1018
1020
  var queryDef = {
1019
1021
  "schema": "xtk:option",
1020
1022
  "operation": "getIfExists",
@@ -1050,7 +1052,7 @@ describe('ACC Client', function () {
1050
1052
  </SOAP-ENV:Body>
1051
1053
  </SOAP-ENV:Envelope>`));
1052
1054
  await query.selectAll(false);
1053
-
1055
+
1054
1056
  // Check that query has new nodes
1055
1057
  const object = query.inspect(); // JSON query object
1056
1058
  expect(object.select.node.length).toBe(14);
@@ -1288,7 +1290,7 @@ describe('ACC Client', function () {
1288
1290
 
1289
1291
  describe("Logon with session token", () => {
1290
1292
  // With session token logon, the session token is passed by the caller, and therefore the will be no "Logon" call
1291
-
1293
+
1292
1294
  it("Should create logged client", async() => {
1293
1295
  const connectionParameters = sdk.ConnectionParameters.ofSessionToken("http://acc-sdk:8080", "mc/");
1294
1296
  const client = await sdk.init(connectionParameters);
@@ -1304,7 +1306,7 @@ describe('ACC Client', function () {
1304
1306
 
1305
1307
  describe("Anonymous login", () => {
1306
1308
  // With anonymous login, one is always logged
1307
-
1309
+
1308
1310
  it("Should create anonymous client", async() => {
1309
1311
  const connectionParameters = sdk.ConnectionParameters.ofAnonymousUser("http://acc-sdk:8080");
1310
1312
  const client = await sdk.init(connectionParameters);
@@ -1553,7 +1555,7 @@ describe('ACC Client', function () {
1553
1555
  "xtk:session#GetOption", true,
1554
1556
  ];
1555
1557
  const observed = [];
1556
-
1558
+
1557
1559
  client.registerObserver({
1558
1560
  onSOAPCall: (soapCall) => {
1559
1561
  const request = soapCall.request;
@@ -1598,7 +1600,7 @@ describe('ACC Client', function () {
1598
1600
  </SOAP-ENV:Envelope>`));
1599
1601
  await expect(client.getOption("XtkDatabaseId")).rejects.toMatchObject({ errorCode: "XXX-000000" });
1600
1602
  expect(observedException).toMatchObject({ errorCode: "XXX-000000" });
1601
-
1603
+
1602
1604
  });
1603
1605
 
1604
1606
  it("Should ignore unregistering non-existant observers", async () => {
@@ -1613,7 +1615,7 @@ describe('ACC Client', function () {
1613
1615
  const client = await Mock.makeClient();
1614
1616
  var countCalls = 0;
1615
1617
  var countSuccesses = 0;
1616
-
1618
+
1617
1619
  const observer1 = {
1618
1620
  onSOAPCall: () => { countCalls = countCalls + 1; },
1619
1621
  onSOAPCallSuccess: () => { countSuccesses = countSuccesses + 1; }
@@ -1643,7 +1645,7 @@ describe('ACC Client', function () {
1643
1645
  const client = await Mock.makeClient();
1644
1646
  var countCalls = 0;
1645
1647
  var countSuccesses = 0;
1646
-
1648
+
1647
1649
  const observer1 = {
1648
1650
  onSOAPCall: () => { countCalls = countCalls + 1; },
1649
1651
  onSOAPCallSuccess: () => { countSuccesses = countSuccesses + 1; }
@@ -1668,7 +1670,7 @@ describe('ACC Client', function () {
1668
1670
  expect(countCalls).toBe(1);
1669
1671
  expect(countSuccesses).toBe(2);
1670
1672
  });
1671
-
1673
+
1672
1674
  it("Should observe internal SOAP calls", async () => {
1673
1675
  const client = await Mock.makeClient();
1674
1676
  const expected = [
@@ -1678,7 +1680,7 @@ describe('ACC Client', function () {
1678
1680
  "xtk:session#GetOption", false,
1679
1681
  ];
1680
1682
  const observed = [];
1681
-
1683
+
1682
1684
  client.registerObserver({
1683
1685
  onSOAPCall: (soapCall) => {
1684
1686
  const request = soapCall.request;
@@ -1703,7 +1705,7 @@ describe('ACC Client', function () {
1703
1705
  client.traceAPICalls(true);
1704
1706
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1705
1707
  await client.NLWS.xtkSession.logon();
1706
-
1708
+
1707
1709
  client._transport.mockReturnValueOnce(Mock.PING);
1708
1710
  const ping = await client.ping();
1709
1711
  expect(ping.status).toBe("OK");
@@ -1727,7 +1729,7 @@ describe('ACC Client', function () {
1727
1729
  expect(logs[0]).toMatch(/HTTP.*request.*GET.*test.com/is)
1728
1730
  expect(logs[1]).toMatch(/HTTP.*response/is)
1729
1731
  })
1730
-
1732
+
1731
1733
  it("Should trace HTTP call with data and no answer", async () => {
1732
1734
  const logs = await Mock.withMockConsole(async () => {
1733
1735
  const client = await Mock.makeClient();
@@ -1782,7 +1784,7 @@ describe('ACC Client', function () {
1782
1784
  url: "http://acc-sdk:8080/nl/jsp/ping.jsp"
1783
1785
  });
1784
1786
  expect(observer.onHTTPCall.mock.calls[0][1]).toBeUndefined();
1785
-
1787
+
1786
1788
  expect(observer.onHTTPCallSuccess.mock.calls.length).toBe(1);
1787
1789
  expect(observer.onHTTPCallSuccess.mock.calls[0].length).toBe(2); // 2 arguments
1788
1790
  expect(observer.onHTTPCallSuccess.mock.calls[0][0]).toMatchObject({
@@ -1903,7 +1905,7 @@ describe('ACC Client', function () {
1903
1905
  expect(client.isLogged()).toBeFalsy();
1904
1906
  // Ensure logoff has been called
1905
1907
  expect(logoff.mock.calls.length).toBe(1);
1906
- })
1908
+ })
1907
1909
  })
1908
1910
 
1909
1911
  describe("Bearer token authentication", () => {
@@ -1967,7 +1969,7 @@ describe('ACC Client', function () {
1967
1969
  await newClient.logon();
1968
1970
  return newClient;
1969
1971
  }
1970
- const connectionParameters = sdk.ConnectionParameters.ofBearerToken("http://acc-sdk:8080",
1972
+ const connectionParameters = sdk.ConnectionParameters.ofBearerToken("http://acc-sdk:8080",
1971
1973
  "$token$", {refreshClient: refreshClient});
1972
1974
  const client = await sdk.init(connectionParameters);
1973
1975
  client.traceAPICalls(true);
@@ -2242,6 +2244,8 @@ describe('ACC Client', function () {
2242
2244
  }
2243
2245
  const client = await Mock.makeClient({ storage: storage });
2244
2246
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2247
+ client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_RESPONSE);
2248
+ client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_RESPONSE);
2245
2249
  client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
2246
2250
  await client.NLWS.xtkSession.logon();
2247
2251
  storage.getItem.mockReturnValueOnce(JSON.stringify({value: { value: "Hello", type: 6 }, cachedAt: 1633715996021 }));
@@ -2330,7 +2334,7 @@ describe('ACC Client', function () {
2330
2334
  expect(cached.value).toMatch("<schema");
2331
2335
 
2332
2336
  // Now simulate reusing the local storage. We need a new client to make sure we do not reuse
2333
- // the in-memory cache of the client.
2337
+ // the in-memory cache of the client.
2334
2338
  client = await Mock.makeClient({ storage: storage });
2335
2339
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2336
2340
  await client.NLWS.xtkSession.logon();
@@ -2351,6 +2355,140 @@ describe('ACC Client', function () {
2351
2355
  expect(schema["namespace"]).toBe("nms");
2352
2356
  expect(schema["name"]).toBe("extAccount");
2353
2357
  });
2358
+
2359
+ it("Should get schema from the cache", async () => {
2360
+ const client = await Mock.makeClient();
2361
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2362
+ await client.NLWS.xtkSession.logon();
2363
+
2364
+ client._transport.mockReturnValueOnce(Mock.GET_NMS_EXTACCOUNT_SCHEMA_RESPONSE);
2365
+ var schema = await client.getSchema("nms:extAccount");
2366
+ expect(schema["namespace"]).toBe("nms");
2367
+ expect(schema["name"]).toBe("extAccount");
2368
+
2369
+ client._transport.mockReturnValue(Promise.resolve(Mock.GETMODIFIEDENTITIES_RESPONSE));
2370
+
2371
+ jest.useFakeTimers();
2372
+ client.startRefreshCaches(5000); // autorefresh every 5000 ms
2373
+ jest.advanceTimersByTime(6000);
2374
+ jest.useRealTimers();
2375
+
2376
+ schema = await client.getSchema("nms:extAccount");
2377
+ expect(schema["namespace"]).toBe("nms");
2378
+ expect(schema["name"]).toBe("extAccount");
2379
+
2380
+ client.stopRefreshCaches();
2381
+ });
2382
+
2383
+ it("Should get schema from server when removed from cache", async () => {
2384
+ const client = await Mock.makeClient();
2385
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2386
+ await client.NLWS.xtkSession.logon();
2387
+
2388
+ client._transport.mockReturnValueOnce(Mock.GET_NMS_EXTACCOUNT_SCHEMA_RESPONSE);
2389
+ var schema = await client.getSchema("nms:extAccount");
2390
+ expect(schema["namespace"]).toBe("nms");
2391
+ expect(schema["name"]).toBe("extAccount");
2392
+
2393
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GETMODIFIEDENTITIES_SCHEMA_RESPONSE));
2394
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GETMODIFIEDENTITIES_SCHEMA_RESPONSE));
2395
+
2396
+ client._transport.mockReturnValue(Promise.resolve(Mock.GET_NMS_EXTACCOUNT_SCHEMA_RESPONSE));
2397
+ jest.useFakeTimers();
2398
+ client.startRefreshCaches(5000); // autorefresh every 5000 ms
2399
+ jest.advanceTimersByTime(6000);
2400
+ jest.useRealTimers();
2401
+
2402
+ schema = await client.getSchema("nms:extAccount");
2403
+ expect(schema["namespace"]).toBe("nms");
2404
+ expect(schema["name"]).toBe("extAccount");
2405
+ client.stopRefreshCaches();
2406
+ });
2407
+
2408
+ it("Should stop refresh", async () => {
2409
+ const client = await Mock.makeClient();
2410
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2411
+ await client.NLWS.xtkSession.logon();
2412
+ jest.useFakeTimers();
2413
+ client.startRefreshCaches();
2414
+ jest.advanceTimersByTime(6000); // autorefresh for xtk:schema should be started after 5000 ms
2415
+ jest.useRealTimers();
2416
+ expect(client._optionCacheRefresher._intervalId).not.toBeNull();
2417
+ expect(client._entityCacheRefresher._intervalId).not.toBeNull();
2418
+ client.stopRefreshCaches();
2419
+ expect(client._optionCacheRefresher._intervalId).toBeNull();
2420
+ expect(client._entityCacheRefresher._intervalId).toBeNull();
2421
+ });
2422
+
2423
+ it("Should stop refresh when logoff", async () => {
2424
+ const client = await Mock.makeClient();
2425
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2426
+ await client.NLWS.xtkSession.logon();
2427
+ jest.useFakeTimers();
2428
+ client.startRefreshCaches();
2429
+ jest.advanceTimersByTime(6000); // autorefresh for xtk:schema should be started after 5000 ms
2430
+ jest.useRealTimers();
2431
+ expect(client._optionCacheRefresher._intervalId).not.toBeNull();
2432
+ expect(client._entityCacheRefresher._intervalId).not.toBeNull();
2433
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
2434
+ await client.logoff();
2435
+ expect(client._optionCacheRefresher._intervalId).toBeNull();
2436
+ expect(client._entityCacheRefresher._intervalId).toBeNull();
2437
+ });
2438
+
2439
+ it("Expired session and refresh cache", async () => {
2440
+ let refreshClient = async () => {
2441
+ const connectionParameters = sdk.ConnectionParameters.ofSecurityToken("http://acc-sdk:8080",
2442
+ "$security_token$", {refreshClient: refreshClient});
2443
+ const newClient = await sdk.init(connectionParameters);
2444
+ newClient._transport = jest.fn();
2445
+ newClient._transport.mockReturnValueOnce(Mock.BEARER_LOGON_RESPONSE);
2446
+ await newClient.logon();
2447
+ return newClient;
2448
+ }
2449
+ const connectionParameters = sdk.ConnectionParameters.ofBearerToken("http://acc-sdk:8080",
2450
+ "$token$", {refreshClient: refreshClient});
2451
+ const client = await sdk.init(connectionParameters);
2452
+ jest.useFakeTimers();
2453
+ client.startRefreshCaches();
2454
+ client._entityCacheRefresher._safeCallAndRefresh = jest.fn();
2455
+ client._optionCacheRefresher._safeCallAndRefresh = jest.fn();
2456
+ jest.advanceTimersByTime(18000);
2457
+ expect(client._entityCacheRefresher._safeCallAndRefresh.mock.calls.length).toBe(1);
2458
+ expect(client._optionCacheRefresher._safeCallAndRefresh.mock.calls.length).toBe(1);
2459
+ client.traceAPICalls(true);
2460
+ client._transport = jest.fn();
2461
+ client._transport.mockReturnValueOnce(Mock.BEARER_LOGON_RESPONSE);
2462
+ client._transport.mockReturnValueOnce(Promise.resolve(`XSV-350008 Session has expired or is invalid. Please reconnect.`));
2463
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
2464
+ client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
2465
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:xtk:queryDef' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
2466
+ <SOAP-ENV:Body>
2467
+ <ExecuteQueryResponse xmlns='urn:xtk:queryDef' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
2468
+ <pdomOutput xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
2469
+ <extAccount-collection/>
2470
+ </pdomOutput></ExecuteQueryResponse>
2471
+ </SOAP-ENV:Body>
2472
+ </SOAP-ENV:Envelope>`));
2473
+ await client.logon();
2474
+ var queryDef = {
2475
+ "schema": "nms:extAccount",
2476
+ "operation": "select",
2477
+ "select": {
2478
+ "node": [
2479
+ { "expr": "@id" },
2480
+ { "expr": "@name" }
2481
+ ]
2482
+ }
2483
+ };
2484
+ var query = client.NLWS.xtkQueryDef.create(queryDef);
2485
+ var extAccount = await query.executeQuery();
2486
+ expect(extAccount).toEqual({ extAccount: [] });
2487
+ jest.advanceTimersByTime(10000);
2488
+ expect(client._entityCacheRefresher._safeCallAndRefresh.mock.calls.length).toBe(2);
2489
+ expect(client._optionCacheRefresher._safeCallAndRefresh.mock.calls.length).toBe(2);
2490
+ jest.useRealTimers();
2491
+ });
2354
2492
  });
2355
2493
 
2356
2494
  describe("Calling SOAP method with parameters as a function", () => {
@@ -2375,7 +2513,7 @@ describe('ACC Client', function () {
2375
2513
  const method = scope["staticP1"]; // SOAP method to call
2376
2514
  const paramsFn = jest.fn(); // function returning SOAP call parameters
2377
2515
  paramsFn.mockReturnValueOnce(["XtkDatabaseId"]);
2378
-
2516
+
2379
2517
  client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
2380
2518
  <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:xtk:session' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
2381
2519
  <SOAP-ENV:Body>
@@ -2403,7 +2541,7 @@ describe('ACC Client', function () {
2403
2541
  const method = scope["nonStaticP1"]; // SOAP method to call
2404
2542
  const paramsFn = jest.fn(); // function returning SOAP call parameters
2405
2543
  paramsFn.mockReturnValueOnce(["XtkDatabaseId"]);
2406
-
2544
+
2407
2545
  client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
2408
2546
  <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:xtk:session' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
2409
2547
  <SOAP-ENV:Body>
@@ -2826,7 +2964,7 @@ describe('ACC Client', function () {
2826
2964
  const query = client.NLWS.pushDown({'foo': 'bar'}).xtkQueryDef.create(queryDef);
2827
2965
  await query.executeQuery();
2828
2966
  const lastCall = client._transport.mock.calls[client._transport.mock.calls.length-1];
2829
- expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef#ExecuteQuery");
2967
+ expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef:ExecuteQuery");
2830
2968
  expect(lastCall[1].charset).toBe("UTF-8");
2831
2969
  expect(lastCall[1].foo).toBe("bar");
2832
2970
  });
@@ -2851,7 +2989,7 @@ describe('ACC Client', function () {
2851
2989
  const query = client.NLWS.pushDown({'foo': 'bar'}).xtkQueryDef.create(queryDef);
2852
2990
  await query.executeQuery();
2853
2991
  const lastCall = client._transport.mock.calls[client._transport.mock.calls.length-1];
2854
- expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef#ExecuteQuery");
2992
+ expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef:ExecuteQuery");
2855
2993
  expect(lastCall[1].charset).toBe("UTF-8");
2856
2994
  expect(lastCall[1].foo).toBe("bar");
2857
2995
  expect(lastCall[1].cnxDefault).toBe(3);
@@ -2878,11 +3016,340 @@ describe('ACC Client', function () {
2878
3016
  const query = client.NLWS.pushDown({'foo': 'bar'}).pushDown().pushDown({'foo': 'fu', x: 2 }).xtkQueryDef.create(queryDef);
2879
3017
  await query.executeQuery();
2880
3018
  const lastCall = client._transport.mock.calls[client._transport.mock.calls.length-1];
2881
- expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef#ExecuteQuery");
3019
+ expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef:ExecuteQuery");
2882
3020
  expect(lastCall[1].charset).toBe("UTF-8");
2883
3021
  expect(lastCall[1].foo).toBe("fu");
2884
3022
  expect(lastCall[1].cnxDefault).toBe(3);
2885
3023
  expect(lastCall[1].x).toBe(2);
2886
3024
  });
2887
3025
  });
3026
+ describe("Schema cache refresh", () => {
3027
+ it("Should unregister listener", async () => {
3028
+ const client = await Mock.makeClient();
3029
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
3030
+ await client.NLWS.xtkSession.logon();
3031
+
3032
+ class Listener {
3033
+ constructor() {
3034
+ this._schemas = {};
3035
+ }
3036
+
3037
+ invalidateCacheItem(schemaId) {
3038
+ this._schemas[schemaId] = undefined;
3039
+ }
3040
+ }
3041
+
3042
+ client._unregisterAllCacheChangeListeners();
3043
+ expect(client._cacheChangeListeners.length).toBe(0);
3044
+ const listener = new Listener();
3045
+
3046
+ client._registerCacheChangeListener(listener);
3047
+ expect(client._cacheChangeListeners.length).toBe(1);
3048
+ client._unregisterCacheChangeListener(listener);
3049
+ expect(client._cacheChangeListeners.length).toBe(0);
3050
+ });
3051
+
3052
+ it("Should not unregister unknown listener", async () => {
3053
+ const client = await Mock.makeClient();
3054
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
3055
+ await client.NLWS.xtkSession.logon();
3056
+
3057
+ class Listener {
3058
+ constructor() {
3059
+ this._schemas = {};
3060
+ }
3061
+
3062
+ invalidateCacheItem(schemaId) {
3063
+ this._schemas[schemaId] = undefined;
3064
+ }
3065
+ }
3066
+
3067
+ client._unregisterAllCacheChangeListeners();
3068
+ expect(client._cacheChangeListeners.length).toBe(0);
3069
+ const listener = new Listener();
3070
+
3071
+ client._registerCacheChangeListener(listener);
3072
+ expect(client._cacheChangeListeners.length).toBe(1);
3073
+
3074
+ const listener2 = new Listener();
3075
+
3076
+ client._unregisterCacheChangeListener(listener2);
3077
+ expect(client._cacheChangeListeners.length).toBe(1);
3078
+ client._unregisterAllCacheChangeListeners();
3079
+ });
3080
+
3081
+ it("Should be notify when register", async () => {
3082
+ const client = await Mock.makeClient();
3083
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
3084
+ await client.NLWS.xtkSession.logon();
3085
+
3086
+ class Listener {
3087
+ constructor() {
3088
+ this._schemas = {};
3089
+ }
3090
+ add(schemaId) {
3091
+ this._schemas[schemaId] = "1";
3092
+ }
3093
+
3094
+ invalidateCacheItem(schemaId) {
3095
+ this._schemas[schemaId] = undefined;
3096
+ }
3097
+ getSchema(schemaId) {
3098
+ return this._schemas[schemaId];
3099
+ }
3100
+ }
3101
+
3102
+ client._unregisterAllCacheChangeListeners();
3103
+
3104
+ const listener = new Listener();
3105
+ listener.add("nms:recipient");
3106
+ listener.add("xtk:operator");
3107
+
3108
+ client._registerCacheChangeListener(listener);
3109
+ client._notifyCacheChangeListeners("nms:recipient");
3110
+ expect(listener.getSchema("nms:recipient")).toBeUndefined();
3111
+ expect(listener.getSchema("xtk:operator")).toBe("1");
3112
+
3113
+ client._unregisterCacheChangeListener(listener);
3114
+ });
3115
+ });
3116
+ describe('File uploader - on server', () => {
3117
+ it('is not supported', async ()=> {
3118
+ const client = await Mock.makeClient();
3119
+ expect(client.fileUploader).toBeDefined()
3120
+ await expect(client.fileUploader.upload({name: 'abcd.txt'})).rejects.toMatchObject({"cause": undefined, "detail": "File uploading is only supported in browser based calls.", "errorCode": "SDK-000013", "faultCode": 16384, "faultString": "\"Failed to upload file abcd.txt", "message": "500 - Error 16384: SDK-000013 \"Failed to upload file abcd.txt. File uploading is only supported in browser based calls.", "methodCall": undefined, "name": "CampaignException", "statusCode": 500})
3121
+ })
3122
+ })
3123
+
3124
+ describe('File uploader - on browser', () => {
3125
+ beforeEach(() => {
3126
+ global.document = dom.window.document
3127
+ global.window = dom.window
3128
+ global.FormData = function () {
3129
+ this.append = jest.fn()
3130
+ }
3131
+
3132
+ // Evaluates JavaScript code returned by the upload.jsp. Evaluation is done in the context
3133
+ // of an iframe and will call the parent window document.controller uploadFileCallBack
3134
+ // function
3135
+ function evalJSReturnedByUploadJSP(js) {
3136
+ const data = eval(`
3137
+ (function () {
3138
+ var result = undefined;
3139
+ window = {
3140
+ parent: {
3141
+ document: {
3142
+ controller: {
3143
+ uploadFileCallBack: (data) => {
3144
+ result = data;
3145
+ }
3146
+ }
3147
+ }
3148
+ }
3149
+ };
3150
+ ${js};
3151
+ return result;
3152
+ }())
3153
+ `);
3154
+ // Call real callback
3155
+ global.document.controller.uploadFileCallBack(data);
3156
+ }
3157
+
3158
+ // Dynamically mock the iframe.contentWindow.document.close(); function
3159
+ const handler = {
3160
+ get: function (target, prop) {
3161
+ if (prop === 'contentWindow') {
3162
+ target.contentWindow.document.close = () => {
3163
+ var scripts = target.contentWindow.document.getElementsByTagName('script');
3164
+ for (let i = 0; i < scripts.length; i++) {
3165
+ const script = scripts[i];
3166
+ const js = DomUtil.elementValue(script);
3167
+ evalJSReturnedByUploadJSP(js);
3168
+ }
3169
+ }
3170
+ }
3171
+ return Reflect.get(...arguments);
3172
+ }
3173
+ };
3174
+
3175
+
3176
+ // Intercept creation of iframe. returns a proxy which will intercept the iframe.contentWindow.document.close(); function
3177
+ const _origiinalCreateElement = document.createElement;
3178
+ global.document.createElement = (tagName) => {
3179
+ const r = _origiinalCreateElement.call(document, tagName);
3180
+ if (tagName === 'iframe') {
3181
+ const p = new Proxy(r, handler);
3182
+ return p;
3183
+ }
3184
+ return r;
3185
+ };
3186
+
3187
+ });
3188
+
3189
+ it('works with successful post upload calls', async () => {
3190
+ // Create a mock client and logon
3191
+ const client = await Mock.makeClient();
3192
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
3193
+ await client.NLWS.xtkSession.logon();
3194
+
3195
+ // Mock the upload protocol
3196
+ // - the upload.jsp (which returns the content of an iframe and JS to eval)
3197
+ // - call to xtk:counter#IncreaseValue (first, retrieve the schema xtk:counter then call the function)
3198
+ // - call to xtk:session#Write
3199
+ // - call to xtk:fileRes#PublishIfNeeded
3200
+ // - call to xtk:fileRes#GetURL
3201
+
3202
+ client._transport.mockReturnValueOnce(Promise.resolve(`Ok
3203
+ <html xmlns="http://www.w3.org/1999/xhtml">
3204
+ <head>
3205
+ <script type="text/javascript">if(window.parent&&window.parent.document.controller&&"function"==typeof window.parent.document.controller.uploadFileCallBack){var aFilesInfo=new Array;aFilesInfo.push({paramName:"file",fileName:"test.txt",newFileName:"d8e8fca2dc0f896fd7cb4cb0031ba249.txt",md5:"d8e8fca2dc0f896fd7cb4cb0031ba249"}),window.parent.document.controller.uploadFileCallBack(aFilesInfo)}</script>
3206
+ </head>
3207
+ <body></body>
3208
+ </html>`)); // upload.jsp
3209
+
3210
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_XTK_COUNTER_RESPONSE)); // GetEntityIfMoreRecentResponse - counter
3211
+ client._transport.mockReturnValueOnce(Mock.INCREASE_VALUE_RESPONSE); // xtk:counter#IncreaseValue
3212
+
3213
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE); // GetEntityIfMoreRecentResponse - session
3214
+ client._transport.mockReturnValueOnce(Mock.FILE_RES_WRITE_RESPONSE); // xtk:session#Write
3215
+
3216
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_FILERES_QUERY_SCHEMA_RESPONSE)); // GetEntityIfMoreRecentResponse - fileRes
3217
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.PUBLISH_IF_NEEDED_RESPONSE)); // xtk:fileRes#PublishIfNeeded
3218
+
3219
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_URL_RESPONSE)); // xtk:fileRes#GetURL
3220
+
3221
+ // Call upload
3222
+ const result = await client.fileUploader.upload({
3223
+ type: 'text/html',
3224
+ size: 12345
3225
+ })
3226
+ expect(result).toMatchObject({
3227
+ md5: "d8e8fca2dc0f896fd7cb4cb0031ba249",
3228
+ name: "test.txt",
3229
+ size: 12345,
3230
+ type: "text/html",
3231
+ url: "http://hello.com"
3232
+ });
3233
+ })
3234
+
3235
+ it('throws error with dependant failures', async () => {
3236
+ // Create a mock client and logon
3237
+ const client = await Mock.makeClient();
3238
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
3239
+ await client.NLWS.xtkSession.logon();
3240
+
3241
+ // Mock the upload protocol
3242
+ // - the upload.jsp (which returns the content of an iframe and JS to eval)
3243
+ // - call to xtk:counter#IncreaseValue (first, retrieve the schema xtk:counter then call the function)
3244
+ // - call to xtk:session#Write
3245
+ // - call to xtk:fileRes#PublishIfNeeded
3246
+ // - call to xtk:fileRes#GetURL
3247
+
3248
+ client._transport.mockReturnValueOnce(Promise.reject(`Some error occurred!!!`)); // upload.jsp
3249
+
3250
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_XTK_COUNTER_RESPONSE)); // GetEntityIfMoreRecentResponse - counter
3251
+ client._transport.mockReturnValueOnce(Mock.INCREASE_VALUE_RESPONSE);
3252
+
3253
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE); // GetEntityIfMoreRecentResponse - session
3254
+ client._transport.mockReturnValueOnce(Mock.FILE_RES_WRITE_RESPONSE); // xtk:session#Write
3255
+
3256
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_FILERES_QUERY_SCHEMA_RESPONSE)); // GetEntityIfMoreRecentResponse - fileRes
3257
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.PUBLISH_IF_NEEDED_RESPONSE)); // xtk:fileRes#PublishIfNeeded
3258
+
3259
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_URL_RESPONSE)); // xtk:fileRes#GetURL
3260
+ // For async handling
3261
+ expect.assertions(1)
3262
+ // Call upload
3263
+ await client.fileUploader.upload({
3264
+ type: 'text/html',
3265
+ size: 12345,
3266
+ name: 'abcd.txt'
3267
+ }).catch((ex) => {
3268
+ expect(ex.message).toMatch('500 - Error 16384: SDK-000013 "Failed to upload file abcd.txt. 500 - Error calling method \'/nl/jsp/uploadFile.jsp\': Some error occurred!!!');
3269
+ })
3270
+
3271
+ })
3272
+
3273
+ it('throws error with not okay response', async () => {
3274
+ // Create a mock client and logon
3275
+ const client = await Mock.makeClient();
3276
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
3277
+ await client.NLWS.xtkSession.logon();
3278
+
3279
+ // Mock the upload protocol
3280
+ // - the upload.jsp (which returns the content of an iframe and JS to eval)
3281
+ // - call to xtk:counter#IncreaseValue (first, retrieve the schema xtk:counter then call the function)
3282
+ // - call to xtk:session#Write
3283
+ // - call to xtk:fileRes#PublishIfNeeded
3284
+ // - call to xtk:fileRes#GetURL
3285
+
3286
+ client._transport.mockReturnValueOnce(Promise.resolve(`Some error occurred!!!`)); // upload.jsp
3287
+
3288
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_XTK_COUNTER_RESPONSE)); // GetEntityIfMoreRecentResponse - counter
3289
+ client._transport.mockReturnValueOnce(Mock.INCREASE_VALUE_RESPONSE);
3290
+
3291
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE); // GetEntityIfMoreRecentResponse - session
3292
+ client._transport.mockReturnValueOnce(Mock.FILE_RES_WRITE_RESPONSE); // xtk:session#Write
3293
+
3294
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_FILERES_QUERY_SCHEMA_RESPONSE)); // GetEntityIfMoreRecentResponse - fileRes
3295
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.PUBLISH_IF_NEEDED_RESPONSE)); // xtk:fileRes#PublishIfNeeded
3296
+
3297
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_URL_RESPONSE)); // xtk:fileRes#GetURL
3298
+ // For async handling
3299
+ expect.assertions(1)
3300
+ // Call upload
3301
+ await client.fileUploader.upload({
3302
+ type: 'text/html',
3303
+ size: 12345,
3304
+ name: 'abcd.txt'
3305
+ }).catch((ex) => {
3306
+ expect(ex.message).toMatch('500 - Error 16384: SDK-000013 "Failed to upload file abcd.txt. Some error occurred!!!');
3307
+ })
3308
+
3309
+ })
3310
+
3311
+ it('throws error with malformed response', async () => {
3312
+ // Create a mock client and logon
3313
+ const client = await Mock.makeClient();
3314
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
3315
+ await client.NLWS.xtkSession.logon();
3316
+
3317
+ // Mock the upload protocol
3318
+ // - the upload.jsp (which returns the content of an iframe and JS to eval)
3319
+ // - call to xtk:counter#IncreaseValue (first, retrieve the schema xtk:counter then call the function)
3320
+ // - call to xtk:session#Write
3321
+ // - call to xtk:fileRes#PublishIfNeeded
3322
+ // - call to xtk:fileRes#GetURL
3323
+
3324
+ client._transport.mockReturnValueOnce(Promise.resolve(`Ok
3325
+ <html xmlns="http://www.w3.org/1999/xhtml">
3326
+ <head>
3327
+ <script type="text/javascript">if(window.parent&&window.parent.document.controller&&"function"==typeof window.parent.document.controller.uploadFileCallBack){window.parent.document.controller.uploadFileCallBack([])}</script>
3328
+ </head>
3329
+ <body></body>
3330
+ </html>`)); // upload.jsp
3331
+
3332
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_XTK_COUNTER_RESPONSE)); // GetEntityIfMoreRecentResponse - counter
3333
+ client._transport.mockReturnValueOnce(Mock.INCREASE_VALUE_RESPONSE);
3334
+
3335
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE); // GetEntityIfMoreRecentResponse - session
3336
+ client._transport.mockReturnValueOnce(Mock.FILE_RES_WRITE_RESPONSE); // xtk:session#Write
3337
+
3338
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_FILERES_QUERY_SCHEMA_RESPONSE)); // GetEntityIfMoreRecentResponse - fileRes
3339
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.PUBLISH_IF_NEEDED_RESPONSE)); // xtk:fileRes#PublishIfNeeded
3340
+
3341
+ client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_URL_RESPONSE)); // xtk:fileRes#GetURL
3342
+ // For async handling
3343
+ expect.assertions(1)
3344
+ // Call upload
3345
+ await client.fileUploader.upload({
3346
+ type: 'text/html',
3347
+ size: 12345,
3348
+ name: 'abcd.txt'
3349
+ }).catch((ex) => {
3350
+ expect(ex.message).toMatch('500 - Error 16384: SDK-000013 "Failed to upload file abcd.txt. Malformed data:');
3351
+ })
3352
+
3353
+ })
3354
+ })
2888
3355
  });