@webex/plugin-meetings 3.6.0-next.9 → 3.7.0-ipv6-multi-turn-urls.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.
Files changed (159) hide show
  1. package/README.md +2 -1
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/common/errors/{webinar-registration-error.js → join-webinar-error.js} +12 -12
  5. package/dist/common/errors/join-webinar-error.js.map +1 -0
  6. package/dist/config.js +3 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/constants.js +50 -7
  9. package/dist/constants.js.map +1 -1
  10. package/dist/controls-options-manager/enums.js +1 -0
  11. package/dist/controls-options-manager/enums.js.map +1 -1
  12. package/dist/controls-options-manager/index.js +10 -3
  13. package/dist/controls-options-manager/index.js.map +1 -1
  14. package/dist/controls-options-manager/types.js.map +1 -1
  15. package/dist/controls-options-manager/util.js +12 -0
  16. package/dist/controls-options-manager/util.js.map +1 -1
  17. package/dist/index.js +7 -7
  18. package/dist/index.js.map +1 -1
  19. package/dist/interpretation/index.js +1 -1
  20. package/dist/interpretation/siLanguage.js +1 -1
  21. package/dist/locus-info/controlsUtils.js +28 -4
  22. package/dist/locus-info/controlsUtils.js.map +1 -1
  23. package/dist/locus-info/fullState.js +2 -1
  24. package/dist/locus-info/fullState.js.map +1 -1
  25. package/dist/locus-info/index.js +61 -3
  26. package/dist/locus-info/index.js.map +1 -1
  27. package/dist/media/index.js +29 -1
  28. package/dist/media/index.js.map +1 -1
  29. package/dist/meeting/in-meeting-actions.js +29 -1
  30. package/dist/meeting/in-meeting-actions.js.map +1 -1
  31. package/dist/meeting/index.js +692 -472
  32. package/dist/meeting/index.js.map +1 -1
  33. package/dist/meeting/locusMediaRequest.js +2 -6
  34. package/dist/meeting/locusMediaRequest.js.map +1 -1
  35. package/dist/meeting/request.js +21 -29
  36. package/dist/meeting/request.js.map +1 -1
  37. package/dist/meeting/util.js +95 -59
  38. package/dist/meeting/util.js.map +1 -1
  39. package/dist/meeting-info/meeting-info-v2.js +29 -17
  40. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  41. package/dist/meetings/index.js +8 -3
  42. package/dist/meetings/index.js.map +1 -1
  43. package/dist/members/index.js +3 -2
  44. package/dist/members/index.js.map +1 -1
  45. package/dist/members/util.js +13 -7
  46. package/dist/members/util.js.map +1 -1
  47. package/dist/metrics/constants.js +3 -1
  48. package/dist/metrics/constants.js.map +1 -1
  49. package/dist/multistream/remoteMedia.js +30 -15
  50. package/dist/multistream/remoteMedia.js.map +1 -1
  51. package/dist/reachability/clusterReachability.js +12 -15
  52. package/dist/reachability/clusterReachability.js.map +1 -1
  53. package/dist/reachability/index.js +433 -136
  54. package/dist/reachability/index.js.map +1 -1
  55. package/dist/reachability/reachability.types.js +7 -0
  56. package/dist/reachability/reachability.types.js.map +1 -0
  57. package/dist/reachability/request.js +23 -9
  58. package/dist/reachability/request.js.map +1 -1
  59. package/dist/recording-controller/enums.js +8 -4
  60. package/dist/recording-controller/enums.js.map +1 -1
  61. package/dist/recording-controller/index.js +18 -9
  62. package/dist/recording-controller/index.js.map +1 -1
  63. package/dist/recording-controller/util.js +13 -9
  64. package/dist/recording-controller/util.js.map +1 -1
  65. package/dist/roap/index.js +5 -7
  66. package/dist/roap/index.js.map +1 -1
  67. package/dist/roap/request.js +45 -79
  68. package/dist/roap/request.js.map +1 -1
  69. package/dist/roap/turnDiscovery.js +3 -6
  70. package/dist/roap/turnDiscovery.js.map +1 -1
  71. package/dist/types/common/errors/{webinar-registration-error.d.ts → join-webinar-error.d.ts} +2 -2
  72. package/dist/types/config.d.ts +2 -0
  73. package/dist/types/constants.d.ts +38 -1
  74. package/dist/types/controls-options-manager/enums.d.ts +2 -1
  75. package/dist/types/controls-options-manager/index.d.ts +2 -1
  76. package/dist/types/controls-options-manager/types.d.ts +2 -0
  77. package/dist/types/index.d.ts +2 -2
  78. package/dist/types/locus-info/index.d.ts +9 -0
  79. package/dist/types/meeting/in-meeting-actions.d.ts +28 -0
  80. package/dist/types/meeting/index.d.ts +34 -3
  81. package/dist/types/meeting/locusMediaRequest.d.ts +2 -3
  82. package/dist/types/meeting/request.d.ts +2 -2
  83. package/dist/types/meeting/util.d.ts +2 -2
  84. package/dist/types/meeting-info/meeting-info-v2.d.ts +4 -4
  85. package/dist/types/meetings/index.d.ts +4 -1
  86. package/dist/types/members/index.d.ts +2 -1
  87. package/dist/types/members/util.d.ts +5 -1
  88. package/dist/types/metrics/constants.d.ts +3 -1
  89. package/dist/types/reachability/clusterReachability.d.ts +1 -10
  90. package/dist/types/reachability/index.d.ts +74 -35
  91. package/dist/types/reachability/reachability.types.d.ts +64 -0
  92. package/dist/types/reachability/request.d.ts +5 -1
  93. package/dist/types/recording-controller/enums.d.ts +5 -2
  94. package/dist/types/recording-controller/index.d.ts +1 -0
  95. package/dist/types/recording-controller/util.d.ts +2 -1
  96. package/dist/types/roap/request.d.ts +1 -13
  97. package/dist/webinar/index.js +382 -19
  98. package/dist/webinar/index.js.map +1 -1
  99. package/package.json +22 -22
  100. package/src/common/errors/join-webinar-error.ts +24 -0
  101. package/src/config.ts +2 -0
  102. package/src/constants.ts +49 -3
  103. package/src/controls-options-manager/enums.ts +1 -0
  104. package/src/controls-options-manager/index.ts +19 -2
  105. package/src/controls-options-manager/types.ts +2 -0
  106. package/src/controls-options-manager/util.ts +12 -0
  107. package/src/index.ts +2 -2
  108. package/src/locus-info/controlsUtils.ts +46 -2
  109. package/src/locus-info/fullState.ts +1 -0
  110. package/src/locus-info/index.ts +60 -0
  111. package/src/media/index.ts +15 -0
  112. package/src/meeting/in-meeting-actions.ts +58 -0
  113. package/src/meeting/index.ts +232 -25
  114. package/src/meeting/locusMediaRequest.ts +4 -8
  115. package/src/meeting/request.ts +4 -11
  116. package/src/meeting/util.ts +25 -4
  117. package/src/meeting-info/meeting-info-v2.ts +23 -11
  118. package/src/meetings/index.ts +54 -41
  119. package/src/members/index.ts +4 -2
  120. package/src/members/util.ts +4 -1
  121. package/src/metrics/constants.ts +3 -1
  122. package/src/multistream/remoteMedia.ts +28 -15
  123. package/src/reachability/clusterReachability.ts +5 -15
  124. package/src/reachability/index.ts +285 -77
  125. package/src/reachability/reachability.types.ts +85 -0
  126. package/src/reachability/request.ts +55 -30
  127. package/src/recording-controller/enums.ts +5 -2
  128. package/src/recording-controller/index.ts +17 -4
  129. package/src/recording-controller/util.ts +20 -5
  130. package/src/roap/index.ts +4 -5
  131. package/src/roap/request.ts +30 -44
  132. package/src/roap/turnDiscovery.ts +2 -4
  133. package/src/webinar/index.ts +223 -17
  134. package/test/unit/spec/controls-options-manager/index.js +56 -32
  135. package/test/unit/spec/controls-options-manager/util.js +44 -0
  136. package/test/unit/spec/locus-info/controlsUtils.js +80 -4
  137. package/test/unit/spec/locus-info/index.js +59 -2
  138. package/test/unit/spec/meeting/in-meeting-actions.ts +31 -1
  139. package/test/unit/spec/meeting/index.js +369 -103
  140. package/test/unit/spec/meeting/locusMediaRequest.ts +18 -11
  141. package/test/unit/spec/meeting/request.js +3 -26
  142. package/test/unit/spec/meeting/utils.js +55 -13
  143. package/test/unit/spec/meeting-info/meetinginfov2.js +9 -4
  144. package/test/unit/spec/meetings/index.js +25 -6
  145. package/test/unit/spec/members/index.js +25 -2
  146. package/test/unit/spec/members/request.js +37 -3
  147. package/test/unit/spec/members/utils.js +110 -1
  148. package/test/unit/spec/multistream/remoteMedia.ts +11 -7
  149. package/test/unit/spec/reachability/clusterReachability.ts +7 -0
  150. package/test/unit/spec/reachability/index.ts +265 -1
  151. package/test/unit/spec/reachability/request.js +56 -15
  152. package/test/unit/spec/recording-controller/index.js +61 -5
  153. package/test/unit/spec/recording-controller/util.js +39 -3
  154. package/test/unit/spec/roap/index.ts +1 -1
  155. package/test/unit/spec/roap/request.ts +51 -109
  156. package/test/unit/spec/roap/turnDiscovery.ts +202 -147
  157. package/test/unit/spec/webinar/index.ts +443 -14
  158. package/dist/common/errors/webinar-registration-error.js.map +0 -1
  159. package/src/common/errors/webinar-registration-error.ts +0 -27
