meadow-endpoints 4.0.14 → 4.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/indoctrinate_content_staging/Indoctrinate-Catalog-AppData.json +1286 -1065
- package/dist/meadow-endpoints.js +253 -164
- package/dist/meadow-endpoints.js.map +1 -1
- package/dist/meadow-endpoints.min.js +7 -7
- package/dist/meadow-endpoints.min.js.map +1 -1
- package/docs/_version.json +7 -0
- package/docs/css/docuserve.css +277 -23
- package/docs/index.html +2 -2
- package/docs/retold-catalog.json +13 -1
- package/docs/retold-keyword-index.json +1 -1
- package/package.json +9 -8
- package/source/Meadow-Endpoints-Browser-Shim.js +4 -1
- package/source/Meadow-Endpoints.js +6 -6
- package/source/controller/Meadow-Endpoints-Controller-Base.js +6 -6
- package/source/controller/components/Meadow-Endpoints-Controller-BehaviorInjection.js +11 -11
- package/source/controller/components/Meadow-Endpoints-Controller-Error.js +23 -15
- package/source/controller/components/Meadow-Endpoints-Controller-Log.js +9 -9
- package/source/controller/utility/Meadow-Endpoints-Filter-Parser.js +16 -16
- package/source/controller/utility/Meadow-Endpoints-Session-Marshaler.js +42 -42
- package/source/controller/utility/Meadow-Endpoints-Stream-RecordArray.js +6 -6
- package/source/endpoints/create/Meadow-Operation-Create.js +1 -1
- package/source/endpoints/schema/Meadow-Endpoint-Validate.js +1 -1
- package/source/endpoints/update/Meadow-Endpoint-BulkUpdate.js +2 -0
- package/source/endpoints/update/Meadow-Operation-Update.js +2 -0
- package/source/endpoints/upsert/Meadow-Endpoint-BulkUpsert.js +3 -1
- package/source/endpoints/upsert/Meadow-Operation-Upsert.js +5 -3
- package/test/MeadowEndpoints_basic_tests.js +776 -0
|
@@ -819,6 +819,45 @@ suite
|
|
|
819
819
|
);
|
|
820
820
|
}
|
|
821
821
|
);
|
|
822
|
+
test
|
|
823
|
+
(
|
|
824
|
+
'upsert: update by GUID when passed ID is zero',
|
|
825
|
+
function (fDone)
|
|
826
|
+
{
|
|
827
|
+
// First create a record so we have a known GUID
|
|
828
|
+
_SuperTest
|
|
829
|
+
.post('1.0/Book')
|
|
830
|
+
.send({ Title: 'Zero ID Upsert Test', Genre: 'Test' })
|
|
831
|
+
.end(
|
|
832
|
+
(pError, pResponse) =>
|
|
833
|
+
{
|
|
834
|
+
let tmpCreated = JSON.parse(pResponse.text);
|
|
835
|
+
let tmpRecord = Array.isArray(tmpCreated) ? tmpCreated[0] : tmpCreated;
|
|
836
|
+
let tmpGUID = tmpRecord.GUIDBook;
|
|
837
|
+
let tmpID = tmpRecord.IDBook;
|
|
838
|
+
Expect(tmpID).to.be.above(0);
|
|
839
|
+
Expect(tmpGUID).to.be.a('string');
|
|
840
|
+
|
|
841
|
+
// Now upsert with ID=0 but the same GUID — should
|
|
842
|
+
// find the record by GUID and update it, not fail
|
|
843
|
+
// with "Record IDs do not match".
|
|
844
|
+
_SuperTest
|
|
845
|
+
.put('1.0/Book/Upsert')
|
|
846
|
+
.send({ IDBook: 0, GUIDBook: tmpGUID, Title: 'Zero ID Upsert Updated' })
|
|
847
|
+
.end(
|
|
848
|
+
(pUpsertError, pUpsertResponse) =>
|
|
849
|
+
{
|
|
850
|
+
Expect(pUpsertResponse.status).to.equal(200);
|
|
851
|
+
let tmpResult = JSON.parse(pUpsertResponse.text);
|
|
852
|
+
Expect(tmpResult.IDBook).to.equal(tmpID);
|
|
853
|
+
Expect(tmpResult.Title).to.equal('Zero ID Upsert Updated');
|
|
854
|
+
fDone();
|
|
855
|
+
}
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
);
|
|
822
861
|
}
|
|
823
862
|
);
|
|
824
863
|
|
|
@@ -1369,6 +1408,743 @@ suite
|
|
|
1369
1408
|
);
|
|
1370
1409
|
}
|
|
1371
1410
|
);
|
|
1411
|
+
|
|
1412
|
+
// ==================================================================
|
|
1413
|
+
// New hooks added 2026-04-18 to restore ME2 parity
|
|
1414
|
+
// (Update-Pre, Update-Query) and to extend ME4's bulk-level hooks
|
|
1415
|
+
// to Update/Upsert (UpdateBulk-*, UpsertBulk-*).
|
|
1416
|
+
// ==================================================================
|
|
1417
|
+
|
|
1418
|
+
test
|
|
1419
|
+
(
|
|
1420
|
+
'setBehavior: Update-PreOperation hook can mutate RecordToModify before DAL update',
|
|
1421
|
+
function (fDone)
|
|
1422
|
+
{
|
|
1423
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Update-PreOperation',
|
|
1424
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1425
|
+
{
|
|
1426
|
+
// Hook sees the incoming payload on RecordToModify,
|
|
1427
|
+
// existing loaded row on Record. Mutations to
|
|
1428
|
+
// RecordToModify flow through to the DAL update.
|
|
1429
|
+
Expect(pRequestState.RecordToModify).to.be.an('object');
|
|
1430
|
+
pRequestState.RecordToModify.Genre = 'MutatedByPreOp';
|
|
1431
|
+
return fCallback();
|
|
1432
|
+
});
|
|
1433
|
+
|
|
1434
|
+
_SuperTest
|
|
1435
|
+
.put('1.0/Book')
|
|
1436
|
+
.send({ IDBook: 4, Title: 'Snow Crash (v2)' })
|
|
1437
|
+
.end(
|
|
1438
|
+
(pError, pResponse) =>
|
|
1439
|
+
{
|
|
1440
|
+
let tmpResult = JSON.parse(pResponse.text);
|
|
1441
|
+
Expect(tmpResult.Genre).to.equal('MutatedByPreOp');
|
|
1442
|
+
Expect(tmpResult.Title).to.equal('Snow Crash (v2)');
|
|
1443
|
+
|
|
1444
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Update-PreOperation'];
|
|
1445
|
+
fDone();
|
|
1446
|
+
}
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1449
|
+
);
|
|
1450
|
+
test
|
|
1451
|
+
(
|
|
1452
|
+
'setBehavior: Update-PreOperation hook can reject an update',
|
|
1453
|
+
function (fDone)
|
|
1454
|
+
{
|
|
1455
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Update-PreOperation',
|
|
1456
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1457
|
+
{
|
|
1458
|
+
if (!pRequestState.RecordToModify.Title)
|
|
1459
|
+
{
|
|
1460
|
+
const tmpError = new Error('Title is required');
|
|
1461
|
+
tmpError.StatusCode = 400;
|
|
1462
|
+
return fCallback(tmpError);
|
|
1463
|
+
}
|
|
1464
|
+
return fCallback();
|
|
1465
|
+
});
|
|
1466
|
+
|
|
1467
|
+
_SuperTest
|
|
1468
|
+
.put('1.0/Book')
|
|
1469
|
+
.send({ IDBook: 3 })
|
|
1470
|
+
.end(
|
|
1471
|
+
(pError, pResponse) =>
|
|
1472
|
+
{
|
|
1473
|
+
const tmpResult = JSON.parse(pResponse.text);
|
|
1474
|
+
Expect(tmpResult).to.have.property('Error');
|
|
1475
|
+
|
|
1476
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Update-PreOperation'];
|
|
1477
|
+
fDone();
|
|
1478
|
+
}
|
|
1479
|
+
);
|
|
1480
|
+
}
|
|
1481
|
+
);
|
|
1482
|
+
test
|
|
1483
|
+
(
|
|
1484
|
+
'setBehavior: Update-QueryConfiguration hook fires after Query.addRecord',
|
|
1485
|
+
function (fDone)
|
|
1486
|
+
{
|
|
1487
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Update-QueryConfiguration',
|
|
1488
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1489
|
+
{
|
|
1490
|
+
// Query should exist and have had the record added;
|
|
1491
|
+
// hook can scope the update further.
|
|
1492
|
+
Expect(pRequestState.Query).to.exist;
|
|
1493
|
+
pRequestState.Query.addFilter('Deleted', 0);
|
|
1494
|
+
return fCallback();
|
|
1495
|
+
});
|
|
1496
|
+
|
|
1497
|
+
_SuperTest
|
|
1498
|
+
.put('1.0/Book')
|
|
1499
|
+
.send({ IDBook: 2, Title: 'Dune (updated)' })
|
|
1500
|
+
.end(
|
|
1501
|
+
(pError, pResponse) =>
|
|
1502
|
+
{
|
|
1503
|
+
const tmpResult = JSON.parse(pResponse.text);
|
|
1504
|
+
Expect(tmpResult.Title).to.equal('Dune (updated)');
|
|
1505
|
+
|
|
1506
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Update-QueryConfiguration'];
|
|
1507
|
+
fDone();
|
|
1508
|
+
}
|
|
1509
|
+
);
|
|
1510
|
+
}
|
|
1511
|
+
);
|
|
1512
|
+
test
|
|
1513
|
+
(
|
|
1514
|
+
'setBehavior: UpdateBulk-PreOperation fires once before the batch',
|
|
1515
|
+
function (fDone)
|
|
1516
|
+
{
|
|
1517
|
+
let _CallCount = 0;
|
|
1518
|
+
let _SawBulkRecords = false;
|
|
1519
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('UpdateBulk-PreOperation',
|
|
1520
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1521
|
+
{
|
|
1522
|
+
_CallCount++;
|
|
1523
|
+
_SawBulkRecords = Array.isArray(pRequestState.BulkRecords);
|
|
1524
|
+
return fCallback();
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
_SuperTest
|
|
1528
|
+
.put('1.0/Books')
|
|
1529
|
+
.send([
|
|
1530
|
+
{ IDBook: 1, Title: 'Angels & Demons (batch)' },
|
|
1531
|
+
{ IDBook: 2, Title: 'Dune (batch)' },
|
|
1532
|
+
])
|
|
1533
|
+
.end(
|
|
1534
|
+
(pError, pResponse) =>
|
|
1535
|
+
{
|
|
1536
|
+
Expect(_CallCount).to.equal(1);
|
|
1537
|
+
Expect(_SawBulkRecords).to.equal(true);
|
|
1538
|
+
|
|
1539
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['UpdateBulk-PreOperation'];
|
|
1540
|
+
fDone();
|
|
1541
|
+
}
|
|
1542
|
+
);
|
|
1543
|
+
}
|
|
1544
|
+
);
|
|
1545
|
+
test
|
|
1546
|
+
(
|
|
1547
|
+
'setBehavior: UpdateBulk-PostOperation fires once after the batch',
|
|
1548
|
+
function (fDone)
|
|
1549
|
+
{
|
|
1550
|
+
let _CallCount = 0;
|
|
1551
|
+
let _SawUpdatedRecords = false;
|
|
1552
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('UpdateBulk-PostOperation',
|
|
1553
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1554
|
+
{
|
|
1555
|
+
_CallCount++;
|
|
1556
|
+
_SawUpdatedRecords = Array.isArray(pRequestState.UpdatedRecords) && pRequestState.UpdatedRecords.length > 0;
|
|
1557
|
+
return fCallback();
|
|
1558
|
+
});
|
|
1559
|
+
|
|
1560
|
+
_SuperTest
|
|
1561
|
+
.put('1.0/Books')
|
|
1562
|
+
.send([
|
|
1563
|
+
{ IDBook: 3, Title: 'Neuromancer (batch post)' },
|
|
1564
|
+
])
|
|
1565
|
+
.end(
|
|
1566
|
+
(pError, pResponse) =>
|
|
1567
|
+
{
|
|
1568
|
+
Expect(_CallCount).to.equal(1);
|
|
1569
|
+
Expect(_SawUpdatedRecords).to.equal(true);
|
|
1570
|
+
|
|
1571
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['UpdateBulk-PostOperation'];
|
|
1572
|
+
fDone();
|
|
1573
|
+
}
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
);
|
|
1577
|
+
test
|
|
1578
|
+
(
|
|
1579
|
+
'setBehavior: UpsertBulk-PreOperation fires once before the batch',
|
|
1580
|
+
function (fDone)
|
|
1581
|
+
{
|
|
1582
|
+
let _CallCount = 0;
|
|
1583
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('UpsertBulk-PreOperation',
|
|
1584
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1585
|
+
{
|
|
1586
|
+
_CallCount++;
|
|
1587
|
+
Expect(Array.isArray(pRequestState.BulkRecords)).to.equal(true);
|
|
1588
|
+
return fCallback();
|
|
1589
|
+
});
|
|
1590
|
+
|
|
1591
|
+
_SuperTest
|
|
1592
|
+
.put('1.0/Book/Upserts')
|
|
1593
|
+
.send([
|
|
1594
|
+
{ Title: 'Bulk Upsert New 1' },
|
|
1595
|
+
{ Title: 'Bulk Upsert New 2' },
|
|
1596
|
+
])
|
|
1597
|
+
.end(
|
|
1598
|
+
(pError, pResponse) =>
|
|
1599
|
+
{
|
|
1600
|
+
Expect(_CallCount).to.equal(1);
|
|
1601
|
+
|
|
1602
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['UpsertBulk-PreOperation'];
|
|
1603
|
+
fDone();
|
|
1604
|
+
}
|
|
1605
|
+
);
|
|
1606
|
+
}
|
|
1607
|
+
);
|
|
1608
|
+
test
|
|
1609
|
+
(
|
|
1610
|
+
'setBehavior: UpsertBulk-PostOperation fires once after the batch',
|
|
1611
|
+
function (fDone)
|
|
1612
|
+
{
|
|
1613
|
+
let _CallCount = 0;
|
|
1614
|
+
let _SawUpserted = false;
|
|
1615
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('UpsertBulk-PostOperation',
|
|
1616
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1617
|
+
{
|
|
1618
|
+
_CallCount++;
|
|
1619
|
+
_SawUpserted = Array.isArray(pRequestState.UpsertedRecords) && pRequestState.UpsertedRecords.length > 0;
|
|
1620
|
+
return fCallback();
|
|
1621
|
+
});
|
|
1622
|
+
|
|
1623
|
+
_SuperTest
|
|
1624
|
+
.put('1.0/Book/Upserts')
|
|
1625
|
+
.send([
|
|
1626
|
+
{ Title: 'Bulk Upsert Post 1' },
|
|
1627
|
+
])
|
|
1628
|
+
.end(
|
|
1629
|
+
(pError, pResponse) =>
|
|
1630
|
+
{
|
|
1631
|
+
Expect(_CallCount).to.equal(1);
|
|
1632
|
+
Expect(_SawUpserted).to.equal(true);
|
|
1633
|
+
|
|
1634
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['UpsertBulk-PostOperation'];
|
|
1635
|
+
fDone();
|
|
1636
|
+
}
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
);
|
|
1640
|
+
|
|
1641
|
+
// ==================================================================
|
|
1642
|
+
// Coverage backfill for hooks that were present but previously
|
|
1643
|
+
// untested. Each test registers a handler, fires the endpoint,
|
|
1644
|
+
// and asserts the hook observed the expected state. These also
|
|
1645
|
+
// act as stage-semantics documentation for the hook surface.
|
|
1646
|
+
// ==================================================================
|
|
1647
|
+
|
|
1648
|
+
test
|
|
1649
|
+
(
|
|
1650
|
+
'setBehavior: Create-QueryConfiguration fires after Query.addRecord',
|
|
1651
|
+
function (fDone)
|
|
1652
|
+
{
|
|
1653
|
+
let _Seen = null;
|
|
1654
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Create-QueryConfiguration',
|
|
1655
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1656
|
+
{
|
|
1657
|
+
_Seen = {
|
|
1658
|
+
hasQuery: !!pRequestState.Query,
|
|
1659
|
+
hasRecordToCreate: !!pRequestState.RecordToCreate,
|
|
1660
|
+
};
|
|
1661
|
+
return fCallback();
|
|
1662
|
+
});
|
|
1663
|
+
|
|
1664
|
+
_SuperTest
|
|
1665
|
+
.post('1.0/Book')
|
|
1666
|
+
.send({ Title: 'Query-Config hook target' })
|
|
1667
|
+
.end(
|
|
1668
|
+
(pError, pResponse) =>
|
|
1669
|
+
{
|
|
1670
|
+
Expect(_Seen).to.deep.equal({ hasQuery: true, hasRecordToCreate: true });
|
|
1671
|
+
|
|
1672
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Create-QueryConfiguration'];
|
|
1673
|
+
fDone();
|
|
1674
|
+
}
|
|
1675
|
+
);
|
|
1676
|
+
}
|
|
1677
|
+
);
|
|
1678
|
+
test
|
|
1679
|
+
(
|
|
1680
|
+
'setBehavior: Create-PostOperation sees the freshly-inserted Record',
|
|
1681
|
+
function (fDone)
|
|
1682
|
+
{
|
|
1683
|
+
let _SeenIDBook = null;
|
|
1684
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Create-PostOperation',
|
|
1685
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1686
|
+
{
|
|
1687
|
+
_SeenIDBook = pRequestState.Record && pRequestState.Record.IDBook;
|
|
1688
|
+
pRequestState.Record.PostOpTag = 'was-here';
|
|
1689
|
+
return fCallback();
|
|
1690
|
+
});
|
|
1691
|
+
|
|
1692
|
+
_SuperTest
|
|
1693
|
+
.post('1.0/Book')
|
|
1694
|
+
.send({ Title: 'Post-op hook target' })
|
|
1695
|
+
.end(
|
|
1696
|
+
(pError, pResponse) =>
|
|
1697
|
+
{
|
|
1698
|
+
const tmpResult = JSON.parse(pResponse.text);
|
|
1699
|
+
Expect(_SeenIDBook).to.be.above(0);
|
|
1700
|
+
Expect(tmpResult.PostOpTag).to.equal('was-here');
|
|
1701
|
+
|
|
1702
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Create-PostOperation'];
|
|
1703
|
+
fDone();
|
|
1704
|
+
}
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
);
|
|
1708
|
+
test
|
|
1709
|
+
(
|
|
1710
|
+
'setBehavior: CreateBulk-PreOperation fires once with RecordsToBulkCreate',
|
|
1711
|
+
function (fDone)
|
|
1712
|
+
{
|
|
1713
|
+
let _CallCount = 0;
|
|
1714
|
+
let _SawRecords = false;
|
|
1715
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('CreateBulk-PreOperation',
|
|
1716
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1717
|
+
{
|
|
1718
|
+
_CallCount++;
|
|
1719
|
+
_SawRecords = Array.isArray(pRequest.RecordsToBulkCreate);
|
|
1720
|
+
return fCallback();
|
|
1721
|
+
});
|
|
1722
|
+
|
|
1723
|
+
_SuperTest
|
|
1724
|
+
.post('1.0/Books')
|
|
1725
|
+
.send([
|
|
1726
|
+
{ Title: 'Bulk Create 1' },
|
|
1727
|
+
{ Title: 'Bulk Create 2' },
|
|
1728
|
+
])
|
|
1729
|
+
.end(
|
|
1730
|
+
(pError, pResponse) =>
|
|
1731
|
+
{
|
|
1732
|
+
Expect(_CallCount).to.equal(1);
|
|
1733
|
+
Expect(_SawRecords).to.equal(true);
|
|
1734
|
+
|
|
1735
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['CreateBulk-PreOperation'];
|
|
1736
|
+
fDone();
|
|
1737
|
+
}
|
|
1738
|
+
);
|
|
1739
|
+
}
|
|
1740
|
+
);
|
|
1741
|
+
test
|
|
1742
|
+
(
|
|
1743
|
+
'setBehavior: CreateBulk-PostOperation fires once with CreatedRecords',
|
|
1744
|
+
function (fDone)
|
|
1745
|
+
{
|
|
1746
|
+
let _SawCreated = null;
|
|
1747
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('CreateBulk-PostOperation',
|
|
1748
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1749
|
+
{
|
|
1750
|
+
_SawCreated = Array.isArray(pRequestState.CreatedRecords) && pRequestState.CreatedRecords.length;
|
|
1751
|
+
return fCallback();
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1754
|
+
_SuperTest
|
|
1755
|
+
.post('1.0/Books')
|
|
1756
|
+
.send([
|
|
1757
|
+
{ Title: 'Bulk Create Post 1' },
|
|
1758
|
+
])
|
|
1759
|
+
.end(
|
|
1760
|
+
(pError, pResponse) =>
|
|
1761
|
+
{
|
|
1762
|
+
Expect(_SawCreated).to.equal(1);
|
|
1763
|
+
|
|
1764
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['CreateBulk-PostOperation'];
|
|
1765
|
+
fDone();
|
|
1766
|
+
}
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1769
|
+
);
|
|
1770
|
+
test
|
|
1771
|
+
(
|
|
1772
|
+
'setBehavior: Delete-QueryConfiguration can scope the delete query',
|
|
1773
|
+
function (fDone)
|
|
1774
|
+
{
|
|
1775
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Delete-QueryConfiguration',
|
|
1776
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1777
|
+
{
|
|
1778
|
+
Expect(pRequestState.Query).to.exist;
|
|
1779
|
+
return fCallback();
|
|
1780
|
+
});
|
|
1781
|
+
|
|
1782
|
+
// Use a record we don't care about the state of; create one inline.
|
|
1783
|
+
_SuperTest
|
|
1784
|
+
.post('1.0/Book')
|
|
1785
|
+
.send({ Title: 'Delete-Query target' })
|
|
1786
|
+
.end(
|
|
1787
|
+
(pPostErr, pPostRes) =>
|
|
1788
|
+
{
|
|
1789
|
+
const tmpID = JSON.parse(pPostRes.text).IDBook;
|
|
1790
|
+
_SuperTest
|
|
1791
|
+
.delete(`1.0/Book/${tmpID}`)
|
|
1792
|
+
.end(
|
|
1793
|
+
(pDelErr, pDelRes) =>
|
|
1794
|
+
{
|
|
1795
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Delete-QueryConfiguration'];
|
|
1796
|
+
fDone();
|
|
1797
|
+
}
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1802
|
+
);
|
|
1803
|
+
test
|
|
1804
|
+
(
|
|
1805
|
+
'setBehavior: Delete-PostOperation fires after soft-delete',
|
|
1806
|
+
function (fDone)
|
|
1807
|
+
{
|
|
1808
|
+
let _HookFired = false;
|
|
1809
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Delete-PostOperation',
|
|
1810
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1811
|
+
{
|
|
1812
|
+
_HookFired = true;
|
|
1813
|
+
return fCallback();
|
|
1814
|
+
});
|
|
1815
|
+
|
|
1816
|
+
_SuperTest
|
|
1817
|
+
.post('1.0/Book')
|
|
1818
|
+
.send({ Title: 'Delete-Post target' })
|
|
1819
|
+
.end(
|
|
1820
|
+
(pPostErr, pPostRes) =>
|
|
1821
|
+
{
|
|
1822
|
+
const tmpID = JSON.parse(pPostRes.text).IDBook;
|
|
1823
|
+
_SuperTest
|
|
1824
|
+
.delete(`1.0/Book/${tmpID}`)
|
|
1825
|
+
.end(
|
|
1826
|
+
() =>
|
|
1827
|
+
{
|
|
1828
|
+
Expect(_HookFired).to.equal(true);
|
|
1829
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Delete-PostOperation'];
|
|
1830
|
+
fDone();
|
|
1831
|
+
}
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1836
|
+
);
|
|
1837
|
+
test
|
|
1838
|
+
(
|
|
1839
|
+
'setBehavior: Read-QueryConfiguration runs after filter is applied',
|
|
1840
|
+
function (fDone)
|
|
1841
|
+
{
|
|
1842
|
+
let _SeenCriteria = null;
|
|
1843
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Read-QueryConfiguration',
|
|
1844
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1845
|
+
{
|
|
1846
|
+
_SeenCriteria = pRequestState.RecordSearchCriteria;
|
|
1847
|
+
return fCallback();
|
|
1848
|
+
});
|
|
1849
|
+
|
|
1850
|
+
_SuperTest
|
|
1851
|
+
.get('1.0/Book/1')
|
|
1852
|
+
.end(
|
|
1853
|
+
() =>
|
|
1854
|
+
{
|
|
1855
|
+
Expect(_SeenCriteria).to.be.a('string').and.satisfy((pS) => pS.includes('IDBook'));
|
|
1856
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Read-QueryConfiguration'];
|
|
1857
|
+
fDone();
|
|
1858
|
+
}
|
|
1859
|
+
);
|
|
1860
|
+
}
|
|
1861
|
+
);
|
|
1862
|
+
test
|
|
1863
|
+
(
|
|
1864
|
+
'setBehavior: Reads-PostOperation fires after list load',
|
|
1865
|
+
function (fDone)
|
|
1866
|
+
{
|
|
1867
|
+
let _SawRecords = false;
|
|
1868
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Reads-PostOperation',
|
|
1869
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1870
|
+
{
|
|
1871
|
+
_SawRecords = Array.isArray(pRequestState.Records) && pRequestState.Records.length > 0;
|
|
1872
|
+
return fCallback();
|
|
1873
|
+
});
|
|
1874
|
+
|
|
1875
|
+
_SuperTest
|
|
1876
|
+
.get('1.0/Books/0/10')
|
|
1877
|
+
.end(
|
|
1878
|
+
() =>
|
|
1879
|
+
{
|
|
1880
|
+
Expect(_SawRecords).to.equal(true);
|
|
1881
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Reads-PostOperation'];
|
|
1882
|
+
fDone();
|
|
1883
|
+
}
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1886
|
+
);
|
|
1887
|
+
test
|
|
1888
|
+
(
|
|
1889
|
+
'setBehavior: ReadMax-QueryConfiguration fires with column name',
|
|
1890
|
+
function (fDone)
|
|
1891
|
+
{
|
|
1892
|
+
let _SeenColumn = null;
|
|
1893
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('ReadMax-QueryConfiguration',
|
|
1894
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1895
|
+
{
|
|
1896
|
+
_SeenColumn = pRequestState.ColumnName;
|
|
1897
|
+
return fCallback();
|
|
1898
|
+
});
|
|
1899
|
+
|
|
1900
|
+
_SuperTest
|
|
1901
|
+
.get('1.0/Book/Max/PublicationYear')
|
|
1902
|
+
.end(
|
|
1903
|
+
() =>
|
|
1904
|
+
{
|
|
1905
|
+
Expect(_SeenColumn).to.equal('PublicationYear');
|
|
1906
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['ReadMax-QueryConfiguration'];
|
|
1907
|
+
fDone();
|
|
1908
|
+
}
|
|
1909
|
+
);
|
|
1910
|
+
}
|
|
1911
|
+
);
|
|
1912
|
+
test
|
|
1913
|
+
(
|
|
1914
|
+
'setBehavior: ReadMax-PostOperation fires after max lookup',
|
|
1915
|
+
function (fDone)
|
|
1916
|
+
{
|
|
1917
|
+
let _HookFired = false;
|
|
1918
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('ReadMax-PostOperation',
|
|
1919
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1920
|
+
{
|
|
1921
|
+
_HookFired = true;
|
|
1922
|
+
return fCallback();
|
|
1923
|
+
});
|
|
1924
|
+
|
|
1925
|
+
_SuperTest
|
|
1926
|
+
.get('1.0/Book/Max/PublicationYear')
|
|
1927
|
+
.end(
|
|
1928
|
+
() =>
|
|
1929
|
+
{
|
|
1930
|
+
Expect(_HookFired).to.equal(true);
|
|
1931
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['ReadMax-PostOperation'];
|
|
1932
|
+
fDone();
|
|
1933
|
+
}
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
);
|
|
1937
|
+
test
|
|
1938
|
+
(
|
|
1939
|
+
'setBehavior: CountBy-QueryConfiguration can modify count-by query',
|
|
1940
|
+
function (fDone)
|
|
1941
|
+
{
|
|
1942
|
+
let _HookFired = false;
|
|
1943
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('CountBy-QueryConfiguration',
|
|
1944
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1945
|
+
{
|
|
1946
|
+
_HookFired = true;
|
|
1947
|
+
Expect(pRequestState.Query).to.exist;
|
|
1948
|
+
return fCallback();
|
|
1949
|
+
});
|
|
1950
|
+
|
|
1951
|
+
_SuperTest
|
|
1952
|
+
.get('1.0/Books/Count/By/Genre/Thriller')
|
|
1953
|
+
.end(
|
|
1954
|
+
() =>
|
|
1955
|
+
{
|
|
1956
|
+
Expect(_HookFired).to.equal(true);
|
|
1957
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['CountBy-QueryConfiguration'];
|
|
1958
|
+
fDone();
|
|
1959
|
+
}
|
|
1960
|
+
);
|
|
1961
|
+
}
|
|
1962
|
+
);
|
|
1963
|
+
test
|
|
1964
|
+
(
|
|
1965
|
+
'setBehavior: Undelete-PreOperation fires before undelete',
|
|
1966
|
+
function (fDone)
|
|
1967
|
+
{
|
|
1968
|
+
let _HookFired = false;
|
|
1969
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Undelete-PreOperation',
|
|
1970
|
+
(pRequest, pRequestState, fCallback) =>
|
|
1971
|
+
{
|
|
1972
|
+
_HookFired = true;
|
|
1973
|
+
return fCallback();
|
|
1974
|
+
});
|
|
1975
|
+
|
|
1976
|
+
// Create, delete, then undelete to hit the hook.
|
|
1977
|
+
_SuperTest
|
|
1978
|
+
.post('1.0/Book')
|
|
1979
|
+
.send({ Title: 'Undelete-Pre target' })
|
|
1980
|
+
.end(
|
|
1981
|
+
(pPostErr, pPostRes) =>
|
|
1982
|
+
{
|
|
1983
|
+
const tmpID = JSON.parse(pPostRes.text).IDBook;
|
|
1984
|
+
_SuperTest
|
|
1985
|
+
.delete(`1.0/Book/${tmpID}`)
|
|
1986
|
+
.end(
|
|
1987
|
+
() =>
|
|
1988
|
+
{
|
|
1989
|
+
_SuperTest
|
|
1990
|
+
.get(`1.0/Book/Undelete/${tmpID}`)
|
|
1991
|
+
.end(
|
|
1992
|
+
() =>
|
|
1993
|
+
{
|
|
1994
|
+
Expect(_HookFired).to.equal(true);
|
|
1995
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Undelete-PreOperation'];
|
|
1996
|
+
fDone();
|
|
1997
|
+
}
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
);
|
|
2001
|
+
}
|
|
2002
|
+
);
|
|
2003
|
+
}
|
|
2004
|
+
);
|
|
2005
|
+
test
|
|
2006
|
+
(
|
|
2007
|
+
'setBehavior: Undelete-PostOperation fires after undelete',
|
|
2008
|
+
function (fDone)
|
|
2009
|
+
{
|
|
2010
|
+
let _HookFired = false;
|
|
2011
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Undelete-PostOperation',
|
|
2012
|
+
(pRequest, pRequestState, fCallback) =>
|
|
2013
|
+
{
|
|
2014
|
+
_HookFired = true;
|
|
2015
|
+
return fCallback();
|
|
2016
|
+
});
|
|
2017
|
+
|
|
2018
|
+
_SuperTest
|
|
2019
|
+
.post('1.0/Book')
|
|
2020
|
+
.send({ Title: 'Undelete-Post target' })
|
|
2021
|
+
.end(
|
|
2022
|
+
(pPostErr, pPostRes) =>
|
|
2023
|
+
{
|
|
2024
|
+
const tmpID = JSON.parse(pPostRes.text).IDBook;
|
|
2025
|
+
_SuperTest
|
|
2026
|
+
.delete(`1.0/Book/${tmpID}`)
|
|
2027
|
+
.end(
|
|
2028
|
+
() =>
|
|
2029
|
+
{
|
|
2030
|
+
_SuperTest
|
|
2031
|
+
.get(`1.0/Book/Undelete/${tmpID}`)
|
|
2032
|
+
.end(
|
|
2033
|
+
() =>
|
|
2034
|
+
{
|
|
2035
|
+
Expect(_HookFired).to.equal(true);
|
|
2036
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Undelete-PostOperation'];
|
|
2037
|
+
fDone();
|
|
2038
|
+
}
|
|
2039
|
+
);
|
|
2040
|
+
}
|
|
2041
|
+
);
|
|
2042
|
+
}
|
|
2043
|
+
);
|
|
2044
|
+
}
|
|
2045
|
+
);
|
|
2046
|
+
test
|
|
2047
|
+
(
|
|
2048
|
+
'setBehavior: Schema-PreOperation fires before schema render',
|
|
2049
|
+
function (fDone)
|
|
2050
|
+
{
|
|
2051
|
+
let _HookFired = false;
|
|
2052
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Schema-PreOperation',
|
|
2053
|
+
(pRequest, pRequestState, fCallback) =>
|
|
2054
|
+
{
|
|
2055
|
+
_HookFired = true;
|
|
2056
|
+
return fCallback();
|
|
2057
|
+
});
|
|
2058
|
+
|
|
2059
|
+
_SuperTest
|
|
2060
|
+
.get('1.0/Book/Schema')
|
|
2061
|
+
.end(
|
|
2062
|
+
() =>
|
|
2063
|
+
{
|
|
2064
|
+
Expect(_HookFired).to.equal(true);
|
|
2065
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Schema-PreOperation'];
|
|
2066
|
+
fDone();
|
|
2067
|
+
}
|
|
2068
|
+
);
|
|
2069
|
+
}
|
|
2070
|
+
);
|
|
2071
|
+
test
|
|
2072
|
+
(
|
|
2073
|
+
'setBehavior: Validate-PreOperation fires before validate',
|
|
2074
|
+
function (fDone)
|
|
2075
|
+
{
|
|
2076
|
+
let _HookFired = false;
|
|
2077
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Validate-PreOperation',
|
|
2078
|
+
(pRequest, pRequestState, fCallback) =>
|
|
2079
|
+
{
|
|
2080
|
+
_HookFired = true;
|
|
2081
|
+
return fCallback();
|
|
2082
|
+
});
|
|
2083
|
+
|
|
2084
|
+
_SuperTest
|
|
2085
|
+
.post('1.0/Book/Schema/Validate')
|
|
2086
|
+
.send({ Title: 'Validate target' })
|
|
2087
|
+
.end(
|
|
2088
|
+
() =>
|
|
2089
|
+
{
|
|
2090
|
+
Expect(_HookFired).to.equal(true);
|
|
2091
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Validate-PreOperation'];
|
|
2092
|
+
fDone();
|
|
2093
|
+
}
|
|
2094
|
+
);
|
|
2095
|
+
}
|
|
2096
|
+
);
|
|
2097
|
+
test
|
|
2098
|
+
(
|
|
2099
|
+
'setBehavior: Validate-PostOperation fires after validate',
|
|
2100
|
+
function (fDone)
|
|
2101
|
+
{
|
|
2102
|
+
let _HookFired = false;
|
|
2103
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('Validate-PostOperation',
|
|
2104
|
+
(pRequest, pRequestState, fCallback) =>
|
|
2105
|
+
{
|
|
2106
|
+
_HookFired = true;
|
|
2107
|
+
return fCallback();
|
|
2108
|
+
});
|
|
2109
|
+
|
|
2110
|
+
_SuperTest
|
|
2111
|
+
.post('1.0/Book/Schema/Validate')
|
|
2112
|
+
.send({ Title: 'Validate target 2' })
|
|
2113
|
+
.end(
|
|
2114
|
+
() =>
|
|
2115
|
+
{
|
|
2116
|
+
Expect(_HookFired).to.equal(true);
|
|
2117
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['Validate-PostOperation'];
|
|
2118
|
+
fDone();
|
|
2119
|
+
}
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
2122
|
+
);
|
|
2123
|
+
test
|
|
2124
|
+
(
|
|
2125
|
+
'setBehavior: New-PreOperation fires before empty record render',
|
|
2126
|
+
function (fDone)
|
|
2127
|
+
{
|
|
2128
|
+
let _HookFired = false;
|
|
2129
|
+
_MeadowEndpoints.controller.BehaviorInjection.setBehavior('New-PreOperation',
|
|
2130
|
+
(pRequest, pRequestState, fCallback) =>
|
|
2131
|
+
{
|
|
2132
|
+
_HookFired = true;
|
|
2133
|
+
return fCallback();
|
|
2134
|
+
});
|
|
2135
|
+
|
|
2136
|
+
_SuperTest
|
|
2137
|
+
.get('1.0/Book/Schema/New')
|
|
2138
|
+
.end(
|
|
2139
|
+
() =>
|
|
2140
|
+
{
|
|
2141
|
+
Expect(_HookFired).to.equal(true);
|
|
2142
|
+
delete _MeadowEndpoints.controller.BehaviorInjection._BehaviorFunctions['New-PreOperation'];
|
|
2143
|
+
fDone();
|
|
2144
|
+
}
|
|
2145
|
+
);
|
|
2146
|
+
}
|
|
2147
|
+
);
|
|
1372
2148
|
}
|
|
1373
2149
|
);
|
|
1374
2150
|
|