@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.
- package/.eslintrc.js +3 -1
- package/CHANGELOG.md +18 -1
- package/README.md +54 -4
- package/compile.js +1 -0
- package/package-lock.json +22 -14
- package/package.json +1 -1
- package/src/application.js +35 -2
- package/src/cache.js +30 -1
- package/src/cacheRefresher.js +267 -0
- package/src/campaign.js +29 -28
- package/src/client.js +403 -110
- package/src/soap.js +1 -1
- package/src/transport.js +11 -10
- package/test/application.test.js +2 -2
- package/test/cacheRefresher.test.js +338 -0
- package/test/caches.test.js +22 -1
- package/test/client.test.js +501 -34
- package/test/mock.js +225 -46
- package/test/observability.test.js +267 -0
- package/test/soap.test.js +1 -1
package/src/soap.js
CHANGED
|
@@ -600,7 +600,7 @@ class SoapMethodCall {
|
|
|
600
600
|
this._method.prepend(sessionTokenElem);
|
|
601
601
|
}
|
|
602
602
|
const noMethodInURL = !!this._pushDownOptions.noMethodInURL;
|
|
603
|
-
const actualUrl = noMethodInURL ? url : `${url}?${this.urn}
|
|
603
|
+
const actualUrl = noMethodInURL ? url : `${url}?${this.urn}:${this.methodName}`;
|
|
604
604
|
|
|
605
605
|
// Prepare request and empty response objects
|
|
606
606
|
[this.request, this.requestOptions] = this._createHTTPRequest(actualUrl);
|
package/src/transport.js
CHANGED
|
@@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
|
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
(function() {
|
|
13
|
-
"use strict";
|
|
13
|
+
"use strict";
|
|
14
14
|
|
|
15
15
|
const { Util } = require('./util.js');
|
|
16
16
|
|
|
@@ -41,9 +41,9 @@ class HttpError {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**********************************************************************************
|
|
44
|
-
*
|
|
44
|
+
*
|
|
45
45
|
* Node implementation
|
|
46
|
-
*
|
|
46
|
+
*
|
|
47
47
|
*********************************************************************************/
|
|
48
48
|
/* istanbul ignore else */
|
|
49
49
|
if (!Util.isBrowser()) {
|
|
@@ -52,13 +52,13 @@ if (!Util.isBrowser()) {
|
|
|
52
52
|
const axios = require('axios');
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
55
|
+
*
|
|
56
56
|
* Request body (options)
|
|
57
57
|
* - headers (kv)
|
|
58
58
|
* - method
|
|
59
59
|
* - url
|
|
60
60
|
* - data
|
|
61
|
-
*
|
|
61
|
+
*
|
|
62
62
|
* Response
|
|
63
63
|
* - data
|
|
64
64
|
* - statusCode
|
|
@@ -96,11 +96,11 @@ if (!Util.isBrowser()) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**********************************************************************************
|
|
99
|
-
*
|
|
99
|
+
*
|
|
100
100
|
* Browser-side implementation of the request-promise-native node module.
|
|
101
101
|
* This simply wraps the fetch API
|
|
102
102
|
* From https://www.npmjs.com/package/request-promise-native
|
|
103
|
-
*
|
|
103
|
+
*
|
|
104
104
|
*********************************************************************************/
|
|
105
105
|
else {
|
|
106
106
|
|
|
@@ -109,11 +109,12 @@ if (!Util.isBrowser()) {
|
|
|
109
109
|
const headers = new Headers();
|
|
110
110
|
for (var k in options.headers) {
|
|
111
111
|
headers.append(k, options.headers[k]);
|
|
112
|
-
}
|
|
112
|
+
}
|
|
113
113
|
const r = new Request(options.url, {
|
|
114
114
|
method: options.method,
|
|
115
115
|
headers: headers,
|
|
116
|
-
body: options.data
|
|
116
|
+
body: options.data,
|
|
117
|
+
credentials: options.credentials || 'same-origin'
|
|
117
118
|
});
|
|
118
119
|
|
|
119
120
|
const p = fetch(r).then(async (response) => {
|
|
@@ -135,4 +136,4 @@ if (!Util.isBrowser()) {
|
|
|
135
136
|
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
})();
|
|
139
|
+
})();
|
package/test/application.test.js
CHANGED
|
@@ -1097,7 +1097,6 @@ describe('Application', () => {
|
|
|
1097
1097
|
</GetEntityIfMoreRecentResponse>
|
|
1098
1098
|
</SOAP-ENV:Body>
|
|
1099
1099
|
</SOAP-ENV:Envelope>`));
|
|
1100
|
-
|
|
1101
1100
|
const nodes = await link.joinNodes();
|
|
1102
1101
|
expect(nodes).toMatchObject([]);
|
|
1103
1102
|
const reverseLink = await link.reverseLink();
|
|
@@ -2156,4 +2155,5 @@ describe('Application', () => {
|
|
|
2156
2155
|
expect(client.application.version).toBe('6.7.0');
|
|
2157
2156
|
})
|
|
2158
2157
|
})
|
|
2159
|
-
});
|
|
2158
|
+
});
|
|
2159
|
+
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**********************************************************************************
|
|
15
|
+
*
|
|
16
|
+
* Unit tests for the cache refresher
|
|
17
|
+
*
|
|
18
|
+
*********************************************************************************/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const sdk = require('../src/index.js');
|
|
22
|
+
const { Cache } = require('../src/cache.js');
|
|
23
|
+
const Mock = require('./mock.js').Mock;
|
|
24
|
+
const CacheRefresher = require('../src/cacheRefresher.js').CacheRefresher;
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
describe("CacheRefresher cache", function () {
|
|
28
|
+
|
|
29
|
+
it('Should call refresh', async () => {
|
|
30
|
+
const client = await Mock.makeClient();
|
|
31
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
32
|
+
|
|
33
|
+
await client.NLWS.xtkSession.logon();
|
|
34
|
+
const cache = new Cache();
|
|
35
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
36
|
+
|
|
37
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_CLEAR_RESPONSE);
|
|
38
|
+
await cacheRefresher._callAndRefresh();
|
|
39
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBe("9469");
|
|
40
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBe("2022-07-28T14:38:55.766Z");
|
|
41
|
+
|
|
42
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_CLEAR_RESPONSE);
|
|
43
|
+
await cacheRefresher._callAndRefresh();
|
|
44
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBe("9469");
|
|
45
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBe("2022-07-28T14:38:55.766Z");
|
|
46
|
+
|
|
47
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
48
|
+
await client.NLWS.xtkSession.logoff();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('Should call refresh after 1 seconds', async () => {
|
|
52
|
+
const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin");
|
|
53
|
+
const client = await sdk.init(connectionParameters);
|
|
54
|
+
client._transport = jest.fn();
|
|
55
|
+
|
|
56
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
57
|
+
|
|
58
|
+
await client.NLWS.xtkSession.logon();
|
|
59
|
+
expect(client.isLogged()).toBeTruthy();
|
|
60
|
+
const cache = new Cache();
|
|
61
|
+
|
|
62
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
63
|
+
|
|
64
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBeUndefined();
|
|
65
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBeUndefined();
|
|
66
|
+
client._transport.mockReturnValue(Promise.resolve(Mock.GETMODIFIEDENTITIES_CLEAR_RESPONSE));
|
|
67
|
+
jest.useFakeTimers();
|
|
68
|
+
cacheRefresher.startAutoRefresh(5000);
|
|
69
|
+
jest.advanceTimersByTime(6000);
|
|
70
|
+
jest.useRealTimers();
|
|
71
|
+
|
|
72
|
+
// to allow soap call to finish
|
|
73
|
+
await new Promise(process.nextTick);
|
|
74
|
+
|
|
75
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBe("9469");
|
|
76
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBe("2022-07-28T14:38:55.766Z");
|
|
77
|
+
|
|
78
|
+
cacheRefresher.stopAutoRefresh();
|
|
79
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
80
|
+
await client.NLWS.xtkSession.logoff();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('Should send buildNumber when call refresh', async () => {
|
|
84
|
+
const client = await Mock.makeClient();
|
|
85
|
+
const logs = await Mock.withMockConsole(async () => {
|
|
86
|
+
client.traceAPICalls(true);
|
|
87
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
88
|
+
|
|
89
|
+
await client.NLWS.xtkSession.logon();
|
|
90
|
+
|
|
91
|
+
const cache = new Cache();
|
|
92
|
+
|
|
93
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
94
|
+
cacheRefresher._refresherStateCache.put("buildNumber", "9469");
|
|
95
|
+
cacheRefresher._refresherStateCache.put("time", "2022-07-28T14:38:55.766Z");
|
|
96
|
+
|
|
97
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_CLEAR_RESPONSE);
|
|
98
|
+
await cacheRefresher._callAndRefresh();
|
|
99
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBe("9469");
|
|
100
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBe("2022-07-28T14:38:55.766Z");
|
|
101
|
+
|
|
102
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
await client.NLWS.xtkSession.logoff();
|
|
106
|
+
|
|
107
|
+
})
|
|
108
|
+
expect(logs.length).toBe(6);
|
|
109
|
+
expect(logs[0]).toMatch(/SOAP.*request.*Logon/is)
|
|
110
|
+
expect(logs[1]).toMatch(/SOAP.*response.*LogonResponse/is)
|
|
111
|
+
expect(logs[2]).toMatch(/SOAP.*request.*buildNumber.*9469.*2022-07-28T14:38:55.766Z.*GetModifiedEntities*/is)
|
|
112
|
+
expect(logs[3]).toMatch(/SOAP.*response.*GetModifiedEntitiesResponse/is)
|
|
113
|
+
expect(logs[4]).toMatch(/SOAP.*request.*Logoff/is)
|
|
114
|
+
expect(logs[5]).toMatch(/SOAP.*response.*LogoffResponse/is)
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('Should refresh cache', async () => {
|
|
118
|
+
const client = await Mock.makeClient();
|
|
119
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
120
|
+
|
|
121
|
+
await client.NLWS.xtkSession.logon();
|
|
122
|
+
const cache = new Cache();
|
|
123
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
124
|
+
|
|
125
|
+
cache.put("xtk:schema|nms:recipient", "<content recipient>");
|
|
126
|
+
cache.put("xtk:schema|nms:replicationStrategy", "<content xtk:schema|nms:replicationStrategy>");
|
|
127
|
+
cache.put("xtk:schema|nms:operation", "<content xtk:schema|nms:operation>");
|
|
128
|
+
expect(cache.get("xtk:schema|nms:recipient")).toBe("<content recipient>");
|
|
129
|
+
expect(cache.get("xtk:schema|nms:replicationStrategy")).toBe("<content xtk:schema|nms:replicationStrategy>");
|
|
130
|
+
expect(cache.get("xtk:schema|nms:operation")).toBe("<content xtk:schema|nms:operation>");
|
|
131
|
+
|
|
132
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_SCHEMA_RESPONSE);
|
|
133
|
+
await cacheRefresher._callAndRefresh();
|
|
134
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBe("9469");
|
|
135
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBe("2022-07-28T15:32:00.785Z");
|
|
136
|
+
expect(cache.get("xtk:schema|nms:recipient")).toBeUndefined();
|
|
137
|
+
expect(cache.get("xtk:schema|nms:replicationStrategy")).toBeUndefined();
|
|
138
|
+
expect(cache.get("xtk:schema|nms:operation")).toBe("<content xtk:schema|nms:operation>");
|
|
139
|
+
|
|
140
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
141
|
+
await client.NLWS.xtkSession.logoff();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('Should stop refresh if method not exist', async () => {
|
|
145
|
+
const client = await Mock.makeClient();
|
|
146
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
147
|
+
|
|
148
|
+
await client.NLWS.xtkSession.logon();
|
|
149
|
+
const cache = new Cache();
|
|
150
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
151
|
+
|
|
152
|
+
cacheRefresher.startAutoRefresh();
|
|
153
|
+
|
|
154
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_UNDEFINED_RESPONSE);
|
|
155
|
+
await cacheRefresher._callAndRefresh();
|
|
156
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBeUndefined();
|
|
157
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBeUndefined();
|
|
158
|
+
expect(cacheRefresher._intervalId).toBeNull();
|
|
159
|
+
|
|
160
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
161
|
+
await client.NLWS.xtkSession.logoff();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('Should not stop refresh if error different from undefined', async () => {
|
|
165
|
+
const client = await Mock.makeClient();
|
|
166
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
167
|
+
|
|
168
|
+
await client.NLWS.xtkSession.logon();
|
|
169
|
+
const cache = new Cache();
|
|
170
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
171
|
+
|
|
172
|
+
cacheRefresher.startAutoRefresh();
|
|
173
|
+
|
|
174
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_ERROR_RESPONSE);
|
|
175
|
+
try {
|
|
176
|
+
await cacheRefresher._callAndRefresh();
|
|
177
|
+
fail('exception is expected');
|
|
178
|
+
} catch (e) {
|
|
179
|
+
expect(e).not.toBeNull();
|
|
180
|
+
}
|
|
181
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBeUndefined();
|
|
182
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBeUndefined();
|
|
183
|
+
expect(cacheRefresher._intervalId).not.toBeNull();
|
|
184
|
+
|
|
185
|
+
cacheRefresher.stopAutoRefresh();
|
|
186
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
187
|
+
await client.NLWS.xtkSession.logoff();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('Should be able to call start refresh twice', async () => {
|
|
191
|
+
const client = await Mock.makeClient();
|
|
192
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
193
|
+
|
|
194
|
+
await client.NLWS.xtkSession.logon();
|
|
195
|
+
const cache = new Cache();
|
|
196
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
197
|
+
|
|
198
|
+
jest.useFakeTimers();
|
|
199
|
+
cacheRefresher.startAutoRefresh(100000);
|
|
200
|
+
expect(cacheRefresher._intervalId).not.toBeNull();
|
|
201
|
+
const firstIntervalId = cacheRefresher._intervalId;
|
|
202
|
+
cacheRefresher.startAutoRefresh(5000);
|
|
203
|
+
expect(cacheRefresher._intervalId).not.toBeNull();
|
|
204
|
+
expect(cacheRefresher._intervalId != firstIntervalId);
|
|
205
|
+
|
|
206
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_CLEAR_RESPONSE);
|
|
207
|
+
|
|
208
|
+
jest.advanceTimersByTime(6000);
|
|
209
|
+
jest.useRealTimers();
|
|
210
|
+
|
|
211
|
+
// to allow soap call to finish
|
|
212
|
+
await new Promise(process.nextTick);
|
|
213
|
+
|
|
214
|
+
expect(cacheRefresher._refresherStateCache.get("buildNumber")).toBe("9469");
|
|
215
|
+
expect(cacheRefresher._refresherStateCache.get("time")).toBe("2022-07-28T14:38:55.766Z");
|
|
216
|
+
|
|
217
|
+
cacheRefresher.stopAutoRefresh();
|
|
218
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
219
|
+
await client.NLWS.xtkSession.logoff();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('Should notify when refresh cache', async () => {
|
|
223
|
+
const client = await Mock.makeClient();
|
|
224
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class Listener {
|
|
228
|
+
constructor() {
|
|
229
|
+
this._schemas = {};
|
|
230
|
+
}
|
|
231
|
+
add(schemaId) {
|
|
232
|
+
this._schemas[schemaId] = "1";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
invalidateCacheItem(schemaId) {
|
|
236
|
+
this._schemas[schemaId] = undefined;
|
|
237
|
+
}
|
|
238
|
+
getSchema(schemaId) {
|
|
239
|
+
return this._schemas[schemaId];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let listener = new Listener();
|
|
244
|
+
client._registerCacheChangeListener(listener);
|
|
245
|
+
|
|
246
|
+
await client.NLWS.xtkSession.logon();
|
|
247
|
+
const cache = new Cache();
|
|
248
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
249
|
+
|
|
250
|
+
cache.put("xtk:schema|nms:recipient", "<content recipient>");
|
|
251
|
+
cache.put("xtk:schema|nms:replicationStrategy", "<content xtk:schema|nms:replicationStrategy>");
|
|
252
|
+
cache.put("xtk:schema|nms:operation", "<content xtk:schema|nms:operation>");
|
|
253
|
+
|
|
254
|
+
listener.add("nms:recipient");
|
|
255
|
+
|
|
256
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_SCHEMA_RESPONSE);
|
|
257
|
+
await cacheRefresher._callAndRefresh();
|
|
258
|
+
|
|
259
|
+
expect(listener.getSchema("nms:recipient")).toBeUndefined();
|
|
260
|
+
|
|
261
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
262
|
+
await client.NLWS.xtkSession.logoff();
|
|
263
|
+
client._unregisterCacheChangeListener(listener);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('Should protect callAndRefresh from re-entrance', async () => {
|
|
267
|
+
const client = await Mock.makeClient();
|
|
268
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
269
|
+
await client.NLWS.xtkSession.logon();
|
|
270
|
+
const cache = new Cache();
|
|
271
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
272
|
+
let count = 0;
|
|
273
|
+
cacheRefresher._callAndRefresh = jest.fn(() => { count = count + 1 });
|
|
274
|
+
expect(cacheRefresher._running).toBe(false);
|
|
275
|
+
await cacheRefresher._callAndRefresh();
|
|
276
|
+
expect(count).toBe(1);
|
|
277
|
+
expect(cacheRefresher._running).toBe(false);
|
|
278
|
+
await cacheRefresher._safeCallAndRefresh();
|
|
279
|
+
expect(count).toBe(2);
|
|
280
|
+
expect(cacheRefresher._running).toBe(false);
|
|
281
|
+
|
|
282
|
+
cacheRefresher._running = true;
|
|
283
|
+
await cacheRefresher._safeCallAndRefresh();
|
|
284
|
+
expect(count).toBe(2); // should not have been called since already executing
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
it('Throw CampaignException when calling _callAndRefresh without logon', async () => {
|
|
288
|
+
const client = await Mock.makeClient();
|
|
289
|
+
const cache = new Cache();
|
|
290
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
await cacheRefresher._callAndRefresh();
|
|
294
|
+
fail('exception is expected');
|
|
295
|
+
} catch (e) {
|
|
296
|
+
expect(e.name).toBe("CampaignException");
|
|
297
|
+
expect(e.errorCode).toBe("SDK-000010");
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('Ignore error when calling _safeCallAndRefresh without logon', async () => {
|
|
302
|
+
const client = await Mock.makeClient();
|
|
303
|
+
const cache = new Cache();
|
|
304
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
await cacheRefresher._safeCallAndRefresh();
|
|
308
|
+
} catch (e) {
|
|
309
|
+
fail('exception is not expected');
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('Catch error in soap call GetModifiedEntities and display a warning', async () => {
|
|
314
|
+
const client = await Mock.makeClient();
|
|
315
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
316
|
+
|
|
317
|
+
await client.NLWS.xtkSession.logon();
|
|
318
|
+
const cache = new Cache();
|
|
319
|
+
const cacheRefresher = new CacheRefresher(cache, client, "xtk:schema", "rootkey");
|
|
320
|
+
|
|
321
|
+
client._transport.mockReturnValueOnce(Mock.GETMODIFIEDENTITIES_ERROR_RESPONSE);
|
|
322
|
+
try {
|
|
323
|
+
jest.useFakeTimers();
|
|
324
|
+
cacheRefresher.startAutoRefresh(5000);
|
|
325
|
+
jest.advanceTimersByTime(6000);
|
|
326
|
+
jest.useRealTimers();
|
|
327
|
+
|
|
328
|
+
// to allow soap call to finish
|
|
329
|
+
await new Promise(process.nextTick);
|
|
330
|
+
} catch (e) {
|
|
331
|
+
fail('exception is not expected');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
cacheRefresher.stopAutoRefresh();
|
|
335
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
336
|
+
await client.NLWS.xtkSession.logoff();
|
|
337
|
+
});
|
|
338
|
+
});
|
package/test/caches.test.js
CHANGED
|
@@ -30,13 +30,16 @@ describe('Caches', function() {
|
|
|
30
30
|
it("Should cache with default TTL and default key function", () => {
|
|
31
31
|
const cache = new Cache();
|
|
32
32
|
cache.put("Hello", "World");
|
|
33
|
+
expect(cache._stats).toMatchObject({ reads: 0, writes: 1 });
|
|
33
34
|
expect(cache.get("Hello")).toBe("World");
|
|
35
|
+
expect(cache._stats).toMatchObject({ reads: 1, writes: 1, memoryHits: 1, storageHits: 0 });
|
|
34
36
|
})
|
|
35
37
|
|
|
36
38
|
it("Should expires after TTL", () => {
|
|
37
39
|
const cache = new Cache(undefined, undefined, -1); // negative TTL => will immediately expire
|
|
38
40
|
cache.put("Hello", "World");
|
|
39
41
|
expect(cache.get("Hello")).toBeUndefined();
|
|
42
|
+
expect(cache._stats).toMatchObject({ reads: 1, writes: 1, memoryHits: 0, storageHits: 0 });
|
|
40
43
|
})
|
|
41
44
|
|
|
42
45
|
it("Should support custom key function", () => {
|
|
@@ -53,8 +56,26 @@ describe('Caches', function() {
|
|
|
53
56
|
expect(cache.get("Hello")).toBe("World");
|
|
54
57
|
cache.clear();
|
|
55
58
|
expect(cache.get("Hello")).toBeUndefined();
|
|
59
|
+
expect(cache._stats).toMatchObject({ reads: 2, writes: 1, memoryHits: 1, storageHits: 0, clears: 1 });
|
|
56
60
|
})
|
|
57
|
-
|
|
61
|
+
|
|
62
|
+
it("Should remove key in cache", () => {
|
|
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");
|
|
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");
|
|
72
|
+
expect(cache._stats).toMatchObject({ reads: 4, writes: 2, memoryHits: 3, removals: 1 });
|
|
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");
|
|
77
|
+
})
|
|
78
|
+
});
|
|
58
79
|
|
|
59
80
|
describe("Entity cache", function() {
|
|
60
81
|
it("Should cache value", function() {
|