@@ -1234,7 +1234,7 @@ describe('gatherReachability', () => {
1234
1234
  assert.equal(receivedEvents['done'], 1);
1235
1235
 
1236
1236
  // and that ip network detection was started
1237
- assert.calledOnceWithExactly(webex.internal.device.ipNetworkDetector.detect);
1237
+ assert.calledOnceWithExactly(webex.internal.device.ipNetworkDetector.detect, true);
1238
1238
 
1239
1239
  // finally, check the metrics - they should contain values from ipNetworkDetector
1240
1240
  assert.calledWith(Metrics.sendBehavioralMetric, 'js_sdk_reachability_completed', {
@@ -1664,6 +1664,270 @@ describe('gatherReachability', () => {
1664
1664
 
1665
1665
  assert.neverCalledWith(clusterReachabilityCtorStub);
1666
1666
  });
1667
+
1668
+ describe('fallback mechanism and multiple calls to getClusters', () => {
1669
+ let receivedEvents;
1670
+
1671
+ const mockGetClustersEmptyResult = {
1672
+ discoveryOptions: {
1673
+ ['early-call-min-clusters']: 0,
1674
+ ['report-version']: 1,
1675
+ },
1676
+ clusters: {}, // empty cluster list
1677
+ joinCookie: {id: 'cookie'},
1678
+ };
1679
+
1680
+ beforeEach(() => {
1681
+ webex.config.meetings.experimental = {
1682
+ enableTcpReachability: true,
1683
+ enableTlsReachability: true,
1684
+ };
1685
+
1686
+ receivedEvents = {
1687
+ done: 0,
1688
+ };
1689
+ });
1690
+
1691
+ it('keeps retrying if minimum required clusters are not reached', async () => {
1692
+ const reachability = new Reachability(webex);
1693
+
1694
+ reachability.on('reachability:done', () => {
1695
+ receivedEvents.done += 1;
1696
+ });
1697
+
1698
+ const mockGetClustersResult1 = {
1699
+ discoveryOptions: {
1700
+ ['early-call-min-clusters']: 2,
1701
+ ['report-version']: 1,
1702
+ },
1703
+ clusters: {
1704
+ clusterA0: {
1705
+ udp: ['udp-urlA'],
1706
+ tcp: ['tcp-urlA'],
1707
+ xtls: ['xtls-urlA'],
1708
+ isVideoMesh: false,
1709
+ },
1710
+ clusterB0: {
1711
+ udp: ['udp-urlB'],
1712
+ tcp: ['tcp-urlB'],
1713
+ xtls: ['xtls-urlB'],
1714
+ isVideoMesh: false,
1715
+ },
1716
+ },
1717
+ joinCookie: {id: 'cookie1'},
1718
+ };
1719
+ const mockGetClustersResult2 = {
1720
+ discoveryOptions: {
1721
+ ['early-call-min-clusters']: 2,
1722
+ ['report-version']: 1,
1723
+ },
1724
+ clusters: {
1725
+ clusterA1: {
1726
+ udp: ['udp-urlA'],
1727
+ tcp: ['tcp-urlA'],
1728
+ xtls: ['xtls-urlA'],
1729
+ isVideoMesh: false,
1730
+ },
1731
+ clusterB1: {
1732
+ udp: ['udp-urlB'],
1733
+ tcp: ['tcp-urlB'],
1734
+ xtls: ['xtls-urlB'],
1735
+ isVideoMesh: false,
1736
+ },
1737
+ },
1738
+ joinCookie: {id: 'cookie2'},
1739
+ };
1740
+ const mockGetClustersResult3 = {
1741
+ discoveryOptions: {
1742
+ ['early-call-min-clusters']: 1,
1743
+ ['report-version']: 1,
1744
+ },
1745
+ clusters: {
1746
+ clusterA2: {
1747
+ udp: ['udp-urlA'],
1748
+ tcp: ['tcp-urlA'],
1749
+ xtls: ['xtls-urlA'],
1750
+ isVideoMesh: false,
1751
+ },
1752
+ clusterB2: {
1753
+ udp: ['udp-urlB'],
1754
+ tcp: ['tcp-urlB'],
1755
+ xtls: ['xtls-urlB'],
1756
+ isVideoMesh: false,
1757
+ },
1758
+ },
1759
+ joinCookie: {id: 'cookie3'},
1760
+ };
1761
+
1762
+ reachability.reachabilityRequest.getClusters = sinon.stub();
1763
+ reachability.reachabilityRequest.getClusters.onCall(0).returns(mockGetClustersResult1);
1764
+ reachability.reachabilityRequest.getClusters.onCall(1).returns(mockGetClustersResult2);
1765
+
1766
+ reachability.reachabilityRequest.getClusters.onCall(2).returns(mockGetClustersResult3);
1767
+
1768
+ const resultPromise = reachability.gatherReachability('test');
1769
+
1770
+ await testUtils.flushPromises();
1771
+
1772
+ // trigger some mock result events from ClusterReachability instances,
1773
+ // but only from 1 cluster, so not enough to reach the minimum required
1774
+ mockClusterReachabilityInstances['clusterA0'].emitFakeResult('udp', {
1775
+ result: 'reachable',
1776
+ clientMediaIPs: ['1.2.3.4'],
1777
+ latencyInMilliseconds: 11,
1778
+ });
1779
+
1780
+ clock.tick(3000);
1781
+ await resultPromise;
1782
+ await testUtils.flushPromises();
1783
+
1784
+ // because the minimum was not reached, another call to getClusters should be made
1785
+ assert.calledTwice(reachability.reachabilityRequest.getClusters);
1786
+
1787
+ // simulate no results this time
1788
+
1789
+ // check that while the 2nd attempt is in progress, the join cookie is already available from the 2nd call to getClusters
1790
+ const clientMediaPreferences = await reachability.getClientMediaPreferences(
1791
+ true,
1792
+ IP_VERSION.unknown
1793
+ );
1794
+
1795
+ assert.deepEqual(clientMediaPreferences.joinCookie, mockGetClustersResult2.joinCookie);
1796
+
1797
+ clock.tick(3000);
1798
+ await testUtils.flushPromises();
1799
+
1800
+ assert.calledThrice(reachability.reachabilityRequest.getClusters);
1801
+
1802
+ await testUtils.flushPromises();
1803
+
1804
+ // this time 1 result will be enough to reach the minimum
1805
+ mockClusterReachabilityInstances['clusterA2'].emitFakeResult('udp', {
1806
+ result: 'reachable',
1807
+ clientMediaIPs: ['1.2.3.4'],
1808
+ latencyInMilliseconds: 11,
1809
+ });
1810
+ clock.tick(3000);
1811
+
1812
+ // the reachability results should include only results from the last attempt
1813
+ await checkResults(
1814
+ {
1815
+ clusterA2: {
1816
+ udp: {result: 'reachable', clientMediaIPs: ['1.2.3.4'], latencyInMilliseconds: 11},
1817
+ tcp: {result: 'unreachable'},
1818
+ xtls: {result: 'unreachable'},
1819
+ isVideoMesh: false,
1820
+ },
1821
+ clusterB2: {
1822
+ udp: {result: 'unreachable'},
1823
+ tcp: {result: 'unreachable'},
1824
+ xtls: {result: 'unreachable'},
1825
+ isVideoMesh: false,
1826
+ },
1827
+ },
1828
+ mockGetClustersResult3.joinCookie
1829
+ );
1830
+
1831
+ // wait some more time to make sure that there are no timers that fire from one of the previous checks
1832
+ clock.tick(20000);
1833
+
1834
+ // as the first 2 attempts failed and didn't reach the overall timeout, there should be only 1 done event emitted
1835
+ assert.equal(receivedEvents.done, 1);
1836
+ });
1837
+
1838
+ it('handles getClusters() returning empty list on 1st call', async () => {
1839
+ const reachability = new Reachability(webex);
1840
+
1841
+ reachability.on('reachability:done', () => {
1842
+ receivedEvents.done += 1;
1843
+ });
1844
+
1845
+ reachability.reachabilityRequest.getClusters = sinon
1846
+ .stub()
1847
+ .resolves(mockGetClustersEmptyResult);
1848
+
1849
+ const resultPromise = reachability.gatherReachability('test');
1850
+
1851
+ await testUtils.flushPromises();
1852
+
1853
+ clock.tick(3000);
1854
+ await resultPromise;
1855
+ await testUtils.flushPromises();
1856
+
1857
+ assert.calledOnce(reachability.reachabilityRequest.getClusters);
1858
+ reachability.reachabilityRequest.getClusters.resetHistory();
1859
+
1860
+ assert.equal(receivedEvents.done, 1);
1861
+ await checkResults({}, mockGetClustersEmptyResult.joinCookie);
1862
+
1863
+ // because we didn't actually test anything (we got empty cluster list from getClusters()), we should
1864
+ // not say that webex backend is unreachable
1865
+ assert.equal(await reachability.isWebexMediaBackendUnreachable(), false);
1866
+
1867
+ // wait to check that there are no other things happening
1868
+ clock.tick(20000);
1869
+ await testUtils.flushPromises();
1870
+
1871
+ assert.notCalled(reachability.reachabilityRequest.getClusters);
1872
+ assert.equal(receivedEvents.done, 1);
1873
+ });
1874
+
1875
+ it('handles getClusters() returning empty list on 2nd call', async () => {
1876
+ const reachability = new Reachability(webex);
1877
+
1878
+ reachability.on('reachability:done', () => {
1879
+ receivedEvents.done += 1;
1880
+ });
1881
+
1882
+ const mockGetClustersResult1 = {
1883
+ discoveryOptions: {
1884
+ ['early-call-min-clusters']: 2,
1885
+ ['report-version']: 1,
1886
+ },
1887
+ clusters: {
1888
+ clusterA0: {
1889
+ udp: ['udp-urlA'],
1890
+ tcp: ['tcp-urlA'],
1891
+ xtls: ['xtls-urlA'],
1892
+ isVideoMesh: false,
1893
+ },
1894
+ clusterB0: {
1895
+ udp: ['udp-urlB'],
1896
+ tcp: ['tcp-urlB'],
1897
+ xtls: ['xtls-urlB'],
1898
+ isVideoMesh: false,
1899
+ },
1900
+ },
1901
+ joinCookie: {id: 'cookie1'},
1902
+ };
1903
+
1904
+ reachability.reachabilityRequest.getClusters = sinon.stub();
1905
+ reachability.reachabilityRequest.getClusters.onCall(0).returns(mockGetClustersResult1);
1906
+ reachability.reachabilityRequest.getClusters.onCall(1).returns(mockGetClustersEmptyResult);
1907
+
1908
+ const resultPromise = reachability.gatherReachability('test');
1909
+
1910
+ await testUtils.flushPromises();
1911
+
1912
+ clock.tick(3000);
1913
+ await resultPromise;
1914
+ await testUtils.flushPromises();
1915
+
1916
+ // because the minimum was not reached, another call to getClusters should be made
1917
+ assert.calledTwice(reachability.reachabilityRequest.getClusters);
1918
+
1919
+ // the reachability results should include only results from the last attempt
1920
+ await checkResults({}, mockGetClustersEmptyResult.joinCookie);
1921
+
1922
+ // as the first 2 attempts failed and didn't reach the overall timeout, there should be only 1 done event emitted
1923
+ assert.equal(receivedEvents.done, 1);
1924
+ // because we didn't actually test anything (we got empty cluster list from getClusters()), we should
1925
+ // not say that webex backend is unreachable
1926
+ assert.equal(await reachability.isWebexMediaBackendUnreachable(), false);
1927
+ });
1928
+ });
1929
+
1930
+
1667
1931
  });
1668
1932
 
1669
1933
  describe('getReachabilityResults', () => {
@@ -35,16 +35,11 @@ describe('plugin-meetings/reachability', () => {
35
35
  });
36
36
 
37
37
  describe('#getClusters', () => {
38
+ let previousReport;
38
39
 
39
40
  beforeEach(() => {
40
41
  sinon.spy(webex.internal.newMetrics.callDiagnosticLatencies, 'measureLatency');
41
- });
42
42
 
43
- afterEach(() => {
44
- sinon.restore();
45
- });
46
-
47
- it('sends a GET request with the correct params', async () => {
48
43
  webex.request = sinon.mock().returns(Promise.resolve({
49
44
  body: {
50
45
  clusterClasses: {
@@ -57,21 +52,67 @@ describe('plugin-meetings/reachability', () => {
57
52
  }
58
53
  }));
59
54
 
60
- const res = await reachabilityRequest.getClusters(IP_VERSION.only_ipv4);
61
- const requestParams = webex.request.getCall(0).args[0];
55
+ webex.config.meetings.reachabilityGetClusterTimeout = 3000;
62
56
 
63
- assert.equal(requestParams.method, 'GET');
64
- assert.equal(requestParams.resource, `clusters`);
65
- assert.equal(requestParams.api, 'calliopeDiscovery');
66
- assert.equal(requestParams.shouldRefreshAccessToken, false);
57
+ previousReport = {
58
+ id: 'fake previous report',
59
+ }
60
+ });
61
+
62
+ afterEach(() => {
63
+ sinon.restore();
64
+ });
65
+
66
+ it('sends a POST request with the correct params when trigger is "startup"', async () => {
67
+ const res = await reachabilityRequest.getClusters('startup', IP_VERSION.only_ipv4, previousReport);
68
+ const requestParams = webex.request.getCall(0).args[0];
67
69
 
68
- assert.deepEqual(requestParams.qs, {
69
- JCSupport: 1,
70
- ipver: 4,
70
+ assert.deepEqual(requestParams, {
71
+ method: 'POST',
72
+ resource: `clusters`,
73
+ api: 'calliopeDiscovery',
74
+ shouldRefreshAccessToken: false,
75
+ timeout: 3000,
76
+ body: {
77
+ ipver: IP_VERSION.only_ipv4,
78
+ 'supported-options': {
79
+ 'report-version': 1,
80
+ 'early-call-min-clusters': true,
81
+ },
82
+ 'previous-report': previousReport,
83
+ trigger: 'startup',
84
+ },
71
85
  });
86
+
72
87
  assert.deepEqual(res.clusters.clusterId, {udp: "testUDP", isVideoMesh: true})
73
88
  assert.deepEqual(res.joinCookie, {anycastEntryPoint: "aws-eu-west-1"})
74
89
  assert.calledOnceWithExactly(webex.internal.newMetrics.callDiagnosticLatencies.measureLatency, sinon.match.func, 'internal.get.cluster.time');
75
90
  });
91
+
92
+ it('sends a POST request with the correct params when trigger is other than "startup"', async () => {
93
+ const res = await reachabilityRequest.getClusters('early-call/no-min-reached', IP_VERSION.only_ipv4, previousReport);
94
+ const requestParams = webex.request.getCall(0).args[0];
95
+
96
+ assert.deepEqual(requestParams, {
97
+ method: 'POST',
98
+ resource: `clusters`,
99
+ api: 'calliopeDiscovery',
100
+ shouldRefreshAccessToken: false,
101
+ timeout: 3000,
102
+ body: {
103
+ ipver: IP_VERSION.only_ipv4,
104
+ 'supported-options': {
105
+ 'report-version': 1,
106
+ 'early-call-min-clusters': true,
107
+ },
108
+ 'previous-report': previousReport,
109
+ trigger: 'early-call/no-min-reached',
110
+ },
111
+ });
112
+
113
+ assert.deepEqual(res.clusters.clusterId, {udp: "testUDP", isVideoMesh: true})
114
+ assert.deepEqual(res.joinCookie, {anycastEntryPoint: "aws-eu-west-1"})
115
+ assert.notCalled(webex.internal.newMetrics.callDiagnosticLatencies.measureLatency);
116
+ });
76
117
  });
77
118
  });
@@ -221,7 +221,21 @@ describe('plugin-meetings', () => {
221
221
 
222
222
  assert.calledWith(request.request, {
223
223
  uri: `test/loci/id/recording`,
224
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'start'}},
224
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'start'}, recordingType: 'cloud'},
225
+ method: HTTP_VERBS.PUT,
226
+ });
227
+
228
+ assert.deepEqual(result, request.request.firstCall.returnValue);
229
+ });
230
+
231
+ it('can start premise recording when the correct display hint is present', () => {
232
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_START']);
233
+
234
+ const result = controller.startRecording();
235
+
236
+ assert.calledWith(request.request, {
237
+ uri: `test/loci/id/recording`,
238
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'start'}, recordingType: 'premise'},
225
239
  method: HTTP_VERBS.PUT,
226
240
  });
227
241
 
@@ -238,14 +252,28 @@ describe('plugin-meetings', () => {
238
252
  assert.isRejected(result);
239
253
  });
240
254
 
241
- it('can start recording when the correct display hint is present', () => {
255
+ it('can stop recording when the correct display hint is present', () => {
242
256
  controller.setDisplayHints(['RECORDING_CONTROL_STOP']);
243
257
 
244
258
  const result = controller.stopRecording();
245
259
 
246
260
  assert.calledWith(request.request, {
247
261
  uri: `test/loci/id/recording`,
248
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'stop'}},
262
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'stop'}, recordingType: 'cloud'},
263
+ method: HTTP_VERBS.PUT,
264
+ });
265
+
266
+ assert.deepEqual(result, request.request.firstCall.returnValue);
267
+ });
268
+
269
+ it('can stop premise recording when the correct display hint is present', () => {
270
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_STOP']);
271
+
272
+ const result = controller.stopRecording();
273
+
274
+ assert.calledWith(request.request, {
275
+ uri: `test/loci/id/recording`,
276
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'stop'}, recordingType: 'premise'},
249
277
  method: HTTP_VERBS.PUT,
250
278
  });
251
279
 
@@ -269,7 +297,21 @@ describe('plugin-meetings', () => {
269
297
 
270
298
  assert.calledWith(request.request, {
271
299
  uri: `test/loci/id/recording`,
272
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'pause'}},
300
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'pause'}, recordingType: 'cloud'},
301
+ method: HTTP_VERBS.PUT,
302
+ });
303
+
304
+ assert.deepEqual(result, request.request.firstCall.returnValue);
305
+ });
306
+
307
+ it('can pause premise recording when the correct display hint is present', () => {
308
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_PAUSE']);
309
+
310
+ const result = controller.pauseRecording();
311
+
312
+ assert.calledWith(request.request, {
313
+ uri: `test/loci/id/recording`,
314
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'pause'}, recordingType: 'premise'},
273
315
  method: HTTP_VERBS.PUT,
274
316
  });
