Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: third_party/WebKit/LayoutTests/media/media-play-promise.html

Issue 1576283003: Have HTMLMediaElement::play() return a Promise. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review comments Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <html>
2 <head>
3 <script src=media-file.js></script>
4 <!-- TODO(mlamouri): use testharness.js, see https://crbug.com/588956 -->
5 <script src=video-test.js></script>
6
7 <script>
8 // This is testing the behavior of play() with regards to the returned
9 // promise. This test file is creating a small framework in order to be able
10 // to test different cases easily and independently of each other.
11 //
12 // All tests have to be part of the TESTS array. When the page is loaded,
13 // first function in the array is run. A test is considered done when the
14 // promise returned by mediaElement.play() is resolved or rejected. Each
15 // test then needs to call play() once which wraps this logic. When a test
16 // is finished, the next test in the array is run until the entire array
17 // was processed.
18 //
19 // Each test should start by printing its name in order to facilitate readin g
20 // the output.
21
22 function runNextTestOrFinish()
23 {
24 currentTest++;
25 if (currentTest >= TESTS.length) {
26 endTest();
27 return;
28 }
29
30 consoleWrite("");
31 TESTS[currentTest]();
32 }
33
34 function play()
philipj_slow 2016/02/24 09:38:28 Maybe consoleWrite something so that one can tell
mlamouri (slow - plz ping) 2016/02/25 11:07:35 Done.
35 {
36 mediaElement.play().then(function() {
37 consoleWrite("arguments.length: " + arguments.length);
philipj_slow 2016/02/24 09:38:28 100% optional nit: If you can make it output just
mlamouri (slow - plz ping) 2016/02/25 11:07:35 I prefer to keep the consoleWrite() for the argume
philipj_slow 2016/02/25 14:06:48 Acknowledged.
38 consoleWrite("arguments[0]: " + arguments[0]);
39 consoleWrite("Promise resolved");
40 }, function(e) {
41 consoleWrite("arguments.length: " + arguments.length);
42 consoleWrite("Promise failed with " + e.name + ": " + e.message);
43 }).then(runNextTestOrFinish);
44 }
45
46 function playWithUserGesture()
47 {
48 var target = document.querySelector("p");
49 target.onclick = function() {
50 play();
51 target.onclick = null;
52 };
53
54 var boundingRect = target.getBoundingClientRect();
55 var x = boundingRect.left + (boundingRect.width / 2);
56 var y = boundingRect.top + (boundingRect.height / 2);
57
58 // Assuming running in Blink LayoutTests.
59 eventSender.mouseMoveTo(x, y);
60 eventSender.mouseDown();
61 eventSender.mouseUp();
62 }
63
64 var currentTest = -1;
65
66 var TESTS = [
67 // Test that play() on an element that doesn't have enough data will
68 // return a promise that resolves successfuly.
69 function playBeforeCanPlay()
70 {
71 consoleWrite("playBeforeCanPlay()");
72 internals.settings.setMediaPlaybackRequiresUserGesture(false);
73
74 run("mediaElement = document.createElement('audio')");
75 var mediaFile = findMediaFile("audio", "content/test");
76 run("mediaElement.src = '" + mediaFile + "'");
77
78 waitForEvent('loadedmetadata');
79 waitForEvent('loadeddata');
80 waitForEvent('canplay');
81 waitForEvent('playing');
82
83 play();
philipj_slow 2016/02/24 09:38:28 For documentation purposes, can you do `testExpect
mlamouri (slow - plz ping) 2016/02/25 11:07:35 Done.
84 },
85
86 // Test that play() on an element that has enough data will return a
87 // promise that resolves successfuly.
88 function playWhenCanPlay()
89 {
90 consoleWrite("playWhenCanPlay()");
91 internals.settings.setMediaPlaybackRequiresUserGesture(false);
92
93 run("mediaElement = document.createElement('audio')");
94 var mediaFile = findMediaFile("audio", "content/test");
95 run("mediaElement.src = '" + mediaFile + "'");
96
97 waitForEvent('playing');
98
99 waitForEvent('canplay', function() {
100 testExpected(HTMLMediaElement.HAVE_ENOUGH_DATA, mediaElement.rea dyState);
philipj_slow 2016/02/24 09:38:28 This could be flaky, readyState may only have reac
mlamouri (slow - plz ping) 2016/02/25 11:07:35 Done^2.
101 testExpected(true, mediaElement.paused)
102
103 play();
104 });
105 },
106
107 function playAfterPlaybackStarted()
108 {
109 consoleWrite("playAfterPlaybackStarted()");
110 internals.settings.setMediaPlaybackRequiresUserGesture(false);
111
112 run("mediaElement = document.createElement('audio')");
113 var mediaFile = findMediaFile("audio", "content/test");
114 run("mediaElement.src = '" + mediaFile + "'");
115
116 waitForEvent('playing', function() {
117 testExpected(HTMLMediaElement.HAVE_ENOUGH_DATA, mediaElement.rea dyState);
118 testExpected(false, mediaElement.paused)
119
120 play();
121 });
122
123 waitForEvent('canplaythrough', function() {
philipj_slow 2016/02/24 09:38:28 For good measure, when depending on canplaythrough
mlamouri (slow - plz ping) 2016/02/25 11:07:35 I used preload = "auto". Setting autoplay sounds l
philipj_slow 2016/02/25 14:06:48 Since you wait for the playing event it wouldn't a
124 run("mediaElement.play()");
125 });
126 },
127
128 // Test that play() on an element when media playback requires a gesture
129 // returns a resolved promise if there is a user gesture.
130 function playRequiresUserGestureAndHasIt()
131 {
132 consoleWrite("playRequiresUserGestureAndHasIt()");
133 internals.settings.setMediaPlaybackRequiresUserGesture(true);
134
135 run("mediaElement = document.createElement('audio')");
136 var mediaFile = findMediaFile("audio", "content/test");
137 run("mediaElement.src = '" + mediaFile + "'");
138
139 waitForEvent('playing');
140 playWithUserGesture();
141 },
142
143 // Test that play() on an element when media playback requires a gesture
144 // returns a rejected promise if there is no user gesture.
145 function playRequiresUserGestureAndDoesNotHaveIt()
146 {
147 consoleWrite("playRequiresUserGestureAndDoesNotHaveIt()");
148 internals.settings.setMediaPlaybackRequiresUserGesture(true);
149
150 run("mediaElement = document.createElement('audio')");
151 var mediaFile = findMediaFile("audio", "content/test");
152 run("mediaElement.src = '" + mediaFile + "'");
153
154 waitForEvent('playing');
155 play();
156 },
157
158 // Test that play() on an element with an unsupported content will
159 // return a rejected promise.
160 function playNotSupportedContent()
161 {
162 consoleWrite("playNotSupportedContent()");
163 internals.settings.setMediaPlaybackRequiresUserGesture(false);
164
165 run("mediaElement = document.createElement('audio')");
166 var mediaFile = findMediaFile("audio", "data:,");
167 run("mediaElement.src = '" + mediaFile + "'");
168
169 waitForEvent('playing');
170 waitForEvent('error', function() {
171 testExpected("mediaElement.error", "[object MediaError]");
172 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
173 });
174 play();
175 },
176
177 // Test that play() returns a resolved promise if called after the
178 // element suffered from a decode error.
179 // This test doesn't test a spec behaviour but tests that the Blink
180 // implementation properly changed after the spec changed.
181 function playDecodeError()
182 {
183 consoleWrite("playDecodeError()");
184 internals.settings.setMediaPlaybackRequiresUserGesture(false);
185
186 run("mediaElement = document.createElement('audio')");
187 var mediaFile = findMediaFile("audio", "content/test");
188 run("mediaElement.src = '" + mediaFile + "'");
189
190 waitForEvent('playing');
191 waitForEvent('error', function() {
192 testExpected("mediaElement.error", "[object MediaError]");
193 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_DEC ODE);
194 });
195
196 // The setMediaElementNetworkState() method requires metadata to be
197 // available.
198 waitForEvent('loadedmetadata', function() {
199 internals.setMediaElementNetworkState(mediaElement, 6 /* NetworkSt ateDecodeError */);
200 play();
201 });
202 },
203
204 // Test that play() returns a resolved promise if called after the
205 // element suffered from a network error.
206 // This test doesn't test a spec behaviour but tests that the Blink
207 // implementation properly changed after the spec changed
208 function playNetworkError()
209 {
210 consoleWrite("playNetworkError()");
211 internals.settings.setMediaPlaybackRequiresUserGesture(false);
212
213 run("mediaElement = document.createElement('audio')");
214 var mediaFile = findMediaFile("audio", "content/test");
215 run("mediaElement.src = '" + mediaFile + "'");
216
217 waitForEvent('playing');
218 waitForEvent('error', function() {
219 testExpected("mediaElement.error", "[object MediaError]");
220 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_NET WORK);
221 });
222
223 // The setMediaElementNetworkState() method requires metadata to be
224 // available.
225 waitForEvent('loadedmetadata', function() {
226 internals.setMediaElementNetworkState(mediaElement, 5 /* NetworkSt ateNetworkError */);
227 play();
228 });
229 },
230
231 // Test that play() returns a rejected promise if the element is
232 // suferring from a not supported error.
233 function playWithErrorAlreadySet()
234 {
235 consoleWrite("playWithErrorAlreadySet()");
236 internals.settings.setMediaPlaybackRequiresUserGesture(false);
237
238 run("mediaElement = document.createElement('audio')");
239 var mediaFile = findMediaFile("audio", "data:,");
240 run("mediaElement.src = '" + mediaFile + "'");
241
242 waitForEvent('playing');
243 waitForEvent('error', function() {
244 testExpected("mediaElement.error", "[object MediaError]");
245 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
246 play();
247 });
248 },
249
250 // Test that play() returns a resolved promise if the element had its
251 // source changed after suffering from an error.
252 function playSrcChangedAfterError()
253 {
254 consoleWrite("playSrcChangedAfterError()");
255 internals.settings.setMediaPlaybackRequiresUserGesture(false);
256
257 run("mediaElement = document.createElement('audio')");
258 var mediaFile = findMediaFile("audio", "data:,");
259 run("mediaElement.src = '" + mediaFile + "'");
260
261 waitForEvent('error', function() {
262 testExpected("mediaElement.error", "[object MediaError]");
263 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
264
265 mediaFile = findMediaFile("audio", "content/test");
266 run("mediaElement.src = '" + mediaFile + "'");
267
268 waitForEvent('playing');
269 waitForEvent('loadedmetadata', function() {
270 play();
271 });
272 });
273 },
274
275 // Test that play() returns a rejected promise if the element had an
276 // error and just changed its source.
277 function playRaceWithSrcChangeError()
278 {
279 consoleWrite("playRaceWithSrcChangeError()");
280 internals.settings.setMediaPlaybackRequiresUserGesture(false);
281
282 run("mediaElement = document.createElement('audio')");
283 var mediaFile = findMediaFile("audio", "data:,");
284 run("mediaElement.src = '" + mediaFile + "'");
285
286 waitForEvent('error', function() {
287 testExpected("mediaElement.error", "[object MediaError]");
288 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
289
290 mediaFile = findMediaFile("audio", "content/test");
291 run("mediaElement.src = '" + mediaFile + "'");
292
293 play();
294 });
295 },
296
297 // Test that play() returns a resolved promise when calling play() then
298 // pause() on an element that already has enough data to play. In other
299 // words, pause() doesn't cancel play() because it was resolved
300 // immediately.
301 function playAndPauseWhenCanPlay()
302 {
303 consoleWrite("playAndPauseWhenCanPlay()");
304 internals.settings.setMediaPlaybackRequiresUserGesture(false);
305
306 run("mediaElement = document.createElement('audio')");
307 var mediaFile = findMediaFile("audio", "content/test");
308 run("mediaElement.src = '" + mediaFile + "'");
309
310 waitForEvent('canplaythrough', function() {
311 waitForEvent('playing');
312 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_EN OUGH_DATA);
313 play();
314 testExpected("mediaElement.paused", false);
315 mediaElement.pause();
316 testExpected("mediaElement.paused", true);
317 });
318 },
319
320 // Test that play() returns a rejected promise when calling play() then
321 // pause() on an element that doesn't have enough data to play. In other
322 // words, pause() cancels play() before it can be resolved.
323 function playAndPauseBeforeCanPlay()
324 {
325 consoleWrite("playAndPauseBeforeCanPlay()");
326 internals.settings.setMediaPlaybackRequiresUserGesture(false);
327
328 run("mediaElement = document.createElement('audio')");
329
330 waitForEvent('playing');
331 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_NOTHIN G);
332 play();
333 testExpected("mediaElement.paused", false);
334 mediaElement.pause();
335 testExpected("mediaElement.paused", true);
336 },
337
338 // Test that load() rejects all the pending play() promises.
339 // This might be tested by other tests in this file but it is present in
340 // order to be explicit.
341 function loadRejectoPendingPromises()
philipj_slow 2016/02/24 09:38:28 Now it says Rejects with an o :)
mlamouri (slow - plz ping) 2016/02/25 11:07:35 Hmm, these two letters are not even on the same ha
342 {
343 consoleWrite("loadRejectsPendingPromises()");
344 internals.settings.setMediaPlaybackRequiresUserGesture(false);
345
346 run("mediaElement = document.createElement('audio')");
347
348 play(); // the promise will be left pending.
349
350 waitForEvent('playing');
351 run("mediaElement.load()");
352 },
353
354 // Test that changing the src rejects the pending play() promises.
355 function newSrcRejectPendingPromises()
356 {
357 consoleWrite("newSrcRejectPendingPromises()");
358 internals.settings.setMediaPlaybackRequiresUserGesture(false);
359
360 run("mediaElement = document.createElement('audio')");
361
362 play(); // the promise will be left pending.
363
364 var mediaFile = findMediaFile("audio", "content/test");
365 run("mediaElement.src = '" + mediaFile + "'");
366 },
367
368 // Test ordering of events and promises.
369 // This is testing a bug in Blink, see https://crbug.com/587871
370 function testEventAndPromiseOrdering()
371 {
372 consoleWrite("testEventAndPromiseOrdering");
373 internals.settings.setMediaPlaybackRequiresUserGesture(false);
374
375 run("mediaElement = document.createElement('audio')");
376 run("mediaElement.src = 'data:,'");
377
378 waitForEvent('error', function() {
379 // Until https://crbug.com/587871 is fixed, the events will be
380 // [ volumechange, volumechange, promise ], it should be
381 // [ volumechange, promise, volumechange ].
382 waitForEvent('volumechange');
383 run("mediaElement.volume = 0.1");
384 play();
385 run("mediaElement.volume = 0.2");
386 });
387
388 }
389 ];
390
391 function start()
392 {
393 if (!('eventSender' in window) || !('internals' in window)) {
394 failTest("Not running in LayoutTests.");
395 return;
396 }
397 runNextTestOrFinish();
398 }
399
400 </script>
401 </head>
402
403 <body onload="start()">
404
405 <p>Test the play() behaviour with regards to the returned promise for media elem ents.</p>
406
407 </body>
408 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698