@itentialopensource/adapter-metaswitch 1.0.3 → 1.2.1

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.
@@ -1474,6 +1474,415 @@ describe('[unit] Metaswitch Adapter Test', () => {
1474
1474
  -----------------------------------------------------------------------
1475
1475
  */
1476
1476
 
1477
+ describe('#SOAP Wrapper Utility Methods', () => {
1478
+ describe('#wrapBodyInSoapEnvelope', () => {
1479
+ it('should have a wrapBodyInSoapEnvelope function', (done) => {
1480
+ try {
1481
+ assert.equal(true, typeof a.wrapBodyInSoapEnvelope === 'function');
1482
+ done();
1483
+ } catch (error) {
1484
+ log.error(`Test Failure: ${error}`);
1485
+ done(error);
1486
+ }
1487
+ }).timeout(attemptTimeout);
1488
+
1489
+ it('should wrap XML payload with SOAP envelope and inject OriginHost', (done) => {
1490
+ try {
1491
+ const xmlPayload = '<sh:ShPull><UserIdentity>12345</UserIdentity></sh:ShPull>';
1492
+ const result = a.wrapBodyInSoapEnvelope(xmlPayload, 'EAS');
1493
+
1494
+ assert.equal(result.error, undefined);
1495
+ assert.notEqual(result.payload, undefined);
1496
+ assert.equal(result.payload.includes('<soapenv:Envelope'), true);
1497
+ assert.equal(result.payload.includes('<soapenv:Header/>'), true);
1498
+ assert.equal(result.payload.includes('<soapenv:Body>'), true);
1499
+ assert.equal(result.payload.includes('<OriginHost>'), true);
1500
+ assert.equal(result.payload.includes('adminName='), true);
1501
+ assert.equal(result.payload.includes('password='), true);
1502
+ assert.equal(result.payload.includes('clientVersion='), true);
1503
+ done();
1504
+ } catch (error) {
1505
+ log.error(`Test Failure: ${error}`);
1506
+ done(error);
1507
+ }
1508
+ }).timeout(attemptTimeout);
1509
+
1510
+ it('should return error for empty body', (done) => {
1511
+ try {
1512
+ const result = a.wrapBodyInSoapEnvelope('', 'EAS');
1513
+
1514
+ assert.notEqual(result.error, undefined);
1515
+ assert.equal(result.error.message, 'Empty payload body provided');
1516
+ assert.equal(result.payload, undefined);
1517
+ done();
1518
+ } catch (error) {
1519
+ log.error(`Test Failure: ${error}`);
1520
+ done(error);
1521
+ }
1522
+ }).timeout(attemptTimeout);
1523
+
1524
+ it('should return error for null body', (done) => {
1525
+ try {
1526
+ const result = a.wrapBodyInSoapEnvelope(null, 'EAS');
1527
+
1528
+ assert.notEqual(result.error, undefined);
1529
+ assert.equal(result.error.message, 'Empty payload body provided');
1530
+ done();
1531
+ } catch (error) {
1532
+ log.error(`Test Failure: ${error}`);
1533
+ done(error);
1534
+ }
1535
+ }).timeout(attemptTimeout);
1536
+
1537
+ it('should detect existing SOAP envelope with soapenv prefix', (done) => {
1538
+ try {
1539
+ const soapPayload = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><TestRequest/></soapenv:Body></soapenv:Envelope>';
1540
+ const result = a.wrapBodyInSoapEnvelope(soapPayload, 'EAS');
1541
+
1542
+ assert.equal(result.error, undefined);
1543
+ assert.equal(result.payload, soapPayload);
1544
+ assert.equal(result.alreadyWrapped, true);
1545
+ done();
1546
+ } catch (error) {
1547
+ log.error(`Test Failure: ${error}`);
1548
+ done(error);
1549
+ }
1550
+ }).timeout(attemptTimeout);
1551
+
1552
+ it('should detect existing SOAP envelope with soap prefix', (done) => {
1553
+ try {
1554
+ const soapPayload = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><TestRequest/></soap:Body></soap:Envelope>';
1555
+ const result = a.wrapBodyInSoapEnvelope(soapPayload, 'EAS');
1556
+
1557
+ assert.equal(result.error, undefined);
1558
+ assert.equal(result.payload, soapPayload);
1559
+ assert.equal(result.alreadyWrapped, true);
1560
+ done();
1561
+ } catch (error) {
1562
+ log.error(`Test Failure: ${error}`);
1563
+ done(error);
1564
+ }
1565
+ }).timeout(attemptTimeout);
1566
+
1567
+ it('should detect existing SOAP envelope with SOAP-ENV prefix', (done) => {
1568
+ try {
1569
+ const soapPayload = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><TestRequest/></SOAP-ENV:Body></SOAP-ENV:Envelope>';
1570
+ const result = a.wrapBodyInSoapEnvelope(soapPayload, 'EAS');
1571
+
1572
+ assert.equal(result.error, undefined);
1573
+ assert.equal(result.payload, soapPayload);
1574
+ assert.equal(result.alreadyWrapped, true);
1575
+ done();
1576
+ } catch (error) {
1577
+ log.error(`Test Failure: ${error}`);
1578
+ done(error);
1579
+ }
1580
+ }).timeout(attemptTimeout);
1581
+
1582
+ it('should use correct namespaces for different API types', (done) => {
1583
+ try {
1584
+ const xmlPayload = '<sh:ShPull><UserIdentity>test</UserIdentity></sh:ShPull>';
1585
+
1586
+ const easResult = a.wrapBodyInSoapEnvelope(xmlPayload, 'EAS');
1587
+ assert.equal(easResult.payload.includes('xmlns:sh="http://www.metaswitch.com/sdp/soap/sh"'), true);
1588
+
1589
+ const nseriesResult = a.wrapBodyInSoapEnvelope(xmlPayload, 'NSeries');
1590
+ assert.equal(nseriesResult.payload.includes('xmlns:sh="http://www.metaswitch.com/nsrs/soap/sh"'), true);
1591
+
1592
+ const metaviewResult = a.wrapBodyInSoapEnvelope(xmlPayload, 'Metaview');
1593
+ assert.equal(metaviewResult.payload.includes('xmlns:sh="http://www.metaswitch.com/ems/soap/sh"'), true);
1594
+
1595
+ const nwsapResult = a.wrapBodyInSoapEnvelope(xmlPayload, 'NWSAP');
1596
+ assert.equal(nwsapResult.payload.includes('xmlns:sh="http://www.metaswitch.com/srb/soap/sh"'), true);
1597
+
1598
+ done();
1599
+ } catch (error) {
1600
+ log.error(`Test Failure: ${error}`);
1601
+ done(error);
1602
+ }
1603
+ }).timeout(attemptTimeout);
1604
+
1605
+ it('should NOT include WS-Security headers (Metaswitch uses OriginHost)', (done) => {
1606
+ try {
1607
+ const xmlPayload = '<sh:ShPull><UserIdentity>test</UserIdentity></sh:ShPull>';
1608
+ const result = a.wrapBodyInSoapEnvelope(xmlPayload, 'EAS');
1609
+
1610
+ // Should have empty header, not WS-Security
1611
+ assert.equal(result.payload.includes('<soapenv:Header/>'), true);
1612
+ assert.equal(result.payload.includes('<wsse:Security'), false);
1613
+ assert.equal(result.payload.includes('<wsse:UsernameToken>'), false);
1614
+
1615
+ // Should have OriginHost with credentials instead
1616
+ assert.equal(result.payload.includes('<OriginHost>'), true);
1617
+ done();
1618
+ } catch (error) {
1619
+ log.error(`Test Failure: ${error}`);
1620
+ done(error);
1621
+ }
1622
+ }).timeout(attemptTimeout);
1623
+ });
1624
+
1625
+ describe('#getSoapNamespaces', () => {
1626
+ it('should have a getSoapNamespaces function', (done) => {
1627
+ try {
1628
+ assert.equal(true, typeof a.getSoapNamespaces === 'function');
1629
+ done();
1630
+ } catch (error) {
1631
+ log.error(`Test Failure: ${error}`);
1632
+ done(error);
1633
+ }
1634
+ }).timeout(attemptTimeout);
1635
+
1636
+ it('should return namespaces for EAS API', (done) => {
1637
+ try {
1638
+ const namespaces = a.getSoapNamespaces('EAS');
1639
+
1640
+ assert.equal(namespaces.includes('xmlns:soapenv='), true);
1641
+ assert.equal(namespaces.includes('xmlns:sh='), true);
1642
+ assert.equal(namespaces.includes('http://www.metaswitch.com/sdp/soap/sh'), true);
1643
+ // Should NOT include WS-Security namespaces (Metaswitch uses OriginHost)
1644
+ assert.equal(namespaces.includes('xmlns:wsse='), false);
1645
+ assert.equal(namespaces.includes('xmlns:wsu='), false);
1646
+ done();
1647
+ } catch (error) {
1648
+ log.error(`Test Failure: ${error}`);
1649
+ done(error);
1650
+ }
1651
+ }).timeout(attemptTimeout);
1652
+
1653
+ it('should return namespaces for all API types', (done) => {
1654
+ try {
1655
+ const apiTypes = ['EAS', 'NSeries', 'Metaview', 'NWSAP'];
1656
+
1657
+ apiTypes.forEach((apiType) => {
1658
+ const namespaces = a.getSoapNamespaces(apiType);
1659
+ assert.notEqual(namespaces, undefined);
1660
+ assert.equal(namespaces.length > 0, true);
1661
+ });
1662
+
1663
+ done();
1664
+ } catch (error) {
1665
+ log.error(`Test Failure: ${error}`);
1666
+ done(error);
1667
+ }
1668
+ }).timeout(attemptTimeout);
1669
+
1670
+ it('should return default namespaces for unknown API type', (done) => {
1671
+ try {
1672
+ const namespaces = a.getSoapNamespaces('UnknownAPI');
1673
+
1674
+ assert.equal(namespaces.includes('xmlns:soapenv='), true);
1675
+ assert.equal(namespaces.includes('xmlns:sh='), true);
1676
+ done();
1677
+ } catch (error) {
1678
+ log.error(`Test Failure: ${error}`);
1679
+ done(error);
1680
+ }
1681
+ }).timeout(attemptTimeout);
1682
+ });
1683
+
1684
+ describe('#buildOriginHost', () => {
1685
+ it('should have a buildOriginHost function', (done) => {
1686
+ try {
1687
+ assert.equal(true, typeof a.buildOriginHost === 'function');
1688
+ done();
1689
+ } catch (error) {
1690
+ log.error(`Test Failure: ${error}`);
1691
+ done(error);
1692
+ }
1693
+ }).timeout(attemptTimeout);
1694
+
1695
+ it('should create OriginHost with credentials from adapter properties', (done) => {
1696
+ try {
1697
+ const result = a.buildOriginHost();
1698
+
1699
+ assert.equal(result.error, undefined);
1700
+ assert.notEqual(result.originHost, undefined);
1701
+ assert.equal(result.originHost.includes('<OriginHost>'), true);
1702
+ assert.equal(result.originHost.includes('</OriginHost>'), true);
1703
+ assert.equal(result.originHost.includes('adminName='), true);
1704
+ assert.equal(result.originHost.includes('password='), true);
1705
+ assert.equal(result.originHost.includes('clientVersion='), true);
1706
+ assert.equal(result.originHost.includes('ignoreSequenceNumber=true'), true);
1707
+ done();
1708
+ } catch (error) {
1709
+ log.error(`Test Failure: ${error}`);
1710
+ done(error);
1711
+ }
1712
+ }).timeout(attemptTimeout);
1713
+
1714
+ it('should URL-encode credentials with special characters', (done) => {
1715
+ try {
1716
+ const result = a.buildOriginHost();
1717
+
1718
+ // If password contains &, it should be URL-encoded as %26
1719
+ // This test validates URL encoding is applied
1720
+ assert.equal(result.error, undefined);
1721
+ assert.notEqual(result.originHost, undefined);
1722
+ // The OriginHost value should be XML-escaped (& becomes &amp;)
1723
+ assert.equal(result.originHost.includes('&amp;adminName='), true);
1724
+ done();
1725
+ } catch (error) {
1726
+ log.error(`Test Failure: ${error}`);
1727
+ done(error);
1728
+ }
1729
+ }).timeout(attemptTimeout);
1730
+ });
1731
+
1732
+ describe('#injectOriginHost', () => {
1733
+ it('should have an injectOriginHost function', (done) => {
1734
+ try {
1735
+ assert.equal(true, typeof a.injectOriginHost === 'function');
1736
+ done();
1737
+ } catch (error) {
1738
+ log.error(`Test Failure: ${error}`);
1739
+ done(error);
1740
+ }
1741
+ }).timeout(attemptTimeout);
1742
+
1743
+ it('should inject OriginHost before closing ShPull tag', (done) => {
1744
+ try {
1745
+ const body = '<sh:ShPull><UserIdentity>12345</UserIdentity></sh:ShPull>';
1746
+ const originHost = '<OriginHost>server@domain?adminName=test&amp;password=test</OriginHost>';
1747
+ const result = a.injectOriginHost(body, originHost);
1748
+
1749
+ assert.equal(result.includes(originHost), true);
1750
+ assert.equal(result.indexOf(originHost) < result.indexOf('</sh:ShPull>'), true);
1751
+ done();
1752
+ } catch (error) {
1753
+ log.error(`Test Failure: ${error}`);
1754
+ done(error);
1755
+ }
1756
+ }).timeout(attemptTimeout);
1757
+
1758
+ it('should inject OriginHost before closing ShUpdate tag', (done) => {
1759
+ try {
1760
+ const body = '<sh:ShUpdate><UserIdentity>12345</UserIdentity></sh:ShUpdate>';
1761
+ const originHost = '<OriginHost>server@domain?adminName=test&amp;password=test</OriginHost>';
1762
+ const result = a.injectOriginHost(body, originHost);
1763
+
1764
+ assert.equal(result.includes(originHost), true);
1765
+ assert.equal(result.indexOf(originHost) < result.indexOf('</sh:ShUpdate>'), true);
1766
+ done();
1767
+ } catch (error) {
1768
+ log.error(`Test Failure: ${error}`);
1769
+ done(error);
1770
+ }
1771
+ }).timeout(attemptTimeout);
1772
+ });
1773
+
1774
+ describe('#escapeXml', () => {
1775
+ it('should have an escapeXml function', (done) => {
1776
+ try {
1777
+ assert.equal(true, typeof a.escapeXml === 'function');
1778
+ done();
1779
+ } catch (error) {
1780
+ log.error(`Test Failure: ${error}`);
1781
+ done(error);
1782
+ }
1783
+ }).timeout(attemptTimeout);
1784
+
1785
+ it('should escape ampersand', (done) => {
1786
+ try {
1787
+ const result = a.escapeXml('test & value');
1788
+ assert.equal(result, 'test &amp; value');
1789
+ done();
1790
+ } catch (error) {
1791
+ log.error(`Test Failure: ${error}`);
1792
+ done(error);
1793
+ }
1794
+ }).timeout(attemptTimeout);
1795
+
1796
+ it('should escape less than', (done) => {
1797
+ try {
1798
+ const result = a.escapeXml('test < value');
1799
+ assert.equal(result, 'test &lt; value');
1800
+ done();
1801
+ } catch (error) {
1802
+ log.error(`Test Failure: ${error}`);
1803
+ done(error);
1804
+ }
1805
+ }).timeout(attemptTimeout);
1806
+
1807
+ it('should escape greater than', (done) => {
1808
+ try {
1809
+ const result = a.escapeXml('test > value');
1810
+ assert.equal(result, 'test &gt; value');
1811
+ done();
1812
+ } catch (error) {
1813
+ log.error(`Test Failure: ${error}`);
1814
+ done(error);
1815
+ }
1816
+ }).timeout(attemptTimeout);
1817
+
1818
+ it('should escape double quote', (done) => {
1819
+ try {
1820
+ const result = a.escapeXml('test "value"');
1821
+ assert.equal(result, 'test &quot;value&quot;');
1822
+ done();
1823
+ } catch (error) {
1824
+ log.error(`Test Failure: ${error}`);
1825
+ done(error);
1826
+ }
1827
+ }).timeout(attemptTimeout);
1828
+
1829
+ it('should escape single quote', (done) => {
1830
+ try {
1831
+ const result = a.escapeXml("test 'value'");
1832
+ assert.equal(result, 'test &apos;value&apos;');
1833
+ done();
1834
+ } catch (error) {
1835
+ log.error(`Test Failure: ${error}`);
1836
+ done(error);
1837
+ }
1838
+ }).timeout(attemptTimeout);
1839
+
1840
+ it('should escape all special characters together', (done) => {
1841
+ try {
1842
+ const result = a.escapeXml('<tag attr="value" other=\'test\'>content & more</tag>');
1843
+ assert.equal(result, '&lt;tag attr=&quot;value&quot; other=&apos;test&apos;&gt;content &amp; more&lt;/tag&gt;');
1844
+ done();
1845
+ } catch (error) {
1846
+ log.error(`Test Failure: ${error}`);
1847
+ done(error);
1848
+ }
1849
+ }).timeout(attemptTimeout);
1850
+
1851
+ it('should return empty string for null input', (done) => {
1852
+ try {
1853
+ const result = a.escapeXml(null);
1854
+ assert.equal(result, '');
1855
+ done();
1856
+ } catch (error) {
1857
+ log.error(`Test Failure: ${error}`);
1858
+ done(error);
1859
+ }
1860
+ }).timeout(attemptTimeout);
1861
+
1862
+ it('should return empty string for undefined input', (done) => {
1863
+ try {
1864
+ const result = a.escapeXml(undefined);
1865
+ assert.equal(result, '');
1866
+ done();
1867
+ } catch (error) {
1868
+ log.error(`Test Failure: ${error}`);
1869
+ done(error);
1870
+ }
1871
+ }).timeout(attemptTimeout);
1872
+
1873
+ it('should not modify strings without special characters', (done) => {
1874
+ try {
1875
+ const result = a.escapeXml('normaltext123');
1876
+ assert.equal(result, 'normaltext123');
1877
+ done();
1878
+ } catch (error) {
1879
+ log.error(`Test Failure: ${error}`);
1880
+ done(error);
1881
+ }
1882
+ }).timeout(attemptTimeout);
1883
+ });
1884
+ });
1885
+
1477
1886
  describe('#postMetaSphereEAS - errors', () => {
1478
1887
  it('should have a postMetaSphereEAS function', (done) => {
1479
1888
  try {