w-orm-postgresql 1.0.10 → 1.0.11
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 +1 -0
- package/dist/w-orm-postgresql.umd.js +2 -2
- package/dist/w-orm-postgresql.umd.js.map +1 -1
- package/docs/WOrmPostgresql.html +8 -8
- package/docs/WOrmPostgresql.mjs.html +116 -29
- package/docs/index.html +1 -1
- package/g-basic.mjs +1 -0
- package/package.json +1 -1
- package/src/WOrmPostgresql.mjs +114 -27
- package/test/api-postgresql.test.mjs +240 -0
|
@@ -1434,6 +1434,246 @@ describe('custom pk', function() {
|
|
|
1434
1434
|
})
|
|
1435
1435
|
|
|
1436
1436
|
|
|
1437
|
+
describe('events', function() {
|
|
1438
|
+
let vans = {}
|
|
1439
|
+
let vget = {}
|
|
1440
|
+
|
|
1441
|
+
before(async function() {
|
|
1442
|
+
this.timeout(120000)
|
|
1443
|
+
|
|
1444
|
+
//wo
|
|
1445
|
+
let cl = 'events'
|
|
1446
|
+
let wo = WOrm(genOpt(cl))
|
|
1447
|
+
|
|
1448
|
+
//createTable
|
|
1449
|
+
await wo.createTable(cl, null, {
|
|
1450
|
+
time: '2000-01-01T00:00:00Z',
|
|
1451
|
+
name: 'abc',
|
|
1452
|
+
value: 0.1,
|
|
1453
|
+
}).catch(() => {})
|
|
1454
|
+
await wo.delAll()
|
|
1455
|
+
|
|
1456
|
+
//evChange, evError, 收集事件供斷言
|
|
1457
|
+
let evChange = []
|
|
1458
|
+
let evError = []
|
|
1459
|
+
wo.on('change', (mode, data, res) => {
|
|
1460
|
+
evChange.push({ mode, res })
|
|
1461
|
+
})
|
|
1462
|
+
wo.on('error', (mode, data, err) => {
|
|
1463
|
+
evError.push({ mode, err })
|
|
1464
|
+
})
|
|
1465
|
+
|
|
1466
|
+
//reset
|
|
1467
|
+
let reset = () => {
|
|
1468
|
+
evChange = []
|
|
1469
|
+
evError = []
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
//t
|
|
1473
|
+
let t1 = '2025-07-01T00:00:00Z'
|
|
1474
|
+
let t2 = '2025-07-01T00:01:00Z'
|
|
1475
|
+
let t3 = '2025-07-01T00:02:00Z'
|
|
1476
|
+
let t4 = '2025-07-01T00:03:00Z'
|
|
1477
|
+
let tNone = '2025-07-01T23:00:00Z'
|
|
1478
|
+
|
|
1479
|
+
//insert正常, 發change且不發error
|
|
1480
|
+
reset()
|
|
1481
|
+
await wo.insert([
|
|
1482
|
+
{ time: t1, name: 'peter', value: 1 },
|
|
1483
|
+
{ time: t2, name: 'rosemary', value: 2 },
|
|
1484
|
+
])
|
|
1485
|
+
vget[1] = evChange.map((v) => v.mode)
|
|
1486
|
+
vget[2] = evError.length
|
|
1487
|
+
|
|
1488
|
+
//insert全數已存在為正常結果, 不得發error
|
|
1489
|
+
reset()
|
|
1490
|
+
await wo.insert({ time: t1, name: 'peter', value: 1 })
|
|
1491
|
+
vget[3] = evError.length
|
|
1492
|
+
|
|
1493
|
+
//save之逐筆插入另發mode為insert之change, 整批再發save
|
|
1494
|
+
reset()
|
|
1495
|
+
await wo.save({ time: t3, name: 'sandler' })
|
|
1496
|
+
vget[4] = evChange.map((v) => v.mode)
|
|
1497
|
+
|
|
1498
|
+
//save合併後內容相同為正常結果, 不得發error
|
|
1499
|
+
reset()
|
|
1500
|
+
await wo.save({ time: t3, name: 'sandler' })
|
|
1501
|
+
vget[5] = evError.length
|
|
1502
|
+
|
|
1503
|
+
//save逐筆失敗發error且整批仍resolve
|
|
1504
|
+
reset()
|
|
1505
|
+
let rsf = await wo.save([
|
|
1506
|
+
{ time: t1, name: 'ok' },
|
|
1507
|
+
{ time: t4, notexistcol: 1 },
|
|
1508
|
+
])
|
|
1509
|
+
vget[6] = evError.map((v) => v.mode)
|
|
1510
|
+
vget[7] = isestr(evError[0].err)
|
|
1511
|
+
vget[8] = rsf.length
|
|
1512
|
+
vget[9] = evChange.map((v) => v.mode)
|
|
1513
|
+
|
|
1514
|
+
//del未帶有效主鍵為逐筆失敗, 發error
|
|
1515
|
+
reset()
|
|
1516
|
+
await wo.del([{ name: 'no-pk' }])
|
|
1517
|
+
vget[10] = evError.map((v) => v.mode)
|
|
1518
|
+
|
|
1519
|
+
//del主鍵未命中為正常結果, 不得發error
|
|
1520
|
+
reset()
|
|
1521
|
+
await wo.del({ time: tNone })
|
|
1522
|
+
vget[11] = evError.length
|
|
1523
|
+
|
|
1524
|
+
//selectByPk查無數據為正常結果, 不得發error
|
|
1525
|
+
reset()
|
|
1526
|
+
await wo.selectByPk(tNone)
|
|
1527
|
+
vget[12] = evError.length
|
|
1528
|
+
|
|
1529
|
+
//selectByPk主鍵值無效為正常結果, 不得發error
|
|
1530
|
+
reset()
|
|
1531
|
+
await wo.selectByPk('abc')
|
|
1532
|
+
vget[13] = evError.length
|
|
1533
|
+
|
|
1534
|
+
//delAll條件無命中為正常結果, 不得發error
|
|
1535
|
+
reset()
|
|
1536
|
+
await wo.delAll({ name: 'notexist' })
|
|
1537
|
+
vget[14] = evError.length
|
|
1538
|
+
|
|
1539
|
+
//整批性錯誤於reject之前發出error
|
|
1540
|
+
reset()
|
|
1541
|
+
vget[15] = await wo.insert({ name: 'no-pk' })
|
|
1542
|
+
.then(() => 'resolved')
|
|
1543
|
+
.catch(() => 'rejected')
|
|
1544
|
+
vget[16] = evError.map((v) => v.mode)
|
|
1545
|
+
|
|
1546
|
+
//T10.1第2條, 操作行為不得因監聽者之有無而改變
|
|
1547
|
+
//woNo未註冊任何監聽, woOn註冊error監聽, 兩者之回傳值須完全相同
|
|
1548
|
+
let woNo = WOrm(genOpt(cl))
|
|
1549
|
+
let woOn = WOrm(genOpt(cl))
|
|
1550
|
+
woOn.on('error', () => {})
|
|
1551
|
+
|
|
1552
|
+
//整批性錯誤
|
|
1553
|
+
let rNo1 = await woNo.insert({ name: 'no-pk' })
|
|
1554
|
+
.then(() => 'resolved')
|
|
1555
|
+
.catch((err) => `rejected:${err}`)
|
|
1556
|
+
let rOn1 = await woOn.insert({ name: 'no-pk' })
|
|
1557
|
+
.then(() => 'resolved')
|
|
1558
|
+
.catch((err) => `rejected:${err}`)
|
|
1559
|
+
vget[17] = rNo1 === rOn1
|
|
1560
|
+
vget[18] = rNo1.indexOf('rejected:') === 0
|
|
1561
|
+
|
|
1562
|
+
//逐筆失敗
|
|
1563
|
+
let rNo2 = await woNo.del([{ name: 'no-pk' }])
|
|
1564
|
+
let rOn2 = await woOn.del([{ name: 'no-pk' }])
|
|
1565
|
+
vget[19] = JSON.stringify(rNo2) === JSON.stringify(rOn2)
|
|
1566
|
+
|
|
1567
|
+
//正常操作
|
|
1568
|
+
let rNo3 = await woNo.selectByPk(t1)
|
|
1569
|
+
let rOn3 = await woOn.selectByPk(t1)
|
|
1570
|
+
vget[20] = JSON.stringify(rNo3) === JSON.stringify(rOn3)
|
|
1571
|
+
|
|
1572
|
+
})
|
|
1573
|
+
|
|
1574
|
+
vans[1] = ['insert']
|
|
1575
|
+
it(`should get ${JSON.stringify(vans[1])} for change modes by insert`, async function() {
|
|
1576
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
1577
|
+
})
|
|
1578
|
+
|
|
1579
|
+
vans[2] = 0
|
|
1580
|
+
it(`should get ${JSON.stringify(vans[2])} for error count by insert`, async function() {
|
|
1581
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
1582
|
+
})
|
|
1583
|
+
|
|
1584
|
+
vans[3] = 0
|
|
1585
|
+
it(`should get ${JSON.stringify(vans[3])} for error count by insert with all existed`, async function() {
|
|
1586
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
1587
|
+
})
|
|
1588
|
+
|
|
1589
|
+
vans[4] = ['insert', 'save']
|
|
1590
|
+
it(`should get ${JSON.stringify(vans[4])} for change modes by save with autoInsert`, async function() {
|
|
1591
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
1592
|
+
})
|
|
1593
|
+
|
|
1594
|
+
vans[5] = 0
|
|
1595
|
+
it(`should get ${JSON.stringify(vans[5])} for error count by save with same content`, async function() {
|
|
1596
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
1597
|
+
})
|
|
1598
|
+
|
|
1599
|
+
vans[6] = ['save']
|
|
1600
|
+
it(`should get ${JSON.stringify(vans[6])} for error modes by save with 1 failed record`, async function() {
|
|
1601
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
1602
|
+
})
|
|
1603
|
+
|
|
1604
|
+
vans[7] = true
|
|
1605
|
+
it(`should get ${JSON.stringify(vans[7])} for err of error event being string`, async function() {
|
|
1606
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
1607
|
+
})
|
|
1608
|
+
|
|
1609
|
+
vans[8] = 2
|
|
1610
|
+
it(`should get ${JSON.stringify(vans[8])} for length of save result while 1 record failed`, async function() {
|
|
1611
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
1612
|
+
})
|
|
1613
|
+
|
|
1614
|
+
vans[9] = ['save']
|
|
1615
|
+
it(`should get ${JSON.stringify(vans[9])} for change modes by save while 1 record failed`, async function() {
|
|
1616
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
1617
|
+
})
|
|
1618
|
+
|
|
1619
|
+
vans[10] = ['del']
|
|
1620
|
+
it(`should get ${JSON.stringify(vans[10])} for error modes by del without valid pk`, async function() {
|
|
1621
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
1622
|
+
})
|
|
1623
|
+
|
|
1624
|
+
vans[11] = 0
|
|
1625
|
+
it(`should get ${JSON.stringify(vans[11])} for error count by del with pk not existed`, async function() {
|
|
1626
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
1627
|
+
})
|
|
1628
|
+
|
|
1629
|
+
vans[12] = 0
|
|
1630
|
+
it(`should get ${JSON.stringify(vans[12])} for error count by selectByPk with pk not existed`, async function() {
|
|
1631
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
1632
|
+
})
|
|
1633
|
+
|
|
1634
|
+
vans[13] = 0
|
|
1635
|
+
it(`should get ${JSON.stringify(vans[13])} for error count by selectByPk with pk invalid`, async function() {
|
|
1636
|
+
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
1637
|
+
})
|
|
1638
|
+
|
|
1639
|
+
vans[14] = 0
|
|
1640
|
+
it(`should get ${JSON.stringify(vans[14])} for error count by delAll with find matched nothing`, async function() {
|
|
1641
|
+
assert.strict.deepStrictEqual(vget[14], vans[14])
|
|
1642
|
+
})
|
|
1643
|
+
|
|
1644
|
+
vans[15] = 'rejected'
|
|
1645
|
+
it(`should get ${JSON.stringify(vans[15])} for insert without valid pk`, async function() {
|
|
1646
|
+
assert.strict.deepStrictEqual(vget[15], vans[15])
|
|
1647
|
+
})
|
|
1648
|
+
|
|
1649
|
+
vans[16] = ['insert']
|
|
1650
|
+
it(`should get ${JSON.stringify(vans[16])} for error modes by insert without valid pk`, async function() {
|
|
1651
|
+
assert.strict.deepStrictEqual(vget[16], vans[16])
|
|
1652
|
+
})
|
|
1653
|
+
|
|
1654
|
+
vans[17] = true
|
|
1655
|
+
it(`should get ${JSON.stringify(vans[17])} for same reject value with and without error listener`, async function() {
|
|
1656
|
+
assert.strict.deepStrictEqual(vget[17], vans[17])
|
|
1657
|
+
})
|
|
1658
|
+
|
|
1659
|
+
vans[18] = true
|
|
1660
|
+
it(`should get ${JSON.stringify(vans[18])} for still rejecting without error listener`, async function() {
|
|
1661
|
+
assert.strict.deepStrictEqual(vget[18], vans[18])
|
|
1662
|
+
})
|
|
1663
|
+
|
|
1664
|
+
vans[19] = true
|
|
1665
|
+
it(`should get ${JSON.stringify(vans[19])} for same del result with and without error listener`, async function() {
|
|
1666
|
+
assert.strict.deepStrictEqual(vget[19], vans[19])
|
|
1667
|
+
})
|
|
1668
|
+
|
|
1669
|
+
vans[20] = true
|
|
1670
|
+
it(`should get ${JSON.stringify(vans[20])} for same selectByPk result with and without error listener`, async function() {
|
|
1671
|
+
assert.strict.deepStrictEqual(vget[20], vans[20])
|
|
1672
|
+
})
|
|
1673
|
+
|
|
1674
|
+
})
|
|
1675
|
+
|
|
1676
|
+
|
|
1437
1677
|
//runProc, 另起行程對同一資料表操作, 用於驗證跨行程之原子性
|
|
1438
1678
|
//子行程以--input-type=module執行, 並以pathToFileURL轉換src路徑, 避免專案路徑含非ASCII字元而無法import
|
|
1439
1679
|
function runProc(tag, opt, mode, payload) {
|