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

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 and cancel tasks Created 4 years, 10 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()
35 {
36 consoleWrite("play()");
37 mediaElement.play().then(function() {
38 consoleWrite("arguments.length: " + arguments.length);
39 consoleWrite("Promise resolved with " + arguments[0]);
40 }, function(e) {
41 consoleWrite("arguments.length: " + arguments.length);
42 consoleWrite("Promise failed with " + e.name + ": " + e.message);
philipj_slow 2016/02/25 14:06:48 Off-topic: I noticed in another review that DOMExc
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 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_NOTHIN G);
84 play();
85 },
86
87 // Test that play() on an element that has enough data will return a
88 // promise that resolves successfuly.
89 function playWhenCanPlay()
90 {
91 consoleWrite("playWhenCanPlay()");
92 internals.settings.setMediaPlaybackRequiresUserGesture(false);
93
94 run("mediaElement = document.createElement('audio')");
95 var mediaFile = findMediaFile("audio", "content/test");
96 run("mediaElement.src = '" + mediaFile + "'");
97
98 waitForEvent('playing');
99
100 waitForEvent('canplay', function() {
101 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_FU TURE_DATA, ">=");
102 testExpected("mediaElement.paused", true);
103
104 play();
105 });
106 },
107
108 function playAfterPlaybackStarted()
109 {
110 consoleWrite("playAfterPlaybackStarted()");
111 internals.settings.setMediaPlaybackRequiresUserGesture(false);
112
113 run("mediaElement = document.createElement('audio')");
114 mediaElement.preload = "auto";
115 var mediaFile = findMediaFile("audio", "content/test");
116 run("mediaElement.src = '" + mediaFile + "'");
117
118 waitForEvent('playing', function() {
119 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_EN OUGH_DATA);
120 testExpected("mediaElement.paused", false);
121
122 play();
123 });
124
125 waitForEvent('canplaythrough', function() {
126 run("mediaElement.play()");
127 });
128 },
129
130 // Test that play() on an element when media playback requires a gesture
131 // returns a resolved promise if there is a user gesture.
132 function playRequiresUserGestureAndHasIt()
133 {
134 consoleWrite("playRequiresUserGestureAndHasIt()");
135 internals.settings.setMediaPlaybackRequiresUserGesture(true);
136
137 run("mediaElement = document.createElement('audio')");
138 var mediaFile = findMediaFile("audio", "content/test");
139 run("mediaElement.src = '" + mediaFile + "'");
140
141 waitForEvent('playing');
142 playWithUserGesture();
143 },
144
145 // Test that play() on an element when media playback requires a gesture
146 // returns a rejected promise if there is no user gesture.
147 function playRequiresUserGestureAndDoesNotHaveIt()
148 {
149 consoleWrite("playRequiresUserGestureAndDoesNotHaveIt()");
150 internals.settings.setMediaPlaybackRequiresUserGesture(true);
151
152 run("mediaElement = document.createElement('audio')");
153 var mediaFile = findMediaFile("audio", "content/test");
154 run("mediaElement.src = '" + mediaFile + "'");
155
156 waitForEvent('playing');
157 play();
158 },
159
160 // Test that play() on an element with an unsupported content will
161 // return a rejected promise.
162 function playNotSupportedContent()
163 {
164 consoleWrite("playNotSupportedContent()");
165 internals.settings.setMediaPlaybackRequiresUserGesture(false);
166
167 run("mediaElement = document.createElement('audio')");
168 var mediaFile = findMediaFile("audio", "data:,");
169 run("mediaElement.src = '" + mediaFile + "'");
170
171 waitForEvent('playing');
172 waitForEvent('error', function() {
173 testExpected("mediaElement.error", "[object MediaError]");
174 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
175 });
176 play();
177 },
178
179 // Test that play() returns a resolved promise if called after the
180 // element suffered from a decode error.
181 // This test doesn't test a spec behaviour but tests that the Blink
182 // implementation properly changed after the spec changed.
183 function playDecodeError()
184 {
185 consoleWrite("playDecodeError()");
186 internals.settings.setMediaPlaybackRequiresUserGesture(false);
187
188 run("mediaElement = document.createElement('audio')");
189 var mediaFile = findMediaFile("audio", "content/test");
190 run("mediaElement.src = '" + mediaFile + "'");
191
192 waitForEvent('playing');
193 waitForEvent('error', function() {
194 testExpected("mediaElement.error", "[object MediaError]");
195 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_DEC ODE);
196 });
197
198 // The setMediaElementNetworkState() method requires metadata to be
199 // available.
200 waitForEvent('loadedmetadata', function() {
201 internals.setMediaElementNetworkState(mediaElement, 6 /* NetworkSt ateDecodeError */);
202 play();
203 });
204 },
205
206 // Test that play() returns a resolved promise if called after the
207 // element suffered from a network error.
208 // This test doesn't test a spec behaviour but tests that the Blink
209 // implementation properly changed after the spec changed
210 function playNetworkError()
211 {
212 consoleWrite("playNetworkError()");
213 internals.settings.setMediaPlaybackRequiresUserGesture(false);
214
215 run("mediaElement = document.createElement('audio')");
216 var mediaFile = findMediaFile("audio", "content/test");
217 run("mediaElement.src = '" + mediaFile + "'");
218
219 waitForEvent('playing');
220 waitForEvent('error', function() {
221 testExpected("mediaElement.error", "[object MediaError]");
222 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_NET WORK);
223 });
224
225 // The setMediaElementNetworkState() method requires metadata to be
226 // available.
227 waitForEvent('loadedmetadata', function() {
228 internals.setMediaElementNetworkState(mediaElement, 5 /* NetworkSt ateNetworkError */);
229 play();
230 });
231 },
232
233 // Test that play() returns a rejected promise if the element is
234 // suferring from a not supported error.
235 function playWithErrorAlreadySet()
236 {
237 consoleWrite("playWithErrorAlreadySet()");
238 internals.settings.setMediaPlaybackRequiresUserGesture(false);
239
240 run("mediaElement = document.createElement('audio')");
241 var mediaFile = findMediaFile("audio", "data:,");
242 run("mediaElement.src = '" + mediaFile + "'");
243
244 waitForEvent('playing');
245 waitForEvent('error', function() {
246 testExpected("mediaElement.error", "[object MediaError]");
247 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
248 play();
249 });
250 },
251
252 // Test that play() returns a resolved promise if the element had its
253 // source changed after suffering from an error.
254 function playSrcChangedAfterError()
255 {
256 consoleWrite("playSrcChangedAfterError()");
257 internals.settings.setMediaPlaybackRequiresUserGesture(false);
258
259 run("mediaElement = document.createElement('audio')");
260 var mediaFile = findMediaFile("audio", "data:,");
261 run("mediaElement.src = '" + mediaFile + "'");
262
263 waitForEvent('error', function() {
264 testExpected("mediaElement.error", "[object MediaError]");
265 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
266
267 mediaFile = findMediaFile("audio", "content/test");
268 run("mediaElement.src = '" + mediaFile + "'");
269
270 waitForEvent('playing');
271 waitForEvent('loadedmetadata', function() {
272 play();
273 });
274 });
275 },
276
277 // Test that play() returns a rejected promise if the element had an
278 // error and just changed its source.
279 function playRaceWithSrcChangeError()
280 {
281 consoleWrite("playRaceWithSrcChangeError()");
282 internals.settings.setMediaPlaybackRequiresUserGesture(false);
283
284 run("mediaElement = document.createElement('audio')");
285 var mediaFile = findMediaFile("audio", "data:,");
286 run("mediaElement.src = '" + mediaFile + "'");
287
288 waitForEvent('error', function() {
289 testExpected("mediaElement.error", "[object MediaError]");
290 testExpected("mediaElement.error.code", MediaError.MEDIA_ERR_SRC _NOT_SUPPORTED);
291
292 mediaFile = findMediaFile("audio", "content/test");
293 run("mediaElement.src = '" + mediaFile + "'");
294
295 testExpected("mediaElement.error", null);
296 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_NO THING);
297
298 waitForEvent('playing');
299 play();
300 });
301 },
302
303 // Test that play() returns a resolved promise when calling play() then
304 // pause() on an element that already has enough data to play. In other
305 // words, pause() doesn't cancel play() because it was resolved
306 // immediately.
307 function playAndPauseWhenCanPlay()
308 {
309 consoleWrite("playAndPauseWhenCanPlay()");
310 internals.settings.setMediaPlaybackRequiresUserGesture(false);
311
312 run("mediaElement = document.createElement('audio')");
313 var mediaFile = findMediaFile("audio", "content/test");
314 run("mediaElement.src = '" + mediaFile + "'");
315
316 waitForEvent('canplaythrough', function() {
317 waitForEvent('playing');
318 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_EN OUGH_DATA);
319 play();
320 testExpected("mediaElement.paused", false);
321 mediaElement.pause();
322 testExpected("mediaElement.paused", true);
323 });
324 },
325
326 // Test that play() returns a rejected promise when calling play() then
327 // pause() on an element that doesn't have enough data to play. In other
328 // words, pause() cancels play() before it can be resolved.
329 function playAndPauseBeforeCanPlay()
330 {
331 consoleWrite("playAndPauseBeforeCanPlay()");
332 internals.settings.setMediaPlaybackRequiresUserGesture(false);
333
334 run("mediaElement = document.createElement('audio')");
335
336 waitForEvent('playing');
337 testExpected("mediaElement.readyState", HTMLMediaElement.HAVE_NOTHIN G);
338 play();
339 testExpected("mediaElement.paused", false);
340 mediaElement.pause();
341 testExpected("mediaElement.paused", true);
342 },
343
344 // Test that load() rejects all the pending play() promises.
345 // This might be tested by other tests in this file but it is present in
346 // order to be explicit.
347 function loadRejectsPendingPromises()
348 {
349 consoleWrite("loadRejectsPendingPromises()");
350 internals.settings.setMediaPlaybackRequiresUserGesture(false);
351
352 run("mediaElement = document.createElement('audio')");
353
354 play(); // the promise will be left pending.
355
356 waitForEvent('playing');
357 run("mediaElement.load()");
358 },
359
360 // Test that changing the src rejects the pending play() promises.
361 function newSrcRejectPendingPromises()
362 {
363 consoleWrite("newSrcRejectPendingPromises()");
364 internals.settings.setMediaPlaybackRequiresUserGesture(false);
365
366 run("mediaElement = document.createElement('audio')");
367
368 play(); // the promise will be left pending.
369
370 var mediaFile = findMediaFile("audio", "content/test");
371 run("mediaElement.src = '" + mediaFile + "'");
372 },
373
374 // Test ordering of events and promises.
375 // This is testing a bug in Blink, see https://crbug.com/587871
376 function testEventAndPromiseOrdering()
377 {
378 consoleWrite("testEventAndPromiseOrdering");
379 internals.settings.setMediaPlaybackRequiresUserGesture(false);
380
381 run("mediaElement = document.createElement('audio')");
382 run("mediaElement.src = 'data:,'");
383
384 waitForEvent('error', function() {
385 // Until https://crbug.com/587871 is fixed, the events will be
386 // [ volumechange, volumechange, promise ], it should be
387 // [ volumechange, promise, volumechange ].
388 waitForEvent('volumechange');
389 run("mediaElement.volume = 0.1");
390 play();
391 run("mediaElement.volume = 0.2");
392 });
393
394 }
395 ];
396
397 function start()
398 {
399 if (!('eventSender' in window) || !('internals' in window)) {
400 failTest("Not running in LayoutTests.");
401 return;
402 }
403 runNextTestOrFinish();
404 }
405
406 </script>
407 </head>
408
409 <body onload="start()">
410
411 <p>Test the play() behaviour with regards to the returned promise for media elem ents.</p>
412
413 </body>
414 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698