275
317
 
@@ -293,7 +335,21 @@ describe('plugin-meetings', () => {
293
335
 
294
336
  assert.calledWith(request.request, {
295
337
  uri: `test/loci/id/recording`,
296
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'resume'}},
338
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'resume'}, recordingType: 'cloud'},
339
+ method: HTTP_VERBS.PUT,
340
+ });
341
+
342
+ assert.deepEqual(result, request.request.firstCall.returnValue);
343
+ });
344
+
345
+ it('can resume premise recording when the correct display hint is present', () => {
346
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_RESUME']);
347
+
348
+ const result = controller.resumeRecording();
349
+
350
+ assert.calledWith(request.request, {
351
+ uri: `test/loci/id/recording`,
352
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'resume'}, recordingType: 'premise'},
297
353
  method: HTTP_VERBS.PUT,
298
354
  });
299
355
 
@@ -1,5 +1,5 @@
1
1
  import RecordingUtil from '@webex/plugin-meetings/src/recording-controller/util';
2
- import RecordingAction from '@webex/plugin-meetings/src/recording-controller/enums';
2
+ import { RecordingAction } from '@webex/plugin-meetings/src/recording-controller/enums';
3
3
  import {SELF_POLICY} from '@webex/plugin-meetings/src/constants';
4
4
 
