video_editor.py 11 KB
Newer Older
1
# -*- coding: utf-8 -*-
cahrens committed
2
# disable missing docstring
3
# pylint: disable=missing-docstring
cahrens committed
4

5
import requests
cahrens committed
6
from lettuce import world, step
7
from nose.tools import assert_true, assert_equal, assert_in, assert_not_equal  # pylint: disable=no-name-in-module
8
from terrain.steps import reload_the_page
9 10 11 12
from django.conf import settings
from common import upload_file, attach_file

TEST_ROOT = settings.COMMON_TEST_DATA_ROOT
13

polesye committed
14
DISPLAY_NAME = "Component Display Name"
15 16 17 18 19
NATIVE_LANGUAGES = {lang: label for lang, label in settings.LANGUAGES if len(lang) == 2}
LANGUAGES = {
    lang: NATIVE_LANGUAGES.get(lang, display)
    for lang, display in settings.ALL_LANGUAGES
}
20

21 22 23 24
LANGUAGES.update({
    'table': 'Table of Contents'
})

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
TRANSLATION_BUTTONS = {
    'add': '.metadata-video-translations .create-action',
    'upload': '.metadata-video-translations .upload-action',
    'download': '.metadata-video-translations .download-action',
    'remove': '.metadata-video-translations .remove-action',
    'clear': '.metadata-video-translations .setting-clear',
}

VIDEO_MENUS = {
    'language': '.lang .menu',
}


class RequestHandlerWithSessionId(object):
    def get(self, url):
        """
        Sends a request.
        """
        kwargs = dict()

        session_id = [{i['name']:i['value']} for i in world.browser.cookies.all() if i['name'] == u'sessionid']
        if session_id:
            kwargs.update({
                'cookies': session_id[0]
            })

        response = requests.get(url, **kwargs)
        self.response = response
        self.status_code = response.status_code
        self.headers = response.headers
        self.content = response.content

        return self

    def is_success(self):
        """
        Returns `True` if the response was succeed, otherwise, returns `False`.
        """
        if self.status_code < 400:
            return True
        return False

    def check_header(self, name, value):
        """
        Returns `True` if the response header exist and has appropriate value,
        otherwise, returns `False`.
        """
        if value in self.headers.get(name, ''):
            return True
        return False


def success_upload_file(filename):
    upload_file(filename, sub_path="uploads/")
    world.css_has_text('#upload_confirm', 'Success!')
80
    world.is_css_not_present('.wrapper-modal-window-assetupload', wait_time=30)
81 82 83


def get_translations_container():
polesye committed
84
    return world.browser.find_by_xpath('//label[text()="Transcript Languages"]/following-sibling::div')
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109


def get_setting_container(lang_code):
    try:
        get_xpath = lambda value: './/descendant::a[@data-lang="{}" and contains(@class,"remove-setting")]/parent::*'.format(value)
        return get_translations_container().find_by_xpath(get_xpath(lang_code)).first
    except Exception:
        return None


def get_last_dropdown():
    return get_translations_container().find_by_xpath('.//descendant::select[last()]').last


def choose_option(dropdown, value):
    dropdown.find_by_value(value)[0].click()


def choose_new_lang(lang_code):
    world.css_click(TRANSLATION_BUTTONS['add'])
    choose_option(get_last_dropdown(), lang_code)
    assert_equal(get_last_dropdown().value, lang_code, "Option with provided value is not available or was not selected")


def open_menu(menu):
polesye committed
110
    world.browser.execute_script("$('{selector}').parent().addClass('is-opened')".format(
111 112
        selector=VIDEO_MENUS[menu]
    ))
113 114


115
@step('I have set "transcript display" to (.*)$')
116
def set_show_captions(step, setting):
117 118 119
    # Prevent cookies from overriding course settings
    world.browser.cookies.delete('hide_captions')

120
    world.edit_component()
121
    world.select_editor_tab('Advanced')
polesye committed
122
    world.browser.select('Show Transcript', setting)
