https://github.com/web-platform-tests/wpt
Raw File
Tip revision: 40dc6ae8bbd4d1ce358402dd518c8ec26439913b authored by Timothy Gu on 31 July 2018, 19:10:11 UTC
Capture readyState changes before document.open too
Tip revision: 40dc6ae
RTCPeerConnection-transceivers.https.html
<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection-transceivers.https.html</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script>
'use strict';

// The following helper functions are called from RTCPeerConnection-helper.js:
//   addEventListenerPromise

function createPeerConnectionWithCleanup(t) {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  return pc;
}

async function createTrackAndStreamWithCleanup(t, kind = 'audio') {
  let constraints = {};
  constraints[kind] = true;
  const stream = await navigator.mediaDevices.getUserMedia(constraints);
  const [track] = stream.getTracks();
  t.add_cleanup(() => track.stop());
  return [track, stream];
}

function findTransceiverForSender(pc, sender) {
  const transceivers = pc.getTransceivers();
  for (let i = 0; i < transceivers.length; ++i) {
    if (transceivers[i].sender == sender)
      return transceivers[i];
  }
  return null;
}

// Performs an offer exchange pc1 -> pc2.
async function exchangeOffer(pc1, pc2) {
  const offer = await pc1.createOffer();
  await pc1.setLocalDescription(offer);
  await pc2.setRemoteDescription(offer);
}

// The returned promise is resolved with pc2's ontrack event.
async function exchangeOfferAndListenToOntrack(t, pc1, pc2) {
  const ontrackPromise = addEventListenerPromise(t, pc2, 'track');
  await exchangeOffer(pc1, pc2);
  return ontrackPromise;
}

// Performs an answer exchange pc2 -> pc1.
async function exchangeAnswer(pc1, pc2) {
  const answer = await pc2.createAnswer();
  await pc2.setLocalDescription(answer);
  await pc1.setRemoteDescription(answer);
}