5
5
  import {assert} from 'chai';
@@ -29,6 +29,15 @@ describe('plugin-meetings', () => {
29
29
  );
30
30
  });
31
31
 
32
+ it('can start premise recording when the correct display hint is present', () => {
33
+ locusInfo.parsedLocus.info.userDisplayHints.push('PREMISE_RECORDING_CONTROL_START');
34
+
35
+ assert.equal(
36
+ RecordingUtil.canUserStart(locusInfo.parsedLocus.info.userDisplayHints),
37
+ true
38
+ );
39
+ });
40
+
32
41
  it('can start recording when the correct display hint is present and the policy is true', () => {
33
42
  locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_START');
34
43
 
@@ -69,6 +78,15 @@ describe('plugin-meetings', () => {
69
78
  );
70
79
  });
71
80
 
81
+ it('can pause premise recording when the correct display hint is present', () => {
82
+ locusInfo.parsedLocus.info.userDisplayHints.push('PREMISE_RECORDING_CONTROL_PAUSE');
83
+
84
+ assert.equal(
85
+ RecordingUtil.canUserPause(locusInfo.parsedLocus.info.userDisplayHints),
86
+ true
87
+ );
88
+ });
89
+
72
90
  it('can pause recording when the correct display hint is present and the policy is true', () => {
73
91
  locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_PAUSE');
74
92
 
@@ -109,6 +127,15 @@ describe('plugin-meetings', () => {
109
127
  );
110
128
  });
111
129
 
130
+ it('can stop premise recording when the correct display hint is present', () => {
131
+ locusInfo.parsedLocus.info.userDisplayHints.push('PREMISE_RECORDING_CONTROL_STOP');
132
+
133
+ assert.equal(
134
+ RecordingUtil.canUserStop(locusInfo.parsedLocus.info.userDisplayHints),
135
+ true
136
+ );
137
+ });
138
+
112
139
  it('can stop recording when the correct display hint is present and the policy is true', () => {
113
140
  locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_STOP', {
114
141
  [SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD]: true,
@@ -142,7 +169,7 @@ describe('plugin-meetings', () => {
142
169
  });
143
170
 
144
171
  describe('canUserResume', () => {
145
- it('can start recording when the correct display hint is present', () => {
172
+ it('can resume recording when the correct display hint is present', () => {
146
173
  locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_RESUME');
147
174
 
148
175
  assert.equal(
@@ -151,7 +178,16 @@ describe('plugin-meetings', () => {
151
178
  );
152
179
  });
153
180
 
154
- it('can start recording when the correct display hint is present and the policy is true', () => {
181
+ it('can resume premise recording when the correct display hint is present', () => {
182
+ locusInfo.parsedLocus.info.userDisplayHints.push('PREMISE_RECORDING_CONTROL_RESUME');
183
+
184
+ assert.equal(
185
+ RecordingUtil.canUserResume(locusInfo.parsedLocus.info.userDisplayHints),
186
+ true
187
+ );
188
+ });
189
+
190
+ it('can resume recording when the correct display hint is present and the policy is true', () => {
155
191
  locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_RESUME');
156
192
 
157
193
  assert.equal(
@@ -161,7 +161,7 @@ describe('Roap', () => {
161
161
  roapMessage: expectedRoapMessage,
162
162
  locusSelfUrl: meeting.selfUrl,
163
163
  mediaId: meeting.mediaId,
164
- meetingId: meeting.id,
164
+ isMultistream: meeting.isMultistream,
165
165
  locusMediaRequest: meeting.locusMediaRequest,
166
166
  })
167
167
  );