Merge pull request #3217 from edx/ammar/convert-lettuce-video-tests-to-bok-choy
Convert lettuce video tests to bok choy
This commit is contained in:
@@ -7,6 +7,7 @@ import datetime
|
||||
from textwrap import dedent
|
||||
from collections import namedtuple
|
||||
import requests
|
||||
from path import path
|
||||
from lazy import lazy
|
||||
from . import STUDIO_BASE_URL
|
||||
|
||||
@@ -185,6 +186,7 @@ class CourseFixture(StudioApiFixture):
|
||||
self._updates = []
|
||||
self._handouts = []
|
||||
self._children = []
|
||||
self._assets = []
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
@@ -215,6 +217,12 @@ class CourseFixture(StudioApiFixture):
|
||||
"""
|
||||
self._handouts.append(asset_name)
|
||||
|
||||
def add_asset(self, asset_name):
|
||||
"""
|
||||
Add the asset to the list of assets to be uploaded when the install method is called.
|
||||
"""
|
||||
self._assets.append(asset_name)
|
||||
|
||||
def install(self):
|
||||
"""
|
||||
Create the course and XBlocks within the course.
|
||||
@@ -223,10 +231,10 @@ class CourseFixture(StudioApiFixture):
|
||||
conflicts between tests.
|
||||
"""
|
||||
self._create_course()
|
||||
|
||||
self._install_course_updates()
|
||||
self._install_course_handouts()
|
||||
self._configure_course()
|
||||
self._upload_assets()
|
||||
self._create_xblock_children(self._course_loc, self._children)
|
||||
|
||||
@property
|
||||
@@ -243,6 +251,13 @@ class CourseFixture(StudioApiFixture):
|
||||
"""
|
||||
return "{org}.{number}.{run}/branch/draft/block/updates".format(**self._course_dict)
|
||||
|
||||
@property
|
||||
def _assets_url(self):
|
||||
"""
|
||||
Return the url string for the assets
|
||||
"""
|
||||
return "/assets/{org}.{number}.{run}/branch/draft/block/{run}".format(**self._course_dict)
|
||||
|
||||
@property
|
||||
def _handouts_loc(self):
|
||||
"""
|
||||
@@ -359,6 +374,32 @@ class CourseFixture(StudioApiFixture):
|
||||
"Could not add update to course: {0}. Status was {1}".format(
|
||||
update, response.status_code))
|
||||
|
||||
def _upload_assets(self):
|
||||
"""
|
||||
Upload assets
|
||||
:raise CourseFixtureError:
|
||||
"""
|
||||
url = STUDIO_BASE_URL + self._assets_url
|
||||
|
||||
test_dir = path(__file__).abspath().dirname().dirname().dirname()
|
||||
|
||||
for asset_name in self._assets:
|
||||
srt_path = test_dir + '/data/uploads/' + asset_name
|
||||
|
||||
asset_file = open(srt_path)
|
||||
files = {'file': (asset_name, asset_file)}
|
||||
|
||||
headers = {
|
||||
'Accept': 'application/json',
|
||||
'X-CSRFToken': self.session_cookies.get('csrftoken', '')
|
||||
}
|
||||
|
||||
upload_response = self.session.post(url, files=files, headers=headers)
|
||||
|
||||
if not upload_response.ok:
|
||||
raise CourseFixtureError('Could not upload {asset_name}. Status code: {code}'.format(
|
||||
asset_name=asset_name, code=upload_response.status_code))
|
||||
|
||||
def _create_xblock_children(self, parent_loc, xblock_descriptions):
|
||||
"""
|
||||
Recursively create XBlock children.
|
||||
|
||||
@@ -2,13 +2,37 @@
|
||||
Video player in the courseware.
|
||||
"""
|
||||
|
||||
import time
|
||||
from bok_choy.page_object import PageObject
|
||||
from bok_choy.promise import EmptyPromise
|
||||
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',
|
||||
'play': '.video_control.play',
|
||||
'pause': '.video_control.pause',
|
||||
'fullscreen': '.add-fullscreen',
|
||||
'download_transcript': '.video-tracks > a',
|
||||
}
|
||||
|
||||
CSS_CLASS_NAMES = {
|
||||
'closed_captions': '.closed .subtitles',
|
||||
'captions': '.subtitles',
|
||||
'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_MODES = {
|
||||
'html5': 'video',
|
||||
'youtube': 'iframe'
|
||||
}
|
||||
|
||||
|
||||
@js_defined('window.Video')
|
||||
@js_defined('window.Video', 'window.RequireJS.require', 'window.jQuery')
|
||||
class VideoPage(PageObject):
|
||||
"""
|
||||
Video player in the courseware.
|
||||
@@ -16,77 +40,142 @@ class VideoPage(PageObject):
|
||||
|
||||
url = None
|
||||
|
||||
@wait_for_js
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='div.xmodule_VideoModule').present
|
||||
|
||||
@property
|
||||
def elapsed_time(self):
|
||||
"""
|
||||
Amount of time elapsed since the start of the video, in seconds.
|
||||
"""
|
||||
elapsed, _ = self._video_time()
|
||||
return elapsed
|
||||
|
||||
@property
|
||||
def duration(self):
|
||||
"""
|
||||
Total duration of the video, in seconds.
|
||||
"""
|
||||
_, duration = self._video_time()
|
||||
return duration
|
||||
|
||||
@property
|
||||
def is_playing(self):
|
||||
"""
|
||||
Return a boolean indicating whether the video is playing.
|
||||
"""
|
||||
return self.q(css='a.video_control').present and self.q(css='a.video_control.pause').present
|
||||
|
||||
@property
|
||||
def is_paused(self):
|
||||
"""
|
||||
Return a boolean indicating whether the video is paused.
|
||||
"""
|
||||
return self.q(css='a.video_control').present and self.q(css='a.video_control.play').present
|
||||
return self.q(css='div{0}'.format(CSS_CLASS_NAMES['video_xmodule'])).present
|
||||
|
||||
@wait_for_js
|
||||
def play(self):
|
||||
def wait_for_video_class(self):
|
||||
"""
|
||||
Start playing the video.
|
||||
Wait until element with class name `video` appeared in DOM.
|
||||
"""
|
||||
self.q(css='a.video_control.play').first.click()
|
||||
EmptyPromise(lambda: self.is_playing, "Video is playing")
|
||||
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()
|
||||
|
||||
@wait_for_js
|
||||
def pause(self):
|
||||
def wait_for_video_player_render(self):
|
||||
"""
|
||||
Pause the video.
|
||||
Wait until Video Player Rendered Completely.
|
||||
"""
|
||||
self.q(css='a.video_control.pause').first.click()
|
||||
EmptyPromise(lambda: self.is_paused, "Video is paused")
|
||||
def _is_finished_loading():
|
||||
"""
|
||||
Check if video loading completed
|
||||
:return: bool
|
||||
"""
|
||||
return not self.q(css=CSS_CLASS_NAMES['video_spinner']).visible
|
||||
|
||||
def _video_time(self):
|
||||
self.wait_for_video_class()
|
||||
return EmptyPromise(_is_finished_loading, 'Finished loading the video', try_limit=10, timeout=60,
|
||||
try_interval=10).fulfill()
|
||||
|
||||
def is_video_rendered(self, mode):
|
||||
"""
|
||||
Return a tuple `(elapsed_time, duration)`, each in seconds.
|
||||
Check that if video is rendered in `mode`.
|
||||
:param mode: Video mode, `html5` or `youtube`
|
||||
"""
|
||||
# The full time has the form "0:32 / 3:14"
|
||||
all_times = self.q(css='div.vidtime').text
|
||||
html_tag = VIDEO_MODES[mode]
|
||||
css = '{0} {1}'.format(CSS_CLASS_NAMES['video_container'], html_tag)
|
||||
|
||||
if len(all_times) == 0:
|
||||
self.warning('Could not find video time')
|
||||
def _is_element_present():
|
||||
"""
|
||||
Check if a web element is present in DOM
|
||||
:return:
|
||||
"""
|
||||
is_present = self.q(css=css).present
|
||||
return is_present, is_present
|
||||
|
||||
else:
|
||||
full_time = all_times[0]
|
||||
return Promise(_is_element_present, 'Video Rendering Failed in {0} mode.'.format(mode)).fulfill()
|
||||
|
||||
# Split the time at the " / ", to get ["0:32", "3:14"]
|
||||
elapsed_str, duration_str = full_time.split(' / ')
|
||||
|
||||
# Convert each string to seconds
|
||||
return self._parse_time_str(elapsed_str), self._parse_time_str(duration_str)
|
||||
|
||||
def _parse_time_str(self, time_str):
|
||||
@property
|
||||
def all_video_sources(self):
|
||||
"""
|
||||
Parse a string of the form 1:23 into seconds (int).
|
||||
Extract all video source urls on current page.
|
||||
"""
|
||||
time_obj = time.strptime(time_str, '%M:%S')
|
||||
return time_obj.tm_min * 60 + time_obj.tm_sec
|
||||
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):
|
||||
"""
|
||||
Extract `data-autoplay` attribute to check video autoplay is enabled or disabled.
|
||||
"""
|
||||
auto_play = self.q(css=CSS_CLASS_NAMES['video_container']).attrs('data-autoplay')[0]
|
||||
|
||||
if auto_play.lower() == 'false':
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_error_message_shown(self):
|
||||
"""
|
||||
Checks if video player error message shown.
|
||||
:return: bool
|
||||
"""
|
||||
return self.q(css=CSS_CLASS_NAMES['error_message']).visible
|
||||
|
||||
@property
|
||||
def error_message_text(self):
|
||||
"""
|
||||
Extract video player error message text.
|
||||
:return: str
|
||||
"""
|
||||
return self.q(css=CSS_CLASS_NAMES['error_message']).text[0]
|
||||
|
||||
def is_button_shown(self, button_id):
|
||||
"""
|
||||
Check if a video button specified by `button_id` is visible
|
||||
:param button_id: button css selector
|
||||
:return: bool
|
||||
"""
|
||||
return self.q(css=VIDEO_BUTTONS[button_id]).visible
|
||||
|
||||
@wait_for_js
|
||||
def show_captions(self):
|
||||
"""
|
||||
Show the video captions.
|
||||
"""
|
||||
def _is_subtitles_open():
|
||||
"""
|
||||
Check if subtitles are opened
|
||||
:return: bool
|
||||
"""
|
||||
is_open = not self.q(css=CSS_CLASS_NAMES['closed_captions']).present
|
||||
return is_open
|
||||
|
||||
# Make sure that the CC button is there
|
||||
EmptyPromise(lambda: self.is_button_shown('CC'),
|
||||
"CC button is shown").fulfill()
|
||||
|
||||
# Check if the captions are already open and click if not
|
||||
if _is_subtitles_open() is False:
|
||||
self.q(css=VIDEO_BUTTONS['CC']).first.click()
|
||||
|
||||
# Verify that they are now open
|
||||
EmptyPromise(_is_subtitles_open,
|
||||
"Subtitles are shown").fulfill()
|
||||
|
||||
@property
|
||||
def captions_text(self):
|
||||
"""
|
||||
Extract captions text.
|
||||
:return: str
|
||||
"""
|
||||
captions_css = CSS_CLASS_NAMES['captions']
|
||||
|
||||
def _captions_text():
|
||||
"""
|
||||
Extract captions text.
|
||||
:return: tuple
|
||||
"""
|
||||
is_present = self.q(css=captions_css).present
|
||||
result = None
|
||||
|
||||
if is_present:
|
||||
result = self.q(css=captions_css).text[0]
|
||||
|
||||
return is_present, result
|
||||
|
||||
return Promise(_captions_text, 'Captions Text').fulfill()
|
||||
|
||||
@@ -3,8 +3,22 @@ Test helper functions and base classes.
|
||||
"""
|
||||
from path import path
|
||||
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.
|
||||
:param browser: selenium.webdriver, The Selenium-controlled browser that this page is loaded in.
|
||||
"""
|
||||
def _is_ajax_finished():
|
||||
"""
|
||||
Check if all the ajax call on current page completed.
|
||||
:return:
|
||||
"""
|
||||
return browser.execute_script("return jQuery.active") == 0
|
||||
|
||||
EmptyPromise(_is_ajax_finished, "Finished waiting for ajax requests.").fulfill()
|
||||
|
||||
def load_data_str(rel_path):
|
||||
"""
|
||||
Load a file from the "data" directory as a string.
|
||||
|
||||
223
common/test/acceptance/tests/test_video_module.py
Normal file
223
common/test/acceptance/tests/test_video_module.py
Normal file
@@ -0,0 +1,223 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Acceptance tests for Video.
|
||||
"""
|
||||
|
||||
from .helpers import UniqueCourseTest
|
||||
from ..pages.lms.video import VideoPage
|
||||
from ..pages.lms.tab_nav import TabNavPage
|
||||
from ..pages.studio.auto_auth import AutoAuthPage
|
||||
from ..pages.lms.course_info import CourseInfoPage
|
||||
from ..fixtures.course import CourseFixture, XBlockFixtureDesc
|
||||
|
||||
|
||||
HTML5_SOURCES = [
|
||||
'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp4',
|
||||
'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.webm',
|
||||
'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.ogv',
|
||||
]
|
||||
|
||||
HTML5_SOURCES_INCORRECT = [
|
||||
'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp99',
|
||||
]
|
||||
|
||||
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):
|
||||
"""
|
||||
Base class for tests of the Video Player
|
||||
Sets up the course and provides helper functions for the Video tests.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Initialization of pages and course fixture for video tests
|
||||
"""
|
||||
super(VideoBaseTest, self).setUp()
|
||||
|
||||
self.video = VideoPage(self.browser)
|
||||
self.tab_nav = TabNavPage(self.browser)
|
||||
self.course_info_page = CourseInfoPage(self.browser, self.course_id)
|
||||
|
||||
self.course_fixture = CourseFixture(
|
||||
self.course_info['org'], self.course_info['number'],
|
||||
self.course_info['run'], self.course_info['display_name']
|
||||
)
|
||||
|
||||
self.metadata = {}
|
||||
self.assets = None
|
||||
|
||||
def navigate_to_video(self):
|
||||
""" Prepare the course and get to the video and render it """
|
||||
self._install_course_fixture()
|
||||
self._navigate_to_courseware_video_and_render()
|
||||
|
||||
def navigate_to_video_no_render(self):
|
||||
"""
|
||||
Prepare the course and get to the video unit
|
||||
however do not wait for it to render, because
|
||||
the has been an error.
|
||||
"""
|
||||
self._install_course_fixture()
|
||||
self._navigate_to_courseware_video_no_render()
|
||||
|
||||
def _install_course_fixture(self):
|
||||
""" Install the course fixture that has been defined """
|
||||
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
|
||||
|
||||
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 _navigate_to_courseware_video(self):
|
||||
""" Register for the course and navigate to the video unit """
|
||||
AutoAuthPage(self.browser, course_id=self.course_id).visit()
|
||||
|
||||
self.course_info_page.visit()
|
||||
self.tab_nav.go_to_tab('Courseware')
|
||||
|
||||
def _navigate_to_courseware_video_and_render(self):
|
||||
""" Wait for the video player to render """
|
||||
self._navigate_to_courseware_video()
|
||||
self.video.wait_for_video_player_render()
|
||||
|
||||
def _navigate_to_courseware_video_no_render(self):
|
||||
""" Wait for the video Xmodule but not for rendering """
|
||||
self._navigate_to_courseware_video()
|
||||
self.video.wait_for_video_class()
|
||||
|
||||
|
||||
class YouTubeVideoTest(VideoBaseTest):
|
||||
""" Test YouTube Video Player """
|
||||
|
||||
def setUp(self):
|
||||
super(YouTubeVideoTest, self).setUp()
|
||||
|
||||
def test_video_component_rendered_in_youtube_without_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
|
||||
Then the video has rendered in "Youtube" mode
|
||||
"""
|
||||
self.navigate_to_video()
|
||||
|
||||
# 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):
|
||||
"""
|
||||
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
|
||||
And I have defined a non-english transcript for the video
|
||||
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'
|
||||
self.navigate_to_video()
|
||||
self.video.show_captions()
|
||||
|
||||
# Verify that we see "好 各位同学" text in the captions
|
||||
unicode_text = "好 各位同学".decode('utf-8')
|
||||
self.assertIn(unicode_text, self.video.captions_text)
|
||||
|
||||
def test_cc_button_transcripts_and_sub_fields_empty(self):
|
||||
"""
|
||||
Scenario: CC button works correctly if transcripts and sub fields are empty,
|
||||
but transcript file exists in assets (Youtube mode of Video component)
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
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.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):
|
||||
"""
|
||||
Scenario: CC button is hidden if no translations
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
Then the "CC" button is hidden
|
||||
"""
|
||||
self.navigate_to_video()
|
||||
self.assertFalse(self.video.is_button_shown('CC'))
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
Scenario: Video component is rendered in the LMS in Youtube mode
|
||||
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.navigate_to_video()
|
||||
|
||||
# Verify that the video has rendered in "Youtube" mode
|
||||
self.assertTrue(self.video.is_video_rendered('youtube'))
|
||||
|
||||
|
||||
class Html5VideoTest(VideoBaseTest):
|
||||
""" Test HTML5 Video Player """
|
||||
|
||||
def setUp(self):
|
||||
super(Html5VideoTest, self).setUp()
|
||||
self.metadata = HTML5_METADATA
|
||||
|
||||
def test_autoplay_disabled_for_video_component(self):
|
||||
"""
|
||||
Scenario: Autoplay is disabled in LMS for a Video component
|
||||
Given the course has a Video component in "HTML5" mode
|
||||
Then it does not have autoplay enabled
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Scenario: Video component is rendered in the 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.navigate_to_video_no_render()
|
||||
|
||||
# Verify that error message is shown
|
||||
self.assertTrue(self.video.is_error_message_shown)
|
||||
|
||||
# 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)
|
||||
@@ -21,25 +21,19 @@ Feature: LMS.Video component
|
||||
And all sources are correct
|
||||
|
||||
# 2
|
||||
@skip_firefox
|
||||
Scenario: Autoplay is disabled in LMS for a Video component
|
||||
Given the course has a Video component in "HTML5" mode
|
||||
Then when I view the video it does not have autoplay enabled
|
||||
|
||||
# 3
|
||||
# Youtube testing
|
||||
Scenario: Video component is fully rendered in the LMS in Youtube mode with HTML5 sources
|
||||
Given youtube server is up and response time is 0.4 seconds
|
||||
And the course has a Video component in "Youtube_HTML5" mode
|
||||
When the video has rendered in "Youtube" mode
|
||||
|
||||
# 4
|
||||
# 3
|
||||
Scenario: Video component is not rendered in the LMS in Youtube mode with HTML5 sources
|
||||
Given youtube server is up and response time is 2 seconds
|
||||
And the course has a Video component in "Youtube_HTML5" mode
|
||||
When the video has rendered in "HTML5" mode
|
||||
|
||||
# 5
|
||||
# 4
|
||||
Scenario: Video component is not rendered in the LMS in Youtube mode with HTML5 sources when YouTube API is blocked
|
||||
Given youtube server is up and response time is 2 seconds
|
||||
And youtube stub server blocks YouTube API
|
||||
@@ -47,25 +41,7 @@ Feature: LMS.Video component
|
||||
And I wait "3" seconds
|
||||
Then the video has rendered in "HTML5" mode
|
||||
|
||||
# 6
|
||||
Scenario: Video component is rendered in the LMS in Youtube mode without HTML5 sources
|
||||
Given youtube server is up and response time is 2 seconds
|
||||
And the course has a Video component in "Youtube" mode
|
||||
When the video has rendered in "Youtube" mode
|
||||
|
||||
# 7
|
||||
Scenario: Video component is rendered in the LMS in Youtube mode with HTML5 sources that doesn't supported by browser
|
||||
Given youtube server is up and response time is 2 seconds
|
||||
And the course has a Video component in "Youtube_HTML5_Unsupported_Video" mode
|
||||
When the video has rendered in "Youtube" mode
|
||||
|
||||
# 8
|
||||
Scenario: Video component is rendered in the 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
|
||||
|
||||
# 9
|
||||
# 5
|
||||
Scenario: Multiple videos in sequentials all load and work, switching between sequentials
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video "A" in "Youtube" mode in position "1" of sequential
|
||||
@@ -87,7 +63,7 @@ Feature: LMS.Video component
|
||||
When I open video "A"
|
||||
Then video "A" should start playing at speed "2.0"
|
||||
|
||||
# 10
|
||||
# 6
|
||||
Scenario: Video component stores speed correctly when each video is in separate sequence
|
||||
Given I am registered for the course "test_course"
|
||||
And it has a video "A" in "Youtube" mode in position "1" of sequential
|
||||
@@ -109,7 +85,7 @@ Feature: LMS.Video component
|
||||
When I open video "C"
|
||||
Then video "C" should start playing at speed "1.0"
|
||||
|
||||
# 11
|
||||
# 7
|
||||
Scenario: Language menu works correctly in Video component
|
||||
Given I am registered for the course "test_course"
|
||||
And I have a "chinese_transcripts.srt" transcript file in assets
|
||||
@@ -124,7 +100,7 @@ Feature: LMS.Video component
|
||||
And I select language with code "en"
|
||||
And I see "Hi, welcome to Edx." text in the captions
|
||||
|
||||
# 12
|
||||
# 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
|
||||
@@ -134,7 +110,7 @@ Feature: LMS.Video component
|
||||
And I make sure captions are opened
|
||||
Then I see "好 各位同学" text in the captions
|
||||
|
||||
# 13
|
||||
# 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
|
||||
@@ -144,30 +120,7 @@ Feature: LMS.Video component
|
||||
And I make sure captions are opened
|
||||
Then I see "Hi, welcome to Edx." text in the captions
|
||||
|
||||
# 14
|
||||
Scenario: CC 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 |
|
||||
| {"zh": "chinese_transcripts.srt"} |
|
||||
And I make sure captions are opened
|
||||
Then I see "好 各位同学" text in the captions
|
||||
|
||||
# 15
|
||||
Scenario: CC button works correctly if transcripts and sub fields are empty, but transcript file exists in assets (Youtube 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 "Youtube" mode
|
||||
And I make sure captions are opened
|
||||
Then I see "Hi, welcome to Edx." text in the captions
|
||||
|
||||
# 16
|
||||
Scenario: CC button is hidden if no translations
|
||||
Given the course has a Video component in "Youtube" mode
|
||||
Then button "CC" is hidden
|
||||
|
||||
# 17
|
||||
# 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
|
||||
@@ -178,13 +131,13 @@ Feature: LMS.Video component
|
||||
And I click video button "fullscreen"
|
||||
Then I see video aligned correctly with enabled transcript
|
||||
|
||||
# 18
|
||||
# 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
|
||||
|
||||
# 19
|
||||
# 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
|
||||
@@ -197,7 +150,7 @@ Feature: LMS.Video component
|
||||
And I click video button "CC"
|
||||
Then I see video aligned correctly without enabled transcript
|
||||
|
||||
# 20
|
||||
# 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
|
||||
@@ -219,7 +172,7 @@ Feature: LMS.Video component
|
||||
When I open video "C"
|
||||
Then menu "download_transcript" doesn't exist
|
||||
|
||||
# 21
|
||||
# 14
|
||||
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
|
||||
@@ -234,7 +187,7 @@ Feature: LMS.Video component
|
||||
Then I see "Hi, welcome to Edx." text in the captions
|
||||
And I see duration "1:00"
|
||||
|
||||
# 22
|
||||
# 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
|
||||
@@ -248,7 +201,7 @@ Feature: LMS.Video component
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 23
|
||||
# 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
|
||||
@@ -262,7 +215,7 @@ Feature: LMS.Video component
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 24
|
||||
# 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
|
||||
@@ -272,7 +225,7 @@ Feature: LMS.Video component
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 25
|
||||
# 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
|
||||
@@ -282,7 +235,7 @@ Feature: LMS.Video component
|
||||
And I see "好 各位同学" text in the captions
|
||||
Then I can download transcript in "srt" format that has text "好 各位同学"
|
||||
|
||||
# 26
|
||||
# 19
|
||||
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"
|
||||
@@ -311,7 +264,7 @@ Feature: LMS.Video component
|
||||
Then the video has rendered in "HTML5" mode
|
||||
And the video does not show the captions
|
||||
|
||||
# 27 Disabled 4/8/14 after intermittent failures in master
|
||||
# 20 Disabled 4/8/14 after intermittent failures in master
|
||||
#Scenario: Transcripts are available on different speeds of Flash mode
|
||||
# Given I am registered for the course "test_course"
|
||||
# And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
@@ -326,7 +279,7 @@ Feature: LMS.Video component
|
||||
# Then I select the "1.25" speed
|
||||
# And I see "Hi, welcome to Edx." text in the captions
|
||||
|
||||
# 28 Disabled 4/8/14 after intermittent failures in master
|
||||
# 21 Disabled 4/8/14 after intermittent failures in master
|
||||
#Scenario: Elapsed time calculates correctly on different speeds of Flash mode
|
||||
# Given I am registered for the course "test_course"
|
||||
# And I have a "subs_OEoXaMPEzfM.srt.sjson" transcript file in assets
|
||||
|
||||
Reference in New Issue
Block a user