123
    world.save_component()
124 125


126 127
@step('when I view the video it (.*) show the captions$')
def shows_captions(_step, show_captions):
128 129
    world.wait_for_js_variable_truthy("Video")
    world.wait(0.5)
130
    if show_captions == 'does not':
131
        assert_true(world.is_css_present('div.video.closed'))
132
    else:
133
        assert_true(world.is_css_not_present('div.video.closed'))
134

polesye committed
135 136 137 138
    # Prevent cookies from overriding course settings
    world.browser.cookies.delete('hide_captions')
    world.browser.cookies.delete('current_player_mode')

139 140 141

@step('I see the correct video settings and default values$')
def correct_video_settings(_step):
142
    expected_entries = [
143
        # basic
polesye committed
144
        [DISPLAY_NAME, 'Video', False],
145
        ['Default Video URL', 'http://youtu.be/3_yD_cEKoCk, , ', False],
146 147

        # advanced
polesye committed
148 149 150 151 152 153
        [DISPLAY_NAME, 'Video', False],
        ['Default Timed Transcript', '', False],
        ['Download Transcript Allowed', 'False', False],
        ['Downloadable Transcript URL', '', False],
        ['Show Transcript', 'True', False],
        ['Transcript Languages', '', False],
polesye committed
154
        ['Upload Handout', '', False],
155
        ['Video Download Allowed', 'False', False],
polesye committed
156 157 158
        ['Video File URLs', '', False],
        ['Video Start Time', '00:00:00', False],
        ['Video Stop Time', '00:00:00', False],
159
        ['YouTube ID', '3_yD_cEKoCk', False],
polesye committed
160 161 162
        ['YouTube ID for .75x speed', '', False],
        ['YouTube ID for 1.25x speed', '', False],
        ['YouTube ID for 1.5x speed', '', False]
163 164
    ]
    world.verify_all_setting_entries(expected_entries)
165 166


Anton Stupak committed
167
@step('my video display name change is persisted on save$')
168
def video_name_persisted(step):
169
    world.save_component()
170
    reload_the_page(step)
171
    world.wait_for_xmodule()
172
    world.edit_component()
173 174

    world.verify_setting_entry(
polesye committed
175 176
        world.get_setting_entry(DISPLAY_NAME),
        DISPLAY_NAME, '3.4', True
177
    )
178 179


polesye committed
180 181 182 183 184 185 186
@step('I can modify video display name')
def i_can_modify_video_display_name(_step):
    index = world.get_setting_entry_index(DISPLAY_NAME)
    world.set_field_value(index, '3.4')
    world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, '3.4', True)


187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
@step('I upload transcript file(?:s)?:$')
def upload_transcript(step):
    input_hidden = '.metadata-video-translations .input'
    # Number of previously added translations
    initial_index = len(world.css_find(TRANSLATION_BUTTONS['download']))

    if step.hashes:
        for i, item in enumerate(step.hashes):
            lang_code = item['lang_code']
            filename = item['filename']
            index = initial_index + i

            choose_new_lang(lang_code)

            expected_text = world.css_text(TRANSLATION_BUTTONS['upload'], index=index)
            assert_equal(expected_text, "Upload")
            assert_equal(world.css_find(input_hidden).last.value, "")

            world.css_click(TRANSLATION_BUTTONS['upload'], index=index)
            success_upload_file(filename)

            world.wait_for_visible(TRANSLATION_BUTTONS['download'], index=index)
            assert_equal(world.css_find(TRANSLATION_BUTTONS['upload']).last.text, "Replace")
            assert_equal(world.css_find(input_hidden).last.value, filename)


@step('I try to upload transcript file "([^"]*)"$')
def try_to_upload_transcript(step, filename):
    world.css_click(TRANSLATION_BUTTONS['upload'])
    attach_file(filename, 'uploads/')


@step('I upload transcript file "([^"]*)" for "([^"]*)" language code$')
def upload_transcript_for_lang(step, filename, lang_code):
    get_xpath = lambda value: './/div/a[contains(@class, "upload-action")]'.format(value)
    container = get_setting_container(lang_code)

    # If translation isn't uploaded, prepare drop-down and try to find container again
    choose_new_lang(lang_code)
    container = get_setting_container(lang_code)

    button = container.find_by_xpath(get_xpath(lang_code)).first
    button.click()
    success_upload_file(filename)


@step('I replace transcript file for "([^"]*)" language code by "([^"]*)"$')
def replace_transcript_for_lang(step, lang_code, filename):
    get_xpath = lambda value: './/div/a[contains(@class, "upload-action")]'.format(value)
    container = get_setting_container(lang_code)

    button = container.find_by_xpath(get_xpath(lang_code)).first
    button.click()
    success_upload_file(filename)


@step('I see validation error "([^"]*)"$')
def verify_validation_error_message(step, error_message):
    assert_equal(world.css_text('#upload_error'), error_message)


@step('I can download transcript for "([^"]*)" language code, that contains text "([^"]*)"$')
def i_can_download_transcript(_step, lang_code, text):
    MIME_TYPE = 'application/x-subrip'
    get_xpath = lambda value: './/div/a[contains(text(), "Download")]'.format(value)
    container = get_setting_container(lang_code)
    assert container
    button = container.find_by_xpath(get_xpath(lang_code)).first
    url = button['href']
    request = RequestHandlerWithSessionId()
    assert_true(request.get(url).is_success())
    assert_true(request.check_header('content-type', MIME_TYPE))
    assert_in(text.encode('utf-8'), request.content)


@step('I remove translation for "([^"]*)" language code$')
def i_can_remove_transcript(_step, lang_code):
    get_xpath = lambda value: './/descendant::a[@data-lang="{}" and contains(@class,"remove-setting")]'.format(value)
    container = get_setting_container(lang_code)
    assert container
    button = container.find_by_xpath(get_xpath(lang_code)).first
    button.click()


@step('I see translations for "([^"]*)"$')
def verify_translations(_step, lang_codes_string):
    expected = [l.strip() for l in lang_codes_string.split(',')]
    actual = [l['data-lang'] for l in world.css_find('.metadata-video-translations .remove-setting')]
    assert_equal(set(expected), set(actual))


@step('I do not see translations$')
def no_translations(_step):
    assert_true(world.is_css_not_present('.metadata-video-translations .remove-setting'))


@step('I confirm prompt$')
def confirm_prompt(_step):
    world.confirm_studio_prompt()


@step('I (cannot )?choose "([^"]*)" language code$')
def i_choose_lang_code(_step, cannot, lang_code):
    choose_option(get_last_dropdown(), lang_code)
    if cannot:
        assert_not_equal(get_last_dropdown().value, lang_code, "Option with provided value was selected, but shouldn't")
    else:
        assert_equal(get_last_dropdown().value, lang_code, "Option with provided value is not available or was not selected")


@step('I click button "([^"]*)"$')
def click_button(_step, button):
    world.css_click(TRANSLATION_BUTTONS[button.lower()])


@step('video language menu has "([^"]*)" translations$')
def i_see_correct_langs(_step, langs):
    menu_name = 'language'
    open_menu(menu_name)
    items = world.css_find(VIDEO_MENUS[menu_name] + ' li')
    translations = {t.strip(): LANGUAGES[t.strip()] for t in langs.split(',')}

    assert_equal(len(translations), len(items))
    for lang_code, label in translations.items():
        assert_true(any([i.text == label for i in items]))
        assert_true(any([i['data-lang-code'] == lang_code for i in items]))
313 314 315 316 317 318 319 320


@step('video language with code "([^"]*)" at position "(\d+)"$')
def i_see_lang_at_position(_step, code, position):
    menu_name = 'language'
    open_menu(menu_name)
    item = world.css_find(VIDEO_MENUS[menu_name] + ' li')[int(position)]
    assert_equal(item['data-lang-code'], code)