@adobe/acc-js-sdk 1.1.19 → 1.1.21

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.
@@ -27,75 +27,75 @@ const { DomUtil } = require('../src/domUtil.js');
27
27
  describe('Caches', function() {
28
28
 
29
29
  describe("Generic cache", () => {
30
- it("Should cache with default TTL and default key function", () => {
30
+ it("Should cache with default TTL and default key function", async () => {
31
31
  const cache = new Cache();
32
- cache.put("Hello", "World");
32
+ await cache.put("Hello", "World");
33
33
  expect(cache._stats).toMatchObject({ reads: 0, writes: 1 });
34
- expect(cache.get("Hello")).toBe("World");
34
+ await expect(cache.get("Hello")).resolves.toBe("World");
35
35
  expect(cache._stats).toMatchObject({ reads: 1, writes: 1, memoryHits: 1, storageHits: 0 });
36
36
  })
37
37
 
38
- it("Should expires after TTL", () => {
38
+ it("Should expires after TTL", async () => {
39
39
  const cache = new Cache(undefined, undefined, -1); // negative TTL => will immediately expire
40
- cache.put("Hello", "World");
41
- expect(cache.get("Hello")).toBeUndefined();
40
+ await cache.put("Hello", "World");
41
+ await expect(cache.get("Hello")).resolves.toBeUndefined();
42
42
  expect(cache._stats).toMatchObject({ reads: 1, writes: 1, memoryHits: 0, storageHits: 0 });
43
43
  })
44
44
 
45
- it("Should support custom key function", () => {
45
+ it("Should support custom key function", async () => {
46
46
  const cache = new Cache(undefined, undefined, 300000, ((a, b) => a + "||" + b));
47
- cache.put("key-part-1", "key-part-2", "value");
48
- expect(cache.get("key-part-1")).toBeUndefined();
49
- expect(cache.get("key-part-2")).toBeUndefined();
50
- expect(cache.get("key-part-1", "key-part-2")).toBe("value");
47
+ await cache.put("key-part-1", "key-part-2", "value");
48
+ await expect(cache.get("key-part-1")).resolves.toBeUndefined();
49
+ await expect(cache.get("key-part-2")).resolves.toBeUndefined();
50
+ await expect(cache.get("key-part-1", "key-part-2")).resolves.toBe("value");
51
51
  })
52
52
 
53
- it("Should clear cache", () => {
53
+ it("Should clear cache", async () => {
54
54
  const cache = new Cache();
55
- cache.put("Hello", "World");
56
- expect(cache.get("Hello")).toBe("World");
57
- cache.clear();
58
- expect(cache.get("Hello")).toBeUndefined();
55
+ await cache.put("Hello", "World");
56
+ await expect(cache.get("Hello")).resolves.toBe("World");
57
+ await cache.clear();
58
+ await expect(cache.get("Hello")).resolves.toBeUndefined();
59
59
  expect(cache._stats).toMatchObject({ reads: 2, writes: 1, memoryHits: 1, storageHits: 0, clears: 1 });
60
60
  })
61
61
 
62
- it("Should remove key in cache", () => {
62
+ it("Should remove key in cache", async () => {
63
63
  const cache = new Cache();
64
- cache.put("Hello", "World");
65
- cache.put("Hi", "A");
66
- expect(cache.get("Hello")).toBe("World");
67
- expect(cache.get("Hi")).toBe("A");
64
+ await cache.put("Hello", "World");
65
+ await cache.put("Hi", "A");
66
+ await expect(cache.get("Hello")).resolves.toBe("World");
67
+ await expect(cache.get("Hi")).resolves.toBe("A");
68
68
  expect(cache._stats).toMatchObject({ reads: 2, writes: 2, memoryHits: 2 });
69
- cache.remove("Hello");
70
- expect(cache.get("Hello")).toBeUndefined();
71
- expect(cache.get("Hi")).toBe("A");
69
+ await cache.remove("Hello");
70
+ await expect(cache.get("Hello")).resolves.toBeUndefined();
71
+ await expect(cache.get("Hi")).resolves.toBe("A");
72
72
  expect(cache._stats).toMatchObject({ reads: 4, writes: 2, memoryHits: 3, removals: 1 });
73
73
  // should support removing a key which has already been removed
74
- cache.remove("Hello");
75
- expect(cache.get("Hello")).toBeUndefined();
76
- expect(cache.get("Hi")).toBe("A");
74
+ await cache.remove("Hello");
75
+ await expect(cache.get("Hello")).resolves.toBeUndefined();
76
+ await expect(cache.get("Hi")).resolves.toBe("A");
77
77
  })
78
78
  });
79
79
 
80
80
  describe("Entity cache", function() {
81
- it("Should cache value", function() {
81
+ it("Should cache value", async () => {
82
82
  const cache = new XtkEntityCache();
83
- assert.equal(cache.get("xtk:srcSchema", "nms:recipient"), undefined);
84
- cache.put("xtk:srcSchema", "nms:recipient", "$$entity$$");
85
- assert.equal(cache.get("xtk:srcSchema", "nms:recipient"), "$$entity$$");
83
+ await expect(cache.get("xtk:srcSchema", "nms:recipient")).resolves.toBeUndefined();
84
+ await cache.put("xtk:srcSchema", "nms:recipient", "$$entity$$");
85
+ await expect(cache.get("xtk:srcSchema", "nms:recipient")).resolves.toBe("$$entity$$");
86
86
  });
87
87
 
88
- it("Should cache interfaces", function() {
88
+ it("Should cache interfaces", async () => {
89
89
  const cache = new XtkEntityCache();
90
90
  const schema = DomUtil.parse(`<schema namespace="xtk" name="session" implements="xtk:persist">
91
91
  <interface name="persist"/>
92
92
  <element name="session"/>
93
93
  </schema>`);
94
- cache.put("xtk:schema", "xtk:session", schema.documentElement);
95
- const session = cache.get("xtk:schema", "xtk:session");
94
+ await cache.put("xtk:schema", "xtk:session", schema.documentElement);
95
+ const session = await cache.get("xtk:schema", "xtk:session");
96
96
  expect(session).not.toBeNull();
97
97
  expect(session.getAttribute("name")).toBe("session");
98
- const persist = cache.get("xtk:schema", "xtk:persist");
98
+ const persist = await cache.get("xtk:schema", "xtk:persist");
99
99
  expect(persist).not.toBeNull();
100
100
  expect(persist.getAttribute("name")).toBe("persist");
101
101
  });
@@ -104,124 +104,124 @@ describe('Caches', function() {
104
104
 
105
105
  describe("Option cache", function() {
106
106
 
107
- it("Should cache value", function() {
107
+ it("Should cache value", async () => {
108
108
  const cache = new OptionCache();
109
- expect(cache.get("hello")).toBeUndefined();
110
- cache.put("hello", ["world", 6]);
111
- expect(cache.get("hello")).toBe("world");
112
- expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
109
+ await expect(cache.get("hello")).resolves.toBeUndefined();
110
+ await cache.put("hello", ["world", 6]);
111
+ await expect(cache.get("hello")).resolves.toBe("world");
112
+ await expect(cache.getOption("hello")).resolves.toEqual({"rawValue": "world", "type": 6, "value": "world"});
113
113
  });
114
114
 
115
- it("Should cache multiple value", function() {
115
+ it("Should cache multiple value", async () => {
116
116
  const cache = new OptionCache();
117
- cache.put("hello", ["world", 6]);
118
- cache.put("foo", ["bar", 6]);
119
- expect(cache.get("hello")).toBe("world");
120
- expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
121
- expect(cache.get("foo")).toBe("bar");
122
- expect(cache.getOption("foo")).toEqual({"rawValue": "bar", "type": 6, "value": "bar"});
117
+ await cache.put("hello", ["world", 6]);
118
+ await cache.put("foo", ["bar", 6]);
119
+ await expect(cache.get("hello")).resolves.toBe("world");
120
+ await expect(cache.getOption("hello")).resolves.toEqual({"rawValue": "world", "type": 6, "value": "world"});
121
+ await expect(cache.get("foo")).resolves.toBe("bar");
122
+ await expect(cache.getOption("foo")).resolves.toEqual({"rawValue": "bar", "type": 6, "value": "bar"});
123
123
  });
124
124
 
125
- it("Should overwrite cached value", function() {
125
+ it("Should overwrite cached value", async () => {
126
126
  const cache = new OptionCache();
127
- cache.put("hello", ["world", 6]);
128
- expect(cache.get("hello")).toBe( "world");
129
- expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
130
- cache.put("hello", ["cruel world", 6]);
131
- expect(cache.get("hello")).toBe("cruel world");
132
- expect(cache.getOption("hello")).toEqual({"rawValue": "cruel world", "type": 6, "value": "cruel world"});
127
+ await cache.put("hello", ["world", 6]);
128
+ await expect(cache.get("hello")).resolves.toBe( "world");
129
+ await expect(cache.getOption("hello")).resolves.toEqual({"rawValue": "world", "type": 6, "value": "world"});
130
+ await cache.put("hello", ["cruel world", 6]);
131
+ await expect(cache.get("hello")).resolves.toBe("cruel world");
132
+ await expect(cache.getOption("hello")).resolves.toEqual({"rawValue": "cruel world", "type": 6, "value": "cruel world"});
133
133
  });
134
134
 
135
- it("Should clear cache", function() {
135
+ it("Should clear cache", async () => {
136
136
  const cache = new OptionCache();
137
- cache.put("hello", ["world", 6]);
138
- expect(cache.get("hello")).toBe("world");
139
- expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
140
- cache.clear();
141
- expect(cache.get("hello")).toBeUndefined();
142
- expect(cache.getOption("hello")).toBeUndefined();
137
+ await cache.put("hello", ["world", 6]);
138
+ await expect(cache.get("hello")).resolves.toBe("world");
139
+ await expect(cache.getOption("hello")).resolves.toEqual({"rawValue": "world", "type": 6, "value": "world"});
140
+ await cache.clear();
141
+ await expect(cache.get("hello")).resolves.toBeUndefined();
142
+ await expect(cache.getOption("hello")).resolves.toBeUndefined();
143
143
  });
144
144
 
145
- it("Should not find", function() {
145
+ it("Should not find", async () => {
146
146
  const cache = new OptionCache();
147
- expect(cache.get("hello")).toBeUndefined();
148
- expect(cache.getOption("hello")).toBeUndefined();
147
+ await expect(cache.get("hello")).resolves.toBeUndefined();
148
+ await expect(cache.getOption("hello")).resolves.toBeUndefined();
149
149
  });
150
150
 
151
- it("Deprecated cache methods should now replaced with put", () => {
151
+ it("Deprecated cache methods should now replaced with put", async () => {
152
152
  const cache = new OptionCache();
153
- cache.cache("hello", ["world", 6]);
154
- expect(cache.get("hello")).toBe("world");
155
- expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
153
+ await cache.cache("hello", ["world", 6]);
154
+ await expect(cache.get("hello")).resolves.toBe("world");
155
+ await expect(cache.getOption("hello")).resolves.toEqual({"rawValue": "world", "type": 6, "value": "world"});
156
156
  });
157
157
  });
158
158
 
159
159
  describe("Method cache", function() {
160
- it("Should cache methods", function() {
160
+ it("Should cache methods", async () => {
161
161
  const cache = new MethodCache();
162
162
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><method name='Create'/></methods></schema>");
163
- cache.put(schema.documentElement);
163
+ await cache.put(schema.documentElement);
164
164
 
165
- var found = cache.get("nms:recipient", "Delete");
165
+ var found = await cache.get("nms:recipient", "Delete");
166
166
  assert.ok(found !== null && found !== undefined);
167
167
  assert.equal(found.nodeName, "method");
168
168
  assert.equal(found.getAttribute("name"), "Delete");
169
169
 
170
- found = cache.get("nms:recipient", "Create");
170
+ found = await cache.get("nms:recipient", "Create");
171
171
  assert.ok(found !== null && found !== undefined);
172
172
  assert.equal(found.nodeName, "method");
173
173
  assert.equal(found.getAttribute("name"), "Create");
174
174
  });
175
175
 
176
- it("Should cache interface methods", function() {
176
+ it("Should cache interface methods", async () => {
177
177
  const cache = new MethodCache();
178
178
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient' implements='nms:i'><interface name='i'><method name='Update'/></interface><element name='recipient'/><methods><method name='Delete'/><method name='Create'/></methods></schema>");
179
- cache.put(schema.documentElement);
179
+ await cache.put(schema.documentElement);
180
180
  // interface method should be on schema
181
- var found = cache.get("nms:recipient", "Update");
181
+ var found = await cache.get("nms:recipient", "Update");
182
182
  assert.ok(found !== null && found !== undefined);
183
183
  // and on interface as well
184
- found = cache.get("nms:i", "Update");
184
+ found = await cache.get("nms:i", "Update");
185
185
  assert.ok(found !== null && found !== undefined);
186
186
  });
187
187
 
188
- it("Should clear the cache", function() {
188
+ it("Should clear the cache", async () => {
189
189
  const cache = new MethodCache();
190
190
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><method name='Create'/></methods></schema>");
191
- cache.put(schema.documentElement);
191
+ await cache.put(schema.documentElement);
192
192
 
193
- var found = cache.get("nms:recipient", "Delete");
193
+ var found = await cache.get("nms:recipient", "Delete");
194
194
  assert.ok(found !== null && found !== undefined);
195
195
 
196
- cache.clear();
197
- found = cache.get("nms:recipient", "Delete");
196
+ await cache.clear();
197
+ found = await cache.get("nms:recipient", "Delete");
198
198
  assert.ok(found === undefined);
199
199
  });
200
200
 
201
- it("Should ignore non-method nodes", function() {
201
+ it("Should ignore non-method nodes", async () => {
202
202
  const cache = new MethodCache();
203
203
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><dummy name='Update'/><method name='Create'/></methods></schema>");
204
- cache.put(schema.documentElement);
204
+ await cache.put(schema.documentElement);
205
205
 
206
- var found = cache.get("nms:recipient", "Delete");
206
+ var found = await cache.get("nms:recipient", "Delete");
207
207
  assert.ok(found !== null && found !== undefined);
208
- found = cache.get("nms:recipient", "Update");
208
+ found = await cache.get("nms:recipient", "Update");
209
209
  assert.ok(found === undefined);
210
- found = cache.get("nms:recipient", "Create");
210
+ found = await cache.get("nms:recipient", "Create");
211
211
  assert.ok(found !== null && found !== undefined);
212
212
  });
213
213
 
214
- it("Deprecated cache methods should now replaced with put", () => {
214
+ it("Deprecated cache methods should now replaced with put", async () => {
215
215
  const cache = new MethodCache();
216
216
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><method name='Create'/></methods></schema>");
217
- cache.cache(schema.documentElement);
217
+ await cache.cache(schema.documentElement);
218
218
 
219
- var found = cache.get("nms:recipient", "Delete");
219
+ var found = await cache.get("nms:recipient", "Delete");
220
220
  assert.ok(found !== null && found !== undefined);
221
221
  assert.equal(found.nodeName, "method");
222
222
  assert.equal(found.getAttribute("name"), "Delete");
223
223
 
224
- found = cache.get("nms:recipient", "Create");
224
+ found = await cache.get("nms:recipient", "Create");
225
225
  assert.ok(found !== null && found !== undefined);
226
226
  assert.equal(found.nodeName, "method");
227
227
  assert.equal(found.getAttribute("name"), "Create");
@@ -240,71 +240,71 @@ describe('Caches', function() {
240
240
  });
241
241
 
242
242
  describe("Method cache for interfaces", function() {
243
- it("Should cache methods", function() {
243
+ it("Should cache methods", async () => {
244
244
  const cache = new MethodCache();
245
245
  // Test for fix in verion 0.1.23. The xtk:session schema has a direct method "Logon" but also implements the
246
246
  // xtk:persist interface.
247
247
  var schema = DomUtil.parse("<schema namespace='xtk' name='session' implements='xtk:persist'><interface name='persist'><method name='Write' static='true'/></interface><methods><method name='Logon'/></methods></schema>");
248
- cache.put(schema.documentElement);
248
+ await cache.put(schema.documentElement);
249
249
 
250
250
  // Logon method should be found in xtk:session and have the xtk:session URN (for SOAP action)
251
- var found = cache.get("xtk:session", "Logon");
252
- var urn = cache.getSoapUrn("xtk:session", "Logon");
251
+ var found = await cache.get("xtk:session", "Logon");
252
+ var urn = await cache.getSoapUrn("xtk:session", "Logon");
253
253
  assert.ok(found !== null && found !== undefined);
254
254
  assert.strictEqual(found.nodeName, "method");
255
255
  assert.strictEqual(found.getAttribute("name"), "Logon");
256
256
  assert.strictEqual(urn, "xtk:session");
257
257
 
258
258
  // Logon method should not exist on the xtk:persist interface
259
- found = cache.get("xtk:persist", "Logon");
260
- urn = cache.getSoapUrn("xtk:persist", "Logon");
259
+ found = await cache.get("xtk:persist", "Logon");
260
+ urn = await cache.getSoapUrn("xtk:persist", "Logon");
261
261
  assert.ok(found === undefined);
262
262
  assert.ok(urn === undefined);
263
263
 
264
264
  // The Write method should also be on xtk:session but use xtk:persist as a URN
265
- found = cache.get("xtk:session", "Write");
266
- urn = cache.getSoapUrn("xtk:session", "Write");
265
+ found = await cache.get("xtk:session", "Write");
266
+ urn = await cache.getSoapUrn("xtk:session", "Write");
267
267
  assert.ok(found !== null && found !== undefined);
268
268
  assert.strictEqual(found.nodeName, "method");
269
269
  assert.strictEqual(found.getAttribute("name"), "Write");
270
270
  assert.strictEqual(urn, "xtk:persist|xtk:session");
271
271
 
272
272
  // For compatibility reasons (SDK versions earlier than 0.1.23), keep the Write method on the interface too
273
- found = cache.get("xtk:persist", "Write");
274
- urn = cache.getSoapUrn("xtk:persist", "Write");
273
+ found = await cache.get("xtk:persist", "Write");
274
+ urn = await cache.getSoapUrn("xtk:persist", "Write");
275
275
  assert.ok(found !== null && found !== undefined);
276
276
  assert.strictEqual(found.nodeName, "method");
277
277
  assert.strictEqual(found.getAttribute("name"), "Write");
278
278
  assert.strictEqual(urn, "xtk:persist");
279
279
  });
280
280
 
281
- it("Edge cases for getSoapUrn", () => {
281
+ it("Edge cases for getSoapUrn", async () => {
282
282
  const cache = new MethodCache();
283
283
  var schema = DomUtil.parse("<schema namespace='xtk' name='session' implements='xtk:persist'><interface name='persist'><method name='Write' static='true'/></interface><methods><method name='Logon'/></methods></schema>");
284
- cache.put(schema.documentElement);
284
+ await cache.put(schema.documentElement);
285
285
 
286
286
  // Schema and method exist
287
- var urn = cache.getSoapUrn("xtk:session", "Logon");
287
+ var urn = await cache.getSoapUrn("xtk:session", "Logon");
288
288
  expect(urn).toBe("xtk:session");
289
289
 
290
290
  // Schema exists but method doesn't
291
- urn = cache.getSoapUrn("xtk:session", "Dummy");
291
+ urn = await cache.getSoapUrn("xtk:session", "Dummy");
292
292
  expect(urn).toBeUndefined();
293
293
 
294
294
  // Neither schema nor method exist
295
- urn = cache.getSoapUrn("xtk:dummy", "Dummy");
295
+ urn = await cache.getSoapUrn("xtk:dummy", "Dummy");
296
296
  expect(urn).toBeUndefined();
297
297
  });
298
298
 
299
- it("Schema has interfaces that do not match what schema implements", () => {
299
+ it("Schema has interfaces that do not match what schema implements", async () => {
300
300
  const cache = new MethodCache();
301
301
  // Schema has xtk:persist interface but does not implement it
302
302
  var schema = DomUtil.parse("<schema namespace='xtk' name='session'><interface name='persist'><method name='Write' static='true'/></interface><methods><method name='Logon'/></methods></schema>");
303
- cache.put(schema.documentElement);
303
+ await cache.put(schema.documentElement);
304
304
 
305
305
  // Logon method should be found in xtk:session and have the xtk:session URN (for SOAP action)
306
- var found = cache.get("xtk:session", "Logon");
307
- var urn = cache.getSoapUrn("xtk:session", "Logon");
306
+ var found = await cache.get("xtk:session", "Logon");
307
+ var urn = await cache.getSoapUrn("xtk:session", "Logon");
308
308
  assert.ok(found !== null && found !== undefined);
309
309
  assert.strictEqual(found.nodeName, "method");
310
310
  assert.strictEqual(found.getAttribute("name"), "Logon");
@@ -316,18 +316,18 @@ describe('Caches', function() {
316
316
 
317
317
  describe("JSON safe storage", () => {
318
318
 
319
- it("Should find mock json from the cache", () => {
319
+ it("Should find mock json from the cache", async () => {
320
320
  const map = {};
321
321
  const delegate = {
322
322
  getItem: jest.fn((key) => map[key]),
323
323
  setItem: jest.fn((key, value) => map[key] = value)
324
324
  }
325
325
  const storage = new SafeStorage(delegate, "");
326
- expect(storage.getItem("not_found")).toBeUndefined();
326
+ await expect(storage.getItem("not_found")).resolves.toBeUndefined();
327
327
  map["k1"] = `{ "hello": "world" }`;
328
- expect(storage.getItem("k1")).toMatchObject({ hello: "world" });
328
+ await expect(storage.getItem("k1")).resolves.toMatchObject({ hello: "world" });
329
329
  map["k2"] = `{ "value": { "hello": "world" } }`;
330
- expect(storage.getItem("k2")).toMatchObject({ value: { hello: "world" } });
330
+ await expect(storage.getItem("k2")).resolves.toMatchObject({ value: { hello: "world" } });
331
331
  });
332
332
  });
333
333
 
@@ -346,32 +346,32 @@ describe('Caches', function() {
346
346
  }
347
347
  };
348
348
 
349
- it("Should find mock xml from the cache", () => {
349
+ it("Should find mock xml from the cache", async () => {
350
350
  const map = {};
351
351
  const delegate = {
352
352
  getItem: jest.fn((key) => map[key]),
353
353
  setItem: jest.fn((key, value) => map[key] = value)
354
354
  }
355
355
  const storage = new SafeStorage(delegate, "", xmlSerDeser);
356
- expect(storage.getItem("not_found")).toBeUndefined();
356
+ await expect(storage.getItem("not_found")).resolves.toBeUndefined();
357
357
  map["k1"] = `{ "hello": "world" }`;
358
- expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute containing serialized XML
358
+ await expect(storage.getItem("k1")).resolves.toBeUndefined(); // k1 cached object does not have "value" attribute containing serialized XML
359
359
  map["k1"] = `{ "hello": "world", "value": "" }`;
360
- expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute containing serialized XML
360
+ await expect(storage.getItem("k1")).resolves.toBeUndefined(); // k1 cached object does not have "value" attribute containing serialized XML
361
361
  map["k1"] = `{ "value": { "hello": "world" } }`;
362
- expect(storage.getItem("k2")).toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
362
+ await expect(storage.getItem("k2")).resolves.toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
363
363
  map["k1"] = `{ "value": "" } }`;
364
- expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
364
+ await expect(storage.getItem("k1")).resolves.toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
365
365
  map["k1"] = `{ "value": "bad" } }`;
366
- expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
366
+ await expect(storage.getItem("k1")).resolves.toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
367
367
  map["k2"] = `{ "value": "<hello/>" }`;
368
- expect(storage.getItem("k2").value.tagName).toBe("hello");
368
+ await expect(storage.getItem("k2")).resolves.toMatchObject({ value: {tagName: "hello"}});
369
369
  });
370
370
  });
371
371
  });
372
372
 
373
373
  describe("Cache seralizers", () => {
374
- it("Should serialize json", () => {
374
+ it("Should serialize json", async () => {
375
375
  const cache = new OptionCache();
376
376
  const serDeser = cache._storage._serDeser;
377
377
  expect(serDeser({ hello: "World" }, true)).toBe('{"hello":"World"}');
@@ -446,5 +446,33 @@ describe('Caches', function() {
446
446
  expect(cached.value.x).toBe(3);
447
447
  expect(cached.value.method.documentElement.tagName).toBe("hello");
448
448
  })
449
- })
449
+ });
450
+
451
+ describe("Sync and Async delegates", () => {
452
+ it("Should support synchronous delegates", async () => {
453
+ const map = {};
454
+ const delegate = {
455
+ getItem: jest.fn((key) => map[key]),
456
+ setItem: jest.fn((key, value) => map[key] = value)
457
+ }
458
+ const storage = new SafeStorage(delegate, "");
459
+ await storage.setItem("Hello", { cruel: "World" });
460
+ await expect(storage.getItem("Hello")).resolves.toMatchObject({ cruel: "World" });
461
+ });
462
+ it("Should support asynchronous delegates", async () => {
463
+ const map = {};
464
+ const delegate = {
465
+ getItem: jest.fn(async (key) => Promise.resolve(map[key]) ),
466
+ setItem: jest.fn(async (key, value) => {
467
+ return new Promise((resolve, reject) => {
468
+ map[key] = value;
469
+ resolve(value);
470
+ });
471
+ })
472
+ }
473
+ const storage = new SafeStorage(delegate, "");
474
+ await storage.setItem("Hello", { cruel: "World" });
475
+ await expect(storage.getItem("Hello")).resolves.toMatchObject({ cruel: "World" });
476
+ });
477
+ });
450
478
  });
@@ -247,7 +247,7 @@ describe('ACC Client', function () {
247
247
  databaseId = await client.getOption("XtkDatabaseId", false);
248
248
  expect(databaseId).toBe("uFE80000000000000F1FA913DD7CC7C480041161C");
249
249
  // Clear cache
250
- client.clearOptionCache();
250
+ await client.clearOptionCache();
251
251
  client._transport.mockReturnValueOnce(Mock.GET_DATABASEID_RESPONSE);
252
252
  databaseId = await client.getOption("XtkDatabaseId");
253
253
  expect(databaseId).toBe("uFE80000000000000F1FA913DD7CC7C480041161C");
@@ -401,7 +401,7 @@ describe('ACC Client', function () {
401
401
  expect(schema["name"]).toBe("extAccount");
402
402
 
403
403
  // Clear cache and ask again
404
- client.clearEntityCache();
404
+ await client.clearEntityCache();
405
405
  client._transport.mockReturnValueOnce(Mock.GET_NMS_EXTACCOUNT_SCHEMA_RESPONSE);
406
406
  schema = await client.getSchema("nms:extAccount");
407
407
  expect(schema["namespace"]).toBe("nms");
@@ -421,11 +421,11 @@ describe('ACC Client', function () {
421
421
  await expect(client.getSchema("nms:extAccount", "invalid")).rejects.toMatchObject({ errorCode: 'SDK-000004' });
422
422
 
423
423
  // Get missing schema
424
- client.clearAllCaches();
424
+ await client.clearAllCaches();
425
425
  client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
426
426
  schema = await client.getSchema("nms:dummy", "BadgerFish");
427
427
  expect(schema).toBeNull();
428
- client.clearAllCaches();
428
+ await client.clearAllCaches();
429
429
  client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
430
430
  schema = await client.getSchema("nms:dummy", "xml");
431
431
  expect(schema).toBeNull();
@@ -477,13 +477,13 @@ describe('ACC Client', function () {
477
477
  client._representation = "xml";
478
478
 
479
479
  // Get non-cached XML representation
480
- client.clearAllCaches();
480
+ await client.clearAllCaches();
481
481
  client._transport.mockReturnValueOnce(Mock.GET_NMS_EXTACCOUNT_SCHEMA_RESPONSE);
482
482
  sysEnum = await client.getSysEnum("nms:extAccount:encryptionType");
483
483
  expect(sysEnum.getAttribute("basetype")).toBe("byte");
484
484
 
485
485
  // Schema does not exist
486
- client.clearAllCaches();
486
+ await client.clearAllCaches();
487
487
  client._transport.mockReturnValueOnce(Mock.GET_MISSING_SCHEMA_RESPONSE);
488
488
  await expect(client.getSysEnum("nms:dummy:encryptionType")).rejects.toMatchObject({ errorCode: "SDK-000006" });
489
489
 
@@ -701,7 +701,7 @@ describe('ACC Client', function () {
701
701
  expect(cipher.iv).not.toBeNull();
702
702
 
703
703
  // Ask again, should be cached (no mock methods)
704
- client.clearAllCaches();
704
+ await client.clearAllCaches();
705
705
  cipher = await client._getSecretKeyCipher();
706
706
  expect(cipher).not.toBeNull();
707
707
  expect(cipher.key).not.toBeNull();
@@ -2283,6 +2283,7 @@ describe('ACC Client', function () {
2283
2283
  client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_RESPONSE);
2284
2284
  client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
2285
2285
  await client.NLWS.xtkSession.logon();
2286
+ storage.getItem.mockReturnValueOnce(undefined); // lastCleared
2286
2287
  storage.getItem.mockReturnValueOnce(JSON.stringify({value: { value: "Hello", type: 6 }, cachedAt: 1633715996021 }));
2287
2288
  const value = await client.getOption("XtkDatabaseId");
2288
2289
  expect(value).toBe("Hello");
@@ -2297,6 +2298,7 @@ describe('ACC Client', function () {
2297
2298
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2298
2299
  client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
2299
2300
  await client.NLWS.xtkSession.logon();
2301
+ storage.getItem.mockReturnValueOnce(undefined); // lastCleared
2300
2302
  storage.getItem.mockReturnValueOnce(JSON.stringify({value: { value: "Hello", type: 6 }, cachedAt: 1633715996021 }));
2301
2303
  client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
2302
2304
  <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/'>
@@ -2443,12 +2445,57 @@ describe('ACC Client', function () {
2443
2445
  expect(NLWS).toBeTruthy();
2444
2446
  expect(client.isLogged()).toBe(false);
2445
2447
  })
2448
+
2449
+ it("Should support storage key type without version information", async () => {
2450
+ // Default has version & instance name
2451
+ const version = sdk.getSDKVersion().version; // "${version}" or similar
2452
+ connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin");
2453
+ var client = await sdk.init(connectionParameters);
2454
+ expect(client._optionCache._storage._rootKey).toBe(`acc.js.sdk.${version}.acc-sdk:8080.cache.OptionCache$`);
2455
+
2456
+ // Default has version & instance name
2457
+ connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", { cacheRootKey: "default" });
2458
+ var client = await sdk.init(connectionParameters);
2459
+ expect(client._optionCache._storage._rootKey).toBe(`acc.js.sdk.${version}.acc-sdk:8080.cache.OptionCache$`);
2460
+
2461
+ // No prefix
2462
+ connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", { cacheRootKey: "none" });
2463
+ var client = await sdk.init(connectionParameters);
2464
+ expect(client._optionCache._storage._rootKey).toBe(`OptionCache$`);
2465
+ });
2466
+
2467
+ describe("Should simulate the Shell Cache API", () => {
2468
+ // See https://github.com/AdobeDocs/exc-app/blob/master/docs/modules/cache.md#sample-code
2469
+ it("Sould get cached option", async () => {
2470
+ const storage = {
2471
+ getItem: jest.fn(),
2472
+ setItem: jest.fn(),
2473
+ }
2474
+ const client = await Mock.makeClient({ storage: storage, cacheRootKey: "instance" });
2475
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2476
+ await client.NLWS.xtkSession.logon();
2477
+ storage.getItem.mockReturnValueOnce(Promise.resolve(undefined)); // lastCleared
2478
+ storage.getItem.mockReturnValueOnce(Promise.resolve(JSON.stringify({value: { value: "Hello", type: 6 }, cachedAt: 1633715996021 })));
2479
+ const value = await client.getOption("Test");
2480
+ expect(value).toBe("Hello");
2481
+ expect(storage.setItem.mock.calls.length).toBe(0);
2482
+
2483
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
2484
+ client._transport.mockReturnValueOnce(Mock.GET_DATABASEID_RESPONSE);
2485
+ var databaseId = await client.getOption("XtkDatabaseId");
2486
+ expect(databaseId).toBe("uFE80000000000000F1FA913DD7CC7C480041161C");
2487
+ const lastCall = storage.setItem.mock.calls[storage.setItem.mock.calls.length-1];
2488
+ expect(lastCall[0]).toMatch("OptionCache$XtkDatabaseId");
2489
+ expect(lastCall[0]).not.toMatch("acc.js.sdk");
2490
+ expect(lastCall[1]).toMatch("uFE80000000000000F1FA913DD7CC7C480041161C");
2491
+ });
2492
+ });
2446
2493
  })
2447
2494
 
2448
2495
  describe("Get Schema, cache and representations", () => {
2449
2496
  it("Should get schema with no cache", async () => {
2450
2497
  const client = await Mock.makeClient();
2451
- client.clearAllCaches();
2498
+ await client.clearAllCaches();
2452
2499
  client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2453
2500
  await client.NLWS.xtkSession.logon();
2454
2501
 
@@ -336,7 +336,7 @@ describe('ACC Client Observability', function () {
336
336
  </SOAP-ENV:Envelope>`);
337
337
  };
338
338
  client._transport.mockImplementationOnce(getOption);
339
- client.clearOptionCache();
339
+ await client.clearOptionCache();
340
340
  var value = await client.getOption("Dummy");
341
341
  expect(value).toBe("DummyZZ");
342
342
 
@@ -345,7 +345,7 @@ describe('ACC Client Observability', function () {
345
345
  if (inputParameters[0].value === "Dummy") inputParameters[0].value = "XtkDatabaseId";
346
346
  });
347
347
  client._transport.mockImplementationOnce(getOption);
348
- client.clearOptionCache();
348
+ await client.clearOptionCache();
349
349
  var value = await client.getOption("Dummy");
350
350
  expect(value).toBe("XtkDatabaseIdZZ");
351
351