w-orm-mongodb 1.1.38 → 1.1.40
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/README.md +51 -47
- package/dist/w-orm-mongodb.umd.js +2 -2
- package/dist/w-orm-mongodb.umd.js.map +1 -1
- package/docs/WOrmMongodb.html +77 -29
- package/docs/WOrmMongodb.mjs.html +75 -38
- package/docs/index.html +2 -2
- package/g-basic.mjs +8 -8
- package/g-gfs.mjs +12 -12
- package/g-unique.mjs +6 -6
- package/package.json +1 -1
- package/src/WOrmMongodb.mjs +73 -36
- package/test/api-basic.test.mjs +258 -30
- package/test/api-gfs.test.mjs +146 -14
package/test/api-basic.test.mjs
CHANGED
|
@@ -10,7 +10,7 @@ let ctDb = 'worm'
|
|
|
10
10
|
let ctPort = null //容器對外埠, 由startContainer動態取得
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
//genOpt
|
|
13
|
+
//genOpt, 不帶autoGenPk以驗證其預設值
|
|
14
14
|
let genOpt = (cl) => {
|
|
15
15
|
return {
|
|
16
16
|
url: genUrl(ctPort),
|
|
@@ -19,6 +19,16 @@ let genOpt = (cl) => {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
//genOptPk, 明確指定autoGenPk
|
|
23
|
+
let genOptPk = (cl, autoGenPk) => {
|
|
24
|
+
return {
|
|
25
|
+
url: genUrl(ctPort),
|
|
26
|
+
db: ctDb,
|
|
27
|
+
cl,
|
|
28
|
+
autoGenPk,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
//genKeys, 取回傳物件之鍵集合, 用於驗證鍵集合固定
|
|
23
33
|
let genKeys = (v) => {
|
|
24
34
|
return Object.keys(v).sort().join(',')
|
|
@@ -296,10 +306,10 @@ describe('basic', function() {
|
|
|
296
306
|
// vans[17] = []
|
|
297
307
|
vget[17] = await wo.select({ name: 'not-existed' })
|
|
298
308
|
|
|
299
|
-
//
|
|
309
|
+
//selectByPk, 由id直接查找單筆
|
|
300
310
|
rt = null
|
|
301
311
|
// vans[10] = { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 }
|
|
302
|
-
await wo.
|
|
312
|
+
await wo.selectByPk('id-rosemary')
|
|
303
313
|
.then(function(msg) {
|
|
304
314
|
rt = msg
|
|
305
315
|
})
|
|
@@ -308,16 +318,16 @@ describe('basic', function() {
|
|
|
308
318
|
})
|
|
309
319
|
vget[10] = rt
|
|
310
320
|
|
|
311
|
-
//
|
|
321
|
+
//selectByPk, 與select(find)取得同一筆之內容須一致
|
|
312
322
|
// vans[11] = true
|
|
313
|
-
let sbi = await wo.
|
|
323
|
+
let sbi = await wo.selectByPk('id-peter')
|
|
314
324
|
let sbf = await wo.select({ id: 'id-peter' })
|
|
315
325
|
vget[11] = JSON.stringify(sbi) === JSON.stringify(sbf[0])
|
|
316
326
|
|
|
317
|
-
//
|
|
327
|
+
//selectByPk by id not existed
|
|
318
328
|
rt = null
|
|
319
329
|
// vans[12] = null
|
|
320
|
-
await wo.
|
|
330
|
+
await wo.selectByPk('id-not-existed')
|
|
321
331
|
.then(function(msg) {
|
|
322
332
|
rt = msg
|
|
323
333
|
})
|
|
@@ -326,12 +336,12 @@ describe('basic', function() {
|
|
|
326
336
|
})
|
|
327
337
|
vget[12] = rt
|
|
328
338
|
|
|
329
|
-
//
|
|
339
|
+
//selectByPk by id invalid, 未給有效id視為查無數據
|
|
330
340
|
// vans[13] = [null, null, null]
|
|
331
341
|
vget[13] = [
|
|
332
|
-
await wo.
|
|
333
|
-
await wo.
|
|
334
|
-
await wo.
|
|
342
|
+
await wo.selectByPk(''),
|
|
343
|
+
await wo.selectByPk(123),
|
|
344
|
+
await wo.selectByPk(null),
|
|
335
345
|
]
|
|
336
346
|
|
|
337
347
|
//del
|
|
@@ -349,9 +359,9 @@ describe('basic', function() {
|
|
|
349
359
|
})
|
|
350
360
|
vget[14] = rt
|
|
351
361
|
|
|
352
|
-
//
|
|
362
|
+
//selectByPk, 已刪除者須回傳null
|
|
353
363
|
// vans[15] = null
|
|
354
|
-
vget[15] = await wo.
|
|
364
|
+
vget[15] = await wo.selectByPk(d[0].id)
|
|
355
365
|
|
|
356
366
|
})
|
|
357
367
|
|
|
@@ -422,22 +432,22 @@ describe('basic', function() {
|
|
|
422
432
|
})
|
|
423
433
|
|
|
424
434
|
vans[10] = { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 }
|
|
425
|
-
it(`should get ${JSON.stringify(vans[10])} for
|
|
435
|
+
it(`should get ${JSON.stringify(vans[10])} for selectByPk`, async function() {
|
|
426
436
|
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
427
437
|
})
|
|
428
438
|
|
|
429
439
|
vans[11] = true
|
|
430
|
-
it(`should get ${JSON.stringify(vans[11])} for same content between
|
|
440
|
+
it(`should get ${JSON.stringify(vans[11])} for same content between selectByPk and select`, async function() {
|
|
431
441
|
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
432
442
|
})
|
|
433
443
|
|
|
434
444
|
vans[12] = null
|
|
435
|
-
it(`should get ${JSON.stringify(vans[12])} for
|
|
445
|
+
it(`should get ${JSON.stringify(vans[12])} for selectByPk by id not existed`, async function() {
|
|
436
446
|
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
437
447
|
})
|
|
438
448
|
|
|
439
449
|
vans[13] = [null, null, null]
|
|
440
|
-
it(`should get ${JSON.stringify(vans[13])} for
|
|
450
|
+
it(`should get ${JSON.stringify(vans[13])} for selectByPk by id invalid`, async function() {
|
|
441
451
|
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
442
452
|
})
|
|
443
453
|
|
|
@@ -447,7 +457,7 @@ describe('basic', function() {
|
|
|
447
457
|
})
|
|
448
458
|
|
|
449
459
|
vans[15] = null
|
|
450
|
-
it(`should get ${JSON.stringify(vans[15])} for
|
|
460
|
+
it(`should get ${JSON.stringify(vans[15])} for selectByPk after del`, async function() {
|
|
451
461
|
assert.strict.deepStrictEqual(vget[15], vans[15])
|
|
452
462
|
})
|
|
453
463
|
|
|
@@ -510,10 +520,10 @@ describe('insert', function() {
|
|
|
510
520
|
vget[7] = (await wo.select()).length
|
|
511
521
|
|
|
512
522
|
//同批重複者僅首筆入庫
|
|
513
|
-
vget[8] = (await wo.
|
|
523
|
+
vget[8] = (await wo.selectByPk('i-dup')).name
|
|
514
524
|
|
|
515
525
|
//已存在id不得被insert覆寫
|
|
516
|
-
vget[9] = await wo.
|
|
526
|
+
vget[9] = await wo.selectByPk('i2')
|
|
517
527
|
|
|
518
528
|
//併發後僅存單筆
|
|
519
529
|
vget[10] = (await wo.select({ id: 'i-race' })).length
|
|
@@ -605,7 +615,7 @@ describe('save', function() {
|
|
|
605
615
|
await Promise.all(Array.from({ length: 10 }, (v, k) => {
|
|
606
616
|
return wo.save({ id: 'u1', [`f${k}`]: k })
|
|
607
617
|
}))
|
|
608
|
-
let vu1 = await wo.
|
|
618
|
+
let vu1 = await wo.selectByPk('u1')
|
|
609
619
|
vget[1] = Object.keys(vu1).filter((k) => k.indexOf('f') === 0).length
|
|
610
620
|
vget[2] = vu1.base
|
|
611
621
|
|
|
@@ -616,7 +626,7 @@ describe('save', function() {
|
|
|
616
626
|
vget[3] = rsn.filter((v) => v[0].nInserted === 1).length
|
|
617
627
|
vget[4] = rsn.filter((v) => v[0].ok !== 1).length
|
|
618
628
|
vget[5] = (await wo.select({ id: 'w1' })).length
|
|
619
|
-
vget[6] = Object.keys(await wo.
|
|
629
|
+
vget[6] = Object.keys(await wo.selectByPk('w1')).filter((k) => k.indexOf('g') === 0).length
|
|
620
630
|
|
|
621
631
|
//save內容相同不更新, 由MongoDB於伺服器端比對合併後結果與現值
|
|
622
632
|
await wo.insert({ id: 's1', name: 'same', value: 5 })
|
|
@@ -633,11 +643,11 @@ describe('save', function() {
|
|
|
633
643
|
//save內容不同須更新, 未給之欄位須保留
|
|
634
644
|
await wo.insert({ id: 'd1', name: 'diff', value: 5 })
|
|
635
645
|
vget[8] = await wo.save({ id: 'd1', value: 6 })
|
|
636
|
-
vget[9] = await wo.
|
|
646
|
+
vget[9] = await wo.selectByPk('d1')
|
|
637
647
|
|
|
638
648
|
//save(autoInsert=false)對不存在之id不得插入
|
|
639
649
|
vget[10] = await wo.save({ id: 'n1', name: 'none' }, { autoInsert: false })
|
|
640
|
-
vget[11] = await wo.
|
|
650
|
+
vget[11] = await wo.selectByPk('n1')
|
|
641
651
|
|
|
642
652
|
//併發save(autoInsert=false)對既有id之不同欄位, 各欄位皆須保留且不得報錯
|
|
643
653
|
await wo.insert({ id: 'p1', name: 'origin', value: 1 })
|
|
@@ -646,7 +656,7 @@ describe('save', function() {
|
|
|
646
656
|
wo.save({ id: 'p1', value: 88 }, { autoInsert: false }),
|
|
647
657
|
])
|
|
648
658
|
vget[12] = rsu.filter((v) => v[0].ok !== 1).length
|
|
649
|
-
vget[13] = await wo.
|
|
659
|
+
vget[13] = await wo.selectByPk('p1')
|
|
650
660
|
|
|
651
661
|
//change事件, autoInsert時仍須發出insert事件
|
|
652
662
|
let woEv = WOrm(genOpt('saveevent'))
|
|
@@ -812,10 +822,10 @@ describe('save single failure', function() {
|
|
|
812
822
|
}
|
|
813
823
|
|
|
814
824
|
//單筆失敗不得中斷整批, 後續筆仍須寫入
|
|
815
|
-
vget[7] = (await wo.
|
|
825
|
+
vget[7] = (await wo.selectByPk('f3')).name
|
|
816
826
|
|
|
817
827
|
//失敗筆不得被寫入
|
|
818
|
-
vget[8] = await wo.
|
|
828
|
+
vget[8] = await wo.selectByPk('f2')
|
|
819
829
|
|
|
820
830
|
})
|
|
821
831
|
|
|
@@ -920,7 +930,7 @@ describe('del', function() {
|
|
|
920
930
|
vget[15] = typeof rbig[0].err === 'string' && rbig[0].err.length > 0
|
|
921
931
|
|
|
922
932
|
//單筆失敗不得中斷整批, 後續筆仍須刪除
|
|
923
|
-
vget[16] = await wo.
|
|
933
|
+
vget[16] = await wo.selectByPk('k3')
|
|
924
934
|
|
|
925
935
|
})
|
|
926
936
|
|
|
@@ -1094,7 +1104,7 @@ describe('change event', function() {
|
|
|
1094
1104
|
})
|
|
1095
1105
|
|
|
1096
1106
|
vget[1] = await wo.insert({ id: 'e1', name: 'a' })
|
|
1097
|
-
vget[2] = await wo.
|
|
1107
|
+
vget[2] = await wo.selectByPk('e1')
|
|
1098
1108
|
vget[3] = await wo.save({ id: 'e1', name: 'b' })
|
|
1099
1109
|
vget[4] = await wo.del({ id: 'e1' })
|
|
1100
1110
|
vget[5] = await wo.delAll()
|
|
@@ -1129,6 +1139,224 @@ describe('change event', function() {
|
|
|
1129
1139
|
})
|
|
1130
1140
|
|
|
1131
1141
|
|
|
1142
|
+
describe('autoGenPk', function() {
|
|
1143
|
+
let rt = null
|
|
1144
|
+
let vans = {}
|
|
1145
|
+
let vget = {}
|
|
1146
|
+
|
|
1147
|
+
before(async function() {
|
|
1148
|
+
this.timeout(120000)
|
|
1149
|
+
|
|
1150
|
+
//woDef, 未給autoGenPk以驗證其預設值為true
|
|
1151
|
+
let woDef = WOrm(genOpt('pkdefault'))
|
|
1152
|
+
await woDef.delAll()
|
|
1153
|
+
|
|
1154
|
+
//預設未帶id者須自動產生, 且產生之id須為有效字串
|
|
1155
|
+
vget[1] = await woDef.insert({ name: 'no-id' })
|
|
1156
|
+
let ssDef = await woDef.select()
|
|
1157
|
+
vget[2] = ssDef.length
|
|
1158
|
+
vget[3] = typeof ssDef[0].id === 'string' && ssDef[0].id.length > 0
|
|
1159
|
+
|
|
1160
|
+
//預設之save未帶id者亦須自動產生
|
|
1161
|
+
vget[4] = await woDef.save({ name: 'no-id-save' })
|
|
1162
|
+
vget[5] = (await woDef.select()).length
|
|
1163
|
+
|
|
1164
|
+
//woOn, 明確開啟
|
|
1165
|
+
let woOn = WOrm(genOptPk('pkon', true))
|
|
1166
|
+
await woOn.delAll()
|
|
1167
|
+
vget[6] = await woOn.insert({ name: 'no-id' })
|
|
1168
|
+
vget[7] = (await woOn.select()).length
|
|
1169
|
+
|
|
1170
|
+
//woOff, 關閉後主鍵須由呼叫端自備
|
|
1171
|
+
let woOff = WOrm(genOptPk('pkoff', false))
|
|
1172
|
+
await woOff.delAll()
|
|
1173
|
+
|
|
1174
|
+
//帶id者正常寫入
|
|
1175
|
+
vget[8] = await woOff.insert({ id: 'p1', name: 'given' })
|
|
1176
|
+
vget[9] = await woOff.selectByPk('p1')
|
|
1177
|
+
|
|
1178
|
+
//未帶id者須reject, 屬整批性錯誤而不進入逐筆結果
|
|
1179
|
+
rt = null
|
|
1180
|
+
// vans[10] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1181
|
+
await woOff.insert({ name: 'no-id' })
|
|
1182
|
+
.then(function(msg) {
|
|
1183
|
+
rt = `不應resolve: ${JSON.stringify(msg)}`
|
|
1184
|
+
})
|
|
1185
|
+
.catch(function(msg) {
|
|
1186
|
+
rt = msg.toString()
|
|
1187
|
+
})
|
|
1188
|
+
vget[10] = rt
|
|
1189
|
+
|
|
1190
|
+
//save未帶id者亦須reject, autoInsert兩種取值皆同
|
|
1191
|
+
rt = null
|
|
1192
|
+
// vans[11] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1193
|
+
await woOff.save({ name: 'no-id' })
|
|
1194
|
+
.then(function(msg) {
|
|
1195
|
+
rt = `不應resolve: ${JSON.stringify(msg)}`
|
|
1196
|
+
})
|
|
1197
|
+
.catch(function(msg) {
|
|
1198
|
+
rt = msg.toString()
|
|
1199
|
+
})
|
|
1200
|
+
vget[11] = rt
|
|
1201
|
+
|
|
1202
|
+
rt = null
|
|
1203
|
+
// vans[12] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1204
|
+
await woOff.save({ name: 'no-id' }, { autoInsert: false })
|
|
1205
|
+
.then(function(msg) {
|
|
1206
|
+
rt = `不應resolve: ${JSON.stringify(msg)}`
|
|
1207
|
+
})
|
|
1208
|
+
.catch(function(msg) {
|
|
1209
|
+
rt = msg.toString()
|
|
1210
|
+
})
|
|
1211
|
+
vget[12] = rt
|
|
1212
|
+
|
|
1213
|
+
//整批reject時, 同批之有效筆數亦不得被寫入
|
|
1214
|
+
rt = null
|
|
1215
|
+
// vans[13] = 'Error: invalid data[1].id, autoGenPk is false'
|
|
1216
|
+
await woOff.insert([
|
|
1217
|
+
{ id: 'p-ok1', name: 'ok1' },
|
|
1218
|
+
{ name: 'no-id' },
|
|
1219
|
+
{ id: 'p-ok2', name: 'ok2' },
|
|
1220
|
+
])
|
|
1221
|
+
.then(function(msg) {
|
|
1222
|
+
rt = `不應resolve: ${JSON.stringify(msg)}`
|
|
1223
|
+
})
|
|
1224
|
+
.catch(function(msg) {
|
|
1225
|
+
rt = msg.toString()
|
|
1226
|
+
})
|
|
1227
|
+
vget[13] = rt
|
|
1228
|
+
vget[14] = [
|
|
1229
|
+
await woOff.selectByPk('p-ok1'),
|
|
1230
|
+
await woOff.selectByPk('p-ok2'),
|
|
1231
|
+
]
|
|
1232
|
+
|
|
1233
|
+
//save之整批reject亦同
|
|
1234
|
+
await woOff.insert({ id: 'p-base', name: 'base' })
|
|
1235
|
+
await woOff.save([
|
|
1236
|
+
{ id: 'p-base', name: 'should-not-write' },
|
|
1237
|
+
{ name: 'no-id' },
|
|
1238
|
+
]).catch(() => {})
|
|
1239
|
+
vget[15] = (await woOff.selectByPk('p-base')).name
|
|
1240
|
+
|
|
1241
|
+
//del不受autoGenPk影響, 未帶有效id仍為該筆ok為0而非reject
|
|
1242
|
+
vget[16] = await woOff.del({ name: 'no-id' })
|
|
1243
|
+
|
|
1244
|
+
//autoGenPk為建構層設定, 不得於option逐次覆寫
|
|
1245
|
+
rt = null
|
|
1246
|
+
// vans[17] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1247
|
+
await woOff.save({ name: 'no-id' }, { autoGenPk: true })
|
|
1248
|
+
.then(function(msg) {
|
|
1249
|
+
rt = `不應resolve: ${JSON.stringify(msg)}`
|
|
1250
|
+
})
|
|
1251
|
+
.catch(function(msg) {
|
|
1252
|
+
rt = msg.toString()
|
|
1253
|
+
})
|
|
1254
|
+
vget[17] = rt
|
|
1255
|
+
|
|
1256
|
+
//輸入無效仍依T5回空結果, 不因autoGenPk為false而reject
|
|
1257
|
+
vget[18] = await woOff.insert(null)
|
|
1258
|
+
vget[19] = await woOff.save(null)
|
|
1259
|
+
|
|
1260
|
+
})
|
|
1261
|
+
|
|
1262
|
+
vans[1] = { n: 1, nInserted: 1, ok: 1 }
|
|
1263
|
+
it(`should get ${JSON.stringify(vans[1])} for insert without id by default autoGenPk`, async function() {
|
|
1264
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
1265
|
+
})
|
|
1266
|
+
|
|
1267
|
+
vans[2] = 1
|
|
1268
|
+
it(`should get ${JSON.stringify(vans[2])} for records after insert without id by default autoGenPk`, async function() {
|
|
1269
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
1270
|
+
})
|
|
1271
|
+
|
|
1272
|
+
vans[3] = true
|
|
1273
|
+
it(`should get ${JSON.stringify(vans[3])} for generated id by default autoGenPk`, async function() {
|
|
1274
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
1275
|
+
})
|
|
1276
|
+
|
|
1277
|
+
vans[4] = [{ n: 1, nInserted: 1, nModified: 0, ok: 1 }]
|
|
1278
|
+
it(`should get ${JSON.stringify(vans[4])} for save without id by default autoGenPk`, async function() {
|
|
1279
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
1280
|
+
})
|
|
1281
|
+
|
|
1282
|
+
vans[5] = 2
|
|
1283
|
+
it(`should get ${JSON.stringify(vans[5])} for records after save without id by default autoGenPk`, async function() {
|
|
1284
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
1285
|
+
})
|
|
1286
|
+
|
|
1287
|
+
vans[6] = { n: 1, nInserted: 1, ok: 1 }
|
|
1288
|
+
it(`should get ${JSON.stringify(vans[6])} for insert without id by autoGenPk=true`, async function() {
|
|
1289
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
1290
|
+
})
|
|
1291
|
+
|
|
1292
|
+
vans[7] = 1
|
|
1293
|
+
it(`should get ${JSON.stringify(vans[7])} for records after insert without id by autoGenPk=true`, async function() {
|
|
1294
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
1295
|
+
})
|
|
1296
|
+
|
|
1297
|
+
vans[8] = { n: 1, nInserted: 1, ok: 1 }
|
|
1298
|
+
it(`should get ${JSON.stringify(vans[8])} for insert with id by autoGenPk=false`, async function() {
|
|
1299
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
1300
|
+
})
|
|
1301
|
+
|
|
1302
|
+
vans[9] = { id: 'p1', name: 'given' }
|
|
1303
|
+
it(`should get ${JSON.stringify(vans[9])} for record after insert with id by autoGenPk=false`, async function() {
|
|
1304
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
1305
|
+
})
|
|
1306
|
+
|
|
1307
|
+
vans[10] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1308
|
+
it(`should get ${JSON.stringify(vans[10])} for insert without id by autoGenPk=false`, async function() {
|
|
1309
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
1310
|
+
})
|
|
1311
|
+
|
|
1312
|
+
vans[11] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1313
|
+
it(`should get ${JSON.stringify(vans[11])} for save without id by autoGenPk=false`, async function() {
|
|
1314
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
1315
|
+
})
|
|
1316
|
+
|
|
1317
|
+
vans[12] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1318
|
+
it(`should get ${JSON.stringify(vans[12])} for save(autoInsert=false) without id by autoGenPk=false`, async function() {
|
|
1319
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
1320
|
+
})
|
|
1321
|
+
|
|
1322
|
+
vans[13] = 'Error: invalid data[1].id, autoGenPk is false'
|
|
1323
|
+
it(`should get ${JSON.stringify(vans[13])} for insert with 1 record without id by autoGenPk=false`, async function() {
|
|
1324
|
+
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
1325
|
+
})
|
|
1326
|
+
|
|
1327
|
+
vans[14] = [null, null]
|
|
1328
|
+
it(`should get ${JSON.stringify(vans[14])} for not writing valid records in rejected batch`, async function() {
|
|
1329
|
+
assert.strict.deepStrictEqual(vget[14], vans[14])
|
|
1330
|
+
})
|
|
1331
|
+
|
|
1332
|
+
vans[15] = 'base'
|
|
1333
|
+
it(`should get ${JSON.stringify(vans[15])} for not writing valid records in rejected save batch`, async function() {
|
|
1334
|
+
assert.strict.deepStrictEqual(vget[15], vans[15])
|
|
1335
|
+
})
|
|
1336
|
+
|
|
1337
|
+
vans[16] = [{ n: 0, nDeleted: 0, ok: 0, err: 'invalid id[undefined]' }]
|
|
1338
|
+
it(`should get ${JSON.stringify(vans[16])} for del without id by autoGenPk=false`, async function() {
|
|
1339
|
+
assert.strict.deepStrictEqual(vget[16], vans[16])
|
|
1340
|
+
})
|
|
1341
|
+
|
|
1342
|
+
vans[17] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
1343
|
+
it(`should get ${JSON.stringify(vans[17])} for not overriding autoGenPk by option`, async function() {
|
|
1344
|
+
assert.strict.deepStrictEqual(vget[17], vans[17])
|
|
1345
|
+
})
|
|
1346
|
+
|
|
1347
|
+
vans[18] = { n: 0, nInserted: 0, ok: 1 }
|
|
1348
|
+
it(`should get ${JSON.stringify(vans[18])} for insert with invalid data by autoGenPk=false`, async function() {
|
|
1349
|
+
assert.strict.deepStrictEqual(vget[18], vans[18])
|
|
1350
|
+
})
|
|
1351
|
+
|
|
1352
|
+
vans[19] = []
|
|
1353
|
+
it(`should get ${JSON.stringify(vans[19])} for save with invalid data by autoGenPk=false`, async function() {
|
|
1354
|
+
assert.strict.deepStrictEqual(vget[19], vans[19])
|
|
1355
|
+
})
|
|
1356
|
+
|
|
1357
|
+
})
|
|
1358
|
+
|
|
1359
|
+
|
|
1132
1360
|
describe('cross process concurrency', function() {
|
|
1133
1361
|
let vans = {}
|
|
1134
1362
|
let vget = {}
|
|
@@ -1160,7 +1388,7 @@ describe('cross process concurrency', function() {
|
|
|
1160
1388
|
runProc('P1', clSav, 'save', keys),
|
|
1161
1389
|
runProc('P2', clSav, 'save', keys),
|
|
1162
1390
|
])
|
|
1163
|
-
let vx1 = await woSav.
|
|
1391
|
+
let vx1 = await woSav.selectByPk('x1')
|
|
1164
1392
|
vget[4] = Object.keys(vx1).filter((k) => k.indexOf('P1k') === 0 || k.indexOf('P2k') === 0).length
|
|
1165
1393
|
vget[5] = vx1.base
|
|
1166
1394
|
vget[6] = (await woSav.select()).length
|
package/test/api-gfs.test.mjs
CHANGED
|
@@ -20,6 +20,16 @@ let genOpt = (cl) => {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
//genOptPk, 明確指定autoGenPk
|
|
24
|
+
let genOptPk = (cl, autoGenPk) => {
|
|
25
|
+
return {
|
|
26
|
+
url: genUrl(ctPort),
|
|
27
|
+
db: ctDb,
|
|
28
|
+
cl,
|
|
29
|
+
autoGenPk,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
23
33
|
//genKeys, 取回傳物件之鍵集合, 用於驗證鍵集合固定
|
|
24
34
|
let genKeys = (v) => {
|
|
25
35
|
return Object.keys(v).sort().join(',')
|
|
@@ -139,10 +149,10 @@ describe('gfs basic', function() {
|
|
|
139
149
|
// vans[3] = { files: 1, chunks: 2 }
|
|
140
150
|
vget[3] = await countDocs(cl)
|
|
141
151
|
|
|
142
|
-
//
|
|
152
|
+
//selectByPkGfs, 取回內容須與來源逐位元組相同, 且形狀與insertGfs所收之數據物件一致
|
|
143
153
|
rt = null
|
|
144
154
|
// vans[4] = { keys: 'id,u8a', id: 'g-big', length: nSize, hash, b0: 0, b1: 1, b255: 255, b256: 0 }
|
|
145
|
-
await wo.
|
|
155
|
+
await wo.selectByPkGfs('g-big')
|
|
146
156
|
.then(function(msg) {
|
|
147
157
|
rt = {
|
|
148
158
|
keys: genKeys(msg),
|
|
@@ -160,10 +170,10 @@ describe('gfs basic', function() {
|
|
|
160
170
|
})
|
|
161
171
|
vget[4] = rt
|
|
162
172
|
|
|
163
|
-
//
|
|
173
|
+
//selectByPkGfs by id not existed
|
|
164
174
|
rt = null
|
|
165
175
|
// vans[5] = null
|
|
166
|
-
await wo.
|
|
176
|
+
await wo.selectByPkGfs('id-not-existed')
|
|
167
177
|
.then(function(msg) {
|
|
168
178
|
rt = msg
|
|
169
179
|
})
|
|
@@ -172,12 +182,12 @@ describe('gfs basic', function() {
|
|
|
172
182
|
})
|
|
173
183
|
vget[5] = rt
|
|
174
184
|
|
|
175
|
-
//
|
|
185
|
+
//selectByPkGfs by id invalid, 未給有效id視為查無數據
|
|
176
186
|
// vans[6] = [null, null, null]
|
|
177
187
|
vget[6] = [
|
|
178
|
-
await wo.
|
|
179
|
-
await wo.
|
|
180
|
-
await wo.
|
|
188
|
+
await wo.selectByPkGfs(''),
|
|
189
|
+
await wo.selectByPkGfs(123),
|
|
190
|
+
await wo.selectByPkGfs(null),
|
|
181
191
|
]
|
|
182
192
|
|
|
183
193
|
//insertGfs未給id時自動產生
|
|
@@ -284,17 +294,17 @@ describe('gfs basic', function() {
|
|
|
284
294
|
b255: 255,
|
|
285
295
|
b256: 0,
|
|
286
296
|
}
|
|
287
|
-
it(`should get same content for
|
|
297
|
+
it(`should get same content for selectByPkGfs`, async function() {
|
|
288
298
|
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
289
299
|
})
|
|
290
300
|
|
|
291
301
|
vans[5] = null
|
|
292
|
-
it(`should get ${JSON.stringify(vans[5])} for
|
|
302
|
+
it(`should get ${JSON.stringify(vans[5])} for selectByPkGfs by id not existed`, async function() {
|
|
293
303
|
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
294
304
|
})
|
|
295
305
|
|
|
296
306
|
vans[6] = [null, null, null]
|
|
297
|
-
it(`should get ${JSON.stringify(vans[6])} for
|
|
307
|
+
it(`should get ${JSON.stringify(vans[6])} for selectByPkGfs by id invalid`, async function() {
|
|
298
308
|
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
299
309
|
})
|
|
300
310
|
|
|
@@ -395,7 +405,7 @@ describe('gfs insert', function() {
|
|
|
395
405
|
vget[3] = { files: c2.files - c1.files, chunks: c2.chunks - c1.chunks }
|
|
396
406
|
|
|
397
407
|
//已存在id不得被覆寫, 內容須為首次所給
|
|
398
|
-
let vi1 = await wo.
|
|
408
|
+
let vi1 = await wo.selectByPkGfs('i1')
|
|
399
409
|
vget[4] = genHash(vi1.u8a) === genHash(genU8a(100, 1))
|
|
400
410
|
|
|
401
411
|
//部份重複, 1筆已存在2筆為新
|
|
@@ -411,7 +421,7 @@ describe('gfs insert', function() {
|
|
|
411
421
|
{ id: 'i-dup', u8a: genU8a(100, 7) },
|
|
412
422
|
{ id: 'i-uniq', u8a: genU8a(100, 8) },
|
|
413
423
|
])
|
|
414
|
-
let vdup = await wo.
|
|
424
|
+
let vdup = await wo.selectByPkGfs('i-dup')
|
|
415
425
|
vget[7] = genHash(vdup.u8a) === genHash(genU8a(100, 6))
|
|
416
426
|
|
|
417
427
|
//併發對同一id插入10次, nInserted總和須為1
|
|
@@ -528,6 +538,128 @@ describe('gfs legacy duplicated id', function() {
|
|
|
528
538
|
})
|
|
529
539
|
|
|
530
540
|
|
|
541
|
+
describe('gfs autoGenPk', function() {
|
|
542
|
+
let rt = null
|
|
543
|
+
let vans = {}
|
|
544
|
+
let vget = {}
|
|
545
|
+
|
|
546
|
+
before(async function() {
|
|
547
|
+
this.timeout(300000)
|
|
548
|
+
|
|
549
|
+
//woDef, 未給autoGenPk以驗證其預設值為true
|
|
550
|
+
let clDef = 'pkdefaultGfs'
|
|
551
|
+
let woDef = WOrm(genOpt(clDef))
|
|
552
|
+
await woDef.delAllGfs()
|
|
553
|
+
|
|
554
|
+
//預設未帶id者須自動產生
|
|
555
|
+
vget[1] = await woDef.insertGfs({ u8a: genU8a(100, 1) })
|
|
556
|
+
vget[2] = (await countDocs(clDef)).files
|
|
557
|
+
|
|
558
|
+
//woOff, 關閉後主鍵須由呼叫端自備
|
|
559
|
+
let clOff = 'pkoffGfs'
|
|
560
|
+
let woOff = WOrm(genOptPk(clOff, false))
|
|
561
|
+
await woOff.delAllGfs()
|
|
562
|
+
|
|
563
|
+
//帶id者正常寫入
|
|
564
|
+
vget[3] = await woOff.insertGfs({ id: 'g1', u8a: genU8a(100, 2) })
|
|
565
|
+
vget[4] = genHash((await woOff.selectByPkGfs('g1')).u8a) === genHash(genU8a(100, 2))
|
|
566
|
+
|
|
567
|
+
//未帶id者須reject
|
|
568
|
+
rt = null
|
|
569
|
+
// vans[5] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
570
|
+
await woOff.insertGfs({ u8a: genU8a(100, 3) })
|
|
571
|
+
.then(function(msg) {
|
|
572
|
+
rt = `不應resolve: ${JSON.stringify(msg)}`
|
|
573
|
+
})
|
|
574
|
+
.catch(function(msg) {
|
|
575
|
+
rt = msg.toString()
|
|
576
|
+
})
|
|
577
|
+
vget[5] = rt
|
|
578
|
+
|
|
579
|
+
//整批reject時, 同批之有效筆數亦不得被寫入
|
|
580
|
+
let cBefore = await countDocs(clOff)
|
|
581
|
+
rt = null
|
|
582
|
+
// vans[6] = 'Error: invalid data[1].id, autoGenPk is false'
|
|
583
|
+
await woOff.insertGfs([
|
|
584
|
+
{ id: 'g-ok1', u8a: genU8a(100, 4) },
|
|
585
|
+
{ u8a: genU8a(100, 5) },
|
|
586
|
+
{ id: 'g-ok2', u8a: genU8a(100, 6) },
|
|
587
|
+
])
|
|
588
|
+
.then(function(msg) {
|
|
589
|
+
rt = `不應resolve: ${JSON.stringify(msg)}`
|
|
590
|
+
})
|
|
591
|
+
.catch(function(msg) {
|
|
592
|
+
rt = msg.toString()
|
|
593
|
+
})
|
|
594
|
+
vget[6] = rt
|
|
595
|
+
let cAfter = await countDocs(clOff)
|
|
596
|
+
vget[7] = { files: cAfter.files - cBefore.files, chunks: cAfter.chunks - cBefore.chunks }
|
|
597
|
+
vget[8] = [
|
|
598
|
+
await woOff.selectByPkGfs('g-ok1'),
|
|
599
|
+
await woOff.selectByPkGfs('g-ok2'),
|
|
600
|
+
]
|
|
601
|
+
|
|
602
|
+
//delGfs不受autoGenPk影響, 未帶有效id仍為該筆ok為0而非reject
|
|
603
|
+
vget[9] = await woOff.delGfs({ u8a: genU8a(10) })
|
|
604
|
+
|
|
605
|
+
//輸入無效仍依T5回空結果
|
|
606
|
+
vget[10] = await woOff.insertGfs(null)
|
|
607
|
+
|
|
608
|
+
})
|
|
609
|
+
|
|
610
|
+
vans[1] = { n: 1, nInserted: 1, ok: 1 }
|
|
611
|
+
it(`should get ${JSON.stringify(vans[1])} for insertGfs without id by default autoGenPk`, async function() {
|
|
612
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
613
|
+
})
|
|
614
|
+
|
|
615
|
+
vans[2] = 1
|
|
616
|
+
it(`should get ${JSON.stringify(vans[2])} for files after insertGfs without id by default autoGenPk`, async function() {
|
|
617
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
618
|
+
})
|
|
619
|
+
|
|
620
|
+
vans[3] = { n: 1, nInserted: 1, ok: 1 }
|
|
621
|
+
it(`should get ${JSON.stringify(vans[3])} for insertGfs with id by autoGenPk=false`, async function() {
|
|
622
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
623
|
+
})
|
|
624
|
+
|
|
625
|
+
vans[4] = true
|
|
626
|
+
it(`should get ${JSON.stringify(vans[4])} for content after insertGfs with id by autoGenPk=false`, async function() {
|
|
627
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
628
|
+
})
|
|
629
|
+
|
|
630
|
+
vans[5] = 'Error: invalid data[0].id, autoGenPk is false'
|
|
631
|
+
it(`should get ${JSON.stringify(vans[5])} for insertGfs without id by autoGenPk=false`, async function() {
|
|
632
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
633
|
+
})
|
|
634
|
+
|
|
635
|
+
vans[6] = 'Error: invalid data[1].id, autoGenPk is false'
|
|
636
|
+
it(`should get ${JSON.stringify(vans[6])} for insertGfs with 1 record without id by autoGenPk=false`, async function() {
|
|
637
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
638
|
+
})
|
|
639
|
+
|
|
640
|
+
vans[7] = { files: 0, chunks: 0 }
|
|
641
|
+
it(`should get ${JSON.stringify(vans[7])} for not writing valid records in rejected insertGfs batch`, async function() {
|
|
642
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
vans[8] = [null, null]
|
|
646
|
+
it(`should get ${JSON.stringify(vans[8])} for records after rejected insertGfs batch`, async function() {
|
|
647
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
648
|
+
})
|
|
649
|
+
|
|
650
|
+
vans[9] = [{ n: 0, nDeleted: 0, ok: 0, err: 'invalid id[undefined]' }]
|
|
651
|
+
it(`should get ${JSON.stringify(vans[9])} for delGfs without id by autoGenPk=false`, async function() {
|
|
652
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
653
|
+
})
|
|
654
|
+
|
|
655
|
+
vans[10] = { n: 0, nInserted: 0, ok: 1 }
|
|
656
|
+
it(`should get ${JSON.stringify(vans[10])} for insertGfs with invalid data by autoGenPk=false`, async function() {
|
|
657
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
658
|
+
})
|
|
659
|
+
|
|
660
|
+
})
|
|
661
|
+
|
|
662
|
+
|
|
531
663
|
describe('gfs change event', function() {
|
|
532
664
|
let vans = {}
|
|
533
665
|
let vget = {}
|
|
@@ -545,7 +677,7 @@ describe('gfs change event', function() {
|
|
|
545
677
|
})
|
|
546
678
|
|
|
547
679
|
vget[1] = await wo.insertGfs({ id: 'e1', u8a: genU8a(100, 1) })
|
|
548
|
-
vget[2] = genHash((await wo.
|
|
680
|
+
vget[2] = genHash((await wo.selectByPkGfs('e1')).u8a) === genHash(genU8a(100, 1))
|
|
549
681
|
vget[3] = await wo.delGfs({ id: 'e1' })
|
|
550
682
|
vget[4] = await wo.delAllGfs()
|
|
551
683
|
|