| OLD | NEW |
| 1 <video></video> | 1 <!DOCTYPE html> |
| 2 <p>Test that stalled, timeupdate and waiting events are sent when media load sta
lls in the middle.</p> | 2 <title>Test that stalled, timeupdate and waiting events are sent when media load
stalls in the middle.</title> |
| 3 <video id="test_video"></video> |
| 4 <div id="log_console"></div> |
| 3 <script src=../../media-resources/media-file.js></script> | 5 <script src=../../media-resources/media-file.js></script> |
| 4 <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 | 6 <script src="/w3c/resources/testharness.js"></script> |
| 5 (Please avoid writing new tests using video-test.js) --> | 7 <script src="/w3c/resources/testharnessreport.js"></script> |
| 6 <script src=../../media-resources/video-test.js></script> | |
| 7 <script> | 8 <script> |
| 9 async_test(t => { |
| 10 let video = document.getElementById('test_video'); |
| 11 let log_console = document.getElementById('log_console'); |
| 8 | 12 |
| 9 var timeupdateCount = 0; | 13 // For debugging. |
| 10 var waitingCount = 0; | 14 function logEvent(e) { |
| 15 let span = document.createElement("span"); |
| 16 span.innerHTML = 'event: ' + e.type + '<br>'; |
| 17 log_console.appendChild(span); |
| 18 }; |
| 11 | 19 |
| 12 waitForEvent('durationchange'); | 20 playback_ew = new EventWatcher(t, video, [ |
| 13 waitForEvent('loadedmetadata'); | 21 'canplay', |
| 14 waitForEvent('loadeddata'); | 22 'canplaythrough', |
| 15 waitForEvent('canplaythrough'); | 23 'durationchange', |
| 16 waitForEvent('canplay', function () { | 24 'loadedmetadata', |
| 25 'loadeddata', |
| 26 'play', |
| 27 'playing', |
| 28 'waiting']); |
| 17 | 29 |
| 18 mediaElement.addEventListener('timeupdate', function () { | 30 // The stalled event needs a separate watcher as it can be fired at any |
| 19 // timeupdate events are fired as playback progresses so only verify
that at least one | 31 // point during the sequence of other playback events. Stalled is triggered |
| 20 // event is fired | 32 // by prolonged network inactivity. |
| 21 ++timeupdateCount; | 33 stalled_ew = new EventWatcher(t, video, [ |
| 22 if (timeupdateCount == 1) | 34 'stalled']); |
| 23 consoleWrite("EVENT(timeupdate)"); | |
| 24 } ); | |
| 25 | 35 |
| 26 waitForEvent('waiting', function () { | 36 // This helper is an alternative to EventWatcher for events that fire on a |
| 27 ++waitingCount; | 37 // recurring basis. EventWatcher is not suitable because you must always be |
| 28 if (waitingCount > 1) | 38 // "waiting" for the event to fire every time, whereas this method allows |
| 29 failTest("too many 'waiting' events fired."); | 39 // you to just verify that it fired once and move on. |
| 40 function waitForRecurringEvent(name) { |
| 41 let resolve_cb; |
| 42 let promise = new Promise(function(resolve, reject) { |
| 43 resolve_cb = resolve; |
| 44 }); |
| 45 video.addEventListener(name, t.step_func((evt) => resolve_cb(evt))); |
| 46 return promise; |
| 47 } |
| 30 | 48 |
| 31 waitForEvent('timeupdate'); | 49 // NOTE: Event sequence verification is achieved by chaining together |
| 32 } ); | 50 // promises via then(). To verify separate parallel event sequences (e.g. |
| 51 // playback vs network), we setup separate chains of promises. Promise.all |
| 52 // ensures that all separate sequences complete. |
| 33 | 53 |
| 34 waitForEventAndEnd('stalled'); | 54 // Verify playback progresses then runs out of data. |
| 35 } ); | 55 Promise.all([ |
| 56 // First wait for the resource to load. |
| 57 playback_ew.wait_for('durationchange').then(logEvent) |
| 58 .then(() => playback_ew.wait_for('loadedmetadata')).then(logEvent) |
| 59 .then(() => playback_ew.wait_for('loadeddata')).then(logEvent) |
| 60 .then(() => playback_ew.wait_for('canplay')).then(logEvent) |
| 61 .then(() => playback_ew.wait_for('canplaythrough')).then(logEvent) |
| 62 .then(t.step_func(function() { |
| 63 assert_true(video.readyState > HTMLMediaElement.HAVE_CURRENT_DAT
A); |
| 64 })) |
| 65 // Now play the file and wait for playback to stall (fire waiting). |
| 66 .then(t.step_func(function() { |
| 67 video.play(); |
| 68 // NOTE: setting the wait_for here because we will miss it if we
do |
| 69 // it after the play call resolves its promise. |
| 70 return playback_ew.wait_for('play').then(logEvent); |
| 71 })) |
| 72 .then(() => playback_ew.wait_for('playing')).then(logEvent) |
| 73 // Now observe waiting event and verify readyState |
| 74 .then(() => playback_ew.wait_for('waiting')).then(logEvent) |
| 75 .then(t.step_func(function(){ |
| 76 assert_equals(HTMLMediaElement.HAVE_CURRENT_DATA, video.readySta
te); |
| 77 })), |
| 78 |
| 79 // timeupdate should fire throughout playback. Make sure we see one. |
| 80 waitForRecurringEvent('timeupdate').then(logEvent), |
| 81 |
| 82 // progress should fire throughout download. Make sure we see one. |
| 83 // Later the download should stall. |
| 84 waitForRecurringEvent('progress').then(logEvent) |
| 85 .then(() => stalled_ew.wait_for('stalled')).then(logEvent) |
| 86 |
| 87 // Verify download and playback resume. |
| 88 ]).then(() => Promise.all([ |
| 89 // Playback should resume when download again makes progress. |
| 90 waitForRecurringEvent('progress').then(logEvent), |
| 91 |
| 92 // timeupdate should fire throughout playback. Make sure we see one. |
| 93 waitForRecurringEvent('timeupdate').then(logEvent), |
| 94 |
| 95 // Verify correct sequence of playback events. |
| 96 playback_ew.wait_for('canplay').then(logEvent) |
| 97 .then(t.step_func(function() { |
| 98 assert_true(video.readyState > HTMLMediaElement.HAVE_CURRENT_DAT
A); |
| 99 })) |
| 100 .then(() => playback_ew.wait_for('playing')).then(logEvent) |
| 101 .then(() => playback_ew.wait_for('canplaythrough')).then(logEvent) |
| 102 ])).then(t.step_func_done()); |
| 103 |
| 36 | 104 |
| 37 // Find a supported media file. | 105 // Find a supported media file. |
| 38 var mediaFile = findMediaFile("video", "content/test"); | 106 var mediaFile = findMediaFile("video", "content/test"); |
| 39 var mimeType = mimeTypeForFile(mediaFile); | 107 var mimeType = mimeTypeForFile(mediaFile); |
| 108 // URL will load part of the file, pause for 8 seconds, then load the rest. |
| 109 // The delay of 8 seconds is chosen to reduce flakiness in waiting for the |
| 110 // stalled event, which should arrive after roughly 3 seconds of inactivity. |
| 111 video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../.
./media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000&stallFor=8"; |
| 40 | 112 |
| 41 video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../.
./media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000&stallFor=6"; | 113 }, "Stalled download pauses playback. When download resumes playback continues.
Verify events and readyStates."); |
| 42 run("video.play()"); | |
| 43 </script> | 114 </script> |
| OLD | NEW |