blob: 4b4d0ea339f0930e3ebd77581b84bdfb98d63bfb [file] [log] [blame]
Soares Chenfda87822017-06-05 14:00:301<!doctype html>
2<meta charset=utf-8>
3<title>RTCPeerConnection.prototype.createOffer</title>
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="RTCPeerConnection-helper.js"></script>
7<script>
8 'use strict';
9
10 // Test is based on the following editor draft:
11 // https://w3c.github.io/webrtc-pc/archives/20170515/webrtc.html
12
Rick Waldron1c5c05d2017-06-07 17:54:4213 // The following helper functions are called from RTCPeerConnection-helper.js:
14 // generateOffer()
15 // generateAnswer()
16 // countAudioLine()
17 // countVideoLine()
Rick Waldron1c5c05d2017-06-07 17:54:4218 // assert_session_desc_equals()
19
Soares Chenfda87822017-06-05 14:00:3020 /*
21 * 4.3.2. createOffer()
22 */
23
24 /*
25 * Final steps to create an offer
26 * 4. Let offer be a newly created RTCSessionDescriptionInit dictionary
27 * with its type member initialized to the string "offer" and its sdp member
28 * initialized to sdpString.
29 */
30 promise_test(t => {
31 const pc = new RTCPeerConnection()
32
33 return pc.createOffer()
34 .then(offer => {
35 assert_equals(typeof offer, 'object',
36 'Expect offer to be plain object dictionary RTCSessionDescriptionInit');
37
38 assert_false(offer instanceof RTCSessionDescription,
39 'Expect offer to not be instance of RTCSessionDescription')
40 });
41 }, 'createOffer() with no argument from newly created RTCPeerConnection should succeed');
42
43 promise_test(t => {
44 const pc = new RTCPeerConnection();
Philipp Hanckeeb37a992018-05-30 15:55:0245
46 const states = [];
47 pc.addEventListener('signalingstatechange', () => states.push(pc.signalingState));
Soares Chenfda87822017-06-05 14:00:3048
49 return pc.createOffer({ offerToReceiveAudio: true })
50 .then(offer =>
51 pc.setLocalDescription(offer)
Nils Ohlmeier6cb97072017-08-31 00:38:2952 .then(() => {
Soares Chenfda87822017-06-05 14:00:3053 assert_equals(pc.signalingState, 'have-local-offer');
54 assert_session_desc_equals(pc.localDescription, offer);
55 assert_session_desc_equals(pc.pendingLocalDescription, offer);
56 assert_equals(pc.currentLocalDescription, null);
Philipp Hanckeeb37a992018-05-30 15:55:0257
58 assert_array_equals(states, ['have-local-offer']);
Soares Chenfda87822017-06-05 14:00:3059 }));
60 }, 'createOffer() and then setLocalDescription() should succeed');
61
62 promise_test(t => {
63 const pc = new RTCPeerConnection();
64 pc.close();
65
66 return promise_rejects(t, 'InvalidStateError',
67 pc.createOffer());
68 }, 'createOffer() after connection is closed should reject with InvalidStateError');
69
Soares Chenfda87822017-06-05 14:00:3070 /*
71 * Final steps to create an offer
72 * 2. If connection was modified in such a way that additional inspection of the
73 * system state is necessary, then in parallel begin the steps to create an
74 * offer again, given p, and abort these steps.
75 *
76 * This test might hit step 2 of final steps to create an offer. But the media stream
77 * is likely added already by the time steps to create an offer is executed, because
78 * that is enqueued as an operation.
79 * Either way it verifies that the media stream is included in the offer even though
80 * the stream is added after synchronous call to createOffer.
81 */
82 promise_test(t => {
83 const pc = new RTCPeerConnection();
84 const promise = pc.createOffer();
85
86 pc.addTransceiver('audio');
87 return promise.then(offer => {
88 assert_equals(countAudioLine(offer.sdp), 1,
89 'Expect m=audio line to be found in offer SDP')
90 });
91 }, 'When media stream is added when createOffer() is running in parallel, the result offer should contain the new media stream');
92
93 /*
94 * TODO
95 * 4.3.2 createOffer
96 * 3. If connection is configured with an identity provider, and an identity
97 * assertion has not yet been generated using said identity provider, then
98 * begin the identity assertion request process if it has not already begun.
99 * Steps to create an offer
100 * 1. If the need for an identity assertion was identified when createOffer was
101 * invoked, wait for the identity assertion request process to complete.
102 *
103 * Non-Testable
104 * 4.3.2 createOffer
105 * Steps to create an offer
106 * 4. Inspect the system state to determine the currently available resources as
107 * necessary for generating the offer, as described in [JSEP] (section 4.1.6.).
108 * 5. If this inspection failed for any reason, reject p with a newly created
109 * OperationError and abort these steps.
110 */
111
112 /*
113 * 4.3.3.2 Configuration data extensions
114 * partial dictionary RTCOfferOptions
115 */
116
117 /*
118 * offerToReceiveAudio of type boolean
119 * When this is given a non-false value, no outgoing track of type
120 * "audio" is attached to the PeerConnection, and the existing
121 * localDescription (if any) doesn't contain any sendrecv or recv
122 * audio media sections, createOffer() will behave as if
123 * addTransceiver("audio") had been called once prior to the createOffer() call.
124 */
125 promise_test(t => {
126 const pc = new RTCPeerConnection();
127
128 return pc.createOffer({ offerToReceiveAudio: true })
129 .then(offer1 => {
130 assert_equals(countAudioLine(offer1.sdp), 1,
131 'Expect created offer to have audio line');
132
133 // The first createOffer implicitly calls addTransceiver('audio'),
134 // so all following offers will also have audio media section
135 // in their SDP.
136 return pc.createOffer({ offerToReceiveAudio: false })
137 .then(offer2 => {
138 assert_equals(countAudioLine(offer2.sdp), 1,
139 'Expect audio line to remain in created offer');
140 })
141 });
142 }, 'createOffer() with offerToReceiveAudio should add audio line to all subsequent created offers');
143
144 /*
145 * offerToReceiveVideo of type boolean
146 * When this is given a non-false value, and no outgoing track
147 * of type "video" is attached to the PeerConnection, and the
148 * existing localDescription (if any) doesn't contain any sendecv
149 * or recv video media sections, createOffer() will behave as if
150 * addTransceiver("video") had been called prior to the createOffer() call.
151 */
152 promise_test(t => {
153 const pc = new RTCPeerConnection();
154
155 return pc.createOffer({ offerToReceiveVideo: true })
156 .then(offer1 => {
157 assert_equals(countVideoLine(offer1.sdp), 1,
158 'Expect created offer to have video line');
159
160 return pc.createOffer({ offerToReceiveVideo: false })
161 .then(offer2 => {
162 assert_equals(countVideoLine(offer2.sdp), 1,
163 'Expect video line to remain in created offer');
164 })
165 });
166 }, 'createOffer() with offerToReceiveVideo should add video line to all subsequent created offers');
167
168 promise_test(t => {
169 const pc = new RTCPeerConnection();
170
171 return pc.createOffer({
172 offerToReceiveAudio: true,
173 offerToReceiveVideo: false
174 }).then(offer1 => {
175 assert_equals(countAudioLine(offer1.sdp), 1,
176 'Expect audio line to be found in created offer');
177
178 assert_equals(countVideoLine(offer1.sdp), 0,
179 'Expect video line to not found in create offer');
180
181 return pc.createOffer({
182 offerToReceiveAudio: false,
183 offerToReceiveVideo: true
184 }).then(offer2 => {
185 assert_equals(countAudioLine(offer2.sdp), 1,
186 'Expect audio line to remain in created offer');
187
188 assert_equals(countVideoLine(offer2.sdp), 1,
189 'Expect video line to be found in create offer');
190 })
191 });
192 }, 'createOffer() with offerToReceiveAudio:true then offerToReceiveVideo:true should have result offer with both audio and video line');
193
194</script>