Home | History | Annotate | Download | only in functional
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import re
      7 import time
      8 
      9 import pyauto_functional
     10 import pyauto
     11 import pyauto_errors
     12 import test_utils
     13 
     14 
     15 class YoutubeTestHelper():
     16   """Helper functions for Youtube tests.
     17 
     18   For sample usage, look at class YoutubeTest.
     19   """
     20 
     21   # YouTube player states
     22   is_unstarted = '-1'
     23   is_playing = '1'
     24   is_paused = '2'
     25   has_ended = '0'
     26   _pyauto = None
     27 
     28   def __init__(self, pyauto):
     29     self._pyauto = pyauto
     30 
     31   def IsFlashPluginEnabled(self):
     32     """Verify flash plugin availability and its state."""
     33     return [x for x in self._pyauto.GetPluginsInfo().Plugins() \
     34             if x['name'] == 'Shockwave Flash' and x['enabled']]
     35 
     36   def AssertPlayerState(self, state, msg):
     37     expected_regex = '^%s$' % state
     38     self.WaitForDomNode('id("playerState")', expected_value=expected_regex,
     39                         msg=msg)
     40 
     41   def WaitUntilPlayerReady(self):
     42     """Verify that player is ready."""
     43     self.AssertPlayerState(state=self.is_unstarted,
     44                            msg='Failed to load youtube player.')
     45 
     46   def GetPlayerState(self):
     47     """Returns a player state."""
     48     js = """
     49         var val = ytplayer.getPlayerState();
     50         window.domAutomationController.send(val + '');
     51     """
     52     return self._pyauto.ExecuteJavascript(js)
     53 
     54   def GetVideoInfo(self):
     55     """Returns Youtube video info."""
     56     youtube_apis = self._pyauto.GetPrivateInfo()['youtube_api']
     57     youtube_debug_text = youtube_apis['GetDebugText']
     58     return  self._pyauto.ExecuteJavascript(
     59         'window.domAutomationController.send(%s);' % youtube_debug_text)
     60 
     61   def GetVideoDroppedFrames(self):
     62     """Returns total Youtube video dropped frames.
     63 
     64     Returns:
     65       -1 if failed to get video frames from the video data
     66     """
     67     video_data = self._pyauto.GetVideoInfo()
     68     matched = re.search('droppedFrames=([\d\.]+)', video_data)
     69     if matched:
     70       return int(matched.group(1))
     71     else:
     72       return -1
     73 
     74   def GetVideoFrames(self):
     75     """Returns Youtube video frames/second.
     76 
     77     Returns:
     78       -1 if failed to get droppd frames from the video data.
     79     """
     80     video_data = self._pyauto.GetVideoInfo()
     81     matched = re.search('videoFps=([\d\.]+)', video_data)
     82     if matched:
     83       return int(matched.group(1))
     84     else:
     85       return -1
     86 
     87   def GetVideoTotalBytes(self):
     88     """Returns video total size in bytes.
     89 
     90     To call this function, video must be in the paying state,
     91     or this returns 0.
     92     """
     93     total_bytes = 0
     94     total_bytes = self._pyauto.ExecuteJavascript("""
     95         bytesTotal = document.getElementById("bytesTotal");
     96         window.domAutomationController.send(bytesTotal.innerHTML);
     97     """)
     98     return int(total_bytes)
     99 
    100   def GetVideoLoadedBytes(self):
    101     """Returns video size in bytes."""
    102     loaded_bytes = 0
    103     loaded_bytes = self.ExecuteJavascript("""
    104         bytesLoaded = document.getElementById("bytesLoaded");
    105         window.domAutomationController.send(bytesLoaded.innerHTML);
    106     """)
    107     return int(loaded_bytes)
    108 
    109   def GetCurrentVideoTime(self):
    110     """Returns the current time of the video in seconds."""
    111     current_time = 0
    112     current_time = self.ExecuteJavascript("""
    113         videoCurrentTime = document.getElementById("videoCurrentTime");
    114         window.domAutomationController.send(videoCurrentTime.innerHTML);
    115     """)
    116     return int(current_time)
    117 
    118   def PlayVideo(self):
    119     """Plays the loaded video."""
    120     self._pyauto.ExecuteJavascript("""
    121         ytplayer.playVideo();
    122         window.domAutomationController.send('');
    123     """)
    124 
    125   def StopVideo(self):
    126     """Stops the video and cancels loading."""
    127     self._pyauto.ExecuteJavascript("""
    128         ytplayer.stopVideo();
    129         window.domAutomationController.send('');
    130     """)
    131 
    132   def PauseVideo(self):
    133     """Pause the video."""
    134     self.ExecuteJavascript("""
    135         ytplayer.pauseVideo();
    136         window.domAutomationController.send('');
    137     """)
    138 
    139   def PlayVideoAndAssert(self, youtube_video='zuzaxlddWbk',
    140                          ignore_assert=False):
    141     """Start video and assert the playing state.
    142 
    143     By default test uses http://www.youtube.com/watch?v=zuzaxlddWbki.
    144 
    145     Args:
    146       youtube_video: The string ID of the youtube video to play.
    147       ignore_assert: flag to ignore the assertion and continue the test. 
    148     """
    149     self._pyauto.assertTrue(self._pyauto.IsFlashPluginEnabled(),
    150         msg='From here Flash plugin is disabled or not available.')
    151     url = self._pyauto.GetHttpURLForDataPath(
    152         'media', 'youtube.html?video=' + youtube_video)
    153     self._pyauto.NavigateToURL(url)
    154     self.WaitUntilPlayerReady()
    155     i = 0
    156     # The YouTube player will get in a state where it does not return the
    157     # number of loaded bytes.  When this happens we need to reload the page
    158     # before starting the test.
    159     while self.GetVideoLoadedBytes() == 1 and i < 30:
    160       self._pyauto.NavigateToURL(url)
    161       self.WaitUntilPlayerReady()
    162       i = i + 1
    163     self.PlayVideo()
    164     if ignore_assert:
    165       return self.is_playing
    166     self.AssertPlayerState(state=self.is_playing,
    167                            msg='Player did not enter the playing state.')
    168 
    169   def VideoBytesLoadingAndAssert(self):
    170     """Assert the video loading."""
    171     total_bytes = self.GetVideoTotalBytes()
    172     prev_loaded_bytes = 0
    173     loaded_bytes = 0
    174     count = 0
    175     while loaded_bytes < total_bytes:
    176       # We want to test bytes loading only twice
    177       count = count + 1
    178       if count == 2:
    179         break
    180       loaded_bytes = self.GetVideoLoadedBytes()
    181       self.assertTrue(prev_loaded_bytes <= loaded_bytes)
    182       prev_loaded_bytes = loaded_bytes
    183       # Give some time to load a video
    184       time.sleep(1)
    185 
    186   def PlayFAVideo(self):
    187     """Play and assert FA video playing.
    188        
    189     We are using multiple test videos in case any FA video playback fails
    190     becuase other tests are palying the same video and the test gets the
    191     simultaneous playback error.
    192     """
    193     fa_videos = ('APRpcscmbY0', 'yQqvrED-np0', 'KJuFw6hQdNY',
    194                  'BeFQbgxr_9g', 'L6JwlOudqA4')
    195     credentials = self.GetPrivateInfo()['test_fa_account']
    196     test_utils.GoogleAccountsLogin(self,
    197         credentials['username'], credentials['password'])
    198     for video in fa_videos:
    199       result = self.PlayVideoAndAssert(video, ignore_assert=True)
    200       if result is self.is_playing:
    201         return
    202     self.assertTrue(False, msg='Player did not enter the playing state.')
    203 
    204 
    205 class YoutubeTest(pyauto.PyUITest, YoutubeTestHelper):
    206   """Test case for Youtube videos."""
    207 
    208   def __init__(self, methodName='runTest', **kwargs):
    209     pyauto.PyUITest.__init__(self, methodName, **kwargs)
    210     YoutubeTestHelper.__init__(self, self)
    211 
    212   def testPlayerStatus(self):
    213     """Test that YouTube loads a player and changes player states.
    214 
    215     Test verifies various player states like unstarted, playing, paused
    216     and ended.
    217     """
    218     # Navigating to Youtube video. This video is 122 seconds long.
    219     # During tests, we are not goinig to play this video full.
    220     self.PlayVideoAndAssert()
    221     self.PauseVideo()
    222     self.AssertPlayerState(state=self.is_paused,
    223                            msg='Player did not enter the paused state.')
    224     # Seek to the end of video
    225     self.ExecuteJavascript("""
    226         val = ytplayer.getDuration();
    227         ytplayer.seekTo(val, true);
    228         window.domAutomationController.send('');
    229     """)
    230     self.PlayVideo()
    231     # We've seeked to almost the end of the video but not quite.
    232     # Wait until the end.
    233     self.AssertPlayerState(state=self.has_ended,
    234                            msg='Player did not reach the stopped state.')
    235 
    236   def testPlayerResolution(self):
    237     """Test various video resolutions."""
    238     self.PlayVideoAndAssert()
    239     resolutions = self.ExecuteJavascript("""
    240         res = ytplayer.getAvailableQualityLevels();
    241         window.domAutomationController.send(res.toString());
    242     """)
    243     resolutions = resolutions.split(',')
    244     for res in resolutions:
    245       self.ExecuteJavascript("""
    246           ytplayer.setPlaybackQuality('%s');
    247           window.domAutomationController.send('');
    248       """ % res)
    249       curr_res = self.ExecuteJavascript("""
    250           res = ytplayer.getPlaybackQuality();
    251           window.domAutomationController.send(res + '');
    252       """)
    253       self.assertEqual(res, curr_res, msg='Resolution is not set to %s.' % res)
    254 
    255   def testPlayerBytes(self):
    256     """Test that player downloads video bytes."""
    257     self.PlayVideoAndAssert()
    258     self.VideoBytesLoadingAndAssert()
    259 
    260   def testFAVideo(self):
    261     """Test that FlashAccess/DRM video plays."""
    262     self.PlayFAVideo()
    263     self.StopVideo()
    264 
    265   def testFAVideoBytes(self):
    266     """Test FlashAccess/DRM video bytes loading."""
    267     self.PlayFAVideo()
    268     self.VideoBytesLoadingAndAssert()
    269     self.StopVideo()
    270 
    271 
    272 if __name__ == '__main__':
    273   pyauto_functional.Main()
    274