diff --git a/spec/test-utils/webrtc.ts b/spec/test-utils/webrtc.ts index 6a571b737..e141e6087 100644 --- a/spec/test-utils/webrtc.ts +++ b/spec/test-utils/webrtc.ts @@ -101,12 +101,12 @@ export class MockAudioContext { export class MockRTCPeerConnection { private static instances: MockRTCPeerConnection[] = []; - private negotiationNeededListener: () => void; + private negotiationNeededListener?: () => void; public iceCandidateListener?: (e: RTCPeerConnectionIceEvent) => void; public onTrackListener?: (e: RTCTrackEvent) => void; public needsNegotiation = false; public readyToNegotiate: Promise; - private onReadyToNegotiate: () => void; + private onReadyToNegotiate?: () => void; localDescription: RTCSessionDescription; signalingState: RTCSignalingState = "stable"; public transceivers: MockRTCRtpTransceiver[] = []; @@ -171,7 +171,7 @@ export class MockRTCPeerConnection { getStats() { return []; } addTransceiver(track: MockMediaStreamTrack): MockRTCRtpTransceiver { this.needsNegotiation = true; - this.onReadyToNegotiate(); + if (this.onReadyToNegotiate) this.onReadyToNegotiate(); const newSender = new MockRTCRtpSender(track); const newReceiver = new MockRTCRtpReceiver(track); @@ -190,7 +190,7 @@ export class MockRTCPeerConnection { removeTrack() { this.needsNegotiation = true; - this.onReadyToNegotiate(); + if (this.onReadyToNegotiate) this.onReadyToNegotiate(); } getTransceivers(): MockRTCRtpTransceiver[] { return this.transceivers; } @@ -217,8 +217,8 @@ export class MockRTCRtpReceiver { export class MockRTCRtpTransceiver { constructor(private peerConn: MockRTCPeerConnection) {} - public sender: RTCRtpSender; - public receiver: RTCRtpReceiver; + public sender?: RTCRtpSender; + public receiver?: RTCRtpReceiver; public set direction(_: string) { this.peerConn.needsNegotiation = true; @@ -234,9 +234,9 @@ export class MockMediaStreamTrack { listeners: [string, (...args: any[]) => any][] = []; public isStopped = false; - public settings: MediaTrackSettings; + public settings?: MediaTrackSettings; - getSettings(): MediaTrackSettings { return this.settings; } + getSettings(): MediaTrackSettings { return this.settings!; } // XXX: Using EventTarget in jest doesn't seem to work, so we write our own // implementation @@ -409,7 +409,7 @@ export class MockCallMatrixClient extends TypedEventEmitter false; checkTurnServers = () => null; - getSyncState = jest.fn().mockReturnValue(SyncState.Syncing); + getSyncState = jest.fn().mockReturnValue(SyncState.Syncing); getRooms = jest.fn().mockReturnValue([]); getRoom = jest.fn(); diff --git a/spec/unit/webrtc/call.spec.ts b/spec/unit/webrtc/call.spec.ts index 4d2c50a35..331830d18 100644 --- a/spec/unit/webrtc/call.spec.ts +++ b/spec/unit/webrtc/call.spec.ts @@ -169,7 +169,7 @@ describe('Call', function() { }, })); - const mockAddIceCandidate = call.peerConn.addIceCandidate = jest.fn(); + const mockAddIceCandidate = call.peerConn!.addIceCandidate = jest.fn(); call.onRemoteIceCandidatesReceived(makeMockEvent("@test:foo", { version: 1, call_id: call.callId, @@ -199,7 +199,7 @@ describe('Call', function() { it('should add candidates received before answer if party ID is correct', async function() { await startVoiceCall(client, call); - const mockAddIceCandidate = call.peerConn.addIceCandidate = jest.fn(); + const mockAddIceCandidate = call.peerConn!.addIceCandidate = jest.fn(); call.onRemoteIceCandidatesReceived(makeMockEvent("@test:foo", { version: 1, @@ -372,12 +372,12 @@ describe('Call', function() { // XXX: Lots of inspecting the prvate state of the call object here const transceivers: Map = (call as any).transceivers; - expect(call.localUsermediaStream.id).toBe("stream"); - expect(call.localUsermediaStream.getAudioTracks()[0].id).toBe("new_audio_track"); - expect(call.localUsermediaStream.getVideoTracks()[0].id).toBe("video_track"); + expect(call.localUsermediaStream!.id).toBe("stream"); + expect(call.localUsermediaStream!.getAudioTracks()[0].id).toBe("new_audio_track"); + expect(call.localUsermediaStream!.getVideoTracks()[0].id).toBe("video_track"); // call has a function for generating these but we hardcode here to avoid exporting it - expect(transceivers.get("m.usermedia:audio").sender.track.id).toBe("new_audio_track"); - expect(transceivers.get("m.usermedia:video").sender.track.id).toBe("video_track"); + expect(transceivers.get("m.usermedia:audio")!.sender.track!.id).toBe("new_audio_track"); + expect(transceivers.get("m.usermedia:video")!.sender.track!.id).toBe("video_track"); }); it("should handle upgrade to video call", async () => { @@ -400,10 +400,10 @@ describe('Call', function() { // XXX: More inspecting private state of the call object const transceivers: Map = (call as any).transceivers; - expect(call.localUsermediaStream.getAudioTracks()[0].id).toBe("usermedia_audio_track"); - expect(call.localUsermediaStream.getVideoTracks()[0].id).toBe("usermedia_video_track"); - expect(transceivers.get("m.usermedia:audio").sender.track.id).toBe("usermedia_audio_track"); - expect(transceivers.get("m.usermedia:video").sender.track.id).toBe("usermedia_video_track"); + expect(call.localUsermediaStream!.getAudioTracks()[0].id).toBe("usermedia_audio_track"); + expect(call.localUsermediaStream!.getVideoTracks()[0].id).toBe("usermedia_video_track"); + expect(transceivers.get("m.usermedia:audio")!.sender.track!.id).toBe("usermedia_audio_track"); + expect(transceivers.get("m.usermedia:video")!.sender.track!.id).toBe("usermedia_video_track"); }); it("should handle SDPStreamMetadata changes", async () => { @@ -601,13 +601,13 @@ describe('Call', function() { (call as any).pushRemoteFeed(remoteUsermediaStream); (call as any).pushRemoteFeed(remoteScreensharingStream); - expect(call.localUsermediaFeed.stream).toBe(localUsermediaStream); + expect(call.localUsermediaFeed!.stream).toBe(localUsermediaStream); expect(call.localUsermediaStream).toBe(localUsermediaStream); - expect(call.localScreensharingFeed.stream).toBe(localScreensharingStream); + expect(call.localScreensharingFeed!.stream).toBe(localScreensharingStream); expect(call.localScreensharingStream).toBe(localScreensharingStream); - expect(call.remoteUsermediaFeed.stream).toBe(remoteUsermediaStream); + expect(call.remoteUsermediaFeed!.stream).toBe(remoteUsermediaStream); expect(call.remoteUsermediaStream).toBe(remoteUsermediaStream); - expect(call.remoteScreensharingFeed.stream).toBe(remoteScreensharingStream); + expect(call.remoteScreensharingFeed!.stream).toBe(remoteScreensharingStream); expect(call.remoteScreensharingStream).toBe(remoteScreensharingStream); expect(call.hasRemoteUserMediaAudioTrack).toBe(false); }); @@ -1214,8 +1214,8 @@ describe('Call', function() { MockRTCPeerConnection.triggerAllNegotiations(); - const mockVideoSender = call.peerConn.getSenders().find(s => s.track.kind === "video"); - const mockReplaceTrack = mockVideoSender.replaceTrack = jest.fn(); + const mockVideoSender = call.peerConn!.getSenders().find(s => s.track!.kind === "video"); + const mockReplaceTrack = mockVideoSender!.replaceTrack = jest.fn(); await call.setScreensharingEnabled(true); @@ -1336,7 +1336,7 @@ describe('Call', function() { await call.placeVoiceCall(); - (call.peerConn as unknown as MockRTCPeerConnection).onTrackListener( + (call.peerConn as unknown as MockRTCPeerConnection).onTrackListener!( { streams: [], track: new MockMediaStreamTrack("track_ev", "audio") } as unknown as RTCTrackEvent, ); @@ -1359,7 +1359,7 @@ describe('Call', function() { })); const stream = new MockMediaStream("stream_ev", [new MockMediaStreamTrack("track_ev", "audio")]); - (call.peerConn as unknown as MockRTCPeerConnection).onTrackListener( + (call.peerConn as unknown as MockRTCPeerConnection).onTrackListener!( { streams: [stream], track: stream.getAudioTracks()[0] } as unknown as RTCTrackEvent, ); diff --git a/spec/unit/webrtc/callEventHandler.spec.ts b/spec/unit/webrtc/callEventHandler.spec.ts index d6012a7a2..b7687cdc2 100644 --- a/spec/unit/webrtc/callEventHandler.spec.ts +++ b/spec/unit/webrtc/callEventHandler.spec.ts @@ -50,8 +50,8 @@ describe("CallEventHandler", () => { }); afterEach(() => { - client.callEventHandler.stop(); - client.groupCallEventHandler.stop(); + client.callEventHandler!.stop(); + client.groupCallEventHandler!.stop(); }); const sync = async () => { @@ -63,7 +63,7 @@ describe("CallEventHandler", () => { }; it("should enforce inbound toDevice message ordering", async () => { - const callEventHandler = client.callEventHandler; + const callEventHandler = client.callEventHandler!; const event1 = new MatrixEvent({ type: EventType.CallInvite, content: { @@ -227,7 +227,7 @@ describe("CallEventHandler", () => { const DEVICE_ID = "device_id"; incomingCallListener.mockImplementation((c) => call = c); - jest.spyOn(client.groupCallEventHandler, "getGroupCallById").mockReturnValue(groupCall); + jest.spyOn(client.groupCallEventHandler!, "getGroupCallById").mockReturnValue(groupCall); // @ts-ignore Mock onIncomingCall is private jest.spyOn(groupCall, "onIncomingCall"); diff --git a/spec/unit/webrtc/groupCall.spec.ts b/spec/unit/webrtc/groupCall.spec.ts index 0c0990aa1..e3c850c70 100644 --- a/spec/unit/webrtc/groupCall.spec.ts +++ b/spec/unit/webrtc/groupCall.spec.ts @@ -939,7 +939,7 @@ describe('Group Call', function() { groupCall.leave(); const call = new MockCall(room.roomId, groupCall.groupCallId); - mockClient.callEventHandler.calls = new Map([ + mockClient.callEventHandler!.calls = new Map([ [call.callId, call.typed()], ]); await groupCall.enter(); diff --git a/spec/unit/webrtc/groupCallEventHandler.spec.ts b/spec/unit/webrtc/groupCallEventHandler.spec.ts index e948f8afa..6712b0f09 100644 --- a/spec/unit/webrtc/groupCallEventHandler.spec.ts +++ b/spec/unit/webrtc/groupCallEventHandler.spec.ts @@ -74,7 +74,7 @@ describe('Group Call Event Handler', function() { { roomId: FAKE_ROOM_ID } as unknown as RoomState, ); - const groupCall = groupCallEventHandler.groupCalls.get(FAKE_ROOM_ID); + const groupCall = groupCallEventHandler.groupCalls.get(FAKE_ROOM_ID)!; expect(groupCall.state).toBe(GroupCallState.LocalCallFeedUninitialized); diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index 3e9950a43..6e43b48be 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -2462,7 +2462,7 @@ export class MatrixCall extends TypedEventEmitter { diff --git a/src/webrtc/callEventHandler.ts b/src/webrtc/callEventHandler.ts index 7c2be58ff..93035e624 100644 --- a/src/webrtc/callEventHandler.ts +++ b/src/webrtc/callEventHandler.ts @@ -183,11 +183,11 @@ export class CallEventHandler { const content = event.getContent(); const callRoomId = ( event.getRoomId() || - this.client.groupCallEventHandler.getGroupCallById(content.conf_id)?.room?.roomId + this.client.groupCallEventHandler!.getGroupCallById(content.conf_id)?.room?.roomId ); const groupCallId = content.conf_id; const type = event.getType() as EventType; - const senderId = event.getSender(); + const senderId = event.getSender()!; const weSentTheEvent = senderId === this.client.credentials.userId; let call = content.call_id ? this.calls.get(content.call_id) : undefined; //console.info("RECV %s content=%s", type, JSON.stringify(content)); @@ -196,7 +196,7 @@ export class CallEventHandler { let groupCall: GroupCall | undefined; if (groupCallId) { - groupCall = this.client.groupCallEventHandler.getGroupCallById(groupCallId); + groupCall = this.client.groupCallEventHandler!.getGroupCallById(groupCallId); if (!groupCall) { logger.warn(`Cannot find a group call ${groupCallId} for event ${type}. Ignoring event.`); diff --git a/src/webrtc/groupCall.ts b/src/webrtc/groupCall.ts index 150b71ea3..c2fd3c4fb 100644 --- a/src/webrtc/groupCall.ts +++ b/src/webrtc/groupCall.ts @@ -207,7 +207,7 @@ export class GroupCall extends TypedEventEmitter< } public async create() { - this.client.groupCallEventHandler.groupCalls.set(this.room.roomId, this); + this.client.groupCallEventHandler!.groupCalls.set(this.room.roomId, this); await this.client.sendStateEvent( this.room.roomId, @@ -324,7 +324,7 @@ export class GroupCall extends TypedEventEmitter< this.client.on(CallEventHandlerEvent.Incoming, this.onIncomingCall); - const calls = this.client.callEventHandler.calls.values(); + const calls = this.client.callEventHandler!.calls.values(); for (const call of calls) { this.onIncomingCall(call); @@ -406,7 +406,7 @@ export class GroupCall extends TypedEventEmitter< } this.participants = []; - this.client.groupCallEventHandler.groupCalls.delete(this.room.roomId); + this.client.groupCallEventHandler!.groupCalls.delete(this.room.roomId); if (emitStateEvent) { const existingStateEvent = this.room.currentState.getStateEvents( @@ -699,7 +699,7 @@ export class GroupCall extends TypedEventEmitter< "m.call_id": this.groupCallId, "m.devices": [ { - "device_id": this.client.getDeviceId(), + "device_id": this.client.getDeviceId()!, "session_id": this.client.getSessionId(), "feeds": this.getLocalFeeds().map((feed) => ({ purpose: feed.purpose, diff --git a/src/webrtc/mediaHandler.ts b/src/webrtc/mediaHandler.ts index a07016bf6..3cea257ca 100644 --- a/src/webrtc/mediaHandler.ts +++ b/src/webrtc/mediaHandler.ts @@ -123,7 +123,7 @@ export class MediaHandler extends TypedEventEmitter< this.userMediaStreams = []; this.localUserMediaStream = undefined; - for (const call of this.client.callEventHandler.calls.values()) { + for (const call of this.client.callEventHandler!.calls.values()) { if (call.callHasEnded() || !callMediaStreamParams.has(call.callId)) { continue; } @@ -140,7 +140,7 @@ export class MediaHandler extends TypedEventEmitter< await call.updateLocalUsermediaStream(stream); } - for (const groupCall of this.client.groupCallEventHandler.groupCalls.values()) { + for (const groupCall of this.client.groupCallEventHandler!.groupCalls.values()) { if (!groupCall.localCallFeed) { continue; } diff --git a/tsconfig.json b/tsconfig.json index 69c3f0196..9776cfbab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "noImplicitAny": false, "noUnusedLocals": true, "noEmit": true, + "strict": true, "declaration": true }, "include": [