@@ -14,8 +14,10 @@ See the License for the specific language governing permissions and
1414limitations under the License.
1515*/
1616
17+ import { mocked } from "jest-mock" ;
18+
1719import { logger } from "../../src/logger" ;
18- import { MatrixClient } from "../../src/client" ;
20+ import { MatrixClient , ClientEvent } from "../../src/client" ;
1921import { Filter } from "../../src/filter" ;
2022import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE } from "../../src/models/MSC3089TreeSpace" ;
2123import {
@@ -35,10 +37,16 @@ import * as testUtils from "../test-utils/test-utils";
3537import { makeBeaconInfoContent } from "../../src/content-helpers" ;
3638import { M_BEACON_INFO } from "../../src/@types/beacon" ;
3739import { ContentHelpers , Room } from "../../src" ;
40+ import { supportsMatrixCall } from "../../src/webrtc/call" ;
3841import { makeBeaconEvent } from "../test-utils/beacon" ;
3942
4043jest . useFakeTimers ( ) ;
4144
45+ jest . mock ( "../../src/webrtc/call" , ( ) => ( {
46+ ...jest . requireActual ( "../../src/webrtc/call" ) ,
47+ supportsMatrixCall : jest . fn ( ( ) => false ) ,
48+ } ) ) ;
49+
4250describe ( "MatrixClient" , function ( ) {
4351 const userId = "@alice:bar" ;
4452 const identityServerUrl = "https://identity.server" ;
@@ -160,6 +168,24 @@ describe("MatrixClient", function() {
160168 return new Promise ( ( ) => { } ) ;
161169 }
162170
171+ function makeClient ( ) {
172+ client = new MatrixClient ( {
173+ baseUrl : "https://my.home.server" ,
174+ idBaseUrl : identityServerUrl ,
175+ accessToken : "my.access.token" ,
176+ request : function ( ) { } as any , // NOP
177+ store : store ,
178+ scheduler : scheduler ,
179+ userId : userId ,
180+ } ) ;
181+ // FIXME: We shouldn't be yanking http like this.
182+ client . http = [
183+ "authedRequest" , "getContentUri" , "request" , "uploadContent" ,
184+ ] . reduce ( ( r , k ) => { r [ k ] = jest . fn ( ) ; return r ; } , { } ) ;
185+ client . http . authedRequest . mockImplementation ( httpReq ) ;
186+ client . http . request . mockImplementation ( httpReq ) ;
187+ }
188+
163189 beforeEach ( function ( ) {
164190 scheduler = [
165191 "getQueueForEvent" , "queueEvent" , "removeEventFromQueue" ,
@@ -177,21 +203,7 @@ describe("MatrixClient", function() {
177203 store . getClientOptions = jest . fn ( ) . mockReturnValue ( Promise . resolve ( null ) ) ;
178204 store . storeClientOptions = jest . fn ( ) . mockReturnValue ( Promise . resolve ( null ) ) ;
179205 store . isNewlyCreated = jest . fn ( ) . mockReturnValue ( Promise . resolve ( true ) ) ;
180- client = new MatrixClient ( {
181- baseUrl : "https://my.home.server" ,
182- idBaseUrl : identityServerUrl ,
183- accessToken : "my.access.token" ,
184- request : function ( ) { } as any , // NOP
185- store : store ,
186- scheduler : scheduler ,
187- userId : userId ,
188- } ) ;
189- // FIXME: We shouldn't be yanking http like this.
190- client . http = [
191- "authedRequest" , "getContentUri" , "request" , "uploadContent" ,
192- ] . reduce ( ( r , k ) => { r [ k ] = jest . fn ( ) ; return r ; } , { } ) ;
193- client . http . authedRequest . mockImplementation ( httpReq ) ;
194- client . http . request . mockImplementation ( httpReq ) ;
206+ makeClient ( ) ;
195207
196208 // set reasonable working defaults
197209 acceptKeepalives = true ;
@@ -1299,6 +1311,93 @@ describe("MatrixClient", function() {
12991311 } ) ;
13001312 } ) ;
13011313
1314+ describe ( "pollingTurnServers" , ( ) => {
1315+ afterEach ( ( ) => {
1316+ mocked ( supportsMatrixCall ) . mockReset ( ) ;
1317+ } ) ;
1318+
1319+ it ( "is false if the client isn't started" , ( ) => {
1320+ expect ( client . clientRunning ) . toBe ( false ) ;
1321+ expect ( client . pollingTurnServers ) . toBe ( false ) ;
1322+ } ) ;
1323+
1324+ it ( "is false if VoIP is not supported" , async ( ) => {
1325+ mocked ( supportsMatrixCall ) . mockReturnValue ( false ) ;
1326+ makeClient ( ) ; // create the client a second time so it picks up the supportsMatrixCall mock
1327+ await client . startClient ( ) ;
1328+ expect ( client . pollingTurnServers ) . toBe ( false ) ;
1329+ } ) ;
1330+
1331+ it ( "is true if VoIP is supported" , async ( ) => {
1332+ mocked ( supportsMatrixCall ) . mockReturnValue ( true ) ;
1333+ makeClient ( ) ; // create the client a second time so it picks up the supportsMatrixCall mock
1334+ await client . startClient ( ) ;
1335+ expect ( client . pollingTurnServers ) . toBe ( true ) ;
1336+ } ) ;
1337+ } ) ;
1338+
1339+ describe ( "checkTurnServers" , ( ) => {
1340+ beforeAll ( ( ) => {
1341+ mocked ( supportsMatrixCall ) . mockReturnValue ( true ) ;
1342+ } ) ;
1343+
1344+ beforeEach ( ( ) => {
1345+ makeClient ( ) ; // create the client a second time so it picks up the supportsMatrixCall mock
1346+ } ) ;
1347+
1348+ afterAll ( ( ) => {
1349+ mocked ( supportsMatrixCall ) . mockReset ( ) ;
1350+ } ) ;
1351+
1352+ it ( "emits an event when new TURN creds are found" , async ( ) => {
1353+ const turnServer = {
1354+ uris : [
1355+ "turn:turn.example.com:3478?transport=udp" ,
1356+ "turn:10.20.30.40:3478?transport=tcp" ,
1357+ "turns:10.20.30.40:443?transport=tcp" ,
1358+ ] ,
1359+ username : "1443779631:@user:example.com" ,
1360+ password : "JlKfBy1QwLrO20385QyAtEyIv0=" ,
1361+ } ;
1362+ jest . spyOn ( client , "turnServer" ) . mockResolvedValue ( turnServer ) ;
1363+
1364+ const events : any [ ] [ ] = [ ] ;
1365+ const onTurnServers = ( ...args ) => events . push ( args ) ;
1366+ client . on ( ClientEvent . TurnServers , onTurnServers ) ;
1367+ expect ( await client . checkTurnServers ( ) ) . toBe ( true ) ;
1368+ client . off ( ClientEvent . TurnServers , onTurnServers ) ;
1369+ expect ( events ) . toEqual ( [ [ [ {
1370+ urls : turnServer . uris ,
1371+ username : turnServer . username ,
1372+ credential : turnServer . password ,
1373+ } ] ] ] ) ;
1374+ } ) ;
1375+
1376+ it ( "emits an event when an error occurs" , async ( ) => {
1377+ const error = new Error ( ":(" ) ;
1378+ jest . spyOn ( client , "turnServer" ) . mockRejectedValue ( error ) ;
1379+
1380+ const events : any [ ] [ ] = [ ] ;
1381+ const onTurnServersError = ( ...args ) => events . push ( args ) ;
1382+ client . on ( ClientEvent . TurnServersError , onTurnServersError ) ;
1383+ expect ( await client . checkTurnServers ( ) ) . toBe ( false ) ;
1384+ client . off ( ClientEvent . TurnServersError , onTurnServersError ) ;
1385+ expect ( events ) . toEqual ( [ [ error , false ] ] ) ; // non-fatal
1386+ } ) ;
1387+
1388+ it ( "considers 403 errors fatal" , async ( ) => {
1389+ const error = { httpStatus : 403 } ;
1390+ jest . spyOn ( client , "turnServer" ) . mockRejectedValue ( error ) ;
1391+
1392+ const events : any [ ] [ ] = [ ] ;
1393+ const onTurnServersError = ( ...args ) => events . push ( args ) ;
1394+ client . on ( ClientEvent . TurnServersError , onTurnServersError ) ;
1395+ expect ( await client . checkTurnServers ( ) ) . toBe ( false ) ;
1396+ client . off ( ClientEvent . TurnServersError , onTurnServersError ) ;
1397+ expect ( events ) . toEqual ( [ [ error , true ] ] ) ; // fatal
1398+ } ) ;
1399+ } ) ;
1400+
13021401 describe ( "encryptAndSendToDevices" , ( ) => {
13031402 it ( "throws an error if crypto is unavailable" , ( ) => {
13041403 client . crypto = undefined ;
0 commit comments