Bok-Choy video tests batch2
This commit is contained in:
committed by
Jay Zoldak
parent
3b49c17c06
commit
1bbfbedb1f
@@ -221,7 +221,7 @@ class CourseFixture(StudioApiFixture):
|
||||
"""
|
||||
Add the asset to the list of assets to be uploaded when the install method is called.
|
||||
"""
|
||||
self._assets.append(asset_name)
|
||||
self._assets.extend(asset_name)
|
||||
|
||||
def install(self):
|
||||
"""
|
||||
@@ -312,7 +312,7 @@ class CourseFixture(StudioApiFixture):
|
||||
details = response.json()
|
||||
except ValueError:
|
||||
raise CourseFixtureError(
|
||||
"Could not decode course details as JSON: '{0}'".format(old_details)
|
||||
"Could not decode course details as JSON: '{0}'".format(details)
|
||||
)
|
||||
|
||||
# Update the old details with our overrides
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
Video player in the courseware.
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
from bok_choy.page_object import PageObject
|
||||
from bok_choy.promise import EmptyPromise, Promise
|
||||
from bok_choy.javascript import wait_for_js, js_defined
|
||||
from ...tests.helpers import wait_for_ajax
|
||||
|
||||
|
||||
VIDEO_BUTTONS = {
|
||||
'CC': '.hide-subtitles',
|
||||
'volume': '.volume',
|
||||
@@ -18,12 +22,16 @@ VIDEO_BUTTONS = {
|
||||
|
||||
CSS_CLASS_NAMES = {
|
||||
'closed_captions': '.closed .subtitles',
|
||||
'captions_rendered': '.video.is-captions-rendered',
|
||||
'captions': '.subtitles',
|
||||
'captions_text': '.subtitles > li',
|
||||
'error_message': '.video .video-player h3',
|
||||
'video_container': 'div.video',
|
||||
'video_sources': '.video-player video source',
|
||||
'video_spinner': '.video-wrapper .spinner',
|
||||
'video_xmodule': '.xmodule_VideoModule'
|
||||
'video_xmodule': '.xmodule_VideoModule',
|
||||
'video_init': '.is-initialized',
|
||||
'video_time': 'div.vidtime'
|
||||
}
|
||||
|
||||
VIDEO_MODES = {
|
||||
@@ -31,6 +39,14 @@ VIDEO_MODES = {
|
||||
'youtube': 'iframe'
|
||||
}
|
||||
|
||||
VIDEO_MENUS = {
|
||||
'language': '.lang .menu',
|
||||
'speed': '.speed .menu',
|
||||
'download_transcript': '.video-tracks .a11y-menu-list',
|
||||
'transcript-format': '.video-tracks .a11y-menu-button'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@js_defined('window.Video', 'window.RequireJS.require', 'window.jQuery')
|
||||
class VideoPage(PageObject):
|
||||
@@ -44,21 +60,43 @@ class VideoPage(PageObject):
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='div{0}'.format(CSS_CLASS_NAMES['video_xmodule'])).present
|
||||
|
||||
@wait_for_js
|
||||
def _wait_for_element(self, element_css_selector, promise_desc):
|
||||
"""
|
||||
Wait for element specified by `element_css_selector` is present in DOM.
|
||||
:param element_css_selector: css selector of the element
|
||||
:param promise_desc: Description of the Promise, used in log messages.
|
||||
:return: BrokenPromise: the `Promise` was not satisfied within the time or attempt limits.
|
||||
"""
|
||||
|
||||
def _is_element_present():
|
||||
"""
|
||||
Check if web-element present in DOM
|
||||
:return: bool
|
||||
"""
|
||||
return self.q(css=element_css_selector).present
|
||||
|
||||
EmptyPromise(_is_element_present, promise_desc, timeout=200).fulfill()
|
||||
|
||||
@wait_for_js
|
||||
def wait_for_video_class(self):
|
||||
"""
|
||||
Wait until element with class name `video` appeared in DOM.
|
||||
"""
|
||||
video_css = '{0}'.format(CSS_CLASS_NAMES['video_container'])
|
||||
|
||||
wait_for_ajax(self.browser)
|
||||
return EmptyPromise(lambda: self.q(css=video_css).present, "Video is initialized").fulfill()
|
||||
|
||||
video_css = '{0}'.format(CSS_CLASS_NAMES['video_container'])
|
||||
self._wait_for_element(video_css, 'Video is initialized')
|
||||
|
||||
@wait_for_js
|
||||
def wait_for_video_player_render(self):
|
||||
"""
|
||||
Wait until Video Player Rendered Completely.
|
||||
"""
|
||||
self.wait_for_video_class()
|
||||
self._wait_for_element(CSS_CLASS_NAMES['video_init'], 'Video Player Initialized')
|
||||
self._wait_for_element(CSS_CLASS_NAMES['video_time'], 'Video Player Initialized')
|
||||
|
||||
def _is_finished_loading():
|
||||
"""
|
||||
Check if video loading completed
|
||||
@@ -66,9 +104,9 @@ class VideoPage(PageObject):
|
||||
"""
|
||||
return not self.q(css=CSS_CLASS_NAMES['video_spinner']).visible
|
||||
|
||||
self.wait_for_video_class()
|
||||
return EmptyPromise(_is_finished_loading, 'Finished loading the video', try_limit=10, timeout=60,
|
||||
try_interval=10).fulfill()
|
||||
EmptyPromise(_is_finished_loading, 'Finished loading the video', timeout=200).fulfill()
|
||||
|
||||
wait_for_ajax(self.browser)
|
||||
|
||||
def is_video_rendered(self, mode):
|
||||
"""
|
||||
@@ -88,14 +126,6 @@ class VideoPage(PageObject):
|
||||
|
||||
return Promise(_is_element_present, 'Video Rendering Failed in {0} mode.'.format(mode)).fulfill()
|
||||
|
||||
@property
|
||||
def all_video_sources(self):
|
||||
"""
|
||||
Extract all video source urls on current page.
|
||||
"""
|
||||
return self.q(css=CSS_CLASS_NAMES['video_sources']).map(
|
||||
lambda el: el.get_attribute('src').split('?')[0]).results
|
||||
|
||||
@property
|
||||
def is_autoplay_enabled(self):
|
||||
"""
|
||||
@@ -137,6 +167,7 @@ class VideoPage(PageObject):
|
||||
"""
|
||||
Show the video captions.
|
||||
"""
|
||||
|
||||
def _is_subtitles_open():
|
||||
"""
|
||||
Check if subtitles are opened
|
||||
@@ -163,19 +194,168 @@ class VideoPage(PageObject):
|
||||
Extract captions text.
|
||||
:return: str
|
||||
"""
|
||||
captions_css = CSS_CLASS_NAMES['captions']
|
||||
# wait until captions rendered completely
|
||||
self._wait_for_element(CSS_CLASS_NAMES['captions_rendered'], 'Captions Rendered')
|
||||
|
||||
def _captions_text():
|
||||
"""
|
||||
Extract captions text.
|
||||
:return: tuple
|
||||
"""
|
||||
is_present = self.q(css=captions_css).present
|
||||
result = None
|
||||
captions_css = CSS_CLASS_NAMES['captions_text']
|
||||
|
||||
if is_present:
|
||||
result = self.q(css=captions_css).text[0]
|
||||
subs = self.q(css=captions_css).html
|
||||
|
||||
return is_present, result
|
||||
return ' '.join(subs)
|
||||
|
||||
return Promise(_captions_text, 'Captions Text').fulfill()
|
||||
def set_speed(self, speed):
|
||||
"""
|
||||
Change the video play speed.
|
||||
:param speed: speed value in str
|
||||
"""
|
||||
self.browser.execute_script("$('.speeds').addClass('is-opened')")
|
||||
speed_css = 'li[data-speed="{0}"] a'.format(speed)
|
||||
|
||||
EmptyPromise(lambda: self.q(css='.speeds').visible, 'Video Speed Control Shown').fulfill()
|
||||
|
||||
self.q(css=speed_css).first.click()
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Get current video speed value.
|
||||
:return: str
|
||||
"""
|
||||
speed_css = '.speeds .value'
|
||||
return self.q(css=speed_css).text[0]
|
||||
|
||||
speed = property(get_speed, set_speed)
|
||||
|
||||
def click_player_button(self, button):
|
||||
"""
|
||||
Click on `button`.
|
||||
:param button: key in VIDEO_BUTTONS dictionary, its value will give us the css selector for `button`
|
||||
"""
|
||||
self.q(css=VIDEO_BUTTONS[button]).first.click()
|
||||
wait_for_ajax(self.browser)
|
||||
|
||||
def _get_element_dimensions(self, selector):
|
||||
"""
|
||||
Gets the width and height of element specified by `selector`
|
||||
:param selector: str, css selector of a web element
|
||||
:return: dict
|
||||
"""
|
||||
element = self.q(css=selector).results[0]
|
||||
return element.size
|
||||
|
||||
def _get_dimensions(self):
|
||||
"""
|
||||
Gets the video player dimensions
|
||||
:return: tuple
|
||||
"""
|
||||
video = self._get_element_dimensions('.video-player iframe, .video-player video')
|
||||
wrapper = self._get_element_dimensions('.tc-wrapper')
|
||||
controls = self._get_element_dimensions('.video-controls')
|
||||
progress_slider = self._get_element_dimensions('.video-controls > .slider')
|
||||
|
||||
expected = dict(wrapper)
|
||||
expected['height'] -= controls['height'] + 0.5 * progress_slider['height']
|
||||
|
||||
return video, expected
|
||||
|
||||
def is_aligned(self, is_transcript_visible):
|
||||
"""
|
||||
Check if video is aligned properly.
|
||||
:param is_transcript_visible: bool
|
||||
:return: bool
|
||||
"""
|
||||
# Width of the video container in css equal 75% of window if transcript enabled
|
||||
wrapper_width = 75 if is_transcript_visible else 100
|
||||
initial = self.browser.get_window_size()
|
||||
|
||||
self.browser.set_window_size(300, 600)
|
||||
|
||||
# Wait for browser to resize completely
|
||||
# Currently there is no other way to wait instead of explicit wait
|
||||
time.sleep(0.2)
|
||||
|
||||
real, expected = self._get_dimensions()
|
||||
|
||||
width = round(100 * real['width'] / expected['width']) == wrapper_width
|
||||
|
||||
self.browser.set_window_size(600, 300)
|
||||
|
||||
# Wait for browser to resize completely
|
||||
# Currently there is no other way to wait instead of explicit wait
|
||||
time.sleep(0.2)
|
||||
|
||||
real, expected = self._get_dimensions()
|
||||
|
||||
height = abs(expected['height'] - real['height']) <= 5
|
||||
|
||||
# Restore initial window size
|
||||
self.browser.set_window_size(
|
||||
initial['width'], initial['height']
|
||||
)
|
||||
|
||||
return all([width, height])
|
||||
|
||||
def _get_transcript(self, url):
|
||||
"""
|
||||
Sends a http get request.
|
||||
"""
|
||||
kwargs = dict()
|
||||
|
||||
session_id = [{i['name']: i['value']} for i in self.browser.get_cookies() if i['name'] == u'sessionid']
|
||||
if session_id:
|
||||
kwargs.update({
|
||||
'cookies': session_id[0]
|
||||
})
|
||||
|
||||
response = requests.get(url, **kwargs)
|
||||
return response.status_code < 400, response.headers, response.content
|
||||
|
||||
def downloaded_transcript_contains_text(self, transcript_format, text_to_search):
|
||||
"""
|
||||
Download the transcript in format `transcript_format` and check that it contains the text `text_to_search`
|
||||
:param transcript_format: `srt` or `txt`
|
||||
:param text_to_search: str
|
||||
:return: bool
|
||||
"""
|
||||
# check if we have a transcript with correct format
|
||||
assert '.' + transcript_format in self.q(css=VIDEO_MENUS['transcript-format']).text[0]
|
||||
|
||||
formats = {
|
||||
'srt': 'application/x-subrip',
|
||||
'txt': 'text/plain',
|
||||
}
|
||||
|
||||
url = self.q(css=VIDEO_BUTTONS['download_transcript']).attrs('href')[0]
|
||||
result, headers, content = self._get_transcript(url)
|
||||
|
||||
assert result
|
||||
assert formats[transcript_format] in headers.get('content-type', '')
|
||||
assert text_to_search in content.decode('utf-8')
|
||||
|
||||
def select_language(self, code):
|
||||
"""
|
||||
Select captions for language `code`
|
||||
:param code: str, two character language code like `en`, `zh`
|
||||
:return: bool, True for Success, False for Failure or BrokenPromise
|
||||
"""
|
||||
wait_for_ajax(self.browser)
|
||||
|
||||
selector = VIDEO_MENUS["language"] + ' li[data-lang-code="{code}"]'.format(code=code)
|
||||
|
||||
# mouse over to CC button
|
||||
element_to_hover_over = self.q(css=VIDEO_BUTTONS["CC"]).results[0]
|
||||
hover = ActionChains(self.browser).move_to_element(element_to_hover_over)
|
||||
hover.perform()
|
||||
|
||||
self.q(css=selector).first.click()
|
||||
|
||||
assert 'is-active' == self.q(css=selector).attrs('class')[0]
|
||||
assert len(self.q(css=VIDEO_MENUS["language"] + ' li.is-active').results) == 1
|
||||
|
||||
# Make sure that all ajax requests that affects the display of captions are finished.
|
||||
# For example, request to get new translation etc.
|
||||
wait_for_ajax(self.browser)
|
||||
|
||||
EmptyPromise(lambda: self.q(css=CSS_CLASS_NAMES['captions']).visible, 'Subtitles Visible').fulfill()
|
||||
|
||||
# wait until captions rendered completely
|
||||
self._wait_for_element(CSS_CLASS_NAMES['captions_rendered'], 'Captions Rendered')
|
||||
|
||||
@@ -6,8 +6,13 @@ from bok_choy.web_app_test import WebAppTest
|
||||
from bok_choy.promise import EmptyPromise
|
||||
|
||||
|
||||
def wait_for_ajax(browser):
|
||||
""" Make sure that all ajax requests are finished.
|
||||
def wait_for_ajax(browser, try_limit=None, try_interval=0.5, timeout=60):
|
||||
"""
|
||||
Make sure that all ajax requests are finished.
|
||||
:param try_limit (int or None): Number of attempts to make to satisfy the `Promise`. Can be `None` to
|
||||
disable the limit.
|
||||
:param try_interval (float): Number of seconds to wait between attempts.
|
||||
:param timeout (float): Maximum number of seconds to wait for the `Promise` to be satisfied before timing out.
|
||||
:param browser: selenium.webdriver, The Selenium-controlled browser that this page is loaded in.
|
||||
"""
|
||||
def _is_ajax_finished():
|
||||
@@ -17,7 +22,9 @@ def wait_for_ajax(browser):
|
||||
"""
|
||||
return browser.execute_script("return jQuery.active") == 0
|
||||
|
||||
EmptyPromise(_is_ajax_finished, "Finished waiting for ajax requests.").fulfill()
|
||||
EmptyPromise(_is_ajax_finished, "Finished waiting for ajax requests.", try_limit=try_limit,
|
||||
try_interval=try_interval, timeout=timeout).fulfill()
|
||||
|
||||
|
||||
def load_data_str(rel_path):
|
||||
"""
|
||||
|
||||
@@ -7,6 +7,7 @@ Acceptance tests for Video.
|
||||
from .helpers import UniqueCourseTest
|
||||
from ..pages.lms.video import VideoPage
|
||||
from ..pages.lms.tab_nav import TabNavPage
|
||||
from ..pages.lms.course_nav import CourseNavPage
|
||||
from ..pages.studio.auto_auth import AutoAuthPage
|
||||
from ..pages.lms.course_info import CourseInfoPage
|
||||
from ..fixtures.course import CourseFixture, XBlockFixtureDesc
|
||||
@@ -23,18 +24,6 @@ HTML5_SOURCES_INCORRECT = [
|
||||
'http://localhost:{0}/gizmo.mp99'.format(VIDEO_SOURCE_PORT),
|
||||
]
|
||||
|
||||
HTML5_METADATA = {
|
||||
'youtube_id_1_0': '',
|
||||
'youtube_id_0_75': '',
|
||||
'youtube_id_1_25': '',
|
||||
'youtube_id_1_5': '',
|
||||
'html5_sources': HTML5_SOURCES
|
||||
}
|
||||
|
||||
YT_HTML5_METADATA = {
|
||||
'html5_sources': HTML5_SOURCES
|
||||
}
|
||||
|
||||
|
||||
class VideoBaseTest(UniqueCourseTest):
|
||||
"""
|
||||
@@ -50,6 +39,7 @@ class VideoBaseTest(UniqueCourseTest):
|
||||
|
||||
self.video = VideoPage(self.browser)
|
||||
self.tab_nav = TabNavPage(self.browser)
|
||||
self.course_nav = CourseNavPage(self.browser)
|
||||
self.course_info_page = CourseInfoPage(self.browser, self.course_id)
|
||||
|
||||
self.course_fixture = CourseFixture(
|
||||
@@ -57,8 +47,9 @@ class VideoBaseTest(UniqueCourseTest):
|
||||
self.course_info['run'], self.course_info['display_name']
|
||||
)
|
||||
|
||||
self.metadata = {}
|
||||
self.assets = None
|
||||
self.metadata = None
|
||||
self.assets = []
|
||||
self.verticals = None
|
||||
|
||||
def navigate_to_video(self):
|
||||
""" Prepare the course and get to the video and render it """
|
||||
@@ -79,16 +70,44 @@ class VideoBaseTest(UniqueCourseTest):
|
||||
if self.assets:
|
||||
self.course_fixture.add_asset(self.assets)
|
||||
|
||||
# If you are not sending any metadata then `None` should be send as metadata to XBlockFixtureDesc
|
||||
# instead of empty dictionary otherwise test will not produce correct results.
|
||||
_metadata = self.metadata if self.metadata else None
|
||||
chapter_sequential = XBlockFixtureDesc('sequential', 'Test Section')
|
||||
chapter_sequential.add_children(*self._add_course_verticals())
|
||||
chapter = XBlockFixtureDesc('chapter', 'Test Chapter').add_children(chapter_sequential)
|
||||
self.course_fixture.add_children(chapter)
|
||||
self.course_fixture.install()
|
||||
|
||||
self.course_fixture.add_children(
|
||||
XBlockFixtureDesc('chapter', 'Test Chapter').add_children(
|
||||
XBlockFixtureDesc('sequential', 'Test Section').add_children(
|
||||
XBlockFixtureDesc('vertical', 'Test Vertical-0').add_children(
|
||||
XBlockFixtureDesc('video', 'Video', metadata=_metadata)
|
||||
)))).install()
|
||||
def _add_course_verticals(self):
|
||||
"""
|
||||
Create XBlockFixtureDesc verticals
|
||||
:return: a list of XBlockFixtureDesc
|
||||
"""
|
||||
xblock_verticals = []
|
||||
_verticals = self.verticals
|
||||
|
||||
# Video tests require at least one vertical with a single video.
|
||||
if not _verticals:
|
||||
_verticals = [[{'display_name': 'Video', 'metadata': self.metadata}]]
|
||||
|
||||
for vertical_index, vertical in enumerate(_verticals):
|
||||
xblock_verticals.append(self._create_single_vertical(vertical, vertical_index))
|
||||
|
||||
return xblock_verticals
|
||||
|
||||
def _create_single_vertical(self, vertical, vertical_index):
|
||||
"""
|
||||
Create a single course vertical of type XBlockFixtureDesc with category `vertical`.
|
||||
A single course vertical can contain single or multiple video modules.
|
||||
:param vertical: vertical data list
|
||||
:param vertical_index: index for the vertical display name
|
||||
:return: XBlockFixtureDesc
|
||||
"""
|
||||
xblock_course_vertical = XBlockFixtureDesc('vertical', 'Test Vertical-{0}'.format(vertical_index))
|
||||
|
||||
for video in vertical:
|
||||
xblock_course_vertical.add_children(
|
||||
XBlockFixtureDesc('video', video['display_name'], metadata=video.get('metadata')))
|
||||
|
||||
return xblock_course_vertical
|
||||
|
||||
def _navigate_to_courseware_video(self):
|
||||
""" Register for the course and navigate to the video unit """
|
||||
@@ -107,6 +126,56 @@ class VideoBaseTest(UniqueCourseTest):
|
||||
self._navigate_to_courseware_video()
|
||||
self.video.wait_for_video_class()
|
||||
|
||||
def metadata_for_mode(self, player_mode, additional_data=None):
|
||||
"""
|
||||
Create a dictionary for video player configuration according to `player_mode`
|
||||
:param player_mode (str): Video player mode
|
||||
:param additional_data (dict): Optional additional metadata.
|
||||
:return: dict
|
||||
"""
|
||||
metadata = {}
|
||||
|
||||
if player_mode == 'html5':
|
||||
metadata.update({
|
||||
'youtube_id_1_0': '',
|
||||
'youtube_id_0_75': '',
|
||||
'youtube_id_1_25': '',
|
||||
'youtube_id_1_5': '',
|
||||
'html5_sources': HTML5_SOURCES
|
||||
})
|
||||
|
||||
if player_mode == 'youtube_html5':
|
||||
metadata.update({
|
||||
'html5_sources': HTML5_SOURCES,
|
||||
})
|
||||
|
||||
if player_mode == 'youtube_html5_unsupported_video':
|
||||
metadata.update({
|
||||
'html5_sources': HTML5_SOURCES_INCORRECT
|
||||
})
|
||||
|
||||
if player_mode == 'html5_unsupported_video':
|
||||
metadata.update({
|
||||
'youtube_id_1_0': '',
|
||||
'youtube_id_0_75': '',
|
||||
'youtube_id_1_25': '',
|
||||
'youtube_id_1_5': '',
|
||||
'html5_sources': HTML5_SOURCES_INCORRECT
|
||||
})
|
||||
|
||||
if additional_data:
|
||||
metadata.update(additional_data)
|
||||
|
||||
return metadata
|
||||
|
||||
def open_video(self, video_display_name):
|
||||
"""
|
||||
Navigate to sequential specified by `video_display_name`
|
||||
:param video_display_name (str): Sequential Title
|
||||
"""
|
||||
self.course_nav.go_to_sequential(video_display_name)
|
||||
self.video.wait_for_video_player_render()
|
||||
|
||||
|
||||
class YouTubeVideoTest(VideoBaseTest):
|
||||
""" Test YouTube Video Player """
|
||||
@@ -114,7 +183,7 @@ class YouTubeVideoTest(VideoBaseTest):
|
||||
def setUp(self):
|
||||
super(YouTubeVideoTest, self).setUp()
|
||||
|
||||
def test_video_component_rendered_in_youtube_without_html5_sources(self):
|
||||
def test_youtube_video_rendering_wo_html5_sources(self):
|
||||
"""
|
||||
Scenario: Video component is rendered in the LMS in Youtube mode without HTML5 sources
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
@@ -125,7 +194,7 @@ class YouTubeVideoTest(VideoBaseTest):
|
||||
# Verify that video has rendered in "Youtube" mode
|
||||
self.assertTrue(self.video.is_video_rendered('youtube'))
|
||||
|
||||
def test_cc_button_without_english_transcript_youtube_mode(self):
|
||||
def test_cc_button_wo_english_transcript_youtube(self):
|
||||
"""
|
||||
Scenario: CC button works correctly w/o english transcript in Youtube mode of Video component
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
@@ -133,8 +202,9 @@ class YouTubeVideoTest(VideoBaseTest):
|
||||
And I have uploaded a non-english transcript file to assets
|
||||
Then I see the correct text in the captions
|
||||
"""
|
||||
self.metadata['transcripts'] = {'zh': 'chinese_transcripts.srt'}
|
||||
self.assets = 'chinese_transcripts.srt'
|
||||
data = {'transcripts': {'zh': 'chinese_transcripts.srt'}}
|
||||
self.metadata = self.metadata_for_mode('youtube', data)
|
||||
self.assets.append('chinese_transcripts.srt')
|
||||
self.navigate_to_video()
|
||||
self.video.show_captions()
|
||||
|
||||
@@ -150,14 +220,14 @@ class YouTubeVideoTest(VideoBaseTest):
|
||||
And I have uploaded a .srt.sjson file to assets
|
||||
Then I see the correct english text in the captions
|
||||
"""
|
||||
self.assets = 'subs_OEoXaMPEzfM.srt.sjson'
|
||||
self.assets.append('subs_OEoXaMPEzfM.srt.sjson')
|
||||
self.navigate_to_video()
|
||||
self.video.show_captions()
|
||||
|
||||
# Verify that we see "Hi, welcome to Edx." text in the captions
|
||||
self.assertIn('Hi, welcome to Edx.', self.video.captions_text)
|
||||
|
||||
def test_cc_button_hidden_if_no_translations(self):
|
||||
def test_cc_button_hidden_no_translations(self):
|
||||
"""
|
||||
Scenario: CC button is hidden if no translations
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
@@ -166,22 +236,111 @@ class YouTubeVideoTest(VideoBaseTest):
|
||||
self.navigate_to_video()
|
||||
self.assertFalse(self.video.is_button_shown('CC'))
|
||||
|
||||
def test_fullscreen_video_alignment_with_transcript_hidden(self):
|
||||
"""
|
||||
Scenario: Video is aligned correctly if transcript is hidden in fullscreen mode
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
"""
|
||||
self.navigate_to_video()
|
||||
|
||||
# click video button "fullscreen"
|
||||
self.video.click_player_button('fullscreen')
|
||||
|
||||
# check if video aligned correctly without enabled transcript
|
||||
self.assertTrue(self.video.is_aligned(False))
|
||||
|
||||
def test_download_button_wo_english_transcript(self):
|
||||
"""
|
||||
Scenario: Download button works correctly w/o english transcript in Youtube mode of Video component
|
||||
Given
|
||||
I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And it has a video in "Youtube" mode
|
||||
"""
|
||||
data = {'download_track': True, 'transcripts': {'zh': 'chinese_transcripts.srt'}}
|
||||
self.metadata = self.metadata_for_mode('youtube', additional_data=data)
|
||||
self.assets.append('chinese_transcripts.srt')
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# check if we can download transcript in "srt" format that has text "好 各位同学"
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.video.downloaded_transcript_contains_text('srt', unicode_text)
|
||||
|
||||
def test_download_button_two_transcript_languages_youtube(self):
|
||||
"""
|
||||
Scenario: Download button works correctly for non-english transcript in Youtube mode of Video component
|
||||
Given
|
||||
I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "Youtube" mode
|
||||
"""
|
||||
self.assets.extend(['chinese_transcripts.srt', 'subs_OEoXaMPEzfM.srt.sjson'])
|
||||
data = {'download_track': True, 'transcripts': {'zh': 'chinese_transcripts.srt'}, 'sub': 'OEoXaMPEzfM'}
|
||||
self.metadata = self.metadata_for_mode('youtube', additional_data=data)
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# check if "Hi, welcome to Edx." text in the captions
|
||||
self.assertIn('Hi, welcome to Edx.', self.video.captions_text)
|
||||
|
||||
# check if we can download transcript in "srt" format that has text "Hi, welcome to Edx."
|
||||
self.video.downloaded_transcript_contains_text('srt', 'Hi, welcome to Edx.')
|
||||
|
||||
# select language with code "zh"
|
||||
self.video.select_language('zh')
|
||||
|
||||
# check if we see "好 各位同学" text in the captions
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.assertIn(unicode_text, self.video.captions_text)
|
||||
|
||||
# check if we can download transcript in "srt" format that has text "好 各位同学"
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.video.downloaded_transcript_contains_text('srt', unicode_text)
|
||||
|
||||
def test_fullscreen_video_alignment_on_transcript_toggle(self):
|
||||
"""
|
||||
Tests that Video is aligned correctly on transcript toggle in fullscreen mode Given I have a
|
||||
"subs_OEoXaMPEzfM.srt.sjson" transcript file in assets And it has a video in "Youtube" mode.
|
||||
"""
|
||||
self.assets.append('subs_OEoXaMPEzfM.srt.sjson')
|
||||
data = {'sub': 'OEoXaMPEzfM'}
|
||||
self.metadata = self.metadata_for_mode('youtube', additional_data=data)
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# make sure captions are opened
|
||||
self.video.show_captions()
|
||||
|
||||
# click video button "fullscreen"
|
||||
self.video.click_player_button('fullscreen')
|
||||
|
||||
# check if video aligned correctly with enabled transcript
|
||||
self.assertTrue(self.video.is_aligned(True))
|
||||
|
||||
# click video button "CC"
|
||||
self.video.click_player_button('CC')
|
||||
|
||||
# check if video aligned correctly without enabled transcript
|
||||
self.assertTrue(self.video.is_aligned(False))
|
||||
|
||||
|
||||
class YouTubeHtml5VideoTest(VideoBaseTest):
|
||||
""" Test YouTube HTML5 Video Player """
|
||||
|
||||
def setUp(self):
|
||||
super(YouTubeHtml5VideoTest, self).setUp()
|
||||
self.metadata = YT_HTML5_METADATA
|
||||
|
||||
def test_video_component_rendered_in_youtube_with_unsupported_html5_sources(self):
|
||||
def test_youtube_video_rendering_with_unsupported_sources(self):
|
||||
"""
|
||||
Scenario: Video component is rendered in the LMS in Youtube mode
|
||||
with HTML5 sources that doesn't supported by browser
|
||||
with HTML5 sources that doesn't supported by browser
|
||||
Given the course has a Video component in "Youtube_HTML5_Unsupported_Video" mode
|
||||
Then the video has rendered in "Youtube" mode
|
||||
"""
|
||||
self.metadata['html5_sources'] = HTML5_SOURCES_INCORRECT
|
||||
self.metadata = self.metadata_for_mode('youtube_html5_unsupported_video')
|
||||
self.navigate_to_video()
|
||||
|
||||
# Verify that the video has rendered in "Youtube" mode
|
||||
@@ -193,7 +352,6 @@ class Html5VideoTest(VideoBaseTest):
|
||||
|
||||
def setUp(self):
|
||||
super(Html5VideoTest, self).setUp()
|
||||
self.metadata = HTML5_METADATA
|
||||
|
||||
def test_autoplay_disabled_for_video_component(self):
|
||||
"""
|
||||
@@ -201,19 +359,20 @@ class Html5VideoTest(VideoBaseTest):
|
||||
Given the course has a Video component in "HTML5" mode
|
||||
Then it does not have autoplay enabled
|
||||
"""
|
||||
self.metadata = self.metadata_for_mode('html5')
|
||||
self.navigate_to_video()
|
||||
|
||||
# Verify that the video has autoplay mode disabled
|
||||
self.assertFalse(self.video.is_autoplay_enabled)
|
||||
|
||||
def test_video_component_rendered_in_html5_with_unsupported_html5_sources(self):
|
||||
def test_html5_video_rendering_with_unsupported_sources(self):
|
||||
"""
|
||||
Scenario: Video component is rendered in the LMS in HTML5 mode with HTML5 sources that doesn't supported by browser
|
||||
Scenario: Video component is rendered in LMS in HTML5 mode with HTML5 sources that doesn't supported by browser
|
||||
Given the course has a Video component in "HTML5_Unsupported_Video" mode
|
||||
Then error message is shown
|
||||
And error message has correct text
|
||||
"""
|
||||
self.metadata['html5_sources'] = HTML5_SOURCES_INCORRECT
|
||||
self.metadata = self.metadata_for_mode('html5_unsupported_video')
|
||||
self.navigate_to_video_no_render()
|
||||
|
||||
# Verify that error message is shown
|
||||
@@ -222,3 +381,122 @@ class Html5VideoTest(VideoBaseTest):
|
||||
# Verify that error message has correct text
|
||||
correct_error_message_text = 'ERROR: No playable video sources found!'
|
||||
self.assertIn(correct_error_message_text, self.video.error_message_text)
|
||||
|
||||
def test_download_button_wo_english_transcript(self):
|
||||
"""
|
||||
Scenario: Download button works correctly w/o english transcript in HTML5 mode of Video component
|
||||
Given
|
||||
I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And it has a video in "HTML5" mode
|
||||
"""
|
||||
data = {'download_track': True, 'transcripts': {'zh': 'chinese_transcripts.srt'}}
|
||||
self.metadata = self.metadata_for_mode('html5', additional_data=data)
|
||||
self.assets.append('chinese_transcripts.srt')
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# check if we see "好 各位同学" text in the captions
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.assertIn(unicode_text, self.video.captions_text)
|
||||
|
||||
# check if we can download transcript in "srt" format that has text "好 各位同学"
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.video.downloaded_transcript_contains_text('srt', unicode_text)
|
||||
|
||||
def test_download_button_two_transcript_languages_html5(self):
|
||||
"""
|
||||
Scenario: Download button works correctly for non-english transcript in HTML5 mode of Video component
|
||||
Given
|
||||
I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "HTML5" mode
|
||||
"""
|
||||
self.assets.extend(['chinese_transcripts.srt', 'subs_OEoXaMPEzfM.srt.sjson'])
|
||||
data = {'download_track': True, 'transcripts': {'zh': 'chinese_transcripts.srt'}, 'sub': 'OEoXaMPEzfM'}
|
||||
self.metadata = self.metadata_for_mode('html5', additional_data=data)
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# check if "Hi, welcome to Edx." text in the captions
|
||||
self.assertIn('Hi, welcome to Edx.', self.video.captions_text)
|
||||
|
||||
# check if we can download transcript in "srt" format that has text "Hi, welcome to Edx."
|
||||
self.video.downloaded_transcript_contains_text('srt', 'Hi, welcome to Edx.')
|
||||
|
||||
# select language with code "zh"
|
||||
self.video.select_language('zh')
|
||||
|
||||
# check if we see "好 各位同学" text in the captions
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
|
||||
self.assertIn(unicode_text, self.video.captions_text)
|
||||
|
||||
#Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.video.downloaded_transcript_contains_text('srt', unicode_text)
|
||||
|
||||
def test_full_screen_video_alignment_with_transcript_visible(self):
|
||||
"""
|
||||
Scenario: Video is aligned correctly if transcript is visible in fullscreen mode
|
||||
Given
|
||||
I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "HTML5" mode
|
||||
"""
|
||||
self.assets.append('subs_OEoXaMPEzfM.srt.sjson')
|
||||
data = {'sub': 'OEoXaMPEzfM'}
|
||||
self.metadata = self.metadata_for_mode('html5', additional_data=data)
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# make sure captions are opened
|
||||
self.video.show_captions()
|
||||
|
||||
# click video button "fullscreen"
|
||||
self.video.click_player_button('fullscreen')
|
||||
|
||||
# check if video aligned correctly with enabled transcript
|
||||
self.assertTrue(self.video.is_aligned(True))
|
||||
|
||||
def test_cc_button_with_english_transcript(self):
|
||||
"""
|
||||
Scenario: CC button works correctly only w/ english transcript in HTML5 mode of Video component
|
||||
Given
|
||||
I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "HTML5" mode
|
||||
"""
|
||||
self.assets.append('subs_OEoXaMPEzfM.srt.sjson')
|
||||
data = {'sub': 'OEoXaMPEzfM'}
|
||||
self.metadata = self.metadata_for_mode('html5', additional_data=data)
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# make sure captions are opened
|
||||
self.video.show_captions()
|
||||
|
||||
# check if we see "Hi, welcome to Edx." text in the captions
|
||||
self.assertIn("Hi, welcome to Edx.", self.video.captions_text)
|
||||
|
||||
def test_cc_button_wo_english_transcript_html5(self):
|
||||
"""
|
||||
Scenario: CC button works correctly w/o english transcript in HTML5 mode of Video component
|
||||
Given
|
||||
I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And it has a video in "HTML5" mode
|
||||
"""
|
||||
self.assets.append('chinese_transcripts.srt')
|
||||
data = {'transcripts': {'zh': 'chinese_transcripts.srt'}}
|
||||
self.metadata = self.metadata_for_mode('html5', additional_data=data)
|
||||
|
||||
# go to video
|
||||
self.navigate_to_video()
|
||||
|
||||
# make sure captions are opened
|
||||
self.video.show_captions()
|
||||
|
||||
# check if we see "好 各位同学" text in the captions
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.assertIn(unicode_text, self.video.captions_text)
|
||||
|
||||
@@ -89,56 +89,6 @@ Feature: LMS.Video component
|
||||
And I see "Hi, welcome to Edx." text in the captions
|
||||
|
||||
# 8
|
||||
Scenario: CC button works correctly w/o english transcript in HTML5 mode of Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And it has a video in "HTML5" mode:
|
||||
| transcripts |
|
||||
| {"zh": "chinese_transcripts.srt"} |
|
||||
And I make sure captions are opened
|
||||
Then I see "好 各位同学" text in the captions
|
||||
|
||||
# 9
|
||||
Scenario: CC button works correctly only w/ english transcript in HTML5 mode of Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "HTML5" mode:
|
||||
| sub |
|
||||
| OEoXaMPEzfM |
|
||||
And I make sure captions are opened
|
||||
Then I see "Hi, welcome to Edx." text in the captions
|
||||
|
||||
# 10
|
||||
Scenario: Video is aligned correctly if transcript is visible in fullscreen mode
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "HTML5" mode:
|
||||
| sub |
|
||||
| OEoXaMPEzfM |
|
||||
And I make sure captions are opened
|
||||
And I click video button "fullscreen"
|
||||
Then I see video aligned correctly with enabled transcript
|
||||
|
||||
# 11
|
||||
Scenario: Video is aligned correctly if transcript is hidden in fullscreen mode
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
And I click video button "fullscreen"
|
||||
Then I see video aligned correctly without enabled transcript
|
||||
|
||||
# 12
|
||||
Scenario: Video is aligned correctly on transcript toggle in fullscreen mode
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "Youtube" mode:
|
||||
| sub |
|
||||
| OEoXaMPEzfM |
|
||||
And I make sure captions are opened
|
||||
And I click video button "fullscreen"
|
||||
Then I see video aligned correctly with enabled transcript
|
||||
And I click video button "CC"
|
||||
Then I see video aligned correctly without enabled transcript
|
||||
|
||||
# 13
|
||||
Scenario: Download Transcript button works correctly in Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
@@ -160,7 +110,7 @@ Feature: LMS.Video component
|
||||
When I open video "C"
|
||||
Then menu "download_transcript" doesn't exist
|
||||
|
||||
# 14
|
||||
# 9
|
||||
Scenario: Youtube video has correct transcript if fields for other speeds are filled.
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
@@ -178,55 +128,7 @@ Feature: LMS.Video component
|
||||
# "1:56" is the duration in the VCR timer before the video plays.
|
||||
And I see duration "1:56"
|
||||
|
||||
# 15
|
||||
Scenario: Download button works correctly for non-english transcript in Youtube mode of Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "Youtube" mode:
|
||||
| transcripts | sub | download_track |
|
||||
| {"zh": "chinese_transcripts.srt"} | OEoXaMPEzfM | true |
|
||||
And I see "Hi, welcome to Edx." text in the captions
|
||||
Then I can download transcript in "srt" format that has text "Hi, welcome to Edx."
|
||||
And I select language with code "zh"
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 16
|
||||
Scenario: Download button works correctly for non-english transcript in HTML5 mode of Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
And it has a video in "HTML5" mode:
|
||||
| transcripts | sub | download_track |
|
||||
| {"zh": "chinese_transcripts.srt"} | OEoXaMPEzfM | true |
|
||||
And I see "Hi, welcome to Edx." text in the captions
|
||||
Then I can download transcript in "srt" format that has text "Hi, welcome to Edx."
|
||||
And I select language with code "zh"
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 17
|
||||
Scenario: Download button works correctly w/o english transcript in HTML5 mode of Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And it has a video in "HTML5" mode:
|
||||
| transcripts | download_track |
|
||||
| {"zh": "chinese_transcripts.srt"} | true |
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 18
|
||||
Scenario: Download button works correctly w/o english transcript in Youtube mode of Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "chinese_transcripts.srt" transcript file in assets
|
||||
And it has a video in "Youtube" mode:
|
||||
| transcripts | download_track |
|
||||
| {"zh": "chinese_transcripts.srt"} | true |
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 19
|
||||
# 10
|
||||
Scenario: Verify that each video in each sub-section includes a transcript for non-Youtube countries.
|
||||
Given youtube server is up and response time is 2 seconds
|
||||
And I am registered for the course "test_course"
|
||||
@@ -255,7 +157,7 @@ Feature: LMS.Video component
|
||||
Then the video has rendered in "HTML5" mode
|
||||
And the video does not show the captions
|
||||
|
||||
# 20
|
||||
# 11
|
||||
Scenario: Start time works for Youtube video
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video in "Youtube" mode:
|
||||
@@ -264,7 +166,7 @@ Feature: LMS.Video component
|
||||
And I click video button "play"
|
||||
Then I see video slider at "0:10" position
|
||||
|
||||
# 21
|
||||
# 12
|
||||
Scenario: End time works for Youtube video
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video in "Youtube" mode:
|
||||
@@ -274,7 +176,7 @@ Feature: LMS.Video component
|
||||
And I wait "5" seconds
|
||||
Then I see video slider at "0:02" position
|
||||
|
||||
# 22
|
||||
# 13
|
||||
Scenario: Youtube video with end-time at 1:00 and the video starts playing at 0:58
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video in "Youtube" mode:
|
||||
@@ -286,7 +188,7 @@ Feature: LMS.Video component
|
||||
And I wait "5" seconds
|
||||
Then I see video slider at "1:00" position
|
||||
|
||||
# 23
|
||||
# 14
|
||||
Scenario: Start time and end time work together for Youtube video
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video in "Youtube" mode:
|
||||
@@ -297,7 +199,7 @@ Feature: LMS.Video component
|
||||
And I wait "5" seconds
|
||||
Then I see video slider at "0:12" position
|
||||
|
||||
# 24
|
||||
# 15
|
||||
Scenario: Youtube video after pausing at end time video plays to the end from end time
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video in "Youtube" mode:
|
||||
@@ -312,7 +214,7 @@ Feature: LMS.Video component
|
||||
# The default video length is 00:01:55.
|
||||
Then I see video slider at "1:55" position
|
||||
|
||||
# 25
|
||||
# 16
|
||||
Scenario: Youtube video with end-time at 0:32 and start-time at 0:30, the video starts playing from 0:28
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video in "Youtube" mode:
|
||||
@@ -324,7 +226,7 @@ Feature: LMS.Video component
|
||||
And I wait "8" seconds
|
||||
Then I see video slider at "0:32" position
|
||||
|
||||
# 26
|
||||
# 17
|
||||
Scenario: Youtube video with end-time at 1:00, the video starts playing from 1:52
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video in "Youtube" mode:
|
||||
@@ -337,7 +239,7 @@ Feature: LMS.Video component
|
||||
# Video stops at the end.
|
||||
Then I see video slider at "1:55" position
|
||||
|
||||
# 27
|
||||
# 18
|
||||
@skip_firefox
|
||||
Scenario: Quality button appears on play
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
@@ -345,7 +247,7 @@ Feature: LMS.Video component
|
||||
And I click video button "play"
|
||||
Then I see video button "quality" is visible
|
||||
|
||||
# 28
|
||||
# 19
|
||||
@skip_firefox
|
||||
Scenario: Quality button works correctly
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
|
||||
Reference in New Issue
Block a user