// The returned promise is resolved with pc1's ontrack event.
async function exchangeAnswerAndListenToOntrack(t, pc1, pc2) {
  const ontrackPromise = addEventListenerPromise(t, pc1, 'track');
  await exchangeAnswer(pc1, pc2);
  return ontrackPromise;
}

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const sender = pc.addTrack(track, stream);
  const transceiver = findTransceiverForSender(pc, sender);
  assert_true(transceiver instanceof RTCRtpTransceiver);
  assert_true(transceiver.sender instanceof RTCRtpSender);
  assert_equals(transceiver.sender, sender);
}, 'addTrack: creates a transceiver for the sender');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_array_equals(pc.getTransceivers(), [transceiver],
                      'pc.getTransceivers() equals [transceiver]');
  assert_array_equals(pc.getSenders(), [transceiver.sender],
                      'pc.getSenders() equals [transceiver.sender]');
  assert_array_equals(pc.getReceivers(), [transceiver.receiver],
                      'pc.getReceivers() equals [transceiver.receiver]');
}, 'addTrack: "transceiver == {sender,receiver}"');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_true(transceiver.sender.track instanceof MediaStreamTrack,
              'transceiver.sender.track instanceof MediaStreamTrack');
  assert_equals(transceiver.sender.track, track,
                'transceiver.sender.track == track');
}, 'addTrack: transceiver.sender is associated with the track');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_true(transceiver.receiver instanceof RTCRtpReceiver,
              'transceiver.receiver instanceof RTCRtpReceiver');
  assert_true(transceiver.receiver.track instanceof MediaStreamTrack,
              'transceiver.receiver.track instanceof MediaStreamTrack');
  assert_not_equals(transceiver.receiver.track, track,
                    'transceiver.receiver.track != track');
}, 'addTrack: transceiver.receiver has its own track');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_true(transceiver.receiver.track.muted);
}, 'addTrack: transceiver.receiver\'s track is muted');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_equals(transceiver.mid, null);
}, 'addTrack: transceiver is not associated with an m-section');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_false(transceiver.stopped);
}, 'addTrack: transceiver is not stopped');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_equals(transceiver.direction, 'sendrecv');
}, 'addTrack: transceiver\'s direction is sendrecv');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  assert_equals(transceiver.currentDirection, null);
}, 'addTrack: transceiver\'s currentDirection is null');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  await pc.setLocalDescription(await pc.createOffer());
  assert_not_equals(transceiver.mid, null, 'transceiver.mid != null');
}, 'setLocalDescription(offer): transceiver gets associated with an m-section');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc, pc.addTrack(track, stream));
  const offer = await pc.createOffer();
  await pc.setLocalDescription(offer);
  let sdp = offer.sdp;
  let sdpMidLineStart = sdp.indexOf('a=mid:');
  let sdpMidLineEnd = sdp.indexOf('\r\n', sdpMidLineStart);
  assert_true(sdpMidLineStart != -1 && sdpMidLineEnd != -1,
              'Failed to parse offer SDP for a=mid');
  let parsedMid = sdp.substring(sdpMidLineStart + 6, sdpMidLineEnd);
  assert_equals(transceiver.mid, parsedMid, 'transceiver.mid == parsedMid');
}, 'setLocalDescription(offer): transceiver.mid matches the offer SDP');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  pc1.addTrack(... await createTrackAndStreamWithCleanup(t));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_true(trackEvent instanceof RTCTrackEvent,
              'trackEvent instanceof RTCTrackEvent');
  assert_true(trackEvent.track instanceof MediaStreamTrack,
              'trackEvent.track instanceof MediaStreamTrack');
}, 'setRemoteDescription(offer): ontrack fires with a track');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  pc1.addTrack(track, stream);
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_true(trackEvent.track instanceof MediaStreamTrack,
              'trackEvent.track instanceof MediaStreamTrack');
  assert_equals(trackEvent.track.id, track.id,
                'trackEvent.track.id == track.id');
}, 'setRemoteDescription(offer): ontrack\'s track.id is the same as track.id');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  pc1.addTrack(... await createTrackAndStreamWithCleanup(t));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_true(trackEvent.transceiver instanceof RTCRtpTransceiver,
              'trackEvent.transceiver instanceof RTCRtpTransceiver');
}, 'setRemoteDescription(offer): ontrack fires with a transceiver.');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc1, pc1.addTrack(track, stream));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(transceiver.mid, trackEvent.transceiver.mid);
}, 'setRemoteDescription(offer): transceiver.mid is the same on both ends');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  pc1.addTrack(... await createTrackAndStreamWithCleanup(t));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  const transceiver = trackEvent.transceiver;
  assert_array_equals(pc2.getTransceivers(), [transceiver],
                      'pc2.getTransceivers() equals [transceiver]');
  assert_array_equals(pc2.getSenders(), [transceiver.sender],
                      'pc2.getSenders() equals [transceiver.sender]');
  assert_array_equals(pc2.getReceivers(), [transceiver.receiver],
                      'pc2.getReceivers() equals [transceiver.receiver]');
}, 'setRemoteDescription(offer): "transceiver == {sender,receiver}"');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  pc1.addTrack(... await createTrackAndStreamWithCleanup(t));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.transceiver.direction, 'recvonly');
}, 'setRemoteDescription(offer): transceiver.direction is recvonly');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  pc1.addTrack(... await createTrackAndStreamWithCleanup(t));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.transceiver.currentDirection, null);
}, 'setRemoteDescription(offer): transceiver.currentDirection is null');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  pc1.addTrack(... await createTrackAndStreamWithCleanup(t));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_false(trackEvent.transceiver.stopped);
}, 'setRemoteDescription(offer): transceiver.stopped is false');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  pc1.addTrack(... await createTrackAndStreamWithCleanup(t));
  const pc2 = createPeerConnectionWithCleanup(t);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  const transceiver = trackEvent.transceiver;
  assert_equals(transceiver.currentDirection, null,
                'SRD(offer): transciever.currentDirection is null');
  await pc2.setLocalDescription(await pc2.createAnswer());
  assert_equals(transceiver.currentDirection, 'recvonly',
                'SLD(answer): transciever.currentDirection is recvonly');
}, 'setLocalDescription(answer): transceiver.currentDirection is recvonly');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = findTransceiverForSender(pc1, pc1.addTrack(track, stream));
  const pc2 = createPeerConnectionWithCleanup(t);
  await exchangeOffer(pc1, pc2);
  assert_equals(transceiver.currentDirection, null,
                'SLD(offer): transciever.currentDirection is null');
  await exchangeAnswer(pc1, pc2);
  assert_equals(transceiver.currentDirection, 'sendonly',
                'SRD(answer): transciever.currentDirection is sendonly');
}, 'setLocalDescription(answer): transceiver.currentDirection is sendonly');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver(track);
  assert_true(transceiver instanceof RTCRtpTransceiver);
  assert_true(transceiver.sender instanceof RTCRtpSender);
  assert_true(transceiver.receiver instanceof RTCRtpReceiver);
  assert_equals(transceiver.sender.track, track);
}, 'addTransceiver(track): creates a transceiver for the track');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver(track);
  assert_array_equals(pc.getTransceivers(), [transceiver],
                      'pc.getTransceivers() equals [transceiver]');
  assert_array_equals(pc.getSenders(), [transceiver.sender],
                      'pc.getSenders() equals [transceiver.sender]');
  assert_array_equals(pc.getReceivers(), [transceiver.receiver],
                      'pc.getReceivers() equals [transceiver.receiver]');
}, 'addTransceiver(track): "transceiver == {sender,receiver}"');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver(track, {direction:'inactive'});
  assert_equals(transceiver.direction, 'inactive');
}, 'addTransceiver(track, init): initialize direction to inactive');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const otherPc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver(track, {
    sendEncodings: [{active:false}]
  });

  // Negotiate parameters.
  const offer = await pc.createOffer();
  await pc.setLocalDescription(offer);
  await otherPc.setRemoteDescription(offer);
  const answer = await otherPc.createAnswer();
  await otherPc.setLocalDescription(answer);
  await pc.setRemoteDescription(answer);

  const params = transceiver.sender.getParameters();
  assert_false(params.encodings[0].active);
}, 'addTransceiver(track, init): initialize sendEncodings[0].active to false');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track] = await createTrackAndStreamWithCleanup(t);
  pc1.addTransceiver(track, {streams:[]});
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.streams.length, 0, 'trackEvent.streams.length == 0');
}, 'addTransceiver(0 streams): ontrack fires with no stream');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track] = await createTrackAndStreamWithCleanup(t);
  const stream = new MediaStream();
  pc1.addTransceiver(track, {streams:[stream]});
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.streams.length, 1, 'trackEvent.streams.length == 1');
  assert_equals(trackEvent.streams[0].id, stream.id,
                'trackEvent.streams[0].id == stream.id');
}, 'addTransceiver(1 stream): ontrack fires with corresponding stream');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track] = await createTrackAndStreamWithCleanup(t);
  const stream0 = new MediaStream();
  const stream1 = new MediaStream();
  pc1.addTransceiver(track, {streams:[stream0, stream1]});
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.streams.length, 2, 'trackEvent.streams.length == 2');
  assert_equals(trackEvent.streams[0].id, stream0.id,
                'trackEvent.streams[0].id == stream0.id');
  assert_equals(trackEvent.streams[1].id, stream1.id,
                'trackEvent.streams[1].id == stream1.id');
}, 'addTransceiver(2 streams): ontrack fires with corresponding two streams');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track] = await createTrackAndStreamWithCleanup(t);
  pc1.addTrack(track);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.streams.length, 0, 'trackEvent.streams.length == 0');
}, 'addTrack(0 streams): ontrack fires with no stream');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track] = await createTrackAndStreamWithCleanup(t);
  const stream = new MediaStream();
  pc1.addTrack(track, stream);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.streams.length, 1, 'trackEvent.streams.length == 1');
  assert_equals(trackEvent.streams[0].id, stream.id,
                'trackEvent.streams[0].id == stream.id');
}, 'addTrack(1 stream): ontrack fires with corresponding stream');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track] = await createTrackAndStreamWithCleanup(t);
  const stream0 = new MediaStream();
  const stream1 = new MediaStream();
  pc1.addTrack(track, stream0, stream1);
  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  assert_equals(trackEvent.streams.length, 2, 'trackEvent.streams.length == 2');
  assert_equals(trackEvent.streams[0].id, stream0.id,
                'trackEvent.streams[0].id == stream0.id');
  assert_equals(trackEvent.streams[1].id, stream1.id,
                'trackEvent.streams[1].id == stream1.id');
}, 'addTrack(2 streams): ontrack fires with corresponding two streams');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver('audio');
  assert_equals(transceiver.direction, 'sendrecv');
}, 'addTransceiver(\'audio\'): creates a transceiver with direction sendrecv');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver('audio');
  assert_equals(transceiver.receiver.track.kind, 'audio');
}, 'addTransceiver(\'audio\'): transceiver.receiver.track.kind == \'audio\'');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver('video');
  assert_equals(transceiver.receiver.track.kind, 'video');
}, 'addTransceiver(\'video\'): transceiver.receiver.track.kind == \'video\'');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver('audio');
  assert_equals(transceiver.sender.track, null);
}, 'addTransceiver(\'audio\'): transceiver.sender.track == null');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver('audio');
  assert_equals(transceiver.currentDirection, null);
}, 'addTransceiver(\'audio\'): transceiver.currentDirection is null');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const transceiver = pc.addTransceiver('audio');
  assert_false(transceiver.stopped);
}, 'addTransceiver(\'audio\'): transceiver.stopped is false');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t, 'audio');
  const transceiver = pc.addTransceiver('audio');
  const sender = pc.addTrack(track, stream);
  assert_equals(sender, transceiver.sender, 'sender == transceiver.sender');
  assert_equals(sender.track, track, 'sender.track == track');
}, 'addTrack reuses reusable transceivers');

promise_test(async t => {
  const pc = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t, 'audio');
  const t1 = pc.addTransceiver('audio');
  const t2 = pc.addTransceiver(track);
  assert_not_equals(t2, t1, 't2 != t1');
  assert_equals(t2.sender.track, track, 't2.sender.track == track');
}, 'addTransceiver does not reuse reusable transceivers');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t);
  const pc1Transceiver = findTransceiverForSender(pc1, pc1.addTrack(track, stream));
  const pc2TrackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
  const pc2Transceiver = pc2TrackEvent.transceiver;
  assert_equals(pc2Transceiver.direction, 'recvonly',
                'pc2Transceiver.direction is recvonly after SRD(offer)');
  const pc2Sender = pc2.addTrack(track, stream);
  assert_equals(pc2Transceiver.sender, pc2Sender,
                'pc2Transceiver.sender == sender');
  assert_equals(pc2Transceiver.direction, 'sendrecv',
                'pc2Transceiver.direction is sendrecv after addTrack()');
  assert_equals(pc2Transceiver.currentDirection, null,
                'pc2Transceiver.currentDirection is null before answer');
  const pc1TrackEvent = await exchangeAnswerAndListenToOntrack(t, pc1, pc2);
  assert_equals(pc2Transceiver.currentDirection, 'sendrecv',
                'pc2Transceiver.currentDirection is sendrecv after SLD(answer)');
  assert_equals(pc1TrackEvent.transceiver, pc1Transceiver,
                'Answer: pc1.ontrack fires with the existing transceiver.');
  assert_equals(pc1Transceiver.currentDirection, 'sendrecv',
                'pc1Transceiver.currentDirection is sendrecv');
  assert_equals(pc2.getTransceivers().length, 1,
                'pc2.getTransceivers().length == 1');
  assert_equals(pc1.getTransceivers().length, 1,
                'pc1.getTransceivers().length == 1');
}, 'Can setup two-way call using a single transceiver');

promise_test(async t => {
  const pc1 = createPeerConnectionWithCleanup(t);
  const pc2 = createPeerConnectionWithCleanup(t);
  const [track, stream] = await createTrackAndStreamWithCleanup(t, 'audio');
  const transceiver = pc1.addTransceiver(track);
  await exchangeOffer(pc1, pc2);
  await exchangeAnswer(pc1, pc2);
  assert_equals(transceiver.currentDirection, 'sendonly');
  assert_false(transceiver.stopped);
  pc1.close();
  assert_equals(transceiver.currentDirection, null);
  assert_true(transceiver.stopped);
}, 'Closing the PC stops the transceivers');

</script>
back to top