summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webrtc/RTCPeerConnection-createOffer.html
blob: 704fa3c6467e377447b140fbcd7b27cb1d9d20dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection.prototype.createOffer</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script>
  'use strict';

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

  // The following helper functions are called from RTCPeerConnection-helper.js:
  //   countAudioLine()
  //   countVideoLine()
  //   assert_session_desc_similar()

  /*
   *  4.3.2.  createOffer()
   */

  /*
   *  Final steps to create an offer
   *    4.  Let offer be a newly created RTCSessionDescriptionInit dictionary
   *        with its type member initialized to the string "offer" and its sdp member
   *        initialized to sdpString.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection()

    t.add_cleanup(() => pc.close());

    return pc.createOffer()
    .then(offer => {
      assert_equals(typeof offer, 'object',
        'Expect offer to be plain object dictionary RTCSessionDescriptionInit');

      assert_false(offer instanceof RTCSessionDescription,
        'Expect offer to not be instance of RTCSessionDescription')
    });
  }, 'createOffer() with no argument from newly created RTCPeerConnection should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const states = [];
    pc.addEventListener('signalingstatechange', () => states.push(pc.signalingState));

    return generateVideoReceiveOnlyOffer(pc)
    .then(offer =>
       pc.setLocalDescription(offer)
      .then(() => {
        assert_equals(pc.signalingState, 'have-local-offer');
        assert_session_desc_similar(pc.localDescription, offer);
        assert_session_desc_similar(pc.pendingLocalDescription, offer);
        assert_equals(pc.currentLocalDescription, null);

        assert_array_equals(states, ['have-local-offer']);
      }));
  }, 'createOffer() and then setLocalDescription() should succeed');

  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    pc.close();

    return promise_rejects_dom(t, 'InvalidStateError',
      pc.createOffer());
  }, 'createOffer() after connection is closed should reject with InvalidStateError');

  /*
   *  Final steps to create an offer
   *    2.  If connection was modified in such a way that additional inspection of the
   *        system state is necessary, then in parallel begin the steps to create an
   *        offer again, given p, and abort these steps.
   *
   *  This test might hit step 2 of final steps to create an offer. But the media stream
   *  is likely added already by the time steps to create an offer is executed, because
   *  that is enqueued as an operation.
   *  Either way it verifies that the media stream is included in the offer even though
   *  the stream is added after synchronous call to createOffer.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const promise = pc.createOffer();

    pc.addTransceiver('audio');
    return promise.then(offer => {
      assert_equals(countAudioLine(offer.sdp), 1,
        'Expect m=audio line to be found in offer SDP')
    });
  }, 'When media stream is added when createOffer() is running in parallel, the result offer should contain the new media stream');

  /*
  If connection's signaling state is neither "stable" nor "have-local-offer", return a promise rejected with a newly created InvalidStateError.
  */
  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const states = [];
    pc.addEventListener('signalingstatechange', () => states.push(pc.signalingState));

    return generateVideoReceiveOnlyOffer(pc)
    .then(offer =>
       pc.setRemoteDescription(offer)
       .then(() => {
          assert_equals(pc.signalingState, 'have-remote-offer');
          return promise_rejects_dom(t, 'InvalidStateError',
             pc.createOffer());
       })
     )
  }, 'createOffer() should fail when signaling state is not stable or have-local-offer');
  /*
   *  TODO
   *  4.3.2 createOffer
   *    3.  If connection is configured with an identity provider, and an identity
   *        assertion has not yet been generated using said identity provider, then
   *        begin the identity assertion request process if it has not already begun.
   *    Steps to create an offer
   *    1.  If the need for an identity assertion was identified when createOffer was
   *        invoked, wait for the identity assertion request process to complete.
   *
   *  Non-Testable
   *  4.3.2 createOffer
   *    Steps to create an offer
   *    4.  Inspect the system state to determine the currently available resources as
   *    necessary for generating the offer, as described in [JSEP] (section 4.1.6.).
   *    5.  If this inspection failed for any reason, reject p with a newly created
   *        OperationError and abort these steps.
   */
</script>