onaddstream.https.html (5565B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>onaddstream tests</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src=/resources/testdriver.js></script> 7 <script src=/resources/testdriver-vendor.js></script> 8 <script src='/mediacapture-streams/permission-helper.js'></script> 9 <script> 10 'use strict'; 11 12 const stopTracks = (...streams) => { 13 streams.forEach(stream => stream.getTracks().forEach(track => track.stop())); 14 }; 15 16 const collectEvents = (target, name, check) => { 17 const events = []; 18 const handler = e => { 19 check(e); 20 events.push(e); 21 }; 22 23 target.addEventListener(name, handler); 24 25 const finishCollecting = () => { 26 target.removeEventListener(name, handler); 27 return events; 28 }; 29 30 return {finish: finishCollecting}; 31 }; 32 33 const collectAddTrackEvents = stream => { 34 const checkEvent = e => { 35 assert_true(e.track instanceof MediaStreamTrack, "Track is set on event"); 36 assert_true(stream.getTracks().includes(e.track), 37 "track in addtrack event is in the stream"); 38 }; 39 return collectEvents(stream, "addtrack", checkEvent); 40 }; 41 42 const collectRemoveTrackEvents = stream => { 43 const checkEvent = e => { 44 assert_true(e.track instanceof MediaStreamTrack, "Track is set on event"); 45 assert_true(!stream.getTracks().includes(e.track), 46 "track in removetrack event is not in the stream"); 47 }; 48 return collectEvents(stream, "removetrack", checkEvent); 49 }; 50 51 const collectTrackEvents = pc => { 52 const checkEvent = e => { 53 assert_true(e.track instanceof MediaStreamTrack, "Track is set on event"); 54 assert_true(e.receiver instanceof RTCRtpReceiver, "Receiver is set on event"); 55 assert_true(e.transceiver instanceof RTCRtpTransceiver, "Transceiver is set on event"); 56 assert_true(Array.isArray(e.streams), "Streams is set on event"); 57 e.streams.forEach(stream => { 58 assert_true(stream.getTracks().includes(e.track), 59 "Each stream in event contains the track"); 60 }); 61 assert_equals(e.receiver, e.transceiver.receiver, 62 "Receiver belongs to transceiver"); 63 assert_equals(e.track, e.receiver.track, 64 "Track belongs to receiver"); 65 }; 66 67 return collectEvents(pc, "track", checkEvent); 68 }; 69 70 // comparable() - produces copy of object that is JSON comparable. 71 // o = original object (required) 72 // t = template of what to examine. Useful if o is non-enumerable (optional) 73 74 const comparable = (o, t = o) => { 75 if (typeof o != 'object' || !o) { 76 return o; 77 } 78 if (Array.isArray(t) && Array.isArray(o)) { 79 return o.map((n, i) => comparable(n, t[i])); 80 } 81 return Object.keys(t).sort() 82 .reduce((r, key) => (r[key] = comparable(o[key], t[key]), r), {}); 83 }; 84 85 const stripKeyQuotes = s => s.replace(/"(\w+)":/g, "$1:"); 86 87 const hasProps = (observed, expected) => { 88 const observable = comparable(observed, expected); 89 assert_equals(stripKeyQuotes(JSON.stringify(observable)), 90 stripKeyQuotes(JSON.stringify(comparable(expected)))); 91 }; 92 93 promise_test(async t => { 94 const pc1 = new RTCPeerConnection(); 95 t.add_cleanup(() => pc1.close()); 96 await setMediaPermission(); 97 const stream1 = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); 98 t.add_cleanup(() => stopTracks(stream1)); 99 const audio1 = stream1.getAudioTracks()[0]; 100 pc1.addTrack(audio1, stream1); 101 const video1 = stream1.getVideoTracks()[0]; 102 pc1.addTrack(video1, stream1); 103 104 const pc2 = new RTCPeerConnection(); 105 t.add_cleanup(() => pc2.close()); 106 const stream2 = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); 107 t.add_cleanup(() => stopTracks(stream2)); 108 const audio2 = stream2.getAudioTracks()[0]; 109 pc2.addTrack(audio2, stream2); 110 const video2 = stream2.getVideoTracks()[0]; 111 pc2.addTrack(video2, stream2); 112 113 const offer = await pc1.createOffer(); 114 115 let trackEventCollector = collectTrackEvents(pc2); 116 let addstreamEventCollector = collectEvents(pc2, "addstream", e => { 117 hasProps(e, {stream: {id: stream1.id}}); 118 assert_equals(e.stream.getAudioTracks().length, 1, "One audio track"); 119 assert_equals(e.stream.getVideoTracks().length, 1, "One video track"); 120 }); 121 122 await pc2.setRemoteDescription(offer); 123 124 let addstreamEvents = addstreamEventCollector.finish(); 125 assert_equals(addstreamEvents.length, 1, "Should have 1 addstream event"); 126 127 let trackEvents = trackEventCollector.finish(); 128 129 hasProps(trackEvents, 130 [ 131 {streams: [addstreamEvents[0].stream]}, 132 {streams: [addstreamEvents[0].stream]} 133 ]); 134 135 await pc1.setLocalDescription(offer); 136 const answer = await pc2.createAnswer(); 137 138 trackEventCollector = collectTrackEvents(pc1); 139 addstreamEventCollector = collectEvents(pc1, "addstream", e => { 140 hasProps(e, {stream: {id: stream2.id}}); 141 assert_equals(e.stream.getAudioTracks().length, 1, "One audio track"); 142 assert_equals(e.stream.getVideoTracks().length, 1, "One video track"); 143 }); 144 145 await pc1.setRemoteDescription(answer); 146 addstreamEvents = addstreamEventCollector.finish(); 147 assert_equals(addstreamEvents.length, 1, "Should have 1 addstream event"); 148 149 trackEvents = trackEventCollector.finish(); 150 151 hasProps(trackEvents, 152 [ 153 {streams: [addstreamEvents[0].stream]}, 154 {streams: [addstreamEvents[0].stream]} 155 ]); 156 },"Check onaddstream"); 157 </script>