|
| 1 | +/* |
| 2 | +Copyright 2022 The Matrix.org Foundation C.I.C. |
| 3 | +
|
| 4 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +you may not use this file except in compliance with the License. |
| 6 | +You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | +Unless required by applicable law or agreed to in writing, software |
| 11 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +See the License for the specific language governing permissions and |
| 14 | +limitations under the License. |
| 15 | +*/ |
| 16 | + |
| 17 | +export const DUMMY_SDP = ( |
| 18 | + "v=0\r\n" + |
| 19 | + "o=- 5022425983810148698 2 IN IP4 127.0.0.1\r\n" + |
| 20 | + "s=-\r\nt=0 0\r\na=group:BUNDLE 0\r\n" + |
| 21 | + "a=msid-semantic: WMS h3wAi7s8QpiQMH14WG3BnDbmlOqo9I5ezGZA\r\n" + |
| 22 | + "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + |
| 23 | + "c=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:hLDR\r\n" + |
| 24 | + "a=ice-pwd:bMGD9aOldHWiI+6nAq/IIlRw\r\n" + |
| 25 | + "a=ice-options:trickle\r\n" + |
| 26 | + "a=fingerprint:sha-256 E4:94:84:F9:4A:98:8A:56:F5:5F:FD:AF:72:B9:32:89:49:5C:4B:9A:" + |
| 27 | + "4A:15:8E:41:8A:F3:69:E4:39:52:DC:D6\r\n" + |
| 28 | + "a=setup:active\r\n" + |
| 29 | + "a=mid:0\r\n" + |
| 30 | + "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + |
| 31 | + "a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" + |
| 32 | + "a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" + |
| 33 | + "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" + |
| 34 | + "a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n" + |
| 35 | + "a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\n" + |
| 36 | + "a=sendrecv\r\n" + |
| 37 | + "a=msid:h3wAi7s8QpiQMH14WG3BnDbmlOqo9I5ezGZA 4357098f-3795-4131-bff4-9ba9c0348c49\r\n" + |
| 38 | + "a=rtcp-mux\r\n" + |
| 39 | + "a=rtpmap:111 opus/48000/2\r\n" + |
| 40 | + "a=rtcp-fb:111 transport-cc\r\n" + |
| 41 | + "a=fmtp:111 minptime=10;useinbandfec=1\r\n" + |
| 42 | + "a=rtpmap:103 ISAC/16000\r\n" + |
| 43 | + "a=rtpmap:104 ISAC/32000\r\n" + |
| 44 | + "a=rtpmap:9 G722/8000\r\n" + |
| 45 | + "a=rtpmap:0 PCMU/8000\r\n" + |
| 46 | + "a=rtpmap:8 PCMA/8000\r\n" + |
| 47 | + "a=rtpmap:106 CN/32000\r\n" + |
| 48 | + "a=rtpmap:105 CN/16000\r\n" + |
| 49 | + "a=rtpmap:13 CN/8000\r\n" + |
| 50 | + "a=rtpmap:110 telephone-event/48000\r\n" + |
| 51 | + "a=rtpmap:112 telephone-event/32000\r\n" + |
| 52 | + "a=rtpmap:113 telephone-event/16000\r\n" + |
| 53 | + "a=rtpmap:126 telephone-event/8000\r\n" + |
| 54 | + "a=ssrc:3619738545 cname:2RWtmqhXLdoF4sOi\r\n" |
| 55 | +); |
| 56 | + |
| 57 | +export class MockRTCPeerConnection { |
| 58 | + localDescription: RTCSessionDescription; |
| 59 | + |
| 60 | + constructor() { |
| 61 | + this.localDescription = { |
| 62 | + sdp: DUMMY_SDP, |
| 63 | + type: 'offer', |
| 64 | + toJSON: function() { }, |
| 65 | + }; |
| 66 | + } |
| 67 | + |
| 68 | + addEventListener() { } |
| 69 | + createDataChannel(label: string, opts: RTCDataChannelInit) { return { label, ...opts }; } |
| 70 | + createOffer() { |
| 71 | + return Promise.resolve({}); |
| 72 | + } |
| 73 | + setRemoteDescription() { |
| 74 | + return Promise.resolve(); |
| 75 | + } |
| 76 | + setLocalDescription() { |
| 77 | + return Promise.resolve(); |
| 78 | + } |
| 79 | + close() { } |
| 80 | + getStats() { return []; } |
| 81 | + addTrack(track: MockMediaStreamTrack) { return new MockRTCRtpSender(track); } |
| 82 | +} |
| 83 | + |
| 84 | +export class MockRTCRtpSender { |
| 85 | + constructor(public track: MockMediaStreamTrack) { } |
| 86 | + |
| 87 | + replaceTrack(track: MockMediaStreamTrack) { this.track = track; } |
| 88 | +} |
| 89 | + |
| 90 | +export class MockMediaStreamTrack { |
| 91 | + constructor(public readonly id: string, public readonly kind: "audio" | "video", public enabled = true) { } |
| 92 | + |
| 93 | + stop() { } |
| 94 | +} |
| 95 | + |
| 96 | +// XXX: Using EventTarget in jest doesn't seem to work, so we write our own |
| 97 | +// implementation |
| 98 | +export class MockMediaStream { |
| 99 | + constructor( |
| 100 | + public id: string, |
| 101 | + private tracks: MockMediaStreamTrack[] = [], |
| 102 | + ) {} |
| 103 | + |
| 104 | + listeners: [string, (...args: any[]) => any][] = []; |
| 105 | + |
| 106 | + dispatchEvent(eventType: string) { |
| 107 | + this.listeners.forEach(([t, c]) => { |
| 108 | + if (t !== eventType) return; |
| 109 | + c(); |
| 110 | + }); |
| 111 | + } |
| 112 | + getTracks() { return this.tracks; } |
| 113 | + getAudioTracks() { return this.tracks.filter((track) => track.kind === "audio"); } |
| 114 | + getVideoTracks() { return this.tracks.filter((track) => track.kind === "video"); } |
| 115 | + addEventListener(eventType: string, callback: (...args: any[]) => any) { |
| 116 | + this.listeners.push([eventType, callback]); |
| 117 | + } |
| 118 | + removeEventListener(eventType: string, callback: (...args: any[]) => any) { |
| 119 | + this.listeners.filter(([t, c]) => { |
| 120 | + return t !== eventType || c !== callback; |
| 121 | + }); |
| 122 | + } |
| 123 | + addTrack(track: MockMediaStreamTrack) { |
| 124 | + this.tracks.push(track); |
| 125 | + this.dispatchEvent("addtrack"); |
| 126 | + } |
| 127 | + removeTrack(track: MockMediaStreamTrack) { this.tracks.splice(this.tracks.indexOf(track), 1); } |
| 128 | +} |
| 129 | + |
| 130 | +export class MockMediaDeviceInfo { |
| 131 | + constructor( |
| 132 | + public kind: "audio" | "video", |
| 133 | + ) { } |
| 134 | +} |
| 135 | + |
| 136 | +export class MockMediaHandler { |
| 137 | + getUserMediaStream(audio: boolean, video: boolean) { |
| 138 | + const tracks = []; |
| 139 | + if (audio) tracks.push(new MockMediaStreamTrack("audio_track", "audio")); |
| 140 | + if (video) tracks.push(new MockMediaStreamTrack("video_track", "video")); |
| 141 | + |
| 142 | + return new MockMediaStream("mock_stream_from_media_handler", tracks); |
| 143 | + } |
| 144 | + stopUserMediaStream() { } |
| 145 | + hasAudioDevice() { return true; } |
| 146 | +} |
0 commit comments