Bug 1211959 - Tests check if video has started using played range. r?AutomatedTester
Previously the tests would check if playback had started by looking at the first
recorded time, and then looking at the current time. If there were a lag it was
possible for the first recorded time to be at the end of the video (i.e.
playback already finished), in which case the video playing would not register.
This patch instead uses the played ranges from the video element. Now so long as
there is a non-empty played range we trust playback started.
MozReview-Commit-ID: 5C39A42KRdj
--- a/dom/media/test/external/external_media_tests/media_utils/video_puppeteer.py
+++ b/dom/media/test/external/external_media_tests/media_utils/video_puppeteer.py
@@ -84,23 +84,23 @@ class VideoPuppeteer(object):
'Using first.')
if len(videos_found) <= 0:
self.marionette.log(type(self).__name__ + ': no video '
'elements found.')
return
self.video = videos_found[0]
self.marionette.execute_script("log('video element obtained');")
if autostart:
- self.start();
+ self.start()
def start(self):
# To get an accurate expected_duration, playback must have started
wait = Wait(self, timeout=self.timeout)
- verbose_until(wait, self, lambda v: v.current_time > 0,
- "Check if video current_time > 0")
+ verbose_until(wait, self, playback_started,
+ "Check if video has played some range")
self._start_time = self.current_time
self._start_wall_time = clock()
self.update_expected_duration()
def update_expected_duration(self):
"""
Update the duration of the target video at self.test_url (in seconds).
@@ -169,16 +169,30 @@ class VideoPuppeteer(object):
def remaining_time(self):
"""
:return: How much time is remaining given the duration of the video
and the duration that has been set.
"""
return self.expected_duration - self.current_time
@property
+ def played(self):
+ """
+ :return: A TimeRanges objected containing the played time ranges.
+ """
+ raw_time_ranges = self.execute_video_script(
+ 'var played = arguments[0].wrappedJSObject.played;'
+ 'var timeRanges = [];'
+ 'for (var i = 0; i < played.length; i++) {'
+ 'timeRanges.push([played.start(i), played.end(i)]);'
+ '}'
+ 'return [played.length, timeRanges];')
+ return TimeRanges(raw_time_ranges[0], raw_time_ranges[1])
+
+ @property
def video_src(self):
"""
:return: The url of the actual video file, as opposed to the url
of the page with the video element.
"""
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
return self.video.get_attribute('src')
@@ -272,28 +286,51 @@ class VideoPuppeteer(object):
class VideoException(Exception):
"""
Exception class to use for video-specific error processing.
"""
pass
+class TimeRanges:
+ """
+ Class to represent the TimeRanges data returned by played(). Exposes a
+ similar interface to the JavaScript TimeRanges object.
+ """
+ def __init__(self, length, ranges):
+ self.length = length
+ self.ranges = [(pair[0], pair[1]) for pair in ranges]
+
+ def __repr__(self):
+ return 'TimeRanges: length: {}, ranges: {}'\
+ .format(self.length, self.ranges)
+
+ def start(self, index):
+ return self.ranges[index][0]
+
+ def end(self, index):
+ return self.ranges[index][1]
+
+
def playback_started(video):
"""
Determine if video has started
:param video: The VideoPuppeteer instance that we are interested in.
:return: True if is playing; False otherwise
"""
try:
- return video.current_time > video._start_time
+ played_ranges = video.played
+ return played_ranges.length > 0 and \
+ played_ranges.start(0) < played_ranges.end(0) and \
+ played_ranges.end(0) > 0.0
except Exception as e:
- print ('Got exception %s' % e)
+ print ('Got exception {}'.format(e))
return False
def playback_done(video):
"""
If we are near the end and there is still a video element, then
we are essentially done. If this happens to be last time we are polled
before the video ends, we won't get another chance.