Runs: Chrome 158.0.8110.0 (wpt@4c84956f8, 2026-10-18) | Firefox 160.0a1 (wpt@b58866519, 2026-10-18) | Safari 254 preview (wpt@850b36a56, 2026-10-18) | Ladybird 1.0-38d35 (wpt@4c84956f8, 2026-10-18) | Servo Servo 0.7 (wpt@df642c414, 2026-10-17) | Blitz 38ca4e777 (wpt@cd1d8aa5b, 2026-10-18)
| Chrome | Firefox | Safari | Ladybird | Servo | Blitz | |
|---|---|---|---|---|---|---|
| Total | 0/1 | 0/1 | 0/1 | 0/1 | 0/1 | NOT RUN |
| Subtest | Chrome | Firefox | Safari | Ladybird | Servo | Blitz |
|---|---|---|---|---|---|---|
| receiver.getStats() should work on a stopped transceiver but not have inbound-rtp objects | FAIL | FAIL | FAIL | FAIL | FAIL | — |
/webrtc/RTCRtpReceiver-getStats.https.html
<!doctype html> <meta charset=utf-8> <meta name="variant" content="?interop-2026"> <meta name="variant" content="?rest"> <meta name="timeout" content="long"> <title>RTCRtpReceiver.prototype.getStats</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="RTCPeerConnection-helper.js"></script> <script> 'use strict'; const rest = !new URLSearchParams(location.search).has("interop-2026"); const interop2026 = !new URLSearchParams(location.search).has("rest"); if (interop2026) { promise_test(async t => { const caller = new RTCPeerConnection(); t.add_cleanup(() => caller.close()); const callee = new RTCPeerConnection(); t.add_cleanup(() => callee.close()); const stream = await getNoiseStream({audio:true}); t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); const [track] = stream.getTracks(); callee.addTrack(track, stream); const { receiver } = caller.addTransceiver('audio'); exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); await listenToConnected(callee); await waitForTrackUnmuted(receiver.track); const statsReport = await receiver.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'inbound-rtp')); }, 'receiver.getStats() via addTransceiver should return stats report containing inbound-rtp stats'); promise_test(async t => { const caller = new RTCPeerConnection(); t.add_cleanup(() => caller.close()); const callee = new RTCPeerConnection(); t.add_cleanup(() => callee.close()); const stream = await getNoiseStream({audio:true}); t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); const [track] = stream.getTracks(); caller.addTrack(track, stream); exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); const receiver = callee.getReceivers()[0]; await listenToConnected(callee); await waitForTrackUnmuted(receiver.track); const statsReport = await receiver.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'inbound-rtp')); }, 'receiver.getStats() via addTrack should return stats report containing inbound-rtp stats'); } // interop2026 if (rest) { promise_test(async t => { const caller = new RTCPeerConnection(); t.add_cleanup(() => caller.close()); const callee = new RTCPeerConnection(); t.add_cleanup(() => callee.close()); const stream = await getNoiseStream({audio:true}); t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); const [track] = stream.getTracks(); caller.addTrack(track, stream); exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); const [receiver] = callee.getReceivers(); await listenToConnected(callee); await waitForTrackUnmuted(receiver.track); const [transceiver] = callee.getTransceivers(); const statsPromiseFirst = receiver.getStats(); transceiver.stop(); const statsReportFirst = await statsPromiseFirst; const statsReportSecond = await receiver.getStats(); assert_true(!![...statsReportFirst.values()].find(({type}) => type === 'inbound-rtp')); assert_false(!![...statsReportSecond.values()].find(({type}) => type === 'inbound-rtp')); }, 'receiver.getStats() should work on a stopped transceiver but not have inbound-rtp objects'); } // rest if (interop2026) { promise_test(async t => { const caller = new RTCPeerConnection(); t.add_cleanup(() => caller.close()); const callee = new RTCPeerConnection(); t.add_cleanup(() => callee.close()); const stream = await getNoiseStream({audio:true}); t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); const [track] = stream.getTracks(); caller.addTrack(track, stream); exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); const [receiver] = callee.getReceivers(); await listenToConnected(callee); await waitForTrackUnmuted(receiver.track); const statsReportFirst = await receiver.getStats(); callee.close(); const statsReportSecond = await receiver.getStats(); assert_true(!![...statsReportFirst.values()].find(({type}) => type === 'inbound-rtp')); assert_false(!![...statsReportSecond.values()].find(({type}) => type === 'inbound-rtp')); }, 'receiver.getStats() should work with a closed PeerConnection but not have inbound-rtp objects'); promise_test(async t => { const caller = new RTCPeerConnection(); t.add_cleanup(() => caller.close()); const callee = new RTCPeerConnection(); t.add_cleanup(() => callee.close()); const stream = await getNoiseStream({audio:true}); t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); const [track] = stream.getTracks(); caller.addTrack(track, stream); exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); const receiver = callee.getReceivers()[0]; await listenToConnected(callee); await waitForTrackUnmuted(receiver.track); const statsReport = await receiver.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'candidate-pair')); assert_true(!![...statsReport.values()].find(({type}) => type === 'local-candidate')); assert_true(!![...statsReport.values()].find(({type}) => type === 'remote-candidate')); }, 'receiver.getStats() should return stats report containing ICE candidate stats'); } // interop2026 </script>