@natlibfi/melinda-rest-api-commons 6.0.1 → 6.2.0-alpha.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/.github/workflows/melinda-node-tests-and-publish.yml +4 -2
- package/README.md +82 -0
- package/dist/amqp.d.ts +41 -0
- package/dist/amqp.d.ts.map +1 -0
- package/dist/amqp.js +242 -218
- package/dist/amqp.js.map +1 -7
- package/dist/constants.d.ts +49 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +38 -38
- package/dist/constants.js.map +1 -7
- package/dist/helpers/conversion.d.ts +8 -0
- package/dist/helpers/conversion.d.ts.map +1 -0
- package/dist/helpers/conversion.js +70 -65
- package/dist/helpers/conversion.js.map +1 -7
- package/dist/helpers/fix-constants.d.ts +76 -0
- package/dist/helpers/fix-constants.d.ts.map +1 -0
- package/dist/helpers/fix-constants.js +41 -41
- package/dist/helpers/fix-constants.js.map +1 -7
- package/dist/helpers/fix-handle-tempurns.d.ts +3 -0
- package/dist/helpers/fix-handle-tempurns.d.ts.map +1 -0
- package/dist/helpers/fix-handle-tempurns.js +73 -71
- package/dist/helpers/fix-handle-tempurns.js.map +1 -7
- package/dist/helpers/fix-strip-f884s.d.ts +10 -0
- package/dist/helpers/fix-strip-f884s.d.ts.map +1 -0
- package/dist/helpers/fix-strip-f884s.js +163 -151
- package/dist/helpers/fix-strip-f884s.js.map +1 -7
- package/dist/helpers/fix.d.ts +6 -0
- package/dist/helpers/fix.d.ts.map +1 -0
- package/dist/helpers/fix.js +133 -117
- package/dist/helpers/fix.js.map +1 -7
- package/dist/helpers/validation.d.ts +9 -0
- package/dist/helpers/validation.d.ts.map +1 -0
- package/dist/helpers/validation.js +14 -16
- package/dist/helpers/validation.js.map +1 -7
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -7
- package/dist/mongo.d.ts +165 -0
- package/dist/mongo.d.ts.map +1 -0
- package/dist/mongo.js +603 -464
- package/dist/mongo.js.map +1 -7
- package/dist/mongoError.d.ts +2 -0
- package/dist/mongoError.d.ts.map +1 -0
- package/dist/mongoError.js +19 -0
- package/dist/mongoError.js.map +1 -0
- package/dist/mongoLog.d.ts +50 -0
- package/dist/mongoLog.d.ts.map +1 -0
- package/dist/mongoLog.js +282 -172
- package/dist/mongoLog.js.map +1 -7
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +118 -87
- package/dist/utils.js.map +1 -7
- package/eslint.config.ts +66 -0
- package/package.json +23 -25
- package/test/amqp-error-branches.test.ts +551 -0
- package/{tests/amqp.healthtest.js → test/amqp.healthtest.ts} +19 -7
- package/{tests/amqp.tests.localtest.js → test/amqp.tests.localtest.ts} +66 -52
- package/{tests/helpers/conversion.test.js → test/helpers/conversion.test.ts} +39 -11
- package/test/helpers/fix-edge.test.ts +201 -0
- package/test/helpers/fix.test.ts +65 -0
- package/{tests/helpers/validation.test.js → test/helpers/validation.test.ts} +13 -8
- package/{tests/mongo-add-blob-size.test.js → test/mongo-add-blob-size.test.ts} +14 -15
- package/{tests/mongo-check-and-check-state.test.js → test/mongo-check-and-check-state.test.ts} +9 -9
- package/{tests/mongo-check-and-set-import-job-state.test.js → test/mongo-check-and-set-import-job-state.test.ts} +9 -10
- package/{tests/mongo-check-timeout.test.js → test/mongo-check-timeout.test.ts} +6 -9
- package/{tests/mongo-create-bulk.test.js → test/mongo-create-bulk.test.ts} +6 -7
- package/{tests/mongo-create-prio.test.js → test/mongo-create-prio.test.ts} +6 -6
- package/test/mongo-error-branches.test.ts +883 -0
- package/{tests/mongo-get-one.test.js → test/mongo-get-one.test.ts} +6 -6
- package/{tests/mongo-get-stream.test.js → test/mongo-get-stream.test.ts} +10 -9
- package/{tests/mongo-push-ids.test.js → test/mongo-push-ids.test.ts} +6 -6
- package/{tests/mongo-push-messages.test.js → test/mongo-push-messages.test.ts} +6 -6
- package/{tests/mongo-query-by-id.test.js → test/mongo-query-by-id.test.ts} +6 -9
- package/{tests/mongo-query.test.js → test/mongo-query.test.ts} +6 -7
- package/{tests/mongo-read-content.test.js → test/mongo-read-content.test.ts} +16 -9
- package/{tests/mongo-remove.test.js → test/mongo-remove.test.ts} +6 -8
- package/{tests/mongo-set-blob-size.test.js → test/mongo-set-blob-size.test.ts} +6 -6
- package/{tests/mongo-set-import-job-state.test.js → test/mongo-set-import-job-state.test.ts} +6 -6
- package/{tests/mongo-set-operation.test.js → test/mongo-set-operation.test.ts} +6 -6
- package/{tests/mongo-set-operations.test.js → test/mongo-set-operations.test.ts} +6 -6
- package/{tests/mongo-set-state.test.js → test/mongo-set-state.test.ts} +6 -6
- package/test/mongoLog-protect.test.ts +182 -0
- package/test/mongoLog.test.ts +191 -0
- package/{tests/testUtils.js → test/testUtils.ts} +49 -15
- package/test/utils.test.ts +360 -0
- package/tsconfig.json +62 -0
- package/tsconfig.test.json +17 -0
- package/dist/helpers/fix-utils.js +0 -39
- package/dist/helpers/fix-utils.js.map +0 -7
- package/eslint.config.js +0 -53
- package/tests/helpers/fix.test.js +0 -41
- package/tests/mongoLog.test.js +0 -84
|
@@ -4,10 +4,10 @@ import {READERS} from '@natlibfi/fixura';
|
|
|
4
4
|
import mongoFixturesFactory from '@natlibfi/fixura-mongo';
|
|
5
5
|
import generateTests from '@natlibfi/fixugen';
|
|
6
6
|
//import {handleError, compareToFirstDbEntry, compareToDbEntry, formatQueueItem, streamToString} from './testUtils.js';
|
|
7
|
-
import {getMongoOperator, handleError, compareToFirstDbEntry} from './testUtils.
|
|
7
|
+
import {getMongoOperator, handleError, compareToFirstDbEntry} from './testUtils.ts';
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
let mongoFixtures;
|
|
10
|
+
let mongoFixtures: any;
|
|
11
11
|
const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons/mongo:set-state:test');
|
|
12
12
|
|
|
13
13
|
generateTests({
|
|
@@ -41,14 +41,14 @@ generateTests({
|
|
|
41
41
|
|
|
42
42
|
async function initMongofixtures() {
|
|
43
43
|
mongoFixtures = await mongoFixturesFactory({
|
|
44
|
-
recurse: false,
|
|
45
44
|
rootPath: [import.meta.dirname, '..', 'test-fixtures', 'mongo', 'set-state'],
|
|
46
45
|
gridFS: {bucketName: 'foobar'},
|
|
47
46
|
useObjectId: true
|
|
48
47
|
});
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
async function callback({
|
|
50
|
+
async function callback(callbackParams: Record<string, any>) {
|
|
51
|
+
const {
|
|
52
52
|
getFixture,
|
|
53
53
|
functionName,
|
|
54
54
|
params,
|
|
@@ -57,14 +57,14 @@ async function callback({
|
|
|
57
57
|
expectedToThrow = false,
|
|
58
58
|
expectedErrorMessage = '',
|
|
59
59
|
expectedErrorStatus = ''
|
|
60
|
-
}
|
|
60
|
+
} = callbackParams;
|
|
61
61
|
|
|
62
62
|
const mongoOperator = await getMongoOperator(mongoFixtures);
|
|
63
63
|
const expectedResult = await getFixture('expectedResult.json');
|
|
64
64
|
|
|
65
65
|
await doPreFillDb(preFillDb);
|
|
66
66
|
|
|
67
|
-
async function doPreFillDb(preFillDb) {
|
|
67
|
+
async function doPreFillDb(preFillDb: boolean) {
|
|
68
68
|
if (preFillDb) {
|
|
69
69
|
await mongoFixtures.populate(getFixture('dbContents.json'));
|
|
70
70
|
return;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import {test, before, after} from 'node:test';
|
|
3
|
+
import mongoFixturesFactory from '@natlibfi/fixura-mongo';
|
|
4
|
+
import {Error as ApiError} from '@natlibfi/melinda-commons';
|
|
5
|
+
import createMongoLogOperator from '../src/mongoLog.ts';
|
|
6
|
+
import type {MongoLogOperator} from '../src/mongoLog.ts';
|
|
7
|
+
|
|
8
|
+
let mongoFixtures: any;
|
|
9
|
+
let mongoLogOperator: MongoLogOperator;
|
|
10
|
+
|
|
11
|
+
async function initMongofixtures() {
|
|
12
|
+
mongoFixtures = await mongoFixturesFactory({
|
|
13
|
+
rootPath: [import.meta.dirname, '..', 'test-fixtures', 'mongoLog'],
|
|
14
|
+
gridFS: {bucketName: 'blobs'},
|
|
15
|
+
useObjectId: true,
|
|
16
|
+
format: {
|
|
17
|
+
logs: {
|
|
18
|
+
creationTime: v => new Date(String(v)),
|
|
19
|
+
modificationTime: v => new Date(String(v))
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const mongoUri = await mongoFixtures.getUri();
|
|
24
|
+
mongoLogOperator = await createMongoLogOperator(mongoUri, '');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function cleanup() {
|
|
28
|
+
await mongoFixtures.clear();
|
|
29
|
+
await mongoFixtures.close();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
before(async () => {
|
|
33
|
+
await initMongofixtures();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
after(async () => {
|
|
37
|
+
await cleanup();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('protect is idempotent: protecting an already protected log keeps it protected', async () => {
|
|
41
|
+
const logItem = {
|
|
42
|
+
logItemType: 'MERGE_LOG',
|
|
43
|
+
cataloger: 'IMP_TEST1',
|
|
44
|
+
correlationId: '22222222-2222-4222-8222-222222222222',
|
|
45
|
+
blobSequence: 1
|
|
46
|
+
};
|
|
47
|
+
await mongoLogOperator.addLogItem(logItem);
|
|
48
|
+
|
|
49
|
+
await mongoLogOperator.protect(logItem.correlationId, logItem.blobSequence);
|
|
50
|
+
|
|
51
|
+
// a second call must not toggle the log back to unprotected
|
|
52
|
+
await mongoLogOperator.protect(logItem.correlationId, logItem.blobSequence);
|
|
53
|
+
|
|
54
|
+
const {logs} = await mongoFixtures.dump();
|
|
55
|
+
const own = logs.filter((doc: any) => doc.correlationId === logItem.correlationId);
|
|
56
|
+
assert.equal(own.length, 1);
|
|
57
|
+
assert.equal(own[0].protected, true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('unprotect sets protected to false after protect', async () => {
|
|
61
|
+
const logItem = {
|
|
62
|
+
logItemType: 'MERGE_LOG',
|
|
63
|
+
cataloger: 'IMP_TEST1',
|
|
64
|
+
correlationId: '33333333-3333-4333-8333-333333333333',
|
|
65
|
+
blobSequence: 2
|
|
66
|
+
};
|
|
67
|
+
await mongoLogOperator.addLogItem(logItem);
|
|
68
|
+
|
|
69
|
+
await mongoLogOperator.protect(logItem.correlationId, logItem.blobSequence);
|
|
70
|
+
const result = await mongoLogOperator.unprotect(logItem.correlationId, logItem.blobSequence);
|
|
71
|
+
assert.equal(result.modifiedCount, 1);
|
|
72
|
+
|
|
73
|
+
const {logs} = await mongoFixtures.dump();
|
|
74
|
+
const own = logs.filter((doc: any) => doc.correlationId === logItem.correlationId);
|
|
75
|
+
assert.equal(own.length, 1);
|
|
76
|
+
assert.equal(own[0].protected, false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('unprotect without blobSequence unprotects all logs of the correlationId', async () => {
|
|
80
|
+
const correlationId = '44444444-4444-4444-8444-444444444444';
|
|
81
|
+
await mongoLogOperator.addLogItem({logItemType: 'MERGE_LOG', cataloger: 'IMP_TEST1', correlationId, blobSequence: 1});
|
|
82
|
+
await mongoLogOperator.addLogItem({logItemType: 'MATCH_LOG', cataloger: 'IMP_TEST1', correlationId, blobSequence: 2});
|
|
83
|
+
|
|
84
|
+
await mongoLogOperator.protect(correlationId);
|
|
85
|
+
const result = await mongoLogOperator.unprotect(correlationId);
|
|
86
|
+
assert.equal(result.modifiedCount, 2);
|
|
87
|
+
|
|
88
|
+
const {logs} = await mongoFixtures.dump();
|
|
89
|
+
const own = logs.filter((doc: any) => doc.correlationId === correlationId);
|
|
90
|
+
assert.equal(own.length, 2);
|
|
91
|
+
assert.ok(own.every((doc: any) => doc.protected === false));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('getExpandedListOfLogs throws ApiError when logItemTypes is provided but is not an array', async () => {
|
|
95
|
+
await assert.rejects(
|
|
96
|
+
() => mongoLogOperator.getExpandedListOfLogs({logItemTypes: 'MERGE_LOG'}),
|
|
97
|
+
(error) => {
|
|
98
|
+
assert.ok(error instanceof ApiError);
|
|
99
|
+
assert.strictEqual(error.status, 400);
|
|
100
|
+
assert.ok((error.payload as string).includes('logItemTypes must be an array'));
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('getExpandedListOfLogs throws ApiError when logItemTypes contains an unknown element', async () => {
|
|
107
|
+
await assert.rejects(
|
|
108
|
+
() => mongoLogOperator.getExpandedListOfLogs({logItemTypes: ['MERGE_LOG', 'BOGUS_LOG']}),
|
|
109
|
+
(error) => {
|
|
110
|
+
assert.ok(error instanceof ApiError);
|
|
111
|
+
assert.strictEqual(error.status, 400);
|
|
112
|
+
assert.ok((error.payload as string).includes('Unknown logItemType'));
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('getExpandedListOfLogs uses Date instances for dateBefore and dateAfter as-is', async () => {
|
|
119
|
+
const logItem = {
|
|
120
|
+
logItemType: 'MERGE_LOG',
|
|
121
|
+
cataloger: 'IMP_TEST1',
|
|
122
|
+
correlationId: '66666666-6666-4666-8666-666666666666',
|
|
123
|
+
blobSequence: 1
|
|
124
|
+
};
|
|
125
|
+
await mongoLogOperator.addLogItem(logItem);
|
|
126
|
+
// both bounds as Date instances: the match must use them as-is (no UTC
|
|
127
|
+
// midnight anchoring), so the freshly created log is inside the window
|
|
128
|
+
const result = await mongoLogOperator.getExpandedListOfLogs({
|
|
129
|
+
logItemTypes: ['MERGE_LOG'],
|
|
130
|
+
catalogers: ['IMP_TEST1'],
|
|
131
|
+
dateBefore: new Date(Date.now() + 60 * 60 * 1000),
|
|
132
|
+
dateAfter: new Date(Date.now() - 60 * 60 * 1000)
|
|
133
|
+
});
|
|
134
|
+
const own = result.filter(entry => entry.correlationId === logItem.correlationId);
|
|
135
|
+
assert.equal(own.length, 1);
|
|
136
|
+
assert.equal(own[0]?.logCount, 1);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('getListOfLogs throws ApiError 500 for an unknown logItemType', async () => {
|
|
140
|
+
await assert.rejects(
|
|
141
|
+
() => mongoLogOperator.getListOfLogs('BOGUS_LOG'),
|
|
142
|
+
(error) => {
|
|
143
|
+
assert.ok(error instanceof ApiError);
|
|
144
|
+
assert.strictEqual(error.status, 500);
|
|
145
|
+
assert.ok((error.payload as string).includes('Unknown logItemType'));
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('addLogItem with an unknown logItemType does not throw (warn path)', async () => {
|
|
152
|
+
const logItem = {
|
|
153
|
+
logItemType: 'BOGUS_LOG',
|
|
154
|
+
cataloger: 'IMP_TEST1',
|
|
155
|
+
correlationId: '77777777-7777-4777-8777-777777777777',
|
|
156
|
+
blobSequence: 1
|
|
157
|
+
};
|
|
158
|
+
// checkLogItemType is called with errorUnknown=false for addLogItem, so an
|
|
159
|
+
// unknown type must only warn, not throw, and the log must be stored
|
|
160
|
+
await mongoLogOperator.addLogItem(logItem);
|
|
161
|
+
|
|
162
|
+
const {logs} = await mongoFixtures.dump();
|
|
163
|
+
const own = logs.filter((doc: any) => doc.correlationId === logItem.correlationId);
|
|
164
|
+
assert.equal(own.length, 1);
|
|
165
|
+
assert.equal(own[0].logItemType, 'BOGUS_LOG');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test('getExpandedListOfLogs with a valid logItemTypes array still works', async () => {
|
|
169
|
+
const logItem = {
|
|
170
|
+
logItemType: 'MERGE_LOG',
|
|
171
|
+
cataloger: 'IMP_TEST1',
|
|
172
|
+
correlationId: '55555555-5555-4555-8555-555555555555',
|
|
173
|
+
blobSequence: 1
|
|
174
|
+
};
|
|
175
|
+
await mongoLogOperator.addLogItem(logItem);
|
|
176
|
+
const result = await mongoLogOperator.getExpandedListOfLogs({logItemTypes: ['MERGE_LOG'], catalogers: ['IMP_TEST1'], dateBefore: new Date(Date.now() + 60 * 60 * 1000)});
|
|
177
|
+
const own = result.filter(entry => entry.correlationId === logItem.correlationId);
|
|
178
|
+
assert.equal(own.length, 1);
|
|
179
|
+
assert.equal(own[0]?.logItemType, 'MERGE_LOG');
|
|
180
|
+
assert.equal(own[0]?.cataloger, 'IMP_TEST1');
|
|
181
|
+
assert.equal(own[0]?.logCount, 1);
|
|
182
|
+
});
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import {READERS} from '@natlibfi/fixura';
|
|
3
|
+
import {Error as ApiError} from '@natlibfi/melinda-commons';
|
|
4
|
+
import generateTests from '@natlibfi/fixugen';
|
|
5
|
+
import mongoFixturesFactory from '@natlibfi/fixura-mongo';
|
|
6
|
+
import createMongoLogOperator from '../src/mongoLog.ts';
|
|
7
|
+
|
|
8
|
+
let mongoFixtures: any;
|
|
9
|
+
|
|
10
|
+
generateTests({
|
|
11
|
+
callback,
|
|
12
|
+
path: [import.meta.dirname, '..', 'test-fixtures', 'mongoLog'],
|
|
13
|
+
recurse: false,
|
|
14
|
+
useMetadataFile: true,
|
|
15
|
+
fixura: {
|
|
16
|
+
failWhenNotFound: true,
|
|
17
|
+
reader: READERS.JSON
|
|
18
|
+
},
|
|
19
|
+
hooks: {
|
|
20
|
+
before: async () => {
|
|
21
|
+
await initMongofixtures();
|
|
22
|
+
},
|
|
23
|
+
beforeEach: () => mongoFixtures.clear(),
|
|
24
|
+
afterEach: () => mongoFixtures.clear(),
|
|
25
|
+
after: async () => {
|
|
26
|
+
await mongoFixtures.close();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
async function initMongofixtures() {
|
|
32
|
+
mongoFixtures = await mongoFixturesFactory({
|
|
33
|
+
rootPath: [import.meta.dirname, '..', 'test-fixtures', 'mongoLog'],
|
|
34
|
+
gridFS: {bucketName: 'blobs'},
|
|
35
|
+
useObjectId: true,
|
|
36
|
+
// fixura-mongo format is keyed by COLLECTION name, so the old
|
|
37
|
+
// {creationTime, modificationTime} form never applied and the fixtures
|
|
38
|
+
// stored creationTime as an ISO string (production addLogItem stores a
|
|
39
|
+
// Date). Format under the 'logs' collection so tests see the real
|
|
40
|
+
// production shape.
|
|
41
|
+
format: {
|
|
42
|
+
logs: {
|
|
43
|
+
creationTime: v => new Date(String(v)),
|
|
44
|
+
modificationTime: v => new Date(String(v))
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function callback(callbackParams: Record<string, any>) {
|
|
51
|
+
const {
|
|
52
|
+
getFixture,
|
|
53
|
+
functionName,
|
|
54
|
+
params,
|
|
55
|
+
preFillDb = false,
|
|
56
|
+
expectError = false,
|
|
57
|
+
expectedErrorStatus = 500
|
|
58
|
+
} = callbackParams;
|
|
59
|
+
const mongoUri = await mongoFixtures.getUri();
|
|
60
|
+
const mongoLogOperator = await createMongoLogOperator(mongoUri, '');
|
|
61
|
+
const expectedResult = expectError ? undefined : await getFixture('expectedResult.json');
|
|
62
|
+
|
|
63
|
+
if (expectError) {
|
|
64
|
+
// assert the throw (like the removeBySequences branch below)
|
|
65
|
+
if (functionName === 'protect') {
|
|
66
|
+
const [correlationId, blobSequence] = params;
|
|
67
|
+
return assert.rejects(
|
|
68
|
+
() => mongoLogOperator.protect(correlationId, blobSequence),
|
|
69
|
+
error => error instanceof ApiError && error.status === expectedErrorStatus
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
if (functionName === 'remove') {
|
|
73
|
+
const [correlationId, force] = params;
|
|
74
|
+
return assert.rejects(
|
|
75
|
+
() => mongoLogOperator.remove(correlationId, force),
|
|
76
|
+
error => error instanceof ApiError && error.status === expectedErrorStatus
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
if (functionName === 'removeBySequences') {
|
|
80
|
+
const [correlationId, sequences, force] = params;
|
|
81
|
+
return assert.rejects(
|
|
82
|
+
() => mongoLogOperator.removeBySequences(correlationId, sequences, force),
|
|
83
|
+
error => error instanceof ApiError && error.status === expectedErrorStatus
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`Unknown functionName with expectError: ${functionName}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// console.log(typeof mongoUri); // eslint-disable-line
|
|
90
|
+
|
|
91
|
+
if (preFillDb) {
|
|
92
|
+
await mongoFixtures.populate(getFixture('dbContents.json'));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (functionName === 'addLogItem') {
|
|
96
|
+
await mongoLogOperator.addLogItem(params);
|
|
97
|
+
const dump = await mongoFixtures.dump();
|
|
98
|
+
return assert.deepStrictEqual(dump.logs[0]['0'], expectedResult);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (functionName === 'getListOfCatalogers') {
|
|
102
|
+
const result = await mongoLogOperator.getListOfCatalogers();
|
|
103
|
+
// console.log(result); // eslint-disable-line
|
|
104
|
+
|
|
105
|
+
return assert.deepEqual(result, expectedResult);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (functionName === 'getExpandedListOfLogs') {
|
|
109
|
+
const result = await mongoLogOperator.getExpandedListOfLogs(params);
|
|
110
|
+
// console.log(result); // eslint-disable-line
|
|
111
|
+
|
|
112
|
+
return assert.deepEqual(normalizeDates(result), expectedResult);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (functionName === 'getListOfLogs') {
|
|
116
|
+
const result = await mongoLogOperator.getListOfLogs(params);
|
|
117
|
+
// console.log(result); // eslint-disable-line
|
|
118
|
+
return assert.deepEqual(result, expectedResult);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (functionName === 'query') {
|
|
122
|
+
const result = normalizeDates(await mongoLogOperator.query(params));
|
|
123
|
+
// console.log(result); // eslint-disable-line
|
|
124
|
+
return assert.deepEqual(result, expectedResult);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (functionName === 'queryById') {
|
|
128
|
+
const [correlationId, logItemType, skip, limit] = params;
|
|
129
|
+
const result = normalizeDates(await mongoLogOperator.queryById(correlationId, logItemType, skip, limit));
|
|
130
|
+
// console.log(result); // eslint-disable-line
|
|
131
|
+
return assert.deepEqual(result, expectedResult);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (functionName === 'getListOfCorrelationIds') {
|
|
135
|
+
const result = await mongoLogOperator.getListOfCorrelationIds();
|
|
136
|
+
// console.log(result); // eslint-disable-line
|
|
137
|
+
return assert.deepEqual(result, expectedResult);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (functionName === 'protect') {
|
|
141
|
+
const [correlationId, blobSequence] = params;
|
|
142
|
+
const result = await mongoLogOperator.protect(correlationId, blobSequence);
|
|
143
|
+
assert.deepEqual(result, expectedResult);
|
|
144
|
+
const remaining = (await dumpRemaining()).map(doc => {
|
|
145
|
+
// protect() sets modificationTime to the current time, so it can't be
|
|
146
|
+
// compared against a static fixture
|
|
147
|
+
const fixed = {...doc};
|
|
148
|
+
delete fixed.modificationTime;
|
|
149
|
+
return fixed;
|
|
150
|
+
});
|
|
151
|
+
return assert.deepEqual(remaining, getFixture('expectedRemaining.json'));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (functionName === 'remove') {
|
|
155
|
+
const [correlationId, force] = params;
|
|
156
|
+
const result = await mongoLogOperator.remove(correlationId, force);
|
|
157
|
+
assert.deepEqual(result, expectedResult);
|
|
158
|
+
return assert.deepEqual(await dumpRemaining(), getFixture('expectedRemaining.json'));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (functionName === 'removeBySequences') {
|
|
162
|
+
const [correlationId, sequences, force] = params;
|
|
163
|
+
const result = await mongoLogOperator.removeBySequences(correlationId, sequences, force);
|
|
164
|
+
assert.deepEqual(result, expectedResult);
|
|
165
|
+
return assert.deepEqual(await dumpRemaining(), getFixture('expectedRemaining.json'));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
throw new Error(`Unknown functionName: ${functionName}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Dump the surviving logs, normalized for comparison against a fixture
|
|
172
|
+
async function dumpRemaining() {
|
|
173
|
+
return normalizeDates((await mongoFixtures.dump()).logs);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Convert BSON Dates in the result to ISO strings and drop _id, so the result
|
|
177
|
+
// can be compared with the plain strings in expectedResult.json /
|
|
178
|
+
// expectedRemaining.json (fixura-mongo dump also strips _id)
|
|
179
|
+
function normalizeDates(docs: any[]): any[] {
|
|
180
|
+
return docs.map(doc => {
|
|
181
|
+
const fixed = {...doc};
|
|
182
|
+
delete fixed._id;
|
|
183
|
+
if (fixed.creationTime instanceof Date) {
|
|
184
|
+
fixed.creationTime = fixed.creationTime.toISOString();
|
|
185
|
+
}
|
|
186
|
+
if (fixed.modificationTime instanceof Date) {
|
|
187
|
+
fixed.modificationTime = fixed.modificationTime.toISOString();
|
|
188
|
+
}
|
|
189
|
+
return fixed;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
@@ -1,23 +1,39 @@
|
|
|
1
|
-
|
|
2
1
|
import assert from 'node:assert';
|
|
3
2
|
import createDebugLogger from 'debug';
|
|
4
|
-
import
|
|
3
|
+
import type {Readable} from 'node:stream';
|
|
4
|
+
import createMongoOperator from '../src/mongo.ts';
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons/mongo:test');
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// the fixura-mongo fixtures object is intentionally untyped in tests
|
|
10
|
+
// (fixture-driven scaffolding, see the eslint house rules for test/)
|
|
11
|
+
export async function getMongoOperator(mongoFixtures: any) {
|
|
10
12
|
const mongoUri = await mongoFixtures.getUri();
|
|
11
13
|
const mongoOperator = await createMongoOperator(mongoUri, 'foobar', '');
|
|
12
14
|
return mongoOperator;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
interface DbEntryCompareParams {
|
|
18
|
+
mongoFixtures: any;
|
|
19
|
+
expectedResult: unknown;
|
|
20
|
+
expectModificationTime?: boolean;
|
|
21
|
+
formatDates?: boolean;
|
|
22
|
+
expectedFileCount?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function compareToFirstDbEntry(params: DbEntryCompareParams) {
|
|
26
|
+
const {mongoFixtures, expectedResult, expectModificationTime = false, formatDates = true, expectedFileCount = undefined} = params;
|
|
16
27
|
const result = await compareToDbEntry({mongoFixtures, expectedResult, resultIndex: 0, expectModificationTime, formatDates, expectedFileCount});
|
|
17
28
|
return result;
|
|
18
29
|
}
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
interface DbEntryParams extends DbEntryCompareParams {
|
|
32
|
+
resultIndex?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function compareToDbEntry(params: DbEntryParams) {
|
|
36
|
+
const {mongoFixtures, expectedResult, resultIndex = 0, expectModificationTime = false, formatDates = true, expectedFileCount = undefined} = params;
|
|
21
37
|
const dump = await mongoFixtures.dump();
|
|
22
38
|
debug(`--- We have ${dump.foobar.length} documents in db`);
|
|
23
39
|
debug(dump.foobar);
|
|
@@ -39,7 +55,13 @@ export async function compareToDbEntry({mongoFixtures, expectedResult, resultInd
|
|
|
39
55
|
return;
|
|
40
56
|
}
|
|
41
57
|
|
|
42
|
-
|
|
58
|
+
interface CheckFileCountParams {
|
|
59
|
+
dump: any;
|
|
60
|
+
expectedFileCount: number | undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function checkFileCount(params: CheckFileCountParams) {
|
|
64
|
+
const {dump, expectedFileCount} = params;
|
|
43
65
|
if (expectedFileCount !== undefined) {
|
|
44
66
|
const fileCount = dump['foobar.files']?.length;
|
|
45
67
|
debug(`--- We have ${fileCount} files in db`);
|
|
@@ -50,7 +72,13 @@ function checkFileCount({dump, expectedFileCount}) {
|
|
|
50
72
|
|
|
51
73
|
}
|
|
52
74
|
|
|
53
|
-
|
|
75
|
+
interface CheckModificationTimeParams {
|
|
76
|
+
result: any;
|
|
77
|
+
expectModificationTime: boolean;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function checkModificationTime(params: CheckModificationTimeParams) {
|
|
81
|
+
const {result, expectModificationTime} = params;
|
|
54
82
|
if (expectModificationTime) {
|
|
55
83
|
debug('Check if modificationTime was edited');
|
|
56
84
|
const isNotEmpty = result.modificationTime !== '';
|
|
@@ -62,7 +90,7 @@ function checkModificationTime({result, expectModificationTime}) {
|
|
|
62
90
|
}
|
|
63
91
|
|
|
64
92
|
|
|
65
|
-
export function formatQueueItem(queueItem) {
|
|
93
|
+
export function formatQueueItem(queueItem: any): any {
|
|
66
94
|
const filteredQueueItem = {
|
|
67
95
|
...queueItem,
|
|
68
96
|
creationTime: '',
|
|
@@ -72,12 +100,19 @@ export function formatQueueItem(queueItem) {
|
|
|
72
100
|
return filteredQueueItem;
|
|
73
101
|
}
|
|
74
102
|
|
|
75
|
-
|
|
103
|
+
interface HandleErrorParams {
|
|
104
|
+
error: any;
|
|
105
|
+
expectedToThrow: boolean;
|
|
106
|
+
expectedErrorMessage: string;
|
|
107
|
+
expectedErrorStatus: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function handleError(params: HandleErrorParams) {
|
|
111
|
+
const {error, expectedToThrow, expectedErrorMessage, expectedErrorStatus} = params;
|
|
76
112
|
debug(error);
|
|
77
113
|
if (expectedToThrow) {
|
|
78
114
|
debug('OK. Expected to throw');
|
|
79
115
|
debug(JSON.stringify(error));
|
|
80
|
-
// eslint-disable-next-line max-lines
|
|
81
116
|
if (expectedErrorMessage !== '' || expectedErrorStatus !== '') {
|
|
82
117
|
const errorMessage = error.message || error.payload.message || error.payload || '';
|
|
83
118
|
debug(errorMessage);
|
|
@@ -92,12 +127,11 @@ export function handleError({error, expectedToThrow, expectedErrorMessage, expec
|
|
|
92
127
|
throw error;
|
|
93
128
|
}
|
|
94
129
|
|
|
95
|
-
export function streamToString(stream) {
|
|
96
|
-
const chunks = [];
|
|
130
|
+
export function streamToString(stream: Readable): Promise<string> {
|
|
131
|
+
const chunks: Buffer[] = [];
|
|
97
132
|
return new Promise((resolve, reject) => {
|
|
98
|
-
|
|
99
|
-
stream.on('
|
|
100
|
-
stream.on('error', (err) => reject(err));
|
|
133
|
+
stream.on('data', (chunk: Buffer) => chunks.push(Buffer.from(chunk)));
|
|
134
|
+
stream.on('error', (err: unknown) => reject(err));
|
|
101
135
|
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
102
136
|
});
|
|
103
137
|
}
|