Moved stub servers to terrain

Refactored stub services for style and DRY

Added unit tests for stub implementations

Updated acceptance tests that depend on stubs.

Updated Studio acceptance tests to use YouTube stub server; fixed failing tests in devstack.
This commit is contained in:
Will Daly
2013-11-23 14:19:56 -05:00
parent 8261f2b4b1
commit 0fd03cfb02
32 changed files with 682 additions and 699 deletions

View File

@@ -1,3 +1,4 @@
@shard_3
Feature: Video Component Editor
As a course author, I want to be able to create video components.
@@ -668,7 +669,7 @@ Feature: Video Component Editor
And I edit the component
And I open tab "Advanced"
And I revert the transcript field"HTML5 Transcript"
And I revert the transcript field "HTML5 Transcript"
And I save changes
Then when I view the video it does not show the captions

View File

@@ -49,25 +49,18 @@ TRANSCRIPTS_BUTTONS = {
}
def _clear_field(index):
world.css_fill(SELECTORS['url_inputs'], '', index)
# In some reason chromeDriver doesn't trigger 'input' event after filling
# field by an empty value. That's why we trigger it manually via jQuery.
world.trigger_event(SELECTORS['url_inputs'], event='input', index=index)
@step('I clear fields$')
def clear_fields(_step):
js_str = '''
# Clear the input fields and trigger an 'input' event
script = """
$('{selector}')
.eq({index})
.prop('disabled', false)
.removeClass('is-disabled');
'''
for index in range(1, 4):
js = js_str.format(selector=SELECTORS['url_inputs'], index=index - 1)
world.browser.execute_script(js)
_clear_field(index)
.removeClass('is-disabled')
.val('')
.trigger('input');
""".format(selector=SELECTORS['url_inputs'])
world.browser.execute_script(script)
world.wait(DELAY)
world.wait_for_ajax_complete()
@@ -76,7 +69,12 @@ def clear_fields(_step):
@step('I clear field number (.+)$')
def clear_field(_step, index):
index = int(index) - 1
_clear_field(index)
world.css_fill(SELECTORS['url_inputs'], '', index)
# For some reason ChromeDriver doesn't trigger an 'input' event after filling
# the field with an empty value. That's why we trigger it manually via jQuery.
world.trigger_event(SELECTORS['url_inputs'], event='input', index=index)
world.wait(DELAY)
world.wait_for_ajax_complete()

View File

@@ -34,7 +34,7 @@ def i_created_a_video_component(step):
world.wait_for_present('.is-initialized')
world.wait(DELAY)
assert not world.css_visible(SELECTORS['spinner'])
world.wait_for_invisible(SELECTORS['spinner'])
@step('I have created a Video component with subtitles$')
@@ -59,8 +59,7 @@ def i_created_a_video_with_subs_with_name(_step, sub_id):
world.disable_jquery_animations()
world.wait_for_present('.is-initialized')
world.wait(DELAY)
assert not world.css_visible(SELECTORS['spinner'])
world.wait_for_invisible(SELECTORS['spinner'])
@step('I have uploaded subtitles "([^"]*)"$')

View File

@@ -1,45 +0,0 @@
#pylint: disable=C0111
#pylint: disable=W0621
from xmodule.util.mock_youtube_server.mock_youtube_server import MockYoutubeServer
from lettuce import before, after, world
from django.conf import settings
import threading
from logging import getLogger
logger = getLogger(__name__)
@before.all
def setup_mock_youtube_server():
server_host = '127.0.0.1'
server_port = settings.VIDEO_PORT
address = (server_host, server_port)
# Create the mock server instance
server = MockYoutubeServer(address)
logger.debug("Youtube server started at {} port".format(str(server_port)))
server.time_to_response = 0.1 # seconds
server.address = address
# Start the server running in a separate daemon thread
# Because the thread is a daemon, it will terminate
# when the main thread terminates.
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
# Store the server instance in lettuce's world
# so that other steps can access it
# (and we can shut it down later)
world.youtube_server = server
@after.all
def teardown_mock_youtube_server(total):
# Stop the LTI server and free up the port
world.youtube_server.shutdown()

View File

@@ -114,22 +114,6 @@ try:
except ImportError:
pass
# Because an override for where to run will affect which ports to use,
# set this up after the local overrides.
if LETTUCE_SELENIUM_CLIENT == 'saucelabs':
LETTUCE_SERVER_PORT = choice(PORTS)
else:
LETTUCE_SERVER_PORT = randint(1024, 65535)
# Set up Video information so that the cms will send
# requests to a mock Youtube server running locally
if LETTUCE_SELENIUM_CLIENT == 'saucelabs':
VIDEO_PORT = choice(PORTS)
PORTS.remove(VIDEO_PORT)
else:
VIDEO_PORT = randint(1024, 65535)
# for testing Youtube
YOUTUBE_API['url'] = "http://127.0.0.1:" + str(VIDEO_PORT) + '/test_transcripts_youtube/'
# Point the URL used to test YouTube availability to our stub YouTube server
YOUTUBE_TEST_URL = "http://127.0.0.1:{0}/test_youtube/".format(YOUTUBE_PORT)
YOUTUBE_API['url'] = "http://127.0.0.1:{0}/test_transcripts_youtube/".format(YOUTUBE_PORT)

View File

@@ -359,6 +359,13 @@ CELERY_QUEUES = {
DEFAULT_PRIORITY_QUEUE: {}
}
############################## Video ##########################################
# URL to test YouTube availability
YOUTUBE_TEST_URL = 'https://gdata.youtube.com/feeds/api/videos/'
############################ APPS #####################################
INSTALLED_APPS = (

View File

@@ -150,6 +150,17 @@ CELERY_ALWAYS_EAGER = True
CELERY_RESULT_BACKEND = 'cache'
BROKER_TRANSPORT = 'memory'
########################### Server Ports ###################################
# These ports are carefully chosen so that if the browser needs to
# access them, they will be available through the SauceLabs SSH tunnel
LETTUCE_SERVER_PORT = 8003
XQUEUE_PORT = 8040
YOUTUBE_PORT = 8031
LTI_PORT = 8765
################### Make tests faster
# http://slacy.com/blog/2012/04/make-your-tests-faster-in-django-1-4/
PASSWORD_HASHERS = (