w-orm-lowdb 1.0.13 → 1.0.14
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 +121 -15
- package/dist/w-orm-lowdb.umd.js +2 -2
- package/dist/w-orm-lowdb.umd.js.map +1 -1
- package/docs/WOrmLowdb.html +628 -27
- package/docs/WOrmLowdb.mjs.html +1068 -779
- package/docs/index.html +2 -2
- package/g-basic.mjs +203 -185
- package/package.json +2 -2
- package/src/WOrmLowdb.mjs +1066 -777
- package/test/lib/procConcurrency.mjs +53 -0
- package/test/unit-autogenpk.test.mjs +205 -0
- package/test/{basic.test.mjs → unit-basic.test.mjs} +51 -54
- package/test/{cache.test.mjs → unit-cache.test.mjs} +2 -2
- package/test/unit-concurrency.test.mjs +140 -0
- package/test/unit-del.test.mjs +140 -0
- package/test/unit-delall.test.mjs +153 -0
- package/test/unit-event.test.mjs +252 -0
- package/test/unit-insert.test.mjs +120 -0
- package/test/unit-insertbulk.test.mjs +188 -0
- package/test/unit-returnlist.test.mjs +159 -0
- package/test/unit-save.test.mjs +199 -0
- package/test/unit-selectbypk.test.mjs +121 -0
- package/toolg/gDistRollup.mjs +3 -3
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
import _ from 'lodash-es'
|
|
3
|
+
import w from 'wsemi'
|
|
4
|
+
import WOrm from '../src/WOrmLowdb.mjs'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe('del', function() {
|
|
8
|
+
let vans = {}
|
|
9
|
+
let vget = {}
|
|
10
|
+
|
|
11
|
+
before(async function() {
|
|
12
|
+
|
|
13
|
+
w.fsDeleteFile('./db_del.json')
|
|
14
|
+
|
|
15
|
+
let wo = WOrm({ url: './db_del.json', db: 'worm', cl: 'users' })
|
|
16
|
+
|
|
17
|
+
//輸入無效, 回傳空陣列
|
|
18
|
+
vget[1] = await wo.del(null)
|
|
19
|
+
vget[2] = await wo.del([])
|
|
20
|
+
|
|
21
|
+
//既有數據
|
|
22
|
+
await wo.insert([{ id: 'a' }, { id: 'b' }, { id: 'c' }, { id: 'd' }])
|
|
23
|
+
|
|
24
|
+
//主鍵命中並刪除
|
|
25
|
+
vget[3] = await wo.del({ id: 'a' })
|
|
26
|
+
vget[4] = await wo.selectByPk('a')
|
|
27
|
+
|
|
28
|
+
//主鍵未命中, 屬正常結果故ok為1而n與nDeleted皆為0
|
|
29
|
+
vget[5] = await wo.del({ id: 'not-existed' })
|
|
30
|
+
|
|
31
|
+
//該筆未帶有效主鍵, 屬輸入問題故ok為0且必附err
|
|
32
|
+
let r = await wo.del({ name: 'no-id' })
|
|
33
|
+
vget[6] = _.map(r, function(v) {
|
|
34
|
+
return _.omit(v, ['err'])
|
|
35
|
+
})
|
|
36
|
+
vget[7] = w.isestr(_.get(r, '0.err'))
|
|
37
|
+
vget[8] = _.keys(_.get(r, '0')).sort().join(',')
|
|
38
|
+
|
|
39
|
+
//單筆失敗不中斷整批: 其餘筆數照常處理, 整批仍resolve
|
|
40
|
+
let rt = null
|
|
41
|
+
await wo.del([{ id: 'b' }, { name: 'no-id' }, { id: 'c' }])
|
|
42
|
+
.then(function(msg) {
|
|
43
|
+
rt = msg
|
|
44
|
+
})
|
|
45
|
+
.catch(function(msg) {
|
|
46
|
+
rt = 'reject: ' + msg.toString()
|
|
47
|
+
})
|
|
48
|
+
vget[9] = _.map(rt, function(v) {
|
|
49
|
+
return _.omit(v, ['err'])
|
|
50
|
+
})
|
|
51
|
+
vget[10] = [await wo.selectByPk('b'), await wo.selectByPk('c')]
|
|
52
|
+
|
|
53
|
+
//同批含重複主鍵者, 僅首筆為命中並刪除, 其餘為未命中
|
|
54
|
+
await wo.insert([{ id: 'e' }])
|
|
55
|
+
vget[11] = await wo.del([{ id: 'e' }, { id: 'e' }])
|
|
56
|
+
vget[12] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
|
|
57
|
+
|
|
58
|
+
//主鍵未命中者不得以ok分辨不出來: 未命中為ok=1, 未帶有效主鍵為ok=0
|
|
59
|
+
let rm = await wo.del([{ id: 'not-existed' }, { id: '' }])
|
|
60
|
+
vget[13] = _.map(rm, 'ok')
|
|
61
|
+
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
after(async function() {
|
|
65
|
+
w.fsDeleteFile('./db_del.json')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
vans[1] = []
|
|
69
|
+
it(`should get ${JSON.stringify(vans[1])} for del(null)`, async function() {
|
|
70
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
vans[2] = []
|
|
74
|
+
it(`should get ${JSON.stringify(vans[2])} for del([])`, async function() {
|
|
75
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
vans[3] = [{ n: 1, nDeleted: 1, ok: 1 }]
|
|
79
|
+
it(`should get ${JSON.stringify(vans[3])} for del with matched pk`, async function() {
|
|
80
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
vans[4] = null
|
|
84
|
+
it(`should get ${JSON.stringify(vans[4])} for row after del`, async function() {
|
|
85
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
vans[5] = [{ n: 0, nDeleted: 0, ok: 1 }]
|
|
89
|
+
it(`should get ${JSON.stringify(vans[5])} for del with unmatched pk`, async function() {
|
|
90
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
vans[6] = [{ n: 0, nDeleted: 0, ok: 0 }]
|
|
94
|
+
it(`should get ${JSON.stringify(vans[6])} for del without valid pk`, async function() {
|
|
95
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
vans[7] = true
|
|
99
|
+
it(`should get ${JSON.stringify(vans[7])} for err of del without valid pk`, async function() {
|
|
100
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
vans[8] = 'err,n,nDeleted,ok'
|
|
104
|
+
it(`should get ${JSON.stringify(vans[8])} for keys of failed item`, async function() {
|
|
105
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
vans[9] = [
|
|
109
|
+
{ n: 1, nDeleted: 1, ok: 1 },
|
|
110
|
+
{ n: 0, nDeleted: 0, ok: 0 },
|
|
111
|
+
{ n: 1, nDeleted: 1, ok: 1 },
|
|
112
|
+
]
|
|
113
|
+
it(`should get ${JSON.stringify(vans[9])} for del with one failed item not breaking others`, async function() {
|
|
114
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
vans[10] = [null, null]
|
|
118
|
+
it(`should get ${JSON.stringify(vans[10])} for rows after del with one failed item`, async function() {
|
|
119
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
vans[11] = [
|
|
123
|
+
{ n: 1, nDeleted: 1, ok: 1 },
|
|
124
|
+
{ n: 0, nDeleted: 0, ok: 1 },
|
|
125
|
+
]
|
|
126
|
+
it(`should get ${JSON.stringify(vans[11])} for del with duplicated pk in same batch`, async function() {
|
|
127
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
vans[12] = ['d']
|
|
131
|
+
it(`should get ${JSON.stringify(vans[12])} for all ids after del`, async function() {
|
|
132
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
vans[13] = [1, 0]
|
|
136
|
+
it(`should get ${JSON.stringify(vans[13])} for ok of unmatched pk and invalid pk`, async function() {
|
|
137
|
+
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
})
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
import _ from 'lodash-es'
|
|
3
|
+
import w from 'wsemi'
|
|
4
|
+
import WOrm from '../src/WOrmLowdb.mjs'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe('delAll', function() {
|
|
8
|
+
let vans = {}
|
|
9
|
+
let vget = {}
|
|
10
|
+
|
|
11
|
+
before(async function() {
|
|
12
|
+
|
|
13
|
+
w.fsDeleteFile('./db_delall.json')
|
|
14
|
+
|
|
15
|
+
let wo = WOrm({ url: './db_delall.json', db: 'worm', cl: 'users' })
|
|
16
|
+
|
|
17
|
+
//空表時條件無命中, 回傳{n:0, nDeleted:0, ok:1}而非錯誤
|
|
18
|
+
vget[1] = await wo.delAll()
|
|
19
|
+
|
|
20
|
+
//既有數據
|
|
21
|
+
let mkData = async function() {
|
|
22
|
+
await wo.delAll()
|
|
23
|
+
await wo.insert([
|
|
24
|
+
{ id: 'a', value: 10 },
|
|
25
|
+
{ id: 'b', value: 20 },
|
|
26
|
+
{ id: 'c', value: 30 },
|
|
27
|
+
{ id: 'd', value: 40 },
|
|
28
|
+
{ id: 'e', value: 50 },
|
|
29
|
+
])
|
|
30
|
+
}
|
|
31
|
+
await mkData()
|
|
32
|
+
|
|
33
|
+
//帶條件且僅部份命中, n須為實際刪除筆數而非全表筆數
|
|
34
|
+
vget[2] = await wo.delAll({ value: { '$gte': 40 } })
|
|
35
|
+
vget[3] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
|
|
36
|
+
|
|
37
|
+
//條件無命中, 回傳{n:0, nDeleted:0, ok:1}且不得改動數據
|
|
38
|
+
vget[4] = await wo.delAll({ value: { '$gt': 9999 } })
|
|
39
|
+
vget[5] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
|
|
40
|
+
|
|
41
|
+
//帶條件且僅命中一筆
|
|
42
|
+
vget[6] = await wo.delAll({ id: 'a' })
|
|
43
|
+
vget[7] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
|
|
44
|
+
|
|
45
|
+
//帶條件且全數命中
|
|
46
|
+
await mkData()
|
|
47
|
+
vget[8] = await wo.delAll({ value: { '$gte': 0 } })
|
|
48
|
+
vget[9] = await wo.select()
|
|
49
|
+
|
|
50
|
+
//find未給時刪除全部數據
|
|
51
|
+
await mkData()
|
|
52
|
+
vget[10] = await wo.delAll()
|
|
53
|
+
vget[11] = await wo.select()
|
|
54
|
+
|
|
55
|
+
//find為空物件時刪除全部數據
|
|
56
|
+
await mkData()
|
|
57
|
+
vget[12] = await wo.delAll({})
|
|
58
|
+
vget[13] = await wo.select()
|
|
59
|
+
|
|
60
|
+
//n恆等於nDeleted
|
|
61
|
+
await mkData()
|
|
62
|
+
let r = await wo.delAll({ value: { '$lte': 20 } })
|
|
63
|
+
vget[14] = r.n === r.nDeleted
|
|
64
|
+
|
|
65
|
+
//複合條件之命中須與select一致
|
|
66
|
+
await mkData()
|
|
67
|
+
let find = { '$or': [{ value: { '$lte': 10 } }, { value: { '$gte': 50 } }] }
|
|
68
|
+
let ns = _.size(await wo.select(find))
|
|
69
|
+
let rd = await wo.delAll(find)
|
|
70
|
+
vget[15] = [ns, rd.nDeleted]
|
|
71
|
+
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
after(async function() {
|
|
75
|
+
w.fsDeleteFile('./db_delall.json')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
vans[1] = { n: 0, nDeleted: 0, ok: 1 }
|
|
79
|
+
it(`should get ${JSON.stringify(vans[1])} for delAll with empty table`, async function() {
|
|
80
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
vans[2] = { n: 2, nDeleted: 2, ok: 1 }
|
|
84
|
+
it(`should get ${JSON.stringify(vans[2])} for delAll with partial matched find`, async function() {
|
|
85
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
vans[3] = ['a', 'b', 'c']
|
|
89
|
+
it(`should get ${JSON.stringify(vans[3])} for remaining ids`, async function() {
|
|
90
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
vans[4] = { n: 0, nDeleted: 0, ok: 1 }
|
|
94
|
+
it(`should get ${JSON.stringify(vans[4])} for delAll with unmatched find`, async function() {
|
|
95
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
vans[5] = ['a', 'b', 'c']
|
|
99
|
+
it(`should get ${JSON.stringify(vans[5])} for remaining ids after unmatched find`, async function() {
|
|
100
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
vans[6] = { n: 1, nDeleted: 1, ok: 1 }
|
|
104
|
+
it(`should get ${JSON.stringify(vans[6])} for delAll with find matching one row`, async function() {
|
|
105
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
vans[7] = ['b', 'c']
|
|
109
|
+
it(`should get ${JSON.stringify(vans[7])} for remaining ids after deleting one row`, async function() {
|
|
110
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
vans[8] = { n: 5, nDeleted: 5, ok: 1 }
|
|
114
|
+
it(`should get ${JSON.stringify(vans[8])} for delAll with find matching all rows`, async function() {
|
|
115
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
vans[9] = []
|
|
119
|
+
it(`should get ${JSON.stringify(vans[9])} for table after deleting all rows by find`, async function() {
|
|
120
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
vans[10] = { n: 5, nDeleted: 5, ok: 1 }
|
|
124
|
+
it(`should get ${JSON.stringify(vans[10])} for delAll without find`, async function() {
|
|
125
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
vans[11] = []
|
|
129
|
+
it(`should get ${JSON.stringify(vans[11])} for table after delAll without find`, async function() {
|
|
130
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
vans[12] = { n: 5, nDeleted: 5, ok: 1 }
|
|
134
|
+
it(`should get ${JSON.stringify(vans[12])} for delAll with empty find`, async function() {
|
|
135
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
vans[13] = []
|
|
139
|
+
it(`should get ${JSON.stringify(vans[13])} for table after delAll with empty find`, async function() {
|
|
140
|
+
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
vans[14] = true
|
|
144
|
+
it(`should get ${JSON.stringify(vans[14])} for n equal to nDeleted`, async function() {
|
|
145
|
+
assert.strict.deepStrictEqual(vget[14], vans[14])
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
vans[15] = [2, 2]
|
|
149
|
+
it(`should get ${JSON.stringify(vans[15])} for count of select and nDeleted with same find`, async function() {
|
|
150
|
+
assert.strict.deepStrictEqual(vget[15], vans[15])
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
})
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
import _ from 'lodash-es'
|
|
3
|
+
import w from 'wsemi'
|
|
4
|
+
import WOrm from '../src/WOrmLowdb.mjs'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe('event', function() {
|
|
8
|
+
let rt = null
|
|
9
|
+
let vans = {}
|
|
10
|
+
let vget = {}
|
|
11
|
+
|
|
12
|
+
before(async function() {
|
|
13
|
+
|
|
14
|
+
w.fsDeleteFile('./db_event.json')
|
|
15
|
+
|
|
16
|
+
let url = './db_event.json'
|
|
17
|
+
|
|
18
|
+
//evs, 蒐集事件, 事件名與各參數皆記錄以供比對
|
|
19
|
+
let mkEvs = function(wo) {
|
|
20
|
+
let evs = []
|
|
21
|
+
wo.on('change', function(mode, data, res) {
|
|
22
|
+
evs.push({ ev: 'change', mode, data, res })
|
|
23
|
+
})
|
|
24
|
+
wo.on('error', function(mode, data, err) {
|
|
25
|
+
evs.push({ ev: 'error', mode, data, err })
|
|
26
|
+
})
|
|
27
|
+
return evs
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//change事件之形狀: 逐筆函數以整批為單位發出一次
|
|
31
|
+
let woC = WOrm({ url, db: 'worm', cl: 'ch' })
|
|
32
|
+
let evsC = mkEvs(woC)
|
|
33
|
+
await woC.insert([{ id: 'c1' }, { id: 'c2' }])
|
|
34
|
+
await woC.insertBulk([{ id: 'c3' }, { id: 'c4' }])
|
|
35
|
+
await woC.save({ id: 'c1', a: 1 })
|
|
36
|
+
await woC.del([{ id: 'c2' }, { id: 'c3' }])
|
|
37
|
+
await woC.delAll()
|
|
38
|
+
vget[1] = _.map(evsC, function(v) {
|
|
39
|
+
return `${v.ev}:${v.mode}`
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
//change之res即本次回傳結果
|
|
43
|
+
let woR = WOrm({ url, db: 'worm', cl: 'res' })
|
|
44
|
+
let evsR = mkEvs(woR)
|
|
45
|
+
let rr = await woR.insert([{ id: 'r1' }])
|
|
46
|
+
vget[2] = _.isEqual(_.get(evsR, '0.res'), rr)
|
|
47
|
+
|
|
48
|
+
//change之data為本次輸入數據, delAll固定為null
|
|
49
|
+
await woR.delAll()
|
|
50
|
+
vget[3] = _.get(_.find(evsR, { mode: 'delAll' }), 'data')
|
|
51
|
+
|
|
52
|
+
//讀取函數不發出change事件
|
|
53
|
+
let woS = WOrm({ url, db: 'worm', cl: 'sel' })
|
|
54
|
+
let evsS = mkEvs(woS)
|
|
55
|
+
await woS.select()
|
|
56
|
+
await woS.selectByPk('none')
|
|
57
|
+
vget[4] = _.size(evsS)
|
|
58
|
+
|
|
59
|
+
//save之逐筆插入另發mode為insert之事件, 且早於整批save事件
|
|
60
|
+
let woI = WOrm({ url, db: 'worm', cl: 'ins' })
|
|
61
|
+
let evsI = mkEvs(woI)
|
|
62
|
+
await woI.save({ id: 'i1', a: 1 })
|
|
63
|
+
vget[5] = _.map(evsI, function(v) {
|
|
64
|
+
return `${v.ev}:${v.mode}`
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
//error事件: 整批性錯誤, 須於reject之前發出且err為字串
|
|
68
|
+
let woE = WOrm({ url, db: 'worm', cl: 'errb', autoGenPk: false })
|
|
69
|
+
let evsE = mkEvs(woE)
|
|
70
|
+
rt = null
|
|
71
|
+
await woE.insert({ name: 'no-id' })
|
|
72
|
+
.then(function() {
|
|
73
|
+
rt = 'resolve'
|
|
74
|
+
})
|
|
75
|
+
.catch(function() {
|
|
76
|
+
rt = 'reject'
|
|
77
|
+
})
|
|
78
|
+
vget[6] = rt
|
|
79
|
+
vget[7] = _.map(evsE, function(v) {
|
|
80
|
+
return `${v.ev}:${v.mode}`
|
|
81
|
+
})
|
|
82
|
+
vget[8] = w.isestr(_.get(evsE, '0.err'))
|
|
83
|
+
|
|
84
|
+
//error事件: 逐筆失敗, 整批仍resolve且每筆一次, err與該筆之err欄位一致
|
|
85
|
+
let woD = WOrm({ url, db: 'worm', cl: 'errd' })
|
|
86
|
+
let evsD = mkEvs(woD)
|
|
87
|
+
await woD.insert([{ id: 'd1' }])
|
|
88
|
+
let rd = await woD.del([{ id: 'd1' }, { name: 'no-id' }, { name: 'no-id2' }])
|
|
89
|
+
vget[9] = _.map(evsD, function(v) {
|
|
90
|
+
return `${v.ev}:${v.mode}`
|
|
91
|
+
})
|
|
92
|
+
vget[10] = _.get(_.find(evsD, { ev: 'error' }), 'err') === _.get(rd, '1.err')
|
|
93
|
+
|
|
94
|
+
//正常結果不得發出error事件
|
|
95
|
+
let woN = WOrm({ url, db: 'worm', cl: 'norm' })
|
|
96
|
+
let evsN = mkEvs(woN)
|
|
97
|
+
await woN.insert([{ id: 'n1' }])
|
|
98
|
+
await woN.insert([{ id: 'n1' }]) //全數已存在
|
|
99
|
+
await woN.save({ id: 'n1' }) //合併後內容相同
|
|
100
|
+
await woN.del([{ id: 'n-none' }]) //主鍵未命中
|
|
101
|
+
await woN.delAll({ id: 'n-none' }) //條件無命中
|
|
102
|
+
await woN.selectByPk('n-none') //查無數據
|
|
103
|
+
await woN.select({ id: 'n-none' }) //查無數據
|
|
104
|
+
vget[11] = _.size(_.filter(evsN, { ev: 'error' }))
|
|
105
|
+
|
|
106
|
+
//操作行為不得因監聽者之有無而改變
|
|
107
|
+
let mk = function(cl, withListener) {
|
|
108
|
+
let wo = WOrm({ url, db: 'worm', cl })
|
|
109
|
+
if (withListener) {
|
|
110
|
+
wo.on('error', function() {})
|
|
111
|
+
wo.on('change', function() {})
|
|
112
|
+
}
|
|
113
|
+
return wo
|
|
114
|
+
}
|
|
115
|
+
let woA = mk('lsn-a', true)
|
|
116
|
+
let woB = mk('lsn-b', false)
|
|
117
|
+
let run = async function(wo) {
|
|
118
|
+
let ms = []
|
|
119
|
+
ms.push(await wo.insert([{ id: 'p1' }]))
|
|
120
|
+
ms.push(await wo.del([{ id: 'p1' }, { name: 'no-id' }]))
|
|
121
|
+
ms.push(await wo.save([{ id: 'p2', a: 1 }]))
|
|
122
|
+
let r = null
|
|
123
|
+
await wo.selectByPk('none')
|
|
124
|
+
.then(function(msg) {
|
|
125
|
+
r = msg
|
|
126
|
+
})
|
|
127
|
+
.catch(function(msg) {
|
|
128
|
+
r = 'reject: ' + msg.toString()
|
|
129
|
+
})
|
|
130
|
+
ms.push(r)
|
|
131
|
+
return ms
|
|
132
|
+
}
|
|
133
|
+
let msA = await run(woA)
|
|
134
|
+
let msB = await run(woB)
|
|
135
|
+
vget[12] = _.isEqual(msA, msB)
|
|
136
|
+
|
|
137
|
+
//訂閱函數拋錯不得影響本次操作
|
|
138
|
+
let woX = WOrm({ url, db: 'worm', cl: 'throw' })
|
|
139
|
+
woX.on('change', function() {
|
|
140
|
+
throw new Error('error in change listener')
|
|
141
|
+
})
|
|
142
|
+
woX.on('error', function() {
|
|
143
|
+
throw new Error('error in error listener')
|
|
144
|
+
})
|
|
145
|
+
rt = null
|
|
146
|
+
await woX.insert([{ id: 'x1' }])
|
|
147
|
+
.then(function(msg) {
|
|
148
|
+
rt = msg
|
|
149
|
+
})
|
|
150
|
+
.catch(function(msg) {
|
|
151
|
+
rt = 'reject: ' + msg.toString()
|
|
152
|
+
})
|
|
153
|
+
vget[13] = rt
|
|
154
|
+
rt = null
|
|
155
|
+
await woX.del([{ name: 'no-id' }])
|
|
156
|
+
.then(function(msg) {
|
|
157
|
+
rt = _.map(msg, 'ok')
|
|
158
|
+
})
|
|
159
|
+
.catch(function(msg) {
|
|
160
|
+
rt = 'reject: ' + msg.toString()
|
|
161
|
+
})
|
|
162
|
+
vget[14] = rt
|
|
163
|
+
vget[15] = await woX.selectByPk('x1')
|
|
164
|
+
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
after(async function() {
|
|
168
|
+
w.fsDeleteFile('./db_event.json')
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
vans[1] = [
|
|
172
|
+
'change:insert',
|
|
173
|
+
'change:insertBulk',
|
|
174
|
+
'change:save',
|
|
175
|
+
'change:del',
|
|
176
|
+
'change:delAll',
|
|
177
|
+
]
|
|
178
|
+
it(`should get ${JSON.stringify(vans[1])} for change events`, async function() {
|
|
179
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
vans[2] = true
|
|
183
|
+
it(`should get ${JSON.stringify(vans[2])} for res of change event equal to returned value`, async function() {
|
|
184
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
vans[3] = null
|
|
188
|
+
it(`should get ${JSON.stringify(vans[3])} for data of change event of delAll`, async function() {
|
|
189
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
vans[4] = 0
|
|
193
|
+
it(`should get ${JSON.stringify(vans[4])} for count of events emitted by select and selectByPk`, async function() {
|
|
194
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
vans[5] = ['change:insert', 'change:save']
|
|
198
|
+
it(`should get ${JSON.stringify(vans[5])} for events of save with auto insert`, async function() {
|
|
199
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
vans[6] = 'reject'
|
|
203
|
+
it(`should get ${JSON.stringify(vans[6])} for insert without pk when autoGenPk=false`, async function() {
|
|
204
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
vans[7] = ['error:insert']
|
|
208
|
+
it(`should get ${JSON.stringify(vans[7])} for events of batch level error`, async function() {
|
|
209
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
vans[8] = true
|
|
213
|
+
it(`should get ${JSON.stringify(vans[8])} for err of error event being string`, async function() {
|
|
214
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
vans[9] = ['change:insert', 'error:del', 'error:del', 'change:del']
|
|
218
|
+
it(`should get ${JSON.stringify(vans[9])} for events of item level error`, async function() {
|
|
219
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
vans[10] = true
|
|
223
|
+
it(`should get ${JSON.stringify(vans[10])} for err of error event equal to err of the item`, async function() {
|
|
224
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
vans[11] = 0
|
|
228
|
+
it(`should get ${JSON.stringify(vans[11])} for count of error events emitted by normal results`, async function() {
|
|
229
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
vans[12] = true
|
|
233
|
+
it(`should get ${JSON.stringify(vans[12])} for results with and without listeners being the same`, async function() {
|
|
234
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
vans[13] = { n: 1, nInserted: 1, ok: 1 }
|
|
238
|
+
it(`should get ${JSON.stringify(vans[13])} for insert with throwing listener`, async function() {
|
|
239
|
+
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
vans[14] = [0]
|
|
243
|
+
it(`should get ${JSON.stringify(vans[14])} for del with throwing listener`, async function() {
|
|
244
|
+
assert.strict.deepStrictEqual(vget[14], vans[14])
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
vans[15] = { id: 'x1' }
|
|
248
|
+
it(`should get ${JSON.stringify(vans[15])} for row inserted with throwing listener`, async function() {
|
|
249
|
+
assert.strict.deepStrictEqual(vget[15], vans[15])
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
})
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
import _ from 'lodash-es'
|
|
3
|
+
import w from 'wsemi'
|
|
4
|
+
import WOrm from '../src/WOrmLowdb.mjs'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe('insert', function() {
|
|
8
|
+
let rt = null
|
|
9
|
+
let vans = {}
|
|
10
|
+
let vget = {}
|
|
11
|
+
|
|
12
|
+
before(async function() {
|
|
13
|
+
|
|
14
|
+
w.fsDeleteFile('./db_insert.json')
|
|
15
|
+
|
|
16
|
+
let wo = WOrm({ url: './db_insert.json', db: 'worm', cl: 'users' })
|
|
17
|
+
|
|
18
|
+
//輸入無效, 回傳空結果而非錯誤
|
|
19
|
+
vget[1] = await wo.insert(null)
|
|
20
|
+
vget[2] = await wo.insert('abc')
|
|
21
|
+
vget[3] = await wo.insert([])
|
|
22
|
+
|
|
23
|
+
//正常插入
|
|
24
|
+
vget[4] = await wo.insert([{ id: 'a', v: 1 }, { id: 'b', v: 2 }])
|
|
25
|
+
|
|
26
|
+
//單一物件亦須回傳單一聚合物件而非陣列
|
|
27
|
+
vget[5] = await wo.insert({ id: 'c', v: 3 })
|
|
28
|
+
|
|
29
|
+
//主鍵已存在者跳過且不覆寫, 全數已存在而nInserted為0屬正常結果不得reject
|
|
30
|
+
rt = null
|
|
31
|
+
await wo.insert([{ id: 'a', v: 999 }, { id: 'b', v: 999 }])
|
|
32
|
+
.then(function(msg) {
|
|
33
|
+
rt = msg
|
|
34
|
+
})
|
|
35
|
+
.catch(function(msg) {
|
|
36
|
+
rt = 'reject: ' + msg.toString()
|
|
37
|
+
})
|
|
38
|
+
vget[6] = rt
|
|
39
|
+
vget[7] = await wo.selectByPk('a')
|
|
40
|
+
|
|
41
|
+
//部份已存在者, nInserted為實際插入筆數
|
|
42
|
+
vget[8] = await wo.insert([{ id: 'a', v: 999 }, { id: 'd', v: 4 }])
|
|
43
|
+
|
|
44
|
+
//同批含重複主鍵時僅首筆計入nInserted, 且資料表不得出現重複主鍵
|
|
45
|
+
vget[9] = await wo.insert([{ id: 'e', v: 1 }, { id: 'e', v: 2 }, { id: 'e', v: 3 }])
|
|
46
|
+
vget[10] = _.size(_.filter(await wo.select(), function(v) {
|
|
47
|
+
return v.id === 'e'
|
|
48
|
+
}))
|
|
49
|
+
vget[11] = await wo.selectByPk('e')
|
|
50
|
+
|
|
51
|
+
//全表內容
|
|
52
|
+
vget[12] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
|
|
53
|
+
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
after(async function() {
|
|
57
|
+
w.fsDeleteFile('./db_insert.json')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
vans[1] = { n: 0, nInserted: 0, ok: 1 }
|
|
61
|
+
it(`should get ${JSON.stringify(vans[1])} for insert(null)`, async function() {
|
|
62
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
vans[2] = { n: 0, nInserted: 0, ok: 1 }
|
|
66
|
+
it(`should get ${JSON.stringify(vans[2])} for insert('abc')`, async function() {
|
|
67
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
vans[3] = { n: 0, nInserted: 0, ok: 1 }
|
|
71
|
+
it(`should get ${JSON.stringify(vans[3])} for insert([])`, async function() {
|
|
72
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
vans[4] = { n: 2, nInserted: 2, ok: 1 }
|
|
76
|
+
it(`should get ${JSON.stringify(vans[4])} for insert 2 rows`, async function() {
|
|
77
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
vans[5] = { n: 1, nInserted: 1, ok: 1 }
|
|
81
|
+
it(`should get ${JSON.stringify(vans[5])} for insert single object`, async function() {
|
|
82
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
vans[6] = { n: 2, nInserted: 0, ok: 1 }
|
|
86
|
+
it(`should get ${JSON.stringify(vans[6])} for insert all existed pk`, async function() {
|
|
87
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
vans[7] = { id: 'a', v: 1 }
|
|
91
|
+
it(`should get ${JSON.stringify(vans[7])} for existed row which not be overwritten`, async function() {
|
|
92
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
vans[8] = { n: 2, nInserted: 1, ok: 1 }
|
|
96
|
+
it(`should get ${JSON.stringify(vans[8])} for insert partial existed pk`, async function() {
|
|
97
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
vans[9] = { n: 3, nInserted: 1, ok: 1 }
|
|
101
|
+
it(`should get ${JSON.stringify(vans[9])} for insert duplicated pk in same batch`, async function() {
|
|
102
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
vans[10] = 1
|
|
106
|
+
it(`should get ${JSON.stringify(vans[10])} for count of duplicated pk in table`, async function() {
|
|
107
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
vans[11] = { id: 'e', v: 1 }
|
|
111
|
+
it(`should get ${JSON.stringify(vans[11])} for first row of duplicated pk in same batch`, async function() {
|
|
112
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
vans[12] = ['a', 'b', 'c', 'd', 'e']
|
|
116
|
+
it(`should get ${JSON.stringify(vans[12])} for all ids in table`, async function() {
|
|
117
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
})
|