<!doctype html>
<meta charset=utf-8>
<title>RTCDTMFSender.prototype.insertDTMF</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script src="RTCDTMFSender-helper.js"></script>
<script>
  'use strict';

  // Test is based on the following editor draft:
  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html

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

  // The following helper functions are called from RTCDTMFSender-helper.js
  //   createDtmfSender
  //   test_tone_change_events
  //   getTransceiver

  /*
    7.  Peer-to-peer DTMF
      partial interface RTCRtpSender {
        readonly attribute RTCDTMFSender? dtmf;
      };

      interface RTCDTMFSender : EventTarget {
        void insertDTMF(DOMString tones,
                        optional unsigned long duration = 100,
                        optional unsigned long interToneGap = 70);
                 attribute EventHandler ontonechange;
        readonly attribute DOMString    toneBuffer;
      };
   */

  /*
    7.2.  insertDTMF
      The tones parameter is treated as a series of characters.

      The characters 0 through 9, A through D, #, and * generate the associated
      DTMF tones.

      The characters a to d MUST be normalized to uppercase on entry and are
      equivalent to A to D.

      As noted in [RTCWEB-AUDIO] Section 3, support for the characters 0 through 9,
      A through D, #, and * are required.

      The character ',' MUST be supported, and indicates a delay of 2 seconds
      before processing the next character in the tones parameter.

      All other characters (and only those other characters) MUST be considered
      unrecognized.
   */
  promise_test(async t => {
    const dtmfSender = await createDtmfSender();
    dtmfSender.insertDTMF('');
    dtmfSender.insertDTMF('012345689');
    dtmfSender.insertDTMF('ABCD');
    dtmfSender.insertDTMF('abcd');
    dtmfSender.insertDTMF('#*');
    dtmfSender.insertDTMF(',');
    dtmfSender.insertDTMF('0123456789ABCDabcd#*,');
  }, 'insertDTMF() should succeed if tones contains valid DTMF characters');


  /*
    7.2.  insertDTMF
      6.  If tones contains any unrecognized characters, throw an
          InvalidCharacterError.
   */
  promise_test(async t => {
    const dtmfSender = await createDtmfSender();
    assert_throws_dom('InvalidCharacterError', () =>
      // 'F' is invalid
      dtmfSender.insertDTMF('123FFABC'));

    assert_throws_dom('InvalidCharacterError', () =>
      // 'E' is invalid
      dtmfSender.insertDTMF('E'));

    assert_throws_dom('InvalidCharacterError', () =>
      // ' ' is invalid
      dtmfSender.insertDTMF('# *'));
  }, 'insertDTMF() should throw InvalidCharacterError if tones contains invalid DTMF characters');

  /*
    7.2.  insertDTMF
      3.  If transceiver.stopped is true, throw an InvalidStateError.
   */
  test(t => {
    const pc = new RTCPeerConnection();
    const transceiver = pc.addTransceiver('audio');
    const dtmfSender = transceiver.sender.dtmf;

    transceiver.stop();
    assert_throws_dom('InvalidStateError', () => dtmfSender.insertDTMF(''));

  }, 'insertDTMF() should throw InvalidStateError if transceiver is stopped');

  /*
    7.2.  insertDTMF
      4.  If transceiver.currentDirection is recvonly or inactive, throw an InvalidStateError.
   */
  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    const transceiver =
        caller.addTransceiver('audio', { direction: 'recvonly' });
    const dtmfSender = transceiver.sender.dtmf;

    const offer = await caller.createOffer();
    await caller.setLocalDescription(offer);
    await callee.setRemoteDescription(offer);
    const stream = await getNoiseStream({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    callee.addTrack(track, stream);
    const answer = await callee.createAnswer();
    await callee.setLocalDescription(answer);
    await caller.setRemoteDescription(answer);
    assert_equals(transceiver.currentDirection, 'recvonly');
    assert_throws_dom('InvalidStateError', () => dtmfSender.insertDTMF(''));
  }, 'insertDTMF() should throw InvalidStateError if transceiver.currentDirection is recvonly');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const transceiver =
        pc.addTransceiver('audio', { direction: 'inactive' });
    const dtmfSender = transceiver.sender.dtmf;

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);
    assert_equals(transceiver.currentDirection, 'inactive');
    assert_throws_dom('InvalidStateError', () => dtmfSender.insertDTMF(''));
  }, 'insertDTMF() should throw InvalidStateError if transceiver.currentDirection is inactive');

  /*
    7.2.  insertDTMF
      The characters a to d MUST be normalized to uppercase on entry and are
      equivalent to A to D.

      7.  Set the object's toneBuffer attribute to tones.
   */
  promise_test(async t => {
    const dtmfSender = await createDtmfSender();
    dtmfSender.insertDTMF('123');
    assert_equals(dtmfSender.toneBuffer, '123');

    dtmfSender.insertDTMF('ABC');
    assert_equals(dtmfSender.toneBuffer, 'ABC');

    dtmfSender.insertDTMF('bcd');
    assert_equals(dtmfSender.toneBuffer, 'BCD');
  }, 'insertDTMF() should set toneBuffer to provided tones normalized, with old tones overridden');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const [track, mediaStream] = await getTrackFromUserMedia('audio');
    const sender = pc.addTrack(track, mediaStream);
    await pc.setLocalDescription(await pc.createOffer());
    const dtmfSender = sender.dtmf;
    pc.removeTrack(sender);
    pc.close();
    assert_throws_dom('InvalidStateError', () =>
                      dtmfSender.insertDTMF('123'));
  }, 'insertDTMF() after remove and close should reject');

</script>
