relational-redis-store
Version:
A Relational Redis Store
745 lines • 33.8 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
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;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var mockStoreFactory_1 = require("../mockStoreFactory");
var testUtils_1 = require("./testUtils");
var ts_results_1 = require("ts-results");
var ts_async_results_1 = require("ts-async-results");
var store;
beforeAll(function () {
store = (0, mockStoreFactory_1.createMockStore)({
namespace: 'test',
logger: testUtils_1.silentLogger,
});
});
beforeEach(function () {
store.flush();
});
describe('Getting Single Item', function () {
test('Get Item newly added Item', function () { return __awaiter(void 0, void 0, void 0, function () {
var input, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
input = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
avatarId: '2',
name: 'Johnny',
id: '1',
isGuest: true,
},
};
return [4 /*yield*/, store
.addItemToCollection('peers', input, undefined, { foreignKeys: {} })
.resolve()];
case 1:
_a.sent();
return [4 /*yield*/, store.getItemInCollection('peers', '1').resolve()];
case 2:
actual = _a.sent();
expect(actual).toEqual(new ts_results_1.Ok(__assign(__assign({}, input), { id: '1' })));
return [2 /*return*/];
}
});
}); });
test('Get Item with 1Level Foreign Keys', function () { return __awaiter(void 0, void 0, void 0, function () {
var store, guestInput, peerInput, redisExecMultiSpy, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
store = (0, mockStoreFactory_1.createMockStore)({
logger: testUtils_1.silentLogger,
});
guestInput = {
avatarId: '12',
name: 'Travolta',
isGuest: true,
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestInput, 'g5', { foreignKeys: {} })
.resolve()];
case 1:
_a.sent();
peerInput = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
g5: null,
},
};
return [4 /*yield*/, store
.addItemToCollection('peers', peerInput, 'p2', {
foreignKeys: {
user: {
type: 'oneToMany',
collection: 'guests',
},
},
})
.resolve()];
case 2:
_a.sent();
redisExecMultiSpy = jest.spyOn(store.redisClient, 'execMulti');
return [4 /*yield*/, store.getItemInCollection('peers', 'p2').resolve()];
case 3:
actual = _a.sent();
expect(redisExecMultiSpy).toHaveBeenCalledTimes(1);
expect(actual).toEqual(new ts_results_1.Ok(__assign(__assign({}, peerInput), { id: 'p2', user: {
g5: __assign(__assign({}, guestInput), { id: 'g5' }),
} })));
return [2 /*return*/];
}
});
}); });
// // TODO: Add test for a nested foreign key value inexistent
test('Get Item with Nested Foreign Keys', function () { return __awaiter(void 0, void 0, void 0, function () {
var store, guestInput, peerInput, now, roomInput, redisExecMultiSpy, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
store = (0, mockStoreFactory_1.createMockStore)({ logger: testUtils_1.silentLogger });
guestInput = {
avatarId: '12',
name: 'Travolta',
isGuest: true,
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestInput, 'g5', { foreignKeys: {} })
.resolve()];
case 1:
_a.sent();
peerInput = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
g5: null,
},
};
return [4 /*yield*/, store
.addItemToCollection('peers', peerInput, 'p3', {
foreignKeys: {
user: {
type: 'oneToMany',
collection: 'guests',
},
},
})
.resolve()];
case 2:
_a.sent();
now = String(new Date());
roomInput = {
createdBy: 'p1',
name: 'Blue Romania',
createdAt: now,
type: 'public',
code: null,
game: {},
gameOffer: undefined,
activity: {
type: 'none',
},
peers: {
p3: null,
},
};
return [4 /*yield*/, store
.addItemToCollection('rooms', roomInput, 'r7', {
foreignKeys: {
peers: {
type: 'oneToMany',
collection: 'peers',
},
},
})
.mapErr(function (s) {
console.error('Error', s);
})
.resolve()];
case 3:
_a.sent();
redisExecMultiSpy = jest.spyOn(store.redisClient, 'execMulti');
return [4 /*yield*/, store.getItemInCollection('rooms', 'r7').resolve()];
case 4:
actual = _a.sent();
// expect(actual.ok).toBe(true);
expect(redisExecMultiSpy).toHaveBeenCalledTimes(2);
expect(actual).toEqual(new ts_results_1.Ok(__assign(__assign({}, roomInput), { id: 'r7', peers: {
p3: __assign(__assign({}, peerInput), { id: 'p3', user: {
g5: __assign(__assign({}, guestInput), { id: 'g5' }),
} }),
} })));
return [2 /*return*/];
}
});
}); });
test('Get Item with Many Many Nested Foreign Keys', function () { return __awaiter(void 0, void 0, void 0, function () {
var store, guestInputG5, guestInputG6, guestInputG7, peerInputP2, peerInputP3, peerInputP4, now, roomInput, redisExecMultiSpy, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
store = (0, mockStoreFactory_1.createMockStore)({ logger: testUtils_1.silentLogger });
guestInputG5 = {
avatarId: '12',
name: 'Travolta',
isGuest: true,
};
guestInputG6 = {
avatarId: '13',
name: 'Cage',
isGuest: true,
};
guestInputG7 = {
avatarId: '14',
name: 'Chan',
isGuest: true,
};
return [4 /*yield*/, ts_async_results_1.AsyncResult.all(store.addItemToCollection('guests', guestInputG5, 'g5', {
foreignKeys: {},
}), store.addItemToCollection('guests', guestInputG6, 'g6', {
foreignKeys: {},
}), store.addItemToCollection('guests', guestInputG7, 'g7', {
foreignKeys: {},
})).resolve()];
case 1:
_a.sent();
peerInputP2 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
g5: null,
g6: null,
},
};
peerInputP3 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
g7: null,
g6: null,
},
};
peerInputP4 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
g7: null,
g6: null,
g5: null,
},
};
return [4 /*yield*/, ts_async_results_1.AsyncResult.all(store.addItemToCollection('peers', peerInputP2, 'p2', {
foreignKeys: {
user: {
type: 'oneToMany',
collection: 'guests',
},
},
}), store.addItemToCollection('peers', peerInputP3, 'p3', {
foreignKeys: {
user: {
type: 'oneToMany',
collection: 'guests',
},
},
}), store.addItemToCollection('peers', peerInputP4, 'p4', {
foreignKeys: {
user: {
type: 'oneToMany',
collection: 'guests',
},
},
})).resolve()];
case 2:
_a.sent();
now = String(new Date());
roomInput = {
createdBy: 'p1',
name: 'Blue Romania',
createdAt: now,
type: 'public',
code: null,
game: {},
gameOffer: undefined,
peers: {
p3: null,
p2: null,
p4: null,
},
activity: {
type: 'none',
},
};
return [4 /*yield*/, store
.addItemToCollection('rooms', roomInput, 'r7', {
foreignKeys: {
peers: {
type: 'oneToMany',
collection: 'peers',
},
},
})
.resolve()];
case 3:
_a.sent();
redisExecMultiSpy = jest.spyOn(store.redisClient, 'execMulti');
return [4 /*yield*/, store.getItemInCollection('rooms', 'r7').resolve()];
case 4:
actual = _a.sent();
// Test Trips to the DB
expect(redisExecMultiSpy).toHaveBeenCalledTimes(2);
expect(actual).toEqual(new ts_results_1.Ok(__assign(__assign({}, roomInput), { id: 'r7', peers: {
p3: __assign(__assign({}, peerInputP3), { id: 'p3', user: {
g6: __assign(__assign({}, guestInputG6), { id: 'g6' }),
g7: __assign(__assign({}, guestInputG7), { id: 'g7' }),
} }),
p2: __assign(__assign({}, peerInputP2), { id: 'p2', user: {
g6: __assign(__assign({}, guestInputG6), { id: 'g6' }),
g5: __assign(__assign({}, guestInputG5), { id: 'g5' }),
} }),
p4: __assign(__assign({}, peerInputP4), { id: 'p4', user: {
g6: __assign(__assign({}, guestInputG6), { id: 'g6' }),
g5: __assign(__assign({}, guestInputG5), { id: 'g5' }),
g7: __assign(__assign({}, guestInputG7), { id: 'g7' }),
} }),
} })));
return [2 /*return*/];
}
});
}); });
});
describe('Getting Multiple Items', function () {
test('Get Newly Added Items W/O Foreign Keys', function () { return __awaiter(void 0, void 0, void 0, function () {
var input1, input2, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
input1 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
avatarId: '2',
name: 'Johnny',
id: '1',
isGuest: true,
},
};
return [4 /*yield*/, store
.addItemToCollection('peers', input1, undefined, { foreignKeys: {} })
.resolve()];
case 1:
_a.sent();
input2 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
avatarId: '1',
name: 'max',
id: '4',
isGuest: true,
},
};
return [4 /*yield*/, store
.addItemToCollection('peers', input2, undefined, { foreignKeys: {} })
.resolve()];
case 2:
_a.sent();
return [4 /*yield*/, store
.getItemsInCollection('peers', ['1', '2'])
.resolve()];
case 3:
actual = _a.sent();
expect(actual).toEqual(new ts_results_1.Ok([
__assign(__assign({}, input1), { id: '1' }),
__assign(__assign({}, input2), { id: '2' }),
]));
return [2 /*return*/];
}
});
}); });
var errWithoutStack = function (e) {
return {
err: e.err,
ok: e.ok,
val: e.val,
};
};
test('Attempting to get an Inexistent Items W/O Foreign Keys Throws an InexistentCollectionField Error', function () { return __awaiter(void 0, void 0, void 0, function () {
var actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, store.getItemsInCollection('peers', ['1']).resolve()];
case 1:
actual = _a.sent();
expect(actual.err).toBe(true);
expect(actual.val).toEqual('CollectionFieldInexistent');
return [2 /*return*/];
}
});
}); });
test('Attempting to get an Item with Inexistent Foreign Items Throws an InexistentCollectionField Error', function () { return __awaiter(void 0, void 0, void 0, function () {
var input1, input2, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
input1 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: {
avatarId: '2',
name: 'Johnny',
id: '1',
isGuest: true,
},
};
return [4 /*yield*/, store
.addItemToCollection('peers', input1, undefined, { foreignKeys: {} })
.resolve()];
case 1:
_a.sent();
input2 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: 'g55',
};
return [4 /*yield*/, store
.addItemToCollection('peers', input2, undefined, {
foreignKeys: {
user: {
type: 'oneToOne',
collection: 'guests',
},
},
})
.resolve()];
case 2:
_a.sent();
return [4 /*yield*/, store
.getItemsInCollection('peers', ['1', '2'])
.resolve()];
case 3:
actual = _a.sent();
expect(actual.err).toBe(true);
expect(actual.val).toBe('CollectionFieldInexistent');
return [2 /*return*/];
}
});
}); });
test('Get Newly Added Items with Foreign Keys', function () { return __awaiter(void 0, void 0, void 0, function () {
var store, guestG4, peer1, peer2, redisHmgetSpy, redisExecMultiSpy, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
store = (0, mockStoreFactory_1.createMockStore)({ logger: testUtils_1.silentLogger });
guestG4 = {
isGuest: true,
avatarId: '2',
name: 'Lee',
};
return [4 /*yield*/, store.addItemToCollection('guests', guestG4, 'g4', {
foreignKeys: {},
})];
case 1:
_a.sent();
peer1 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: 'g4',
};
return [4 /*yield*/, store
.addItemToCollection('peers', peer1, undefined, {
foreignKeys: {
user: {
type: 'oneToOne',
collection: 'guests',
},
},
})
.resolve()];
case 2:
_a.sent();
peer2 = {
hasJoinedRoom: false,
joinedRoomId: null,
joinedRoomAt: null,
user: 'g4',
};
return [4 /*yield*/, store
.addItemToCollection('peers', peer2, undefined, {
foreignKeys: {
user: {
type: 'oneToOne',
collection: 'guests',
},
},
})
.resolve()];
case 3:
_a.sent();
redisHmgetSpy = jest.spyOn(store.redisClient, 'hmget');
redisExecMultiSpy = jest.spyOn(store.redisClient, 'execMulti');
return [4 /*yield*/, store
.getItemsInCollection('peers', ['1', '2'])
.resolve()];
case 4:
actual = _a.sent();
// Test Trips to the DB
expect(redisExecMultiSpy).toHaveBeenCalledTimes(1);
expect(redisHmgetSpy).toHaveBeenCalledTimes(1);
expect(actual).toEqual(new ts_results_1.Ok([
__assign(__assign({}, peer1), { id: '1', user: __assign(__assign({}, guestG4), { id: 'g4' }) }),
__assign(__assign({}, peer1), { id: '2', user: __assign(__assign({}, guestG4), { id: 'g4' }) }),
]));
return [2 /*return*/];
}
});
}); });
});
describe('Retrieve All Items in collection', function () {
test('All Items W/O Foreign Keys', function () { return __awaiter(void 0, void 0, void 0, function () {
var guestG1, guestG2, guestG3, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
guestG1 = {
isGuest: true,
avatarId: '2',
name: 'Lee',
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestG1, 'g1', { foreignKeys: {} })
.resolve()];
case 1:
_a.sent();
guestG2 = {
isGuest: true,
avatarId: '2',
name: 'Lee',
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestG2, 'g2', { foreignKeys: {} })
.resolve()];
case 2:
_a.sent();
guestG3 = {
isGuest: true,
avatarId: '2',
name: 'Lee',
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestG3, 'g3', { foreignKeys: {} })
.resolve()];
case 3:
_a.sent();
return [4 /*yield*/, store.getAllItemsInCollection('guests').resolve()];
case 4:
actual = _a.sent();
expect(actual).toEqual(new ts_results_1.Ok([
__assign(__assign({}, guestG1), { id: 'g1' }),
__assign(__assign({}, guestG2), { id: 'g2' }),
__assign(__assign({}, guestG3), { id: 'g3' }),
]));
return [2 /*return*/];
}
});
}); });
test('All Items With Foreign Keys', function () { return __awaiter(void 0, void 0, void 0, function () {
var store, guestG1, guestG2, guestG3, peerP1, peerP2, redisHgetAllSpy, redisExecMultiSpy, actual;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
store = (0, mockStoreFactory_1.createMockStore)({ logger: testUtils_1.silentLogger });
guestG1 = {
isGuest: true,
avatarId: '2',
name: 'Lee',
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestG1, 'g1', { foreignKeys: {} })
.resolve()];
case 1:
_a.sent();
guestG2 = {
isGuest: true,
avatarId: '22',
name: 'Chan',
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestG2, 'g2', { foreignKeys: {} })
.resolve()];
case 2:
_a.sent();
guestG3 = {
isGuest: true,
avatarId: '12',
name: 'Keanu',
};
return [4 /*yield*/, store
.addItemToCollection('guests', guestG3, 'g3', { foreignKeys: {} })
.resolve()];
case 3:
_a.sent();
peerP1 = {
hasJoinedRoom: false,
joinedRoomAt: null,
joinedRoomId: null,
user: 'g1',
};
return [4 /*yield*/, store
.addItemToCollection('peers', peerP1, 'p1', {
foreignKeys: {
user: {
type: 'oneToOne',
collection: 'guests',
},
},
})
.resolve()];
case 4:
_a.sent();
peerP2 = {
hasJoinedRoom: false,
joinedRoomAt: null,
joinedRoomId: null,
user: {
g2: null,
g3: null,
},
};
return [4 /*yield*/, store
.addItemToCollection('peers', peerP2, 'p2', {
foreignKeys: {
user: {
type: 'oneToMany',
collection: 'guests',
},
},
})
.resolve()];
case 5:
_a.sent();
redisHgetAllSpy = jest.spyOn(store.redisClient, 'hgetall');
redisExecMultiSpy = jest.spyOn(store.redisClient, 'execMulti');
return [4 /*yield*/, store.getAllItemsInCollection('peers').resolve()];
case 6:
actual = _a.sent();
expect(redisHgetAllSpy).toHaveBeenCalledTimes(1);
expect(redisExecMultiSpy).toHaveBeenCalledTimes(1);
expect(actual).toEqual(new ts_results_1.Ok([
__assign(__assign({}, peerP1), { id: 'p1', user: __assign(__assign({}, guestG1), { id: 'g1' }) }),
__assign(__assign({}, peerP2), { id: 'p2', user: {
g3: __assign(__assign({}, guestG3), { id: 'g3' }),
g2: __assign(__assign({}, guestG2), { id: 'g2' }),
} }),
]));
return [2 /*return*/];
}
});
}); });
// describe('All Items In Collection By', () => {
// test('Retrieve all Items in Collection Indexed By', async () => {
// const endedItem1 = {
// name: 'ended item 1',
// type: 'ended',
// } as const;
// await store.addItemToCollection('simpleIndexableItems', endedItem1, 'ended1Id', {
// foreignKeys: {},
// indexBy: ['type'],
// }).resolve();
// const endedItem2 = {
// name: 'ended item 2',
// type: 'ended',
// } as const;
// await store.addItemToCollection('simpleIndexableItems', endedItem2, 'ended2Id', {
// foreignKeys: {},
// indexBy: ['type'],
// }).resolve();
// const pendingItem1 = {
// name: 'pending item 1',
// type: 'pending',
// } as const;
// await store.addItemToCollection('simpleIndexableItems', pendingItem1, 'pending1Id', {
// foreignKeys: {},
// indexBy: ['type'],
// }).resolve();
// const startedItem1 = {
// name: 'started item 1',
// type: 'started',
// } as const;
// await store.addItemToCollection('simpleIndexableItems', startedItem1, 'started1Id', {
// foreignKeys: {},
// indexBy: ['type'],
// }).resolve();
// const allItemsResult = await store.getAllItemsInCollection('simpleIndexableItems').resolve();
// // expect(2).toEqual(3);
// expect(allItemsResult.ok).toBe(true);
// expect(allItemsResult.val[0]).toEqual({
// id: 'ended1Id',
// ...endedItem1
// });
// expect(allItemsResult.val.length).toEqual(4);
// const onlyPendingItemsResult = await store.getAllItemsInCollectionBy('simpleIndexableItems', 'type').resolve();
// expect(onlyPendingItemsResult.ok).toBe(true);
// });
// });
});
//# sourceMappingURL=Store.getting.test.js.map