diff --git a/common/test/acceptance/fixtures/course.py b/common/test/acceptance/fixtures/course.py index 5d54f66112..d81bf59e68 100644 --- a/common/test/acceptance/fixtures/course.py +++ b/common/test/acceptance/fixtures/course.py @@ -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. diff --git a/common/test/acceptance/pages/lms/video.py b/common/test/acceptance/pages/lms/video.py index 7d8477f46a..4e6da4c85e 100644 --- a/common/test/acceptance/pages/lms/video.py +++ b/common/test/acceptance/pages/lms/video.py @@ -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() diff --git a/common/test/acceptance/tests/helpers.py b/common/test/acceptance/tests/helpers.py index 7e384bc019..8de5cfa153 100644 --- a/common/test/acceptance/tests/helpers.py +++ b/common/test/acceptance/tests/helpers.py @@ -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. diff --git a/common/test/acceptance/tests/test_video_module.py b/common/test/acceptance/tests/test_video_module.py new file mode 100644 index 0000000000..4fe9f321a6 --- /dev/null +++ b/common/test/acceptance/tests/test_video_module.py @@ -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) diff --git a/lms/djangoapps/courseware/features/video.feature b/lms/djangoapps/courseware/features/video.feature index 78515f2acc..d1a9e78911 100644 --- a/lms/djangoapps/courseware/features/video.feature +++ b/lms/djangoapps/courseware/features/video.feature @@ -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