@luvio/adapter-test-library 0.105.0 → 0.108.0
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/babel.config.js +1 -0
- package/dist/es/es2018/{durableStore.d.ts → MockDurableStore.d.ts} +5 -3
- package/dist/es/es2018/durableStorePersistence.d.ts +2 -0
- package/dist/es/es2018/main.d.ts +2 -2
- package/dist/es/es2018/network.d.ts +7 -0
- package/dist/es/es2018/test-library.js +82 -34
- package/dist/es/es2018/utils.d.ts +1 -0
- package/dist/umd/es2018/{durableStore.d.ts → MockDurableStore.d.ts} +5 -3
- package/dist/umd/es2018/durableStorePersistence.d.ts +2 -0
- package/dist/umd/es2018/main.d.ts +2 -2
- package/dist/umd/es2018/network.d.ts +7 -0
- package/dist/umd/es2018/test-library.js +86 -36
- package/dist/umd/es2018/utils.d.ts +1 -0
- package/dist/umd/es5/{durableStore.d.ts → MockDurableStore.d.ts} +5 -3
- package/dist/umd/es5/durableStorePersistence.d.ts +2 -0
- package/dist/umd/es5/main.d.ts +2 -2
- package/dist/umd/es5/network.d.ts +7 -0
- package/dist/umd/es5/test-library.js +234 -101
- package/dist/umd/es5/utils.d.ts +1 -0
- package/jest.config.js +16 -0
- package/package.json +4 -4
- package/rollup.config.js +3 -0
- package/src/MockDurableStore.ts +142 -0
- package/src/__tests__/MockDurableStore.spec.ts +53 -0
- package/src/durableStorePersistence.ts +13 -0
- package/src/main.ts +2 -1
- package/src/network.ts +16 -1
- package/src/utils.ts +4 -0
- package/src/durableStore.ts +0 -108
|
@@ -1,13 +1,66 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('sinon')
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', 'sinon'
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.luvioAdapterTestLibrary = {}, global.sinon
|
|
5
|
-
})(this, (function (exports, sinon
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('sinon')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'sinon'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.luvioAdapterTestLibrary = {}, global.sinon));
|
|
5
|
+
})(this, (function (exports, sinon) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
8
|
|
|
9
9
|
var sinon__default = /*#__PURE__*/_interopDefaultLegacy(sinon);
|
|
10
10
|
|
|
11
|
+
/*! *****************************************************************************
|
|
12
|
+
Copyright (c) Microsoft Corporation.
|
|
13
|
+
|
|
14
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
15
|
+
purpose with or without fee is hereby granted.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
18
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
19
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
20
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
21
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
22
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
23
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
24
|
+
***************************************************************************** */
|
|
25
|
+
|
|
26
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
27
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
28
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
29
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
30
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
31
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
32
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function __generator(thisArg, body) {
|
|
37
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
38
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
39
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
40
|
+
function step(op) {
|
|
41
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
42
|
+
while (_) try {
|
|
43
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
44
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
45
|
+
switch (op[0]) {
|
|
46
|
+
case 0: case 1: t = op; break;
|
|
47
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
48
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
49
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
50
|
+
default:
|
|
51
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
52
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
53
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
54
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
55
|
+
if (t[2]) _.ops.pop();
|
|
56
|
+
_.trys.pop(); continue;
|
|
57
|
+
}
|
|
58
|
+
op = body.call(thisArg, _);
|
|
59
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
60
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
11
64
|
/**
|
|
12
65
|
* Clone an object
|
|
13
66
|
*
|
|
@@ -56,6 +109,9 @@
|
|
|
56
109
|
return true;
|
|
57
110
|
}
|
|
58
111
|
return false;
|
|
112
|
+
}
|
|
113
|
+
function flushPromises() {
|
|
114
|
+
return new Promise(function (resolve) { return setTimeout(resolve, 0); });
|
|
59
115
|
}
|
|
60
116
|
|
|
61
117
|
var networkConnectivityStateMap = new WeakMap();
|
|
@@ -101,6 +157,31 @@
|
|
|
101
157
|
function isOkResponse(status) {
|
|
102
158
|
return status >= 200 && status <= 299;
|
|
103
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Flushes any pending network requests. Useful for tests that need to ensure all
|
|
162
|
+
* un-awaited background refreshes are complete
|
|
163
|
+
*
|
|
164
|
+
* @param _mockNetworkAdapter {NetworkAdapter} The network adapter instance to flush
|
|
165
|
+
*/
|
|
166
|
+
function flushPendingNetworkRequests(_mockNetworkAdapter) {
|
|
167
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
168
|
+
return __generator(this, function (_a) {
|
|
169
|
+
switch (_a.label) {
|
|
170
|
+
case 0:
|
|
171
|
+
// since the network mock is actually synchronous (just returns things wrapped
|
|
172
|
+
// in Promise.resolve/reject) the only thing necessary to flush any pending
|
|
173
|
+
// network activity is to flush the pending microtask queue
|
|
174
|
+
return [4 /*yield*/, flushPromises()];
|
|
175
|
+
case 1:
|
|
176
|
+
// since the network mock is actually synchronous (just returns things wrapped
|
|
177
|
+
// in Promise.resolve/reject) the only thing necessary to flush any pending
|
|
178
|
+
// network activity is to flush the pending microtask queue
|
|
179
|
+
_a.sent();
|
|
180
|
+
return [2 /*return*/];
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
104
185
|
function buildMockNetworkAdapter(mockPayloads) {
|
|
105
186
|
// any endpoints not setup with a fake will return a rejected promise
|
|
106
187
|
var networkAdapter = sinon__default["default"].stub().rejects(buildMockSetupError());
|
|
@@ -285,59 +366,6 @@
|
|
|
285
366
|
return mockFulfilledSnapshot;
|
|
286
367
|
}
|
|
287
368
|
|
|
288
|
-
/*! *****************************************************************************
|
|
289
|
-
Copyright (c) Microsoft Corporation.
|
|
290
|
-
|
|
291
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
292
|
-
purpose with or without fee is hereby granted.
|
|
293
|
-
|
|
294
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
295
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
296
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
297
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
298
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
299
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
300
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
301
|
-
***************************************************************************** */
|
|
302
|
-
|
|
303
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
304
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
305
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
306
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
307
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
308
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
309
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function __generator(thisArg, body) {
|
|
314
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
315
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
316
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
317
|
-
function step(op) {
|
|
318
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
319
|
-
while (_) try {
|
|
320
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
321
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
322
|
-
switch (op[0]) {
|
|
323
|
-
case 0: case 1: t = op; break;
|
|
324
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
325
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
326
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
327
|
-
default:
|
|
328
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
329
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
330
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
331
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
332
|
-
if (t[2]) _.ops.pop();
|
|
333
|
-
_.trys.pop(); continue;
|
|
334
|
-
}
|
|
335
|
-
op = body.call(thisArg, _);
|
|
336
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
337
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
369
|
var MemoryDurableStorePersistence = /** @class */ (function () {
|
|
342
370
|
function MemoryDurableStorePersistence() {
|
|
343
371
|
this.store = {};
|
|
@@ -352,8 +380,18 @@
|
|
|
352
380
|
MemoryDurableStorePersistence.prototype.set = function (key, value) {
|
|
353
381
|
return __awaiter(this, void 0, void 0, function () {
|
|
354
382
|
return __generator(this, function (_a) {
|
|
355
|
-
|
|
356
|
-
|
|
383
|
+
switch (_a.label) {
|
|
384
|
+
case 0:
|
|
385
|
+
// simulate a more realistic durable store by making the write wait a
|
|
386
|
+
// tick before actually setting the value
|
|
387
|
+
return [4 /*yield*/, flushPromises()];
|
|
388
|
+
case 1:
|
|
389
|
+
// simulate a more realistic durable store by making the write wait a
|
|
390
|
+
// tick before actually setting the value
|
|
391
|
+
_a.sent();
|
|
392
|
+
this.store[key] = value;
|
|
393
|
+
return [2 /*return*/];
|
|
394
|
+
}
|
|
357
395
|
});
|
|
358
396
|
});
|
|
359
397
|
};
|
|
@@ -365,51 +403,95 @@
|
|
|
365
403
|
});
|
|
366
404
|
});
|
|
367
405
|
};
|
|
406
|
+
MemoryDurableStorePersistence.prototype.flushPendingWork = function () {
|
|
407
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
408
|
+
return __generator(this, function (_a) {
|
|
409
|
+
switch (_a.label) {
|
|
410
|
+
case 0:
|
|
411
|
+
// since this implementation does actual "IO" synchronously the only
|
|
412
|
+
// thing necessary to await any pending IO is to flush the current
|
|
413
|
+
// microtask queue
|
|
414
|
+
return [4 /*yield*/, flushPromises()];
|
|
415
|
+
case 1:
|
|
416
|
+
// since this implementation does actual "IO" synchronously the only
|
|
417
|
+
// thing necessary to await any pending IO is to flush the current
|
|
418
|
+
// microtask queue
|
|
419
|
+
_a.sent();
|
|
420
|
+
return [2 /*return*/];
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
};
|
|
368
425
|
return MemoryDurableStorePersistence;
|
|
369
426
|
}());
|
|
370
427
|
|
|
428
|
+
function waitForPromiseSet(set) {
|
|
429
|
+
// NOTE: we are building an array from the Set at this point in time. If
|
|
430
|
+
// more Promises are added to the Set while this is awaiting it won't
|
|
431
|
+
// await the newly-added Promise. That's what we want.
|
|
432
|
+
return Promise.all(Array.from(set)).then();
|
|
433
|
+
}
|
|
371
434
|
var MockDurableStore = /** @class */ (function () {
|
|
372
435
|
function MockDurableStore(persistence) {
|
|
373
|
-
//
|
|
436
|
+
// for read/write synchronization
|
|
437
|
+
this.writePromises = new Set();
|
|
374
438
|
this.listeners = new Set();
|
|
375
439
|
this.persistence = persistence || new MemoryDurableStorePersistence();
|
|
376
440
|
}
|
|
377
441
|
MockDurableStore.prototype.getEntries = function (entryIds, segment) {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
442
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
443
|
+
var entries, returnSource, _i, entryIds_1, entryId, entry;
|
|
444
|
+
return __generator(this, function (_a) {
|
|
445
|
+
switch (_a.label) {
|
|
446
|
+
case 0:
|
|
447
|
+
if (!(this.writePromises.size > 0)) return [3 /*break*/, 2];
|
|
448
|
+
return [4 /*yield*/, waitForPromiseSet(this.writePromises)];
|
|
449
|
+
case 1:
|
|
450
|
+
_a.sent();
|
|
451
|
+
_a.label = 2;
|
|
452
|
+
case 2: return [4 /*yield*/, this.persistence.get(segment)];
|
|
453
|
+
case 3:
|
|
454
|
+
entries = _a.sent();
|
|
455
|
+
if (entries === undefined) {
|
|
456
|
+
return [2 /*return*/, undefined];
|
|
457
|
+
}
|
|
458
|
+
returnSource = Object.create(null);
|
|
459
|
+
for (_i = 0, entryIds_1 = entryIds; _i < entryIds_1.length; _i++) {
|
|
460
|
+
entryId = entryIds_1[_i];
|
|
461
|
+
entry = entries[entryId];
|
|
462
|
+
if (entry !== undefined) {
|
|
463
|
+
returnSource[entryId] = clone(entry);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return [2 /*return*/, returnSource];
|
|
388
467
|
}
|
|
389
|
-
}
|
|
390
|
-
return returnSource;
|
|
468
|
+
});
|
|
391
469
|
});
|
|
392
470
|
};
|
|
393
471
|
MockDurableStore.prototype.getAllEntries = function (segment) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
472
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
473
|
+
var entries;
|
|
474
|
+
return __generator(this, function (_a) {
|
|
475
|
+
switch (_a.label) {
|
|
476
|
+
case 0:
|
|
477
|
+
if (!(this.writePromises.size > 0)) return [3 /*break*/, 2];
|
|
478
|
+
return [4 /*yield*/, waitForPromiseSet(this.writePromises)];
|
|
479
|
+
case 1:
|
|
480
|
+
_a.sent();
|
|
481
|
+
_a.label = 2;
|
|
482
|
+
case 2: return [4 /*yield*/, this.persistence.get(segment)];
|
|
483
|
+
case 3:
|
|
484
|
+
entries = _a.sent();
|
|
485
|
+
return [2 /*return*/, entries];
|
|
486
|
+
}
|
|
487
|
+
});
|
|
402
488
|
});
|
|
403
489
|
};
|
|
404
490
|
MockDurableStore.prototype.setEntries = function (entries, segment) {
|
|
405
|
-
return this.batchOperations([
|
|
406
|
-
{ entries: entries, segment: segment, type: environments.DurableStoreOperationType.SetEntries },
|
|
407
|
-
]);
|
|
491
|
+
return this.batchOperations([{ entries: entries, segment: segment, type: 'setEntries' }]);
|
|
408
492
|
};
|
|
409
493
|
MockDurableStore.prototype.evictEntries = function (ids, segment) {
|
|
410
|
-
return this.batchOperations([
|
|
411
|
-
{ ids: ids, segment: segment, type: environments.DurableStoreOperationType.EvictEntries },
|
|
412
|
-
]);
|
|
494
|
+
return this.batchOperations([{ ids: ids, segment: segment, type: 'evictEntries' }]);
|
|
413
495
|
};
|
|
414
496
|
MockDurableStore.prototype.registerOnChangedListener = function (listener) {
|
|
415
497
|
var _this = this;
|
|
@@ -421,24 +503,52 @@
|
|
|
421
503
|
};
|
|
422
504
|
MockDurableStore.prototype.batchOperations = function (operations) {
|
|
423
505
|
return __awaiter(this, void 0, void 0, function () {
|
|
424
|
-
var changes,
|
|
425
|
-
|
|
426
|
-
|
|
506
|
+
var changes, writePromise;
|
|
507
|
+
var _this = this;
|
|
508
|
+
return __generator(this, function (_a) {
|
|
509
|
+
switch (_a.label) {
|
|
427
510
|
case 0:
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
_c.label = 1;
|
|
511
|
+
if (!(this.writePromises.size > 0)) return [3 /*break*/, 2];
|
|
512
|
+
return [4 /*yield*/, waitForPromiseSet(this.writePromises)];
|
|
431
513
|
case 1:
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
return [4 /*yield*/, this.performOperation(operations[i])];
|
|
514
|
+
_a.sent();
|
|
515
|
+
_a.label = 2;
|
|
435
516
|
case 2:
|
|
436
|
-
|
|
437
|
-
|
|
517
|
+
changes = [];
|
|
518
|
+
writePromise = (function () { return __awaiter(_this, void 0, void 0, function () {
|
|
519
|
+
var _i, operations_1, operation, _a, _b;
|
|
520
|
+
return __generator(this, function (_c) {
|
|
521
|
+
switch (_c.label) {
|
|
522
|
+
case 0:
|
|
523
|
+
_i = 0, operations_1 = operations;
|
|
524
|
+
_c.label = 1;
|
|
525
|
+
case 1:
|
|
526
|
+
if (!(_i < operations_1.length)) return [3 /*break*/, 4];
|
|
527
|
+
operation = operations_1[_i];
|
|
528
|
+
_b = (_a = changes).push;
|
|
529
|
+
return [4 /*yield*/, this.performOperation(operation)];
|
|
530
|
+
case 2:
|
|
531
|
+
_b.apply(_a, [_c.sent()]);
|
|
532
|
+
_c.label = 3;
|
|
533
|
+
case 3:
|
|
534
|
+
_i++;
|
|
535
|
+
return [3 /*break*/, 1];
|
|
536
|
+
case 4: return [2 /*return*/];
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
}); })();
|
|
540
|
+
this.writePromises.add(writePromise);
|
|
541
|
+
_a.label = 3;
|
|
438
542
|
case 3:
|
|
439
|
-
|
|
440
|
-
return [
|
|
543
|
+
_a.trys.push([3, , 5, 6]);
|
|
544
|
+
return [4 /*yield*/, writePromise];
|
|
441
545
|
case 4:
|
|
546
|
+
_a.sent();
|
|
547
|
+
return [3 /*break*/, 6];
|
|
548
|
+
case 5:
|
|
549
|
+
this.writePromises.delete(writePromise);
|
|
550
|
+
return [7 /*endfinally*/];
|
|
551
|
+
case 6:
|
|
442
552
|
this.listeners.forEach(function (listener) {
|
|
443
553
|
listener(changes);
|
|
444
554
|
});
|
|
@@ -460,13 +570,13 @@
|
|
|
460
570
|
entries = rawEntries === undefined ? {} : rawEntries;
|
|
461
571
|
ids = [];
|
|
462
572
|
switch (operation.type) {
|
|
463
|
-
case
|
|
573
|
+
case 'setEntries':
|
|
464
574
|
ids = Object.keys(operation.entries);
|
|
465
575
|
ids.forEach(function (id) {
|
|
466
576
|
entries[id] = clone(operation.entries[id]);
|
|
467
577
|
});
|
|
468
578
|
break;
|
|
469
|
-
case
|
|
579
|
+
case 'evictEntries':
|
|
470
580
|
ids = operation.ids;
|
|
471
581
|
ids.forEach(function (id) {
|
|
472
582
|
delete entries[id];
|
|
@@ -480,6 +590,28 @@
|
|
|
480
590
|
});
|
|
481
591
|
});
|
|
482
592
|
};
|
|
593
|
+
MockDurableStore.prototype.flushPendingOperations = function () {
|
|
594
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
595
|
+
return __generator(this, function (_a) {
|
|
596
|
+
switch (_a.label) {
|
|
597
|
+
case 0:
|
|
598
|
+
// flush any pending read operations
|
|
599
|
+
return [4 /*yield*/, this.persistence.flushPendingWork()];
|
|
600
|
+
case 1:
|
|
601
|
+
// flush any pending read operations
|
|
602
|
+
_a.sent();
|
|
603
|
+
_a.label = 2;
|
|
604
|
+
case 2:
|
|
605
|
+
if (!(this.writePromises.size > 0)) return [3 /*break*/, 4];
|
|
606
|
+
return [4 /*yield*/, waitForPromiseSet(this.writePromises)];
|
|
607
|
+
case 3:
|
|
608
|
+
_a.sent();
|
|
609
|
+
return [3 /*break*/, 2];
|
|
610
|
+
case 4: return [2 /*return*/];
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
};
|
|
483
615
|
return MockDurableStore;
|
|
484
616
|
}());
|
|
485
617
|
|
|
@@ -489,6 +621,7 @@
|
|
|
489
621
|
exports.buildFetchResponse = buildFetchResponse;
|
|
490
622
|
exports.buildMockNetworkAdapter = buildMockNetworkAdapter;
|
|
491
623
|
exports.buildSuccessMockPayload = buildSuccessMockPayload;
|
|
624
|
+
exports.flushPendingNetworkRequests = flushPendingNetworkRequests;
|
|
492
625
|
exports.getMockFulfilledSnapshot = getMockFulfilledSnapshot;
|
|
493
626
|
exports.getMockLuvioWithFulfilledSnapshot = getMockLuvioWithFulfilledSnapshot;
|
|
494
627
|
exports.getMockNetworkAdapterCallCount = getMockNetworkAdapterCallCount;
|
package/dist/umd/es5/utils.d.ts
CHANGED
package/jest.config.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const baseConfig = require('../../../scripts/jest/base.config');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...baseConfig,
|
|
5
|
+
|
|
6
|
+
displayName: '@luvio/adapter-test-library',
|
|
7
|
+
|
|
8
|
+
roots: ['<rootDir>/src'],
|
|
9
|
+
coverageThreshold: {
|
|
10
|
+
global: {
|
|
11
|
+
branches: 0,
|
|
12
|
+
functions: 0,
|
|
13
|
+
lines: 0,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luvio/adapter-test-library",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.108.0",
|
|
4
4
|
"description": "Test library for luvio adapters",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"watch": "yarn build --watch"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"sinon": "^
|
|
21
|
+
"sinon": "^14.0.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@luvio/engine": "0.
|
|
25
|
-
"@luvio/environments": "0.
|
|
24
|
+
"@luvio/engine": "0.108.0",
|
|
25
|
+
"@luvio/environments": "0.108.0",
|
|
26
26
|
"@types/sinon": "^7.5.2"
|
|
27
27
|
},
|
|
28
28
|
"nx": {
|
package/rollup.config.js
CHANGED
|
@@ -8,13 +8,16 @@ function rollupConfig(config) {
|
|
|
8
8
|
const { formats, target } = config;
|
|
9
9
|
return {
|
|
10
10
|
input: entry,
|
|
11
|
+
external: ['sinon'],
|
|
11
12
|
output: formats.map((format) => {
|
|
12
13
|
return {
|
|
13
14
|
file: `${dist}/${format}/${target}/test-library.js`,
|
|
14
15
|
format,
|
|
15
16
|
name: 'luvioAdapterTestLibrary',
|
|
17
|
+
globals: { sinon: 'sinon' },
|
|
16
18
|
};
|
|
17
19
|
}),
|
|
20
|
+
|
|
18
21
|
plugins: [
|
|
19
22
|
typescript({
|
|
20
23
|
clean: true,
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DurableStore,
|
|
3
|
+
DurableStoreEntries,
|
|
4
|
+
OnDurableStoreChangedListener,
|
|
5
|
+
DurableStoreOperation,
|
|
6
|
+
DurableStoreChange,
|
|
7
|
+
} from '@luvio/environments';
|
|
8
|
+
import { clone } from './utils';
|
|
9
|
+
import type { DurableStorePersistence } from './durableStorePersistence';
|
|
10
|
+
import { MemoryDurableStorePersistence } from './durableStorePersistence';
|
|
11
|
+
|
|
12
|
+
function waitForPromiseSet(set: Set<Promise<unknown>>): Promise<void> {
|
|
13
|
+
// NOTE: we are building an array from the Set at this point in time. If
|
|
14
|
+
// more Promises are added to the Set while this is awaiting it won't
|
|
15
|
+
// await the newly-added Promise. That's what we want.
|
|
16
|
+
return Promise.all(Array.from(set)).then();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class MockDurableStore implements DurableStore {
|
|
20
|
+
// for read/write synchronization
|
|
21
|
+
private writePromises = new Set<Promise<unknown>>();
|
|
22
|
+
|
|
23
|
+
listeners = new Set<OnDurableStoreChangedListener>();
|
|
24
|
+
persistence: DurableStorePersistence;
|
|
25
|
+
|
|
26
|
+
constructor(persistence?: DurableStorePersistence) {
|
|
27
|
+
this.persistence = persistence || new MemoryDurableStorePersistence();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getEntries<T>(
|
|
31
|
+
entryIds: string[],
|
|
32
|
+
segment: string
|
|
33
|
+
): Promise<DurableStoreEntries<T> | undefined> {
|
|
34
|
+
// await any current write operations
|
|
35
|
+
if (this.writePromises.size > 0) {
|
|
36
|
+
await waitForPromiseSet(this.writePromises);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const entries = await this.persistence.get<DurableStoreEntries<T>>(segment);
|
|
40
|
+
|
|
41
|
+
if (entries === undefined) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const returnSource = Object.create(null);
|
|
46
|
+
for (const entryId of entryIds) {
|
|
47
|
+
const entry = entries[entryId];
|
|
48
|
+
if (entry !== undefined) {
|
|
49
|
+
returnSource[entryId] = clone(entry);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return returnSource;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async getAllEntries<T>(segment: string): Promise<DurableStoreEntries<T> | undefined> {
|
|
56
|
+
// await any current write operations
|
|
57
|
+
if (this.writePromises.size > 0) {
|
|
58
|
+
await waitForPromiseSet(this.writePromises);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const entries = await this.persistence.get<DurableStoreEntries<T>>(segment);
|
|
62
|
+
|
|
63
|
+
return entries;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setEntries<T>(entries: DurableStoreEntries<T>, segment: string): Promise<void> {
|
|
67
|
+
return this.batchOperations([{ entries, segment, type: 'setEntries' }]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
evictEntries(ids: string[], segment: string): Promise<void> {
|
|
71
|
+
return this.batchOperations([{ ids, segment, type: 'evictEntries' }]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
registerOnChangedListener(listener: OnDurableStoreChangedListener): () => Promise<void> {
|
|
75
|
+
this.listeners.add(listener);
|
|
76
|
+
return () => {
|
|
77
|
+
this.listeners.delete(listener);
|
|
78
|
+
return Promise.resolve();
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async batchOperations<T>(operations: DurableStoreOperation<T>[]): Promise<void> {
|
|
83
|
+
// await any current write operations
|
|
84
|
+
if (this.writePromises.size > 0) {
|
|
85
|
+
await waitForPromiseSet(this.writePromises);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const changes: DurableStoreChange[] = [];
|
|
89
|
+
|
|
90
|
+
const writePromise = (async () => {
|
|
91
|
+
for (const operation of operations) {
|
|
92
|
+
changes.push(await this.performOperation(operation));
|
|
93
|
+
}
|
|
94
|
+
})();
|
|
95
|
+
this.writePromises.add(writePromise);
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
await writePromise;
|
|
99
|
+
} finally {
|
|
100
|
+
this.writePromises.delete(writePromise);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.listeners.forEach((listener) => {
|
|
104
|
+
listener(changes);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private async performOperation<T>(
|
|
109
|
+
operation: DurableStoreOperation<T>
|
|
110
|
+
): Promise<DurableStoreChange> {
|
|
111
|
+
const segment = operation.segment;
|
|
112
|
+
const rawEntries = await this.persistence.get<DurableStoreEntries<T>>(segment);
|
|
113
|
+
const entries = rawEntries === undefined ? {} : rawEntries;
|
|
114
|
+
let ids: string[] = [];
|
|
115
|
+
switch (operation.type) {
|
|
116
|
+
case 'setEntries':
|
|
117
|
+
ids = Object.keys(operation.entries);
|
|
118
|
+
ids.forEach((id) => {
|
|
119
|
+
entries[id] = clone(operation.entries[id]);
|
|
120
|
+
});
|
|
121
|
+
break;
|
|
122
|
+
case 'evictEntries':
|
|
123
|
+
ids = operation.ids;
|
|
124
|
+
ids.forEach((id) => {
|
|
125
|
+
delete entries[id];
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
await this.persistence.set(operation.segment, entries);
|
|
130
|
+
return { ids, segment, type: operation.type };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async flushPendingOperations(): Promise<void> {
|
|
134
|
+
// flush any pending read operations
|
|
135
|
+
await this.persistence.flushPendingWork();
|
|
136
|
+
|
|
137
|
+
// wait for any pending writes to finish
|
|
138
|
+
while (this.writePromises.size > 0) {
|
|
139
|
+
await waitForPromiseSet(this.writePromises);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|