@naturalcycles/db-lib 10.0.0 → 10.0.1
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/dist/testing/daoTest.d.ts +1 -1
- package/dist/testing/daoTest.js +89 -74
- package/dist/testing/dbTest.d.ts +1 -2
- package/dist/testing/dbTest.js +68 -68
- package/dist/testing/keyValueDBTest.d.ts +1 -1
- package/dist/testing/keyValueDBTest.js +37 -37
- package/dist/testing/keyValueDaoTest.d.ts +1 -1
- package/dist/testing/keyValueDaoTest.js +33 -33
- package/package.json +1 -1
- package/src/testing/daoTest.ts +26 -4
- package/src/testing/dbTest.ts +21 -20
- package/src/testing/keyValueDBTest.ts +3 -2
- package/src/testing/keyValueDaoTest.ts +3 -2
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { CommonDB } from '../common.db';
|
|
2
2
|
import { CommonDBImplementationQuirks } from './dbTest';
|
|
3
|
-
export declare function runCommonDaoTest(db: CommonDB, quirks?: CommonDBImplementationQuirks): void
|
|
3
|
+
export declare function runCommonDaoTest(db: CommonDB, quirks?: CommonDBImplementationQuirks): Promise<void>;
|
package/dist/testing/daoTest.js
CHANGED
|
@@ -4,12 +4,12 @@ exports.runCommonDaoTest = runCommonDaoTest;
|
|
|
4
4
|
const node_stream_1 = require("node:stream");
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
6
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
7
|
-
const vitest_1 = require("vitest");
|
|
8
7
|
const __1 = require("..");
|
|
9
8
|
const common_dao_1 = require("../commondao/common.dao");
|
|
10
|
-
const dbTest_1 = require("./dbTest");
|
|
11
9
|
const test_model_1 = require("./test.model");
|
|
12
|
-
function runCommonDaoTest(db, quirks = {}) {
|
|
10
|
+
async function runCommonDaoTest(db, quirks = {}) {
|
|
11
|
+
// this is because vitest cannot be "required" from cjs
|
|
12
|
+
const { test, expect } = await import('vitest');
|
|
13
13
|
const { support } = db;
|
|
14
14
|
const dao = new common_dao_1.CommonDao({
|
|
15
15
|
table: test_model_1.TEST_TABLE,
|
|
@@ -24,52 +24,52 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
24
24
|
const item1 = items[0];
|
|
25
25
|
const expectedItems = items.map(i => ({
|
|
26
26
|
...i,
|
|
27
|
-
updated:
|
|
27
|
+
updated: expect.any(Number),
|
|
28
28
|
}));
|
|
29
|
-
|
|
29
|
+
test('ping', async () => {
|
|
30
30
|
await dao.ping();
|
|
31
31
|
});
|
|
32
32
|
// CREATE TABLE, DROP
|
|
33
33
|
if (support.createTable) {
|
|
34
|
-
|
|
34
|
+
test('createTable, dropIfExists=true', async () => {
|
|
35
35
|
await dao.createTable(test_model_1.testItemBMJsonSchema, { dropIfExists: true });
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
if (support.queries) {
|
|
39
39
|
// DELETE ALL initially
|
|
40
|
-
|
|
40
|
+
test('deleteByIds test items', async () => {
|
|
41
41
|
const rows = await dao.query().select(['id']).runQuery();
|
|
42
42
|
await db.deleteByQuery(__1.DBQuery.create(test_model_1.TEST_TABLE).filter('id', 'in', rows.map(r => r.id)));
|
|
43
43
|
});
|
|
44
44
|
// QUERY empty
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
test('runQuery(all), runQueryCount should return empty', async () => {
|
|
46
|
+
expect(await dao.query().runQuery()).toEqual([]);
|
|
47
|
+
expect(await dao.query().runQueryCount()).toBe(0);
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
// GET empty
|
|
51
|
-
|
|
51
|
+
test('getByIds(item1.id) should return empty', async () => {
|
|
52
52
|
const [item1Loaded] = await dao.getByIds([item1.id]);
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
expect(item1Loaded).toBeUndefined();
|
|
54
|
+
expect(await dao.getById(item1.id)).toBeNull();
|
|
55
55
|
});
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
test('getByIds([]) should return []', async () => {
|
|
57
|
+
expect(await dao.getByIds([])).toEqual([]);
|
|
58
58
|
});
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
test('getByIds(...) should return empty', async () => {
|
|
60
|
+
expect(await dao.getByIds(['abc', 'abcd'])).toEqual([]);
|
|
61
61
|
});
|
|
62
62
|
// TimeMachine
|
|
63
63
|
if (support.timeMachine) {
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
test('getByIds(...) 10 minutes ago should return []', async () => {
|
|
65
|
+
expect(await dao.getByIds([item1.id, 'abc'], {
|
|
66
66
|
readAt: js_lib_1.localTime.now().minus(10, 'minute').unix,
|
|
67
67
|
})).toEqual([]);
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
70
|
// SAVE
|
|
71
71
|
if (support.nullValues) {
|
|
72
|
-
|
|
72
|
+
test('should allow to save and load null values', async () => {
|
|
73
73
|
const item3 = {
|
|
74
74
|
...(0, test_model_1.createTestItemBM)(3),
|
|
75
75
|
k2: null,
|
|
@@ -77,13 +77,13 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
77
77
|
// deepFreeze(item3) // no, Dao is expected to mutate object to add id, created, updated
|
|
78
78
|
await dao.save(item3);
|
|
79
79
|
const item3Loaded = await dao.requireById(item3.id);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
expectMatch([item3], [item3Loaded], quirks);
|
|
81
|
+
expect(item3Loaded.k2).toBeNull();
|
|
82
|
+
expect(Object.keys(item3)).toContain('k2');
|
|
83
|
+
expect(item3.k2).toBeNull();
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
|
-
|
|
86
|
+
test('undefined values should not be saved/loaded', async () => {
|
|
87
87
|
const item3 = {
|
|
88
88
|
...(0, test_model_1.createTestItemBM)(3),
|
|
89
89
|
k2: undefined,
|
|
@@ -94,22 +94,22 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
94
94
|
await dao.save(item3);
|
|
95
95
|
expected.updated = item3.updated; // as it's mutated
|
|
96
96
|
const item3Loaded = await dao.requireById(item3.id);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
expectMatch([expected], [item3Loaded], quirks);
|
|
98
|
+
expect(item3Loaded.k2).toBeUndefined();
|
|
99
|
+
expect(Object.keys(item3Loaded)).not.toContain('k2');
|
|
100
|
+
expect(Object.keys(item3)).toContain('k2');
|
|
101
|
+
expect(item3.k2).toBeUndefined();
|
|
102
102
|
});
|
|
103
|
-
|
|
103
|
+
test('saveBatch test items', async () => {
|
|
104
104
|
const itemsSaved = await dao.saveBatch(items);
|
|
105
|
-
|
|
105
|
+
expect(itemsSaved[0]).toBe(items[0]); // expect "same object" returned
|
|
106
106
|
// no unnecessary mutation
|
|
107
107
|
const { updated: _, ...clone } = itemsClone[0];
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
expect(items[0]).toMatchObject(clone);
|
|
109
|
+
expectMatch(expectedItems, itemsSaved, quirks);
|
|
110
110
|
});
|
|
111
111
|
if (support.increment) {
|
|
112
|
-
|
|
112
|
+
test('increment', async () => {
|
|
113
113
|
await dao.incrementBatch('k3', { id1: 1, id2: 2 });
|
|
114
114
|
let rows = await dao.query().runQuery();
|
|
115
115
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
@@ -128,104 +128,104 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
128
128
|
}
|
|
129
129
|
return r;
|
|
130
130
|
});
|
|
131
|
-
|
|
131
|
+
expectMatch(expected, rows, quirks);
|
|
132
132
|
// reset the changes
|
|
133
133
|
await dao.increment('k3', 'id1', -1);
|
|
134
134
|
await dao.increment('k3', 'id2', -2);
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
// GET not empty
|
|
138
|
-
|
|
138
|
+
test('getByIds all items', async () => {
|
|
139
139
|
const rows = await dao.getByIds(items.map(i => i.id).concat('abcd'));
|
|
140
|
-
|
|
140
|
+
expectMatch(expectedItems, (0, js_lib_1._sortBy)(rows, r => r.id), quirks);
|
|
141
141
|
});
|
|
142
142
|
// QUERY
|
|
143
143
|
if (support.queries) {
|
|
144
|
-
|
|
144
|
+
test('runQuery(all) should return all items', async () => {
|
|
145
145
|
let rows = await dao.query().runQuery();
|
|
146
146
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
147
|
-
|
|
147
|
+
expectMatch(expectedItems, rows, quirks);
|
|
148
148
|
});
|
|
149
149
|
if (support.dbQueryFilter) {
|
|
150
|
-
|
|
150
|
+
test('query even=true', async () => {
|
|
151
151
|
let rows = await dao.query().filter('even', '==', true).runQuery();
|
|
152
152
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
153
|
-
|
|
153
|
+
expectMatch(expectedItems.filter(i => i.even), rows, quirks);
|
|
154
154
|
});
|
|
155
|
-
|
|
155
|
+
test('query nested property', async () => {
|
|
156
156
|
let rows = await dao
|
|
157
157
|
.query()
|
|
158
158
|
.filter('nested.foo', '==', 1)
|
|
159
159
|
.runQuery();
|
|
160
160
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
161
|
-
|
|
161
|
+
expectMatch(expectedItems.filter(i => i.nested?.foo === 1), rows, quirks);
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
if (support.dbQueryOrder) {
|
|
165
|
-
|
|
165
|
+
test('query order by k1 desc', async () => {
|
|
166
166
|
const rows = await dao.query().order('k1', true).runQuery();
|
|
167
|
-
|
|
167
|
+
expectMatch([...expectedItems].reverse(), rows, quirks);
|
|
168
168
|
});
|
|
169
169
|
}
|
|
170
170
|
if (support.dbQuerySelectFields) {
|
|
171
|
-
|
|
171
|
+
test('projection query with only ids', async () => {
|
|
172
172
|
let rows = await dao.query().select(['id']).runQuery();
|
|
173
173
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
174
|
-
|
|
174
|
+
expectMatch(expectedItems.map(item => (0, js_lib_1._pick)(item, ['id'])), rows, quirks);
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
test('runQueryCount should return 3', async () => {
|
|
178
|
+
expect(await dao.query().runQueryCount()).toBe(3);
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
181
|
// STREAM
|
|
182
182
|
if (support.streaming) {
|
|
183
|
-
|
|
183
|
+
test('streamQueryForEach all', async () => {
|
|
184
184
|
let rows = [];
|
|
185
185
|
await dao.query().streamQueryForEach(bm => void rows.push(bm));
|
|
186
186
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
187
|
-
|
|
187
|
+
expectMatch(expectedItems, rows, quirks);
|
|
188
188
|
});
|
|
189
|
-
|
|
189
|
+
test('streamQuery all', async () => {
|
|
190
190
|
let rows = await dao.query().streamQuery().toArray();
|
|
191
191
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id);
|
|
192
|
-
|
|
192
|
+
expectMatch(expectedItems, rows, quirks);
|
|
193
193
|
});
|
|
194
|
-
|
|
194
|
+
test('streamQueryIdsForEach all', async () => {
|
|
195
195
|
let ids = [];
|
|
196
196
|
await dao.query().streamQueryIdsForEach(id => void ids.push(id));
|
|
197
197
|
ids = ids.sort();
|
|
198
|
-
|
|
198
|
+
expectMatch(expectedItems.map(i => i.id), ids, quirks);
|
|
199
199
|
});
|
|
200
|
-
|
|
200
|
+
test('streamQueryIds all', async () => {
|
|
201
201
|
let ids = await dao.query().streamQueryIds().toArray();
|
|
202
202
|
ids = ids.sort();
|
|
203
|
-
|
|
203
|
+
expectMatch(expectedItems.map(i => i.id), ids, quirks);
|
|
204
204
|
});
|
|
205
|
-
|
|
205
|
+
test('streamSaveTransform', async () => {
|
|
206
206
|
const items2 = (0, test_model_1.createTestItemsBM)(2).map(i => ({ ...i, id: i.id + '_str' }));
|
|
207
207
|
const ids = items2.map(i => i.id);
|
|
208
208
|
await (0, nodejs_lib_1._pipeline)([node_stream_1.Readable.from(items2), ...dao.streamSaveTransform()]);
|
|
209
209
|
const items2Loaded = await dao.getByIds(ids);
|
|
210
|
-
|
|
210
|
+
expectMatch(items2, items2Loaded, quirks);
|
|
211
211
|
// cleanup
|
|
212
212
|
await dao.query().filterIn('id', ids).deleteByQuery();
|
|
213
213
|
});
|
|
214
214
|
}
|
|
215
215
|
// DELETE BY
|
|
216
216
|
if (support.queries) {
|
|
217
|
-
|
|
217
|
+
test('deleteByQuery even=false', async () => {
|
|
218
218
|
const deleted = await dao.query().filter('even', '==', false).deleteByQuery();
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
expect(deleted).toBe(items.filter(item => !item.even).length);
|
|
220
|
+
expect(await dao.query().runQueryCount()).toBe(1);
|
|
221
221
|
});
|
|
222
|
-
|
|
222
|
+
test('cleanup', async () => {
|
|
223
223
|
// CLEAN UP
|
|
224
224
|
await dao.query().deleteByQuery();
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
227
|
if (support.transactions) {
|
|
228
|
-
|
|
228
|
+
test('transaction happy path', async () => {
|
|
229
229
|
// cleanup
|
|
230
230
|
await dao.query().deleteByQuery();
|
|
231
231
|
// Test that id, created, updated are created
|
|
@@ -235,10 +235,10 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
235
235
|
await tx.save(dao, row);
|
|
236
236
|
});
|
|
237
237
|
const loaded = await dao.query().runQuery();
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
expect(loaded.length).toBe(1);
|
|
239
|
+
expect(loaded[0].id).toBeDefined();
|
|
240
|
+
expect(loaded[0].created).toBeGreaterThanOrEqual(now);
|
|
241
|
+
expect(loaded[0].updated).toBe(loaded[0].created);
|
|
242
242
|
await dao.runInTransaction(async (tx) => {
|
|
243
243
|
await tx.deleteById(dao, loaded[0].id);
|
|
244
244
|
});
|
|
@@ -253,21 +253,36 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
253
253
|
});
|
|
254
254
|
const rows = await dao.query().runQuery();
|
|
255
255
|
const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
|
|
256
|
-
|
|
256
|
+
expectMatch(expected, rows, quirks);
|
|
257
257
|
});
|
|
258
|
-
|
|
259
|
-
await
|
|
258
|
+
test('transaction rollback', async () => {
|
|
259
|
+
await expect(dao.runInTransaction(async (tx) => {
|
|
260
260
|
await tx.deleteById(dao, items[2].id);
|
|
261
261
|
await tx.save(dao, { ...items[0], k1: 5 }); // it should fail here
|
|
262
262
|
})).rejects.toThrow();
|
|
263
263
|
const rows = await dao.query().runQuery();
|
|
264
264
|
const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
|
|
265
|
-
|
|
265
|
+
expectMatch(expected, rows, quirks);
|
|
266
266
|
});
|
|
267
267
|
if (support.queries) {
|
|
268
|
-
|
|
268
|
+
test('transaction cleanup', async () => {
|
|
269
269
|
await dao.query().deleteByQuery();
|
|
270
270
|
});
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
|
+
function expectMatch(expected, actual, quirks) {
|
|
274
|
+
// const expectedSorted = sortObjectDeep(expected)
|
|
275
|
+
// const actualSorted = sortObjectDeep(actual)
|
|
276
|
+
if (quirks.allowBooleansAsUndefined) {
|
|
277
|
+
expected = expected.map(r => {
|
|
278
|
+
return typeof r !== 'object' ? r : (0, js_lib_1._filterObject)(r, (_k, v) => v !== false);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
if (quirks.allowExtraPropertiesInResponse) {
|
|
282
|
+
expect(actual).toMatchObject(expected);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
expect(actual).toEqual(expected);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
273
288
|
}
|
package/dist/testing/dbTest.d.ts
CHANGED
|
@@ -12,5 +12,4 @@ export interface CommonDBImplementationQuirks {
|
|
|
12
12
|
*/
|
|
13
13
|
allowBooleansAsUndefined?: boolean;
|
|
14
14
|
}
|
|
15
|
-
export declare function runCommonDBTest(db: CommonDB, quirks?: CommonDBImplementationQuirks): void
|
|
16
|
-
export declare function expectMatch(expected: any[], actual: any[], quirks: CommonDBImplementationQuirks): void;
|
|
15
|
+
export declare function runCommonDBTest(db: CommonDB, quirks?: CommonDBImplementationQuirks): Promise<void>;
|
package/dist/testing/dbTest.js
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runCommonDBTest = runCommonDBTest;
|
|
4
|
-
exports.expectMatch = expectMatch;
|
|
5
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
-
const vitest_1 = require("vitest");
|
|
7
5
|
const common_db_1 = require("../common.db");
|
|
8
6
|
const dbQuery_1 = require("../query/dbQuery");
|
|
9
7
|
const test_model_1 = require("./test.model");
|
|
10
|
-
function runCommonDBTest(db, quirks = {}) {
|
|
8
|
+
async function runCommonDBTest(db, quirks = {}) {
|
|
9
|
+
// this is because vitest cannot be "required" from cjs
|
|
10
|
+
const { test, expect } = await import('vitest');
|
|
11
11
|
const { support } = db;
|
|
12
12
|
const items = (0, test_model_1.createTestItemsDBM)(3);
|
|
13
13
|
(0, js_lib_1._deepFreeze)(items);
|
|
14
14
|
const item1 = items[0];
|
|
15
15
|
const queryAll = () => dbQuery_1.DBQuery.create(test_model_1.TEST_TABLE);
|
|
16
|
-
|
|
16
|
+
test('ping', async () => {
|
|
17
17
|
await db.ping();
|
|
18
18
|
});
|
|
19
19
|
// CREATE TABLE, DROP
|
|
20
20
|
if (support.createTable) {
|
|
21
|
-
|
|
21
|
+
test('createTable, dropIfExists=true', async () => {
|
|
22
22
|
await db.createTable(test_model_1.TEST_TABLE, test_model_1.testItemBMJsonSchema, { dropIfExists: true });
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
if (support.queries) {
|
|
26
26
|
// DELETE ALL initially
|
|
27
|
-
|
|
27
|
+
test('deleteByIds test items', async () => {
|
|
28
28
|
const { rows } = await db.runQuery(queryAll().select(['id']));
|
|
29
29
|
await db.deleteByQuery(queryAll().filterIn('id', rows.map(i => i.id)));
|
|
30
30
|
});
|
|
31
31
|
// QUERY empty
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
test('runQuery(all), runQueryCount should return empty', async () => {
|
|
33
|
+
expect((await db.runQuery(queryAll())).rows).toEqual([]);
|
|
34
|
+
expect(await db.runQueryCount(queryAll())).toBe(0);
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
// GET empty
|
|
38
|
-
|
|
38
|
+
test('getByIds(item1.id) should return empty', async () => {
|
|
39
39
|
const [item1Loaded] = await db.getByIds(test_model_1.TEST_TABLE, [item1.id]);
|
|
40
40
|
// console.log(a)
|
|
41
|
-
|
|
41
|
+
expect(item1Loaded).toBeUndefined();
|
|
42
42
|
});
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
test('getByIds([]) should return []', async () => {
|
|
44
|
+
expect(await db.getByIds(test_model_1.TEST_TABLE, [])).toEqual([]);
|
|
45
45
|
});
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
test('getByIds(...) should return empty', async () => {
|
|
47
|
+
expect(await db.getByIds(test_model_1.TEST_TABLE, ['abc', 'abcd'])).toEqual([]);
|
|
48
48
|
});
|
|
49
49
|
// TimeMachine
|
|
50
50
|
if (support.timeMachine) {
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
test('getByIds(...) 10 minutes ago should return []', async () => {
|
|
52
|
+
expect(await db.getByIds(test_model_1.TEST_TABLE, [item1.id, 'abc'], {
|
|
53
53
|
readAt: js_lib_1.localTime.now().minus(10, 'minute').unix,
|
|
54
54
|
})).toEqual([]);
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
57
|
// SAVE
|
|
58
58
|
if (support.nullValues) {
|
|
59
|
-
|
|
59
|
+
test('should allow to save and load null values', async () => {
|
|
60
60
|
const item3 = {
|
|
61
61
|
...(0, test_model_1.createTestItemDBM)(3),
|
|
62
62
|
k2: null,
|
|
@@ -65,11 +65,11 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
65
65
|
await db.saveBatch(test_model_1.TEST_TABLE, [item3]);
|
|
66
66
|
const item3Loaded = (await db.getByIds(test_model_1.TEST_TABLE, [item3.id]))[0];
|
|
67
67
|
expectMatch([item3], [item3Loaded], quirks);
|
|
68
|
-
|
|
68
|
+
expect(item3Loaded.k2).toBeNull();
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
if (db.dbType === common_db_1.CommonDBType.document) {
|
|
72
|
-
|
|
72
|
+
test('undefined values should not be saved/loaded', async () => {
|
|
73
73
|
const item3 = {
|
|
74
74
|
...(0, test_model_1.createTestItemDBM)(3),
|
|
75
75
|
k2: undefined,
|
|
@@ -80,45 +80,45 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
80
80
|
await db.saveBatch(test_model_1.TEST_TABLE, [item3]);
|
|
81
81
|
const item3Loaded = (await db.getByIds(test_model_1.TEST_TABLE, [item3.id]))[0];
|
|
82
82
|
expectMatch([expected], [item3Loaded], quirks);
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
expect(item3Loaded.k2).toBeUndefined();
|
|
84
|
+
expect(Object.keys(item3Loaded)).not.toContain('k2');
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
if (support.updateSaveMethod) {
|
|
88
|
-
|
|
89
|
-
await
|
|
88
|
+
test('saveBatch UPDATE method should throw', async () => {
|
|
89
|
+
await expect(db.saveBatch(test_model_1.TEST_TABLE, items, { saveMethod: 'update' })).rejects.toThrow();
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
|
-
|
|
92
|
+
test('saveBatch test items', async () => {
|
|
93
93
|
await db.saveBatch(test_model_1.TEST_TABLE, items);
|
|
94
94
|
});
|
|
95
|
-
|
|
96
|
-
await
|
|
95
|
+
test('saveBatch should throw on null id', async () => {
|
|
96
|
+
await expect(db.saveBatch(test_model_1.TEST_TABLE, [{ ...item1, id: null }])).rejects.toThrow();
|
|
97
97
|
});
|
|
98
98
|
if (support.insertSaveMethod) {
|
|
99
|
-
|
|
100
|
-
await
|
|
99
|
+
test('saveBatch INSERT method should throw', async () => {
|
|
100
|
+
await expect(db.saveBatch(test_model_1.TEST_TABLE, items, { saveMethod: 'insert' })).rejects.toThrow();
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
if (support.updateSaveMethod) {
|
|
104
|
-
|
|
104
|
+
test('saveBatch UPDATE method should pass', async () => {
|
|
105
105
|
await db.saveBatch(test_model_1.TEST_TABLE, items, { saveMethod: 'update' });
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
108
|
// GET not empty
|
|
109
|
-
|
|
109
|
+
test('getByIds all items', async () => {
|
|
110
110
|
const rows = await db.getByIds(test_model_1.TEST_TABLE, items.map(i => i.id).concat('abcd'));
|
|
111
111
|
expectMatch(items, (0, js_lib_1._sortBy)(rows, r => r.id), quirks);
|
|
112
112
|
});
|
|
113
113
|
// QUERY
|
|
114
114
|
if (support.queries) {
|
|
115
|
-
|
|
115
|
+
test('runQuery(all) should return all items', async () => {
|
|
116
116
|
let { rows } = await db.runQuery(queryAll());
|
|
117
117
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id); // because query doesn't specify order here
|
|
118
118
|
expectMatch(items, rows, quirks);
|
|
119
119
|
});
|
|
120
120
|
if (support.dbQueryFilter) {
|
|
121
|
-
|
|
121
|
+
test('query even=true', async () => {
|
|
122
122
|
const q = new dbQuery_1.DBQuery(test_model_1.TEST_TABLE).filter('even', '==', true);
|
|
123
123
|
let { rows } = await db.runQuery(q);
|
|
124
124
|
if (!support.dbQueryOrder)
|
|
@@ -127,67 +127,67 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
if (support.dbQueryOrder) {
|
|
130
|
-
|
|
130
|
+
test('query order by k1 desc', async () => {
|
|
131
131
|
const q = new dbQuery_1.DBQuery(test_model_1.TEST_TABLE).order('k1', true);
|
|
132
132
|
const { rows } = await db.runQuery(q);
|
|
133
133
|
expectMatch([...items].reverse(), rows, quirks);
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
if (support.dbQuerySelectFields) {
|
|
137
|
-
|
|
137
|
+
test('projection query with only ids', async () => {
|
|
138
138
|
const q = new dbQuery_1.DBQuery(test_model_1.TEST_TABLE).select(['id']);
|
|
139
139
|
let { rows } = await db.runQuery(q);
|
|
140
140
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id); // cause order is not specified
|
|
141
141
|
expectMatch(items.map(item => (0, js_lib_1._pick)(item, ['id'])), rows, quirks);
|
|
142
142
|
});
|
|
143
|
-
|
|
143
|
+
test('projection query without ids', async () => {
|
|
144
144
|
const q = new dbQuery_1.DBQuery(test_model_1.TEST_TABLE).select(['k1']);
|
|
145
145
|
let { rows } = await db.runQuery(q);
|
|
146
146
|
rows = (0, js_lib_1._sortBy)(rows, r => r.k1); // cause order is not specified
|
|
147
147
|
expectMatch(items.map(item => (0, js_lib_1._pick)(item, ['k1'])), rows, quirks);
|
|
148
148
|
});
|
|
149
|
-
|
|
149
|
+
test('projection query empty fields (edge case)', async () => {
|
|
150
150
|
const q = new dbQuery_1.DBQuery(test_model_1.TEST_TABLE).select([]);
|
|
151
151
|
const { rows } = await db.runQuery(q);
|
|
152
152
|
expectMatch(items.map(() => ({})), rows, quirks);
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
test('runQueryCount should return 3', async () => {
|
|
156
|
+
expect(await db.runQueryCount(new dbQuery_1.DBQuery(test_model_1.TEST_TABLE))).toBe(3);
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
159
|
// STREAM
|
|
160
160
|
if (support.streaming) {
|
|
161
|
-
|
|
161
|
+
test('streamQuery all', async () => {
|
|
162
162
|
let rows = await db.streamQuery(queryAll()).toArray();
|
|
163
163
|
rows = (0, js_lib_1._sortBy)(rows, r => r.id); // cause order is not specified in DBQuery
|
|
164
164
|
expectMatch(items, rows, quirks);
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
167
|
// getTables
|
|
168
|
-
|
|
168
|
+
test('getTables, getTableSchema (if supported)', async () => {
|
|
169
169
|
const tables = await db.getTables();
|
|
170
170
|
// console.log({ tables })
|
|
171
171
|
if (support.tableSchemas) {
|
|
172
172
|
await (0, js_lib_1.pMap)(tables, async (table) => {
|
|
173
173
|
const schema = await db.getTableSchema(table);
|
|
174
174
|
// console.log(schema)
|
|
175
|
-
|
|
175
|
+
expect(schema.$id).toBe(`${table}.schema.json`);
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
178
|
});
|
|
179
179
|
// DELETE BY
|
|
180
180
|
if (support.queries && support.dbQueryFilter) {
|
|
181
|
-
|
|
181
|
+
test('deleteByQuery even=false', async () => {
|
|
182
182
|
const q = new dbQuery_1.DBQuery(test_model_1.TEST_TABLE).filter('even', '==', false);
|
|
183
183
|
const deleted = await db.deleteByQuery(q);
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
expect(deleted).toBe(items.filter(item => !item.even).length);
|
|
185
|
+
expect(await db.runQueryCount(queryAll())).toBe(1);
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
188
|
// BUFFER
|
|
189
189
|
if (support.bufferValues) {
|
|
190
|
-
|
|
190
|
+
test('buffer values', async () => {
|
|
191
191
|
const s = 'helloWorld 1';
|
|
192
192
|
const b1 = Buffer.from(s);
|
|
193
193
|
const item = {
|
|
@@ -205,12 +205,12 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
205
205
|
// b1,
|
|
206
206
|
// b1Loaded,
|
|
207
207
|
// })
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
expect(b1Loaded).toEqual(b1);
|
|
209
|
+
expect(b1Loaded.toString()).toBe(s);
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
212
|
if (support.transactions) {
|
|
213
|
-
|
|
213
|
+
test('transaction happy path', async () => {
|
|
214
214
|
// cleanup
|
|
215
215
|
await db.deleteByQuery(queryAll());
|
|
216
216
|
// saveBatch [item1, 2, 3]
|
|
@@ -226,7 +226,7 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
226
226
|
const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
|
|
227
227
|
expectMatch(expected, rows, quirks);
|
|
228
228
|
});
|
|
229
|
-
|
|
229
|
+
test('transaction rollback', async () => {
|
|
230
230
|
let err;
|
|
231
231
|
try {
|
|
232
232
|
await db.runInTransaction(async (tx) => {
|
|
@@ -238,14 +238,14 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
238
238
|
catch (err_) {
|
|
239
239
|
err = err_;
|
|
240
240
|
}
|
|
241
|
-
|
|
241
|
+
expect(err).toBeDefined();
|
|
242
242
|
const { rows } = await db.runQuery(queryAll());
|
|
243
243
|
const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
|
|
244
244
|
expectMatch(expected, rows, quirks);
|
|
245
245
|
});
|
|
246
246
|
}
|
|
247
247
|
if (support.patchByQuery) {
|
|
248
|
-
|
|
248
|
+
test('patchByQuery', async () => {
|
|
249
249
|
// cleanup, reset initial data
|
|
250
250
|
await db.deleteByQuery(queryAll());
|
|
251
251
|
await db.saveBatch(test_model_1.TEST_TABLE, items);
|
|
@@ -265,7 +265,7 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
267
|
if (support.increment) {
|
|
268
|
-
|
|
268
|
+
test('incrementBatch', async () => {
|
|
269
269
|
// cleanup, reset initial data
|
|
270
270
|
await db.deleteByQuery(queryAll());
|
|
271
271
|
await db.saveBatch(test_model_1.TEST_TABLE, items);
|
|
@@ -284,24 +284,24 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
284
284
|
});
|
|
285
285
|
}
|
|
286
286
|
if (support.queries) {
|
|
287
|
-
|
|
287
|
+
test('cleanup', async () => {
|
|
288
288
|
// CLEAN UP
|
|
289
289
|
await db.deleteByQuery(queryAll());
|
|
290
290
|
});
|
|
291
291
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
292
|
+
function expectMatch(expected, actual, quirks) {
|
|
293
|
+
// const expectedSorted = sortObjectDeep(expected)
|
|
294
|
+
// const actualSorted = sortObjectDeep(actual)
|
|
295
|
+
if (quirks.allowBooleansAsUndefined) {
|
|
296
|
+
expected = expected.map(r => {
|
|
297
|
+
return typeof r !== 'object' ? r : (0, js_lib_1._filterObject)(r, (_k, v) => v !== false);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
if (quirks.allowExtraPropertiesInResponse) {
|
|
301
|
+
expect(actual).toMatchObject(expected);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
expect(actual).toEqual(expected);
|
|
305
|
+
}
|
|
306
306
|
}
|
|
307
307
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { CommonKeyValueDB } from '../kv/commonKeyValueDB';
|
|
2
|
-
export declare function runCommonKeyValueDBTest(db: CommonKeyValueDB): void
|
|
2
|
+
export declare function runCommonKeyValueDBTest(db: CommonKeyValueDB): Promise<void>;
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runCommonKeyValueDBTest = runCommonKeyValueDBTest;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const vitest_1 = require("vitest");
|
|
6
5
|
const test_model_1 = require("./test.model");
|
|
7
6
|
const testIds = (0, js_lib_1._range)(1, 4).map(n => `id${n}`);
|
|
8
7
|
const testEntries = testIds.map(id => [
|
|
9
8
|
id,
|
|
10
9
|
Buffer.from(`${id}value`),
|
|
11
10
|
]);
|
|
12
|
-
function runCommonKeyValueDBTest(db) {
|
|
13
|
-
|
|
11
|
+
async function runCommonKeyValueDBTest(db) {
|
|
12
|
+
const { afterAll, beforeAll, expect, test } = await import('vitest');
|
|
13
|
+
beforeAll(async () => {
|
|
14
14
|
// Tests in this suite are not isolated,
|
|
15
15
|
// and failing tests can leave the DB in an unexpected state for other tests,
|
|
16
16
|
// including the following test run.
|
|
@@ -18,98 +18,98 @@ function runCommonKeyValueDBTest(db) {
|
|
|
18
18
|
const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
|
|
19
19
|
await db.deleteByIds(test_model_1.TEST_TABLE, ids);
|
|
20
20
|
});
|
|
21
|
-
|
|
21
|
+
afterAll(async () => {
|
|
22
22
|
const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
|
|
23
23
|
await db.deleteByIds(test_model_1.TEST_TABLE, ids);
|
|
24
24
|
});
|
|
25
25
|
const { support } = db;
|
|
26
|
-
|
|
26
|
+
test('ping', async () => {
|
|
27
27
|
await db.ping();
|
|
28
28
|
});
|
|
29
|
-
|
|
29
|
+
test('createTable', async () => {
|
|
30
30
|
await db.createTable(test_model_1.TEST_TABLE, { dropIfExists: true });
|
|
31
31
|
});
|
|
32
|
-
|
|
32
|
+
test('deleteByIds non existing', async () => {
|
|
33
33
|
await db.deleteByIds(test_model_1.TEST_TABLE, testIds);
|
|
34
34
|
});
|
|
35
|
-
|
|
35
|
+
test('getByIds should return empty', async () => {
|
|
36
36
|
const results = await db.getByIds(test_model_1.TEST_TABLE, testIds);
|
|
37
|
-
|
|
37
|
+
expect(results).toEqual([]);
|
|
38
38
|
});
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
test('count should be 0', async () => {
|
|
40
|
+
expect(await db.count(test_model_1.TEST_TABLE)).toBe(0);
|
|
41
41
|
});
|
|
42
|
-
|
|
42
|
+
test('saveBatch, then getByIds', async () => {
|
|
43
43
|
await db.saveBatch(test_model_1.TEST_TABLE, testEntries);
|
|
44
44
|
const entries = await db.getByIds(test_model_1.TEST_TABLE, testIds);
|
|
45
45
|
(0, js_lib_1._sortBy)(entries, e => e[0], true);
|
|
46
|
-
|
|
46
|
+
expect(entries).toEqual(testEntries);
|
|
47
47
|
});
|
|
48
48
|
if (support.count) {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
test('count should be 3', async () => {
|
|
50
|
+
expect(await db.count(test_model_1.TEST_TABLE)).toBe(3);
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
test('streamIds', async () => {
|
|
54
54
|
const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
|
|
55
55
|
ids.sort();
|
|
56
|
-
|
|
56
|
+
expect(ids).toEqual(testIds);
|
|
57
57
|
});
|
|
58
|
-
|
|
58
|
+
test('streamIds limited', async () => {
|
|
59
59
|
const idsLimited = await db.streamIds(test_model_1.TEST_TABLE, 2).toArray();
|
|
60
60
|
// Order is non-deterministic, so, cannot compare values
|
|
61
61
|
// idsLimited.sort()
|
|
62
62
|
// expect(idsLimited).toEqual(testIds.slice(0, 2))
|
|
63
|
-
|
|
63
|
+
expect(idsLimited.length).toBe(2);
|
|
64
64
|
});
|
|
65
|
-
|
|
65
|
+
test('streamValues', async () => {
|
|
66
66
|
const values = await db.streamValues(test_model_1.TEST_TABLE).toArray();
|
|
67
67
|
values.sort();
|
|
68
|
-
|
|
68
|
+
expect(values).toEqual(testEntries.map(e => e[1]));
|
|
69
69
|
});
|
|
70
|
-
|
|
70
|
+
test('streamValues limited', async () => {
|
|
71
71
|
const valuesLimited = await db.streamValues(test_model_1.TEST_TABLE, 2).toArray();
|
|
72
72
|
// valuesLimited.sort()
|
|
73
73
|
// expect(valuesLimited).toEqual(testEntries.map(e => e[1]).slice(0, 2))
|
|
74
|
-
|
|
74
|
+
expect(valuesLimited.length).toBe(2);
|
|
75
75
|
});
|
|
76
|
-
|
|
76
|
+
test('streamEntries', async () => {
|
|
77
77
|
const entries = await db.streamEntries(test_model_1.TEST_TABLE).toArray();
|
|
78
78
|
entries.sort();
|
|
79
|
-
|
|
79
|
+
expect(entries).toEqual(testEntries);
|
|
80
80
|
});
|
|
81
|
-
|
|
81
|
+
test('streamEntries limited', async () => {
|
|
82
82
|
const entriesLimited = await db.streamEntries(test_model_1.TEST_TABLE, 2).toArray();
|
|
83
83
|
// entriesLimited.sort()
|
|
84
84
|
// expect(entriesLimited).toEqual(testEntries.slice(0, 2))
|
|
85
|
-
|
|
85
|
+
expect(entriesLimited.length).toBe(2);
|
|
86
86
|
});
|
|
87
|
-
|
|
87
|
+
test('deleteByIds should clear', async () => {
|
|
88
88
|
await db.deleteByIds(test_model_1.TEST_TABLE, testIds);
|
|
89
89
|
const results = await db.getByIds(test_model_1.TEST_TABLE, testIds);
|
|
90
|
-
|
|
90
|
+
expect(results).toEqual([]);
|
|
91
91
|
});
|
|
92
92
|
if (support.increment) {
|
|
93
93
|
const id = 'nonExistingField';
|
|
94
94
|
const id2 = 'nonExistingField2';
|
|
95
|
-
|
|
95
|
+
test('increment on a non-existing field should set the value to 1', async () => {
|
|
96
96
|
const result = await db.incrementBatch(test_model_1.TEST_TABLE, [[id, 1]]);
|
|
97
|
-
|
|
97
|
+
expect(result).toEqual([[id, 1]]);
|
|
98
98
|
});
|
|
99
|
-
|
|
99
|
+
test('increment on a existing field should increase the value by one', async () => {
|
|
100
100
|
const result = await db.incrementBatch(test_model_1.TEST_TABLE, [[id, 1]]);
|
|
101
|
-
|
|
101
|
+
expect(result).toEqual([[id, 2]]);
|
|
102
102
|
});
|
|
103
|
-
|
|
103
|
+
test('increment should increase the value by the specified amount', async () => {
|
|
104
104
|
const result = await db.incrementBatch(test_model_1.TEST_TABLE, [[id, 2]]);
|
|
105
|
-
|
|
105
|
+
expect(result).toEqual([[id, 4]]);
|
|
106
106
|
});
|
|
107
|
-
|
|
107
|
+
test('increment 2 ids at the same time', async () => {
|
|
108
108
|
const result = await db.incrementBatch(test_model_1.TEST_TABLE, [
|
|
109
109
|
[id, 1],
|
|
110
110
|
[id2, 2],
|
|
111
111
|
]);
|
|
112
|
-
|
|
112
|
+
expect(Object.fromEntries(result)).toEqual({
|
|
113
113
|
[id]: 5,
|
|
114
114
|
[id2]: 2,
|
|
115
115
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { CommonKeyValueDB } from '../kv/commonKeyValueDB';
|
|
2
|
-
export declare function runCommonKeyValueDaoTest(db: CommonKeyValueDB): void
|
|
2
|
+
export declare function runCommonKeyValueDaoTest(db: CommonKeyValueDB): Promise<void>;
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runCommonKeyValueDaoTest = runCommonKeyValueDaoTest;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const vitest_1 = require("vitest");
|
|
6
5
|
const commonKeyValueDao_1 = require("../kv/commonKeyValueDao");
|
|
7
6
|
const test_model_1 = require("./test.model");
|
|
8
7
|
const testItems = (0, test_model_1.createTestItemsBM)(4);
|
|
9
8
|
const testIds = testItems.map(e => e.id);
|
|
10
9
|
const testEntries = testItems.map(e => [e.id, Buffer.from(`${e.id}value`)]);
|
|
11
|
-
function runCommonKeyValueDaoTest(db) {
|
|
10
|
+
async function runCommonKeyValueDaoTest(db) {
|
|
11
|
+
const { afterAll, beforeAll, expect, test } = await import('vitest');
|
|
12
12
|
const dao = new commonKeyValueDao_1.CommonKeyValueDao({
|
|
13
13
|
db,
|
|
14
14
|
table: test_model_1.TEST_TABLE,
|
|
15
15
|
// todo: make this test support "deflatedJson" transformer
|
|
16
16
|
});
|
|
17
17
|
const { support } = db;
|
|
18
|
-
|
|
18
|
+
beforeAll(async () => {
|
|
19
19
|
// Tests in this suite are not isolated,
|
|
20
20
|
// and failing tests can leave the DB in an unexpected state for other tests,
|
|
21
21
|
// including the following test run.
|
|
@@ -23,92 +23,92 @@ function runCommonKeyValueDaoTest(db) {
|
|
|
23
23
|
const ids = await dao.streamIds().toArray();
|
|
24
24
|
await dao.deleteByIds(ids);
|
|
25
25
|
});
|
|
26
|
-
|
|
26
|
+
afterAll(async () => {
|
|
27
27
|
const ids = await dao.streamIds().toArray();
|
|
28
28
|
await dao.deleteByIds(ids);
|
|
29
29
|
});
|
|
30
|
-
|
|
30
|
+
test('ping', async () => {
|
|
31
31
|
await dao.ping();
|
|
32
32
|
});
|
|
33
|
-
|
|
33
|
+
test('createTable', async () => {
|
|
34
34
|
await dao.createTable({ dropIfExists: true });
|
|
35
35
|
});
|
|
36
|
-
|
|
36
|
+
test('deleteByIds non existing', async () => {
|
|
37
37
|
await dao.deleteByIds(testIds);
|
|
38
38
|
});
|
|
39
|
-
|
|
39
|
+
test('getByIds should return empty', async () => {
|
|
40
40
|
const results = await dao.getByIds(testIds);
|
|
41
|
-
|
|
41
|
+
expect(results).toEqual([]);
|
|
42
42
|
});
|
|
43
|
-
|
|
43
|
+
test('saveBatch, then getByIds', async () => {
|
|
44
44
|
await dao.saveBatch(testEntries);
|
|
45
45
|
const entries = await dao.getByIds(testIds);
|
|
46
46
|
// console.log(typeof entries[0]![1], entries[0]![1])
|
|
47
47
|
(0, js_lib_1._sortBy)(entries, e => e[0], true);
|
|
48
|
-
|
|
48
|
+
expect(entries).toEqual(testEntries); // Jest doesn't allow to compare Buffers directly
|
|
49
49
|
// expect(entries.map(e => e[0])).toEqual(testEntries.map(e => e[0]))
|
|
50
50
|
// expect(entries.map(e => e[1].toString())).toEqual(testEntries.map(e => e[1].toString()))
|
|
51
51
|
});
|
|
52
|
-
|
|
52
|
+
test('streamIds', async () => {
|
|
53
53
|
const ids = await dao.streamIds().toArray();
|
|
54
54
|
ids.sort();
|
|
55
|
-
|
|
55
|
+
expect(ids).toEqual(testIds);
|
|
56
56
|
});
|
|
57
|
-
|
|
57
|
+
test('streamIds limited', async () => {
|
|
58
58
|
const idsLimited = await dao.streamIds(2).toArray();
|
|
59
59
|
// Order is non-deterministic, so, cannot compare values
|
|
60
60
|
// idsLimited.sort()
|
|
61
61
|
// expect(idsLimited).toEqual(testIds.slice(0, 2))
|
|
62
|
-
|
|
62
|
+
expect(idsLimited.length).toBe(2);
|
|
63
63
|
});
|
|
64
|
-
|
|
64
|
+
test('streamValues', async () => {
|
|
65
65
|
const values = await dao.streamValues().toArray();
|
|
66
66
|
values.sort();
|
|
67
|
-
|
|
67
|
+
expect(values).toEqual(testEntries.map(e => e[1]));
|
|
68
68
|
});
|
|
69
|
-
|
|
69
|
+
test('streamValues limited', async () => {
|
|
70
70
|
const valuesLimited = await dao.streamValues(2).toArray();
|
|
71
71
|
// valuesLimited.sort()
|
|
72
72
|
// expect(valuesLimited).toEqual(testEntries.map(e => e[1]).slice(0, 2))
|
|
73
|
-
|
|
73
|
+
expect(valuesLimited.length).toBe(2);
|
|
74
74
|
});
|
|
75
|
-
|
|
75
|
+
test('streamEntries', async () => {
|
|
76
76
|
const entries = await dao.streamEntries().toArray();
|
|
77
77
|
entries.sort();
|
|
78
|
-
|
|
78
|
+
expect(entries).toEqual(testEntries);
|
|
79
79
|
});
|
|
80
|
-
|
|
80
|
+
test('streamEntries limited', async () => {
|
|
81
81
|
const entriesLimited = await dao.streamEntries(2).toArray();
|
|
82
82
|
// entriesLimited.sort()
|
|
83
83
|
// expect(entriesLimited).toEqual(testEntries.slice(0, 2))
|
|
84
|
-
|
|
84
|
+
expect(entriesLimited.length).toBe(2);
|
|
85
85
|
});
|
|
86
|
-
|
|
86
|
+
test('deleteByIds should clear', async () => {
|
|
87
87
|
await dao.deleteByIds(testIds);
|
|
88
88
|
const results = await dao.getByIds(testIds);
|
|
89
|
-
|
|
89
|
+
expect(results).toEqual([]);
|
|
90
90
|
});
|
|
91
91
|
if (support.increment) {
|
|
92
92
|
const id = 'nonExistingField';
|
|
93
93
|
const id2 = 'nonExistingField2';
|
|
94
|
-
|
|
94
|
+
test('increment on a non-existing field should set the value to 1', async () => {
|
|
95
95
|
const result = await dao.increment(id);
|
|
96
|
-
|
|
96
|
+
expect(result).toBe(1);
|
|
97
97
|
});
|
|
98
|
-
|
|
98
|
+
test('increment on a existing field should increase the value by one', async () => {
|
|
99
99
|
const result = await dao.increment(id);
|
|
100
|
-
|
|
100
|
+
expect(result).toBe(2);
|
|
101
101
|
});
|
|
102
|
-
|
|
102
|
+
test('increment should increase the value by the specified amount', async () => {
|
|
103
103
|
const result = await dao.increment(id, 2);
|
|
104
|
-
|
|
104
|
+
expect(result).toBe(4);
|
|
105
105
|
});
|
|
106
|
-
|
|
106
|
+
test('increment 2 ids at the same time', async () => {
|
|
107
107
|
const result = await dao.incrementBatch([
|
|
108
108
|
[id, 1],
|
|
109
109
|
[id2, 2],
|
|
110
110
|
]);
|
|
111
|
-
|
|
111
|
+
expect(Object.fromEntries(result)).toEqual({
|
|
112
112
|
[id]: 5,
|
|
113
113
|
[id2]: 2,
|
|
114
114
|
});
|
package/package.json
CHANGED
package/src/testing/daoTest.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Readable } from 'node:stream'
|
|
2
|
-
import { _deepCopy, _omit, _pick, _sortBy, localTime } from '@naturalcycles/js-lib'
|
|
2
|
+
import { _deepCopy, _filterObject, _omit, _pick, _sortBy, localTime } from '@naturalcycles/js-lib'
|
|
3
3
|
import { _pipeline } from '@naturalcycles/nodejs-lib'
|
|
4
|
-
import { expect, test } from 'vitest'
|
|
5
4
|
import { CommonDaoLogLevel, DBQuery } from '..'
|
|
6
5
|
import { CommonDB } from '../common.db'
|
|
7
6
|
import { CommonDao } from '../commondao/common.dao'
|
|
8
7
|
import { TestItemBM } from '.'
|
|
9
|
-
import { CommonDBImplementationQuirks
|
|
8
|
+
import { CommonDBImplementationQuirks } from './dbTest'
|
|
10
9
|
import {
|
|
11
10
|
createTestItemBM,
|
|
12
11
|
createTestItemsBM,
|
|
@@ -15,7 +14,13 @@ import {
|
|
|
15
14
|
testItemBMSchema,
|
|
16
15
|
} from './test.model'
|
|
17
16
|
|
|
18
|
-
export function runCommonDaoTest(
|
|
17
|
+
export async function runCommonDaoTest(
|
|
18
|
+
db: CommonDB,
|
|
19
|
+
quirks: CommonDBImplementationQuirks = {},
|
|
20
|
+
): Promise<void> {
|
|
21
|
+
// this is because vitest cannot be "required" from cjs
|
|
22
|
+
const { test, expect } = await import('vitest')
|
|
23
|
+
|
|
19
24
|
const { support } = db
|
|
20
25
|
const dao = new CommonDao({
|
|
21
26
|
table: TEST_TABLE,
|
|
@@ -359,4 +364,21 @@ export function runCommonDaoTest(db: CommonDB, quirks: CommonDBImplementationQui
|
|
|
359
364
|
})
|
|
360
365
|
}
|
|
361
366
|
}
|
|
367
|
+
|
|
368
|
+
function expectMatch(expected: any[], actual: any[], quirks: CommonDBImplementationQuirks): void {
|
|
369
|
+
// const expectedSorted = sortObjectDeep(expected)
|
|
370
|
+
// const actualSorted = sortObjectDeep(actual)
|
|
371
|
+
|
|
372
|
+
if (quirks.allowBooleansAsUndefined) {
|
|
373
|
+
expected = expected.map(r => {
|
|
374
|
+
return typeof r !== 'object' ? r : _filterObject(r, (_k, v) => v !== false)
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (quirks.allowExtraPropertiesInResponse) {
|
|
379
|
+
expect(actual).toMatchObject(expected)
|
|
380
|
+
} else {
|
|
381
|
+
expect(actual).toEqual(expected)
|
|
382
|
+
}
|
|
383
|
+
}
|
|
362
384
|
}
|
package/src/testing/dbTest.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { _deepFreeze, _filterObject, _pick, _sortBy, localTime, pMap } from '@naturalcycles/js-lib'
|
|
2
|
-
import { expect, test } from 'vitest'
|
|
3
2
|
import { CommonDB, CommonDBType } from '../common.db'
|
|
4
3
|
import { DBQuery } from '../query/dbQuery'
|
|
5
4
|
import {
|
|
@@ -25,7 +24,13 @@ export interface CommonDBImplementationQuirks {
|
|
|
25
24
|
allowBooleansAsUndefined?: boolean
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
export function runCommonDBTest(
|
|
27
|
+
export async function runCommonDBTest(
|
|
28
|
+
db: CommonDB,
|
|
29
|
+
quirks: CommonDBImplementationQuirks = {},
|
|
30
|
+
): Promise<void> {
|
|
31
|
+
// this is because vitest cannot be "required" from cjs
|
|
32
|
+
const { test, expect } = await import('vitest')
|
|
33
|
+
|
|
29
34
|
const { support } = db
|
|
30
35
|
const items = createTestItemsDBM(3)
|
|
31
36
|
_deepFreeze(items)
|
|
@@ -380,25 +385,21 @@ export function runCommonDBTest(db: CommonDB, quirks: CommonDBImplementationQuir
|
|
|
380
385
|
await db.deleteByQuery(queryAll())
|
|
381
386
|
})
|
|
382
387
|
}
|
|
383
|
-
}
|
|
384
388
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
quirks: CommonDBImplementationQuirks,
|
|
389
|
-
): void {
|
|
390
|
-
// const expectedSorted = sortObjectDeep(expected)
|
|
391
|
-
// const actualSorted = sortObjectDeep(actual)
|
|
392
|
-
|
|
393
|
-
if (quirks.allowBooleansAsUndefined) {
|
|
394
|
-
expected = expected.map(r => {
|
|
395
|
-
return typeof r !== 'object' ? r : _filterObject(r, (_k, v) => v !== false)
|
|
396
|
-
})
|
|
397
|
-
}
|
|
389
|
+
function expectMatch(expected: any[], actual: any[], quirks: CommonDBImplementationQuirks): void {
|
|
390
|
+
// const expectedSorted = sortObjectDeep(expected)
|
|
391
|
+
// const actualSorted = sortObjectDeep(actual)
|
|
398
392
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
393
|
+
if (quirks.allowBooleansAsUndefined) {
|
|
394
|
+
expected = expected.map(r => {
|
|
395
|
+
return typeof r !== 'object' ? r : _filterObject(r, (_k, v) => v !== false)
|
|
396
|
+
})
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (quirks.allowExtraPropertiesInResponse) {
|
|
400
|
+
expect(actual).toMatchObject(expected)
|
|
401
|
+
} else {
|
|
402
|
+
expect(actual).toEqual(expected)
|
|
403
|
+
}
|
|
403
404
|
}
|
|
404
405
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { _range, _sortBy, KeyValueTuple } from '@naturalcycles/js-lib'
|
|
2
|
-
import { afterAll, beforeAll, expect, test } from 'vitest'
|
|
3
2
|
import { CommonKeyValueDB } from '../kv/commonKeyValueDB'
|
|
4
3
|
import { TEST_TABLE } from './test.model'
|
|
5
4
|
|
|
@@ -10,7 +9,9 @@ const testEntries: KeyValueTuple<string, Buffer>[] = testIds.map(id => [
|
|
|
10
9
|
Buffer.from(`${id}value`),
|
|
11
10
|
])
|
|
12
11
|
|
|
13
|
-
export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
|
|
12
|
+
export async function runCommonKeyValueDBTest(db: CommonKeyValueDB): Promise<void> {
|
|
13
|
+
const { afterAll, beforeAll, expect, test } = await import('vitest')
|
|
14
|
+
|
|
14
15
|
beforeAll(async () => {
|
|
15
16
|
// Tests in this suite are not isolated,
|
|
16
17
|
// and failing tests can leave the DB in an unexpected state for other tests,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { _sortBy } from '@naturalcycles/js-lib'
|
|
2
|
-
import { afterAll, beforeAll, expect, test } from 'vitest'
|
|
3
2
|
import { CommonKeyValueDao } from '../kv/commonKeyValueDao'
|
|
4
3
|
import { CommonKeyValueDB, KeyValueDBTuple } from '../kv/commonKeyValueDB'
|
|
5
4
|
import { createTestItemsBM, TEST_TABLE } from './test.model'
|
|
@@ -8,7 +7,9 @@ const testItems = createTestItemsBM(4)
|
|
|
8
7
|
const testIds = testItems.map(e => e.id)
|
|
9
8
|
const testEntries: KeyValueDBTuple[] = testItems.map(e => [e.id, Buffer.from(`${e.id}value`)])
|
|
10
9
|
|
|
11
|
-
export function runCommonKeyValueDaoTest(db: CommonKeyValueDB): void {
|
|
10
|
+
export async function runCommonKeyValueDaoTest(db: CommonKeyValueDB): Promise<void> {
|
|
11
|
+
const { afterAll, beforeAll, expect, test } = await import('vitest')
|
|
12
|
+
|
|
12
13
|
const dao = new CommonKeyValueDao({
|
|
13
14
|
db,
|
|
14
15
|
table: TEST_TABLE,
|