--- a/dom/media/test/external/external_media_tests/media_utils/youtube_puppeteer.py
+++ b/dom/media/test/external/external_media_tests/media_utils/youtube_puppeteer.py
@@ -10,19 +10,26 @@ from marionette import Marionette
from marionette_driver import By, expected, Wait
from marionette_driver.errors import TimeoutException, NoSuchElementException
from video_puppeteer import VideoPuppeteer, VideoException
from external_media_tests.utils import verbose_until
class YouTubePuppeteer(VideoPuppeteer):
"""
- Wrapper around a YouTube #movie_player element.
+ Wrapper around a YouTube .html5-video-player element.
- Partial reference: https://developers.google.com/youtube/js_api_reference.
+ Can be used with youtube videos or youtube videos at embedded URLS. E.g.
+ both https://www.youtube.com/watch?v=AbAACm1IQE0 and
+ https://www.youtube.com/embed/AbAACm1IQE0 should work.
+
+ Using an embedded video has the advantage of not auto-playing more videos
+ while a test is running.
+
+ Partial reference: https://developers.google.com/youtube/iframe_api_reference.
This reference is useful for site-specific features such as interacting
with ads, or accessing YouTube's debug data.
"""
_yt_player_state = {
'UNSTARTED': -1,
'ENDED': 0,
'PLAYING': 1,
@@ -32,24 +39,26 @@ class YouTubePuppeteer(VideoPuppeteer):
}
_yt_player_state_name = {v: k for k, v in _yt_player_state.items()}
_time_pattern = re.compile('(?P<minute>\d+):(?P<second>\d+)')
def __init__(self, marionette, url, **kwargs):
self.player = None
super(YouTubePuppeteer,
self).__init__(marionette, url,
- video_selector='#movie_player video',
+ video_selector='.html5-video-player video',
**kwargs)
wait = Wait(self.marionette, timeout=30)
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
verbose_until(wait, self,
- expected.element_present(By.ID, 'movie_player'))
- self.player = self.marionette.find_element(By.ID, 'movie_player')
- self.marionette.execute_script("log('#movie_player "
+ expected.element_present(By.CLASS_NAME,
+ 'html5-video-player'))
+ self.player = self.marionette.find_element(By.CLASS_NAME,
+ 'html5-video-player')
+ self.marionette.execute_script("log('.html5-video-player "
"element obtained');")
# When an ad is playing, self.player_duration indicates the duration
# of the spliced-in ad stream, not the duration of the main video, so
# we attempt to skip the ad first.
for attempt in range(5):
sleep(1)
self.process_ad()
if (self.ad_inactive and self.duration and not
@@ -112,31 +121,31 @@ class YouTubePuppeteer(VideoPuppeteer):
return loads(text)
except ValueError:
self.marionette.log('Error loading json: DebugText',
level='DEBUG')
def execute_yt_script(self, script):
"""
Execute JS script in content context with access to video element and
- YouTube #movie_player element.
+ YouTube .html5-video-player element.
:param script: script to be executed.
:return: value returned by script
"""
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
return self.marionette.execute_script(script,
script_args=[self.video,
self.player])
@property
def playback_quality(self):
"""
- Please see https://developers.google.com/youtube/js_api_reference#Playback_quality
+ Please see https://developers.google.com/youtube/iframe_api_reference#Playback_quality
for valid values.
:return: A string with a valid value returned via YouTube.
"""
return self.execute_yt_script('return arguments[1].'
'wrappedJSObject.getPlaybackQuality();')
@property
@@ -171,29 +180,29 @@ class YouTubePuppeteer(VideoPuppeteer):
return self.execute_yt_script('return arguments[1].'
'wrappedJSObject.getVideoUrl();')
@property
def player_state(self):
"""
:return: The YouTube state of the video. See
- https://developers.google.com/youtube/js_api_reference#getPlayerState
+ https://developers.google.com/youtube/iframe_api_reference#getPlayerState
for valid values.
"""
state = self.execute_yt_script('return arguments[1].'
'wrappedJSObject.getPlayerState();')
return state
@property
def player_unstarted(self):
"""
This and the following properties are based on the
player.getPlayerState() call
- (https://developers.google.com/youtube/js_api_reference#Playback_status)
+ (https://developers.google.com/youtube/iframe_api_reference#Playback_status)
:return: True if the video has not yet started.
"""
return self.player_state == self._yt_player_state['UNSTARTED']
@property
def player_ended(self):
"""
@@ -235,17 +244,17 @@ class YouTubePuppeteer(VideoPuppeteer):
return self.player_state == self._yt_player_state['CUED']
@property
def ad_state(self):
"""
Get state of current ad.
:return: Returns one of the constants listed in
- https://developers.google.com/youtube/js_api_reference#Playback_status
+ https://developers.google.com/youtube/iframe_api_reference#Playback_status
for an ad.
"""
# Note: ad_state is sometimes not accurate, due to some sort of lag?
return self.execute_yt_script('return arguments[1].'
'wrappedJSObject.getAdState();')
@property
@@ -345,17 +354,17 @@ class YouTubePuppeteer(VideoPuppeteer):
"""
if self.ad_playing:
self.marionette.log('Waiting while ad plays')
sleep(10)
else:
# no ad playing
return False
if self.ad_skippable:
- selector = '#movie_player .videoAdUiSkipContainer'
+ selector = '.html5-video-player .videoAdUiSkipContainer'
wait = Wait(self.marionette, timeout=30)
try:
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
wait.until(expected.element_displayed(By.CSS_SELECTOR,
selector))
ad_button = self.marionette.find_element(By.CSS_SELECTOR,
selector)
ad_button.click()
@@ -373,17 +382,17 @@ class YouTubePuppeteer(VideoPuppeteer):
:return: ad duration in seconds, if currently displayed in player
"""
if not (self.ad_playing or self.player_measure_progress() == 0):
return None
# If the ad is not Flash...
if (self.ad_playing and self.video_src.startswith('mediasource') and
self.duration):
return self.duration
- selector = '#movie_player .videoAdUiAttribution'
+ selector = '.html5-media-player .videoAdUiAttribution'
wait = Wait(self.marionette, timeout=5)
try:
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
wait.until(expected.element_present(By.CSS_SELECTOR,
selector))
countdown = self.marionette.find_element(By.CSS_SELECTOR,
selector)
ad_time = self._time_pattern.search(countdown.text)
@@ -459,28 +468,28 @@ class YouTubePuppeteer(VideoPuppeteer):
return False
def __str__(self):
messages = [super(YouTubePuppeteer, self).__str__()]
if self.player:
player_state = self._yt_player_state_name[self.player_state]
ad_state = self._yt_player_state_name[self.ad_state]
messages += [
- '#movie_player: {',
+ '.html5-media-player: {',
'\tvideo id: {0},'.format(self.movie_id),
'\tvideo_title: {0}'.format(self.movie_title),
'\tcurrent_state: {0},'.format(player_state),
'\tad_state: {0},'.format(ad_state),
'\tplayback_quality: {0},'.format(self.playback_quality),
'\tcurrent_time: {0},'.format(self.player_current_time),
'\tduration: {0},'.format(self.player_duration),
'}'
]
else:
- messages += ['\t#movie_player: None']
+ messages += ['\t.html5-media-player: None']
return '\n'.join(messages)
def playback_started(yt):
"""
Check whether playback has started.
:param yt: YouTubePuppeteer