Bug 1211959 - Tests check if video has started using played range. r?AutomatedTester draft
authorBryce Van Dyk <bvandyk@mozilla.com>
Fri, 05 Aug 2016 12:38:54 +1200
changeset 397705 2d90dd7d110163bb514f6b0d0929667efe5db7e9
parent 397688 763fe887c37cee5fcfe0f00e94fdffc84a41ea1c
child 527512 f9e3a6948b493021c193043390bdd85203a16517
push id25361
push userbvandyk@mozilla.com
push dateMon, 08 Aug 2016 04:00:23 +0000
reviewersAutomatedTester
bugs1211959
milestone51.0a1
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
dom/media/test/external/external_media_tests/media_utils/video_puppeteer.py
--- 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.