@adobe/acc-js-sdk 1.0.2 → 1.0.6

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.
@@ -18,6 +18,7 @@ governing permissions and limitations under the License.
18
18
  *********************************************************************************/
19
19
 
20
20
  const assert = require('assert');
21
+ const { Cache, SafeStorage } = require('../src/cache.js');
21
22
  const OptionCache = require('../src/optionCache.js').OptionCache;
22
23
  const MethodCache = require('../src/methodCache.js').MethodCache;
23
24
  const XtkEntityCache = require('../src/xtkEntityCache.js').XtkEntityCache;
@@ -25,6 +26,36 @@ const { DomUtil } = require('../src/domUtil.js');
25
26
 
26
27
  describe('Caches', function() {
27
28
 
29
+ describe("Generic cache", () => {
30
+ it("Should cache with default TTL and default key function", () => {
31
+ const cache = new Cache();
32
+ cache.put("Hello", "World");
33
+ expect(cache.get("Hello")).toBe("World");
34
+ })
35
+
36
+ it("Should expires after TTL", () => {
37
+ const cache = new Cache(undefined, undefined, -1); // negative TTL => will immediately expire
38
+ cache.put("Hello", "World");
39
+ expect(cache.get("Hello")).toBeUndefined();
40
+ })
41
+
42
+ it("Should support custom key function", () => {
43
+ const cache = new Cache(undefined, undefined, 300000, ((a, b) => a + "||" + b));
44
+ cache.put("key-part-1", "key-part-2", "value");
45
+ expect(cache.get("key-part-1")).toBeUndefined();
46
+ expect(cache.get("key-part-2")).toBeUndefined();
47
+ expect(cache.get("key-part-1", "key-part-2")).toBe("value");
48
+ })
49
+
50
+ it("Should clear cache", () => {
51
+ const cache = new Cache();
52
+ cache.put("Hello", "World");
53
+ expect(cache.get("Hello")).toBe("World");
54
+ cache.clear();
55
+ expect(cache.get("Hello")).toBeUndefined();
56
+ })
57
+ })
58
+
28
59
  describe("Entity cache", function() {
29
60
  it("Should cache value", function() {
30
61
  const cache = new XtkEntityCache();
@@ -55,15 +86,15 @@ describe('Caches', function() {
55
86
  it("Should cache value", function() {
56
87
  const cache = new OptionCache();
57
88
  expect(cache.get("hello")).toBeUndefined();
58
- cache.cache("hello", ["world", 6]);
89
+ cache.put("hello", ["world", 6]);
59
90
  expect(cache.get("hello")).toBe("world");
60
91
  expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
61
92
  });
62
93
 
63
94
  it("Should cache multiple value", function() {
64
95
  const cache = new OptionCache();
65
- cache.cache("hello", ["world", 6]);
66
- cache.cache("foo", ["bar", 6]);
96
+ cache.put("hello", ["world", 6]);
97
+ cache.put("foo", ["bar", 6]);
67
98
  expect(cache.get("hello")).toBe("world");
68
99
  expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
69
100
  expect(cache.get("foo")).toBe("bar");
@@ -72,17 +103,17 @@ describe('Caches', function() {
72
103
 
73
104
  it("Should overwrite cached value", function() {
74
105
  const cache = new OptionCache();
75
- cache.cache("hello", ["world", 6]);
106
+ cache.put("hello", ["world", 6]);
76
107
  expect(cache.get("hello")).toBe( "world");
77
108
  expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
78
- cache.cache("hello", ["cruel world", 6]);
109
+ cache.put("hello", ["cruel world", 6]);
79
110
  expect(cache.get("hello")).toBe("cruel world");
80
111
  expect(cache.getOption("hello")).toEqual({"rawValue": "cruel world", "type": 6, "value": "cruel world"});
81
112
  });
82
113
 
83
114
  it("Should clear cache", function() {
84
115
  const cache = new OptionCache();
85
- cache.cache("hello", ["world", 6]);
116
+ cache.put("hello", ["world", 6]);
86
117
  expect(cache.get("hello")).toBe("world");
87
118
  expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
88
119
  cache.clear();
@@ -96,13 +127,19 @@ describe('Caches', function() {
96
127
  expect(cache.getOption("hello")).toBeUndefined();
97
128
  });
98
129
 
130
+ it("Deprecated cache methods should now replaced with put", () => {
131
+ const cache = new OptionCache();
132
+ cache.cache("hello", ["world", 6]);
133
+ expect(cache.get("hello")).toBe("world");
134
+ expect(cache.getOption("hello")).toEqual({"rawValue": "world", "type": 6, "value": "world"});
135
+ });
99
136
  });
100
137
 
101
138
  describe("Method cache", function() {
102
139
  it("Should cache methods", function() {
103
140
  const cache = new MethodCache();
104
141
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><method name='Create'/></methods></schema>");
105
- cache.cache(schema.documentElement);
142
+ cache.put(schema.documentElement);
106
143
 
107
144
  var found = cache.get("nms:recipient", "Delete");
108
145
  assert.ok(found !== null && found !== undefined);
@@ -118,7 +155,7 @@ describe('Caches', function() {
118
155
  it("Should cache interface methods", function() {
119
156
  const cache = new MethodCache();
120
157
  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>");
121
- cache.cache(schema.documentElement);
158
+ cache.put(schema.documentElement);
122
159
  // interface method should be on schema
123
160
  var found = cache.get("nms:recipient", "Update");
124
161
  assert.ok(found !== null && found !== undefined);
@@ -127,10 +164,10 @@ describe('Caches', function() {
127
164
  assert.ok(found !== null && found !== undefined);
128
165
  });
129
166
 
130
- it("Should cler the cache", function() {
167
+ it("Should clear the cache", function() {
131
168
  const cache = new MethodCache();
132
169
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><method name='Create'/></methods></schema>");
133
- cache.cache(schema.documentElement);
170
+ cache.put(schema.documentElement);
134
171
 
135
172
  var found = cache.get("nms:recipient", "Delete");
136
173
  assert.ok(found !== null && found !== undefined);
@@ -143,7 +180,7 @@ describe('Caches', function() {
143
180
  it("Should ignore non-method nodes", function() {
144
181
  const cache = new MethodCache();
145
182
  var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><dummy name='Update'/><method name='Create'/></methods></schema>");
146
- cache.cache(schema.documentElement);
183
+ cache.put(schema.documentElement);
147
184
 
148
185
  var found = cache.get("nms:recipient", "Delete");
149
186
  assert.ok(found !== null && found !== undefined);
@@ -152,6 +189,33 @@ describe('Caches', function() {
152
189
  found = cache.get("nms:recipient", "Create");
153
190
  assert.ok(found !== null && found !== undefined);
154
191
  });
192
+
193
+ it("Deprecated cache methods should now replaced with put", () => {
194
+ const cache = new MethodCache();
195
+ var schema = DomUtil.parse("<schema namespace='nms' name='recipient'><methods><method name='Delete'/><method name='Create'/></methods></schema>");
196
+ cache.cache(schema.documentElement);
197
+
198
+ var found = cache.get("nms:recipient", "Delete");
199
+ assert.ok(found !== null && found !== undefined);
200
+ assert.equal(found.nodeName, "method");
201
+ assert.equal(found.getAttribute("name"), "Delete");
202
+
203
+ found = cache.get("nms:recipient", "Create");
204
+ assert.ok(found !== null && found !== undefined);
205
+ assert.equal(found.nodeName, "method");
206
+ assert.equal(found.getAttribute("name"), "Create");
207
+ })
208
+
209
+ it("Deserialized method should be a DOM element", () => {
210
+ const cache = new MethodCache();
211
+ const serDeser = cache._storage._serDeser;
212
+ const cached = {value: { x:3, method:DomUtil.parse("<hello/>")} };
213
+ const serialized = serDeser(cached, true);
214
+ const deserialized = serDeser(serialized, false);
215
+ const method = deserialized.value.method;
216
+ // should be a DOM element, not a DOM document
217
+ expect(method.nodeType).toBe(1);
218
+ })
155
219
  });
156
220
 
157
221
  describe("Method cache for interfaces", function() {
@@ -160,7 +224,7 @@ describe('Caches', function() {
160
224
  // Test for fix in verion 0.1.23. The xtk:session schema has a direct method "Logon" but also implements the
161
225
  // xtk:persist interface.
162
226
  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>");
163
- cache.cache(schema.documentElement);
227
+ cache.put(schema.documentElement);
164
228
 
165
229
  // Logon method should be found in xtk:session and have the xtk:session URN (for SOAP action)
166
230
  var found = cache.get("xtk:session", "Logon");
@@ -196,7 +260,7 @@ describe('Caches', function() {
196
260
  it("Edge cases for getSoapUrn", () => {
197
261
  const cache = new MethodCache();
198
262
  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>");
199
- cache.cache(schema.documentElement);
263
+ cache.put(schema.documentElement);
200
264
 
201
265
  // Schema and method exist
202
266
  var urn = cache.getSoapUrn("xtk:session", "Logon");
@@ -215,7 +279,7 @@ describe('Caches', function() {
215
279
  const cache = new MethodCache();
216
280
  // Schema has xtk:persist interface but does not implement it
217
281
  var schema = DomUtil.parse("<schema namespace='xtk' name='session'><interface name='persist'><method name='Write' static='true'/></interface><methods><method name='Logon'/></methods></schema>");
218
- cache.cache(schema.documentElement);
282
+ cache.put(schema.documentElement);
219
283
 
220
284
  // Logon method should be found in xtk:session and have the xtk:session URN (for SOAP action)
221
285
  var found = cache.get("xtk:session", "Logon");
@@ -226,4 +290,140 @@ describe('Caches', function() {
226
290
  assert.strictEqual(urn, "xtk:session");
227
291
  });
228
292
  });
293
+
294
+ describe("SafeStorage", () => {
295
+
296
+ describe("JSON safe storage", () => {
297
+
298
+ it("Should find mock json from the cache", () => {
299
+ const map = {};
300
+ const delegate = {
301
+ getItem: jest.fn((key) => map[key]),
302
+ setItem: jest.fn((key, value) => map[key] = value)
303
+ }
304
+ const storage = new SafeStorage(delegate, "");
305
+ expect(storage.getItem("not_found")).toBeUndefined();
306
+ map["k1"] = `{ "hello": "world" }`;
307
+ expect(storage.getItem("k1")).toMatchObject({ hello: "world" });
308
+ map["k2"] = `{ "value": { "hello": "world" } }`;
309
+ expect(storage.getItem("k2")).toMatchObject({ value: { hello: "world" } });
310
+ });
311
+ });
312
+
313
+ describe("XML safe storage", () => {
314
+
315
+ const xmlSerDeser = (item, serDeser) => {
316
+ if (serDeser) {
317
+ const xml = DomUtil.toXMLString(item.value);
318
+ const value = {...item, value: xml };
319
+ return JSON.stringify(value);
320
+ }
321
+ else {
322
+ const json = JSON.parse(item);
323
+ const dom = DomUtil.parse(json.value);
324
+ return {...json, value:dom.documentElement};
325
+ }
326
+ };
327
+
328
+ it("Should find mock xml from the cache", () => {
329
+ const map = {};
330
+ const delegate = {
331
+ getItem: jest.fn((key) => map[key]),
332
+ setItem: jest.fn((key, value) => map[key] = value)
333
+ }
334
+ const storage = new SafeStorage(delegate, "", xmlSerDeser);
335
+ expect(storage.getItem("not_found")).toBeUndefined();
336
+ map["k1"] = `{ "hello": "world" }`;
337
+ expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute containing serialized XML
338
+ map["k1"] = `{ "hello": "world", "value": "" }`;
339
+ expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute containing serialized XML
340
+ map["k1"] = `{ "value": { "hello": "world" } }`;
341
+ expect(storage.getItem("k2")).toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
342
+ map["k1"] = `{ "value": "" } }`;
343
+ expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
344
+ map["k1"] = `{ "value": "bad" } }`;
345
+ expect(storage.getItem("k1")).toBeUndefined(); // k1 cached object does not have "value" attribute but it's not valid XML
346
+ map["k2"] = `{ "value": "<hello/>" }`;
347
+ expect(storage.getItem("k2").value.tagName).toBe("hello");
348
+ });
349
+ });
350
+ });
351
+
352
+ describe("Cache seralizers", () => {
353
+ it("Should serialize json", () => {
354
+ const cache = new OptionCache();
355
+ const serDeser = cache._storage._serDeser;
356
+ expect(serDeser({ hello: "World" }, true)).toBe('{"hello":"World"}');
357
+ expect(serDeser({ }, true)).toBe('{}');
358
+ expect(() => {serDeser(null, true)}).toThrow("Cannot serialize");
359
+ expect(() => {serDeser(undefined, true)}).toThrow("Cannot serialize");
360
+ expect(() => {serDeser("", true)}).toThrow("Cannot serialize");
361
+ expect(() => {serDeser("Hello", true)}).toThrow("Cannot serialize");
362
+ })
363
+
364
+ it("Should deserialize json", () => {
365
+ const cache = new OptionCache();
366
+ const serDeser = cache._storage._serDeser;
367
+ expect(serDeser('{"hello":"World"}', false)).toMatchObject({ hello: "World" });
368
+ expect(serDeser('{}', false)).toMatchObject({ });
369
+ expect(() => {serDeser(null, false)}).toThrow("Cannot deserialize");
370
+ expect(() => {serDeser(undefined, false)}).toThrow("Cannot deserialize");
371
+ expect(() => {serDeser("", false)}).toThrow("Cannot deserialize");
372
+ expect(() => {serDeser("Hello", false)}).toThrow("Unexpected token");
373
+ })
374
+
375
+ it("Should serialize XML entity", () => {
376
+ const cache = new XtkEntityCache();
377
+ const serDeser = cache._storage._serDeser;
378
+ expect(serDeser({value: DomUtil.parse("<hello/>")}, true)).toBe('{"value":"<hello/>"}')
379
+ expect(() => { serDeser({}, true); }).toThrow();
380
+ expect(() => { serDeser(null, true); }).toThrow();
381
+ expect(() => { serDeser(undefined, true); }).toThrow();
382
+ expect(() => { serDeser("", true); }).toThrow();
383
+ expect(() => { serDeser("Hello", true); }).toThrow();
384
+ })
385
+
386
+ it("Should deserialize XML entity", () => {
387
+ const cache = new XtkEntityCache();
388
+ const serDeser = cache._storage._serDeser;
389
+ expect(DomUtil.toXMLString(serDeser(`{"value":"<hello/>"}`, false).value)).toBe("<hello/>");
390
+ expect(() => {serDeser(null, false)}).toThrow();
391
+ expect(() => {serDeser(undefined, false)}).toThrow();
392
+ expect(() => {serDeser("", false)}).toThrow();
393
+ expect(() => {serDeser("Hello", false)}).toThrow();
394
+ })
395
+
396
+ it("Should serialize methods", () => {
397
+ const cache = new MethodCache();
398
+ const serDeser = cache._storage._serDeser;
399
+ expect(serDeser({value: { x:3, method:DomUtil.parse("<hello/>")} }, true)).toBe('{"value":{"x":3,"method":"<hello/>"}}')
400
+ expect(() => { serDeser({value: { x:3 }}, true); }).toThrow();
401
+ expect(() => { serDeser({}, true); }).toThrow();
402
+ expect(() => { serDeser(null, true); }).toThrow();
403
+ expect(() => { serDeser(undefined, true); }).toThrow();
404
+ expect(() => { serDeser("", true); }).toThrow();
405
+ expect(() => { serDeser("Hello", true); }).toThrow();
406
+ })
407
+
408
+ it("Should deserialize methods", () => {
409
+ const cache = new MethodCache();
410
+ const serDeser = cache._storage._serDeser;
411
+ expect(DomUtil.toXMLString(serDeser('{"value":{"x":3,"method":"<hello/>"}}', false).value.method)).toBe("<hello/>");
412
+ expect(() => { serDeser('{"value":{"x":3}}', false); }).toThrow();
413
+ expect(() => { serDeser({}, false); }).toThrow();
414
+ expect(() => { serDeser(null, false); }).toThrow();
415
+ expect(() => { serDeser(undefined, false); }).toThrow();
416
+ expect(() => { serDeser("", false); }).toThrow();
417
+ expect(() => { serDeser("Hello", false); }).toThrow();
418
+ })
419
+
420
+ it("Method serialization should not change initial object", () => {
421
+ const cache = new MethodCache();
422
+ const serDeser = cache._storage._serDeser;
423
+ const cached = {value: { x:3, method:DomUtil.parse("<hello/>")} };
424
+ serDeser(cached, true); // make sure this call does not change the input parameter "cached"
425
+ expect(cached.value.x).toBe(3);
426
+ expect(cached.value.method.documentElement.tagName).toBe("hello");
427
+ })
428
+ })
229
429
  });