diff --git a/spec/unit/webrtc/call.spec.ts b/spec/unit/webrtc/call.spec.ts index 7336a7371..0e7b67547 100644 --- a/spec/unit/webrtc/call.spec.ts +++ b/spec/unit/webrtc/call.spec.ts @@ -79,6 +79,7 @@ class MockRTCPeerConnection { return Promise.resolve(); } close() {} + getStats() { return []; } } describe('Call', function() { @@ -122,6 +123,7 @@ describe('Call', function() { // We just stub out sendEvent: we're not interested in testing the client's // event sending code here client.client.sendEvent = () => {}; + client.httpBackend.when("GET", "/voip/turnServer").respond(200, {}); call = new MatrixCall({ client: client.client, roomId: '!foo:bar', @@ -138,7 +140,9 @@ describe('Call', function() { }); it('should ignore candidate events from non-matching party ID', async function() { - await call.placeVoiceCall(); + const callPromise = call.placeVoiceCall(); + await client.httpBackend.flush(); + await callPromise; await call.onAnswerReceived({ getContent: () => { return { @@ -192,7 +196,9 @@ describe('Call', function() { }); it('should add candidates received before answer if party ID is correct', async function() { - await call.placeVoiceCall(); + const callPromise = call.placeVoiceCall(); + await client.httpBackend.flush(); + await callPromise; call.peerConn.addIceCandidate = jest.fn(); call.onRemoteIceCandidatesReceived({ diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index 849b2cd92..a9c8799cd 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -333,11 +333,11 @@ export class MatrixCall extends EventEmitter { * Place a voice call to this room. * @throws If you have not specified a listener for 'error' events. */ - placeVoiceCall() { + async placeVoiceCall() { logger.debug("placeVoiceCall"); this.checkForErrorListener(); const constraints = getUserMediaContraints(ConstraintsType.Audio); - this.placeCallWithConstraints(constraints); + await this.placeCallWithConstraints(constraints); this.type = CallType.Voice; } @@ -349,13 +349,13 @@ export class MatrixCall extends EventEmitter { * to render the local camera preview. * @throws If you have not specified a listener for 'error' events. */ - placeVideoCall(remoteVideoElement: HTMLVideoElement, localVideoElement: HTMLVideoElement) { + async placeVideoCall(remoteVideoElement: HTMLVideoElement, localVideoElement: HTMLVideoElement) { logger.debug("placeVideoCall"); this.checkForErrorListener(); this.localVideoElement = localVideoElement; this.remoteVideoElement = remoteVideoElement; const constraints = getUserMediaContraints(ConstraintsType.Video); - this.placeCallWithConstraints(constraints); + await this.placeCallWithConstraints(constraints); this.type = CallType.Video; } @@ -864,7 +864,6 @@ export class MatrixCall extends EventEmitter { // why do we enable audio (and only audio) tracks here? -- matthew setTracksEnabled(stream.getAudioTracks(), true); - this.peerConn = this.createPeerConnection(); for (const audioTrack of stream.getAudioTracks()) { logger.info("Adding audio track with id " + audioTrack.id); @@ -1677,11 +1676,10 @@ export class MatrixCall extends EventEmitter { logger.warn("Failed to get TURN credentials! Proceeding with call anyway..."); } - // It would be really nice if we could start gathering candidates at this point - // so the ICE agent could be gathering while we open our media devices: we already - // know the type of the call and therefore what tracks we want to send. - // Perhaps we could do this by making fake tracks now and then using replaceTrack() - // once we have the actual tracks? (Can we make fake tracks?) + // create the peer connection now so it can be gathering candidates while we get user + // media (assuming a candidate pool size is configured) + this.peerConn = this.createPeerConnection(); + try { const mediaStream = await navigator.mediaDevices.getUserMedia(constraints); this.gotUserMediaForInvite(mediaStream);