Commit 0c53f6c8 by Ben Patterson Committed by GitHub

Merge pull request #14491 from edx/benp/lettuce-fixes-chrome-stub-servers

Fix lettuce tests for Xenial compatibility and newer Chrome version.
parents e6e32d79 c0dd2b87
...@@ -110,7 +110,7 @@ Feature: CMS.HTML Editor ...@@ -110,7 +110,7 @@ Feature: CMS.HTML Editor
When I edit the page When I edit the page
And I click font selection dropdown And I click font selection dropdown
Then I should see a list of available fonts Then I should see a list of available fonts
And "Default" option sets "'Open Sans', Verdana, Arial, Helvetica, sans-serif" font family And "Default" option sets the expected font family
And all standard tinyMCE fonts should be available And all standard tinyMCE fonts should be available
# Skipping in master due to brittleness JZ 05/22/2014 # Skipping in master due to brittleness JZ 05/22/2014
......
...@@ -229,41 +229,45 @@ def font_selector_dropdown_is_shown(step): ...@@ -229,41 +229,45 @@ def font_selector_dropdown_is_shown(step):
assert_equal(actual_fonts, expected_fonts) assert_equal(actual_fonts, expected_fonts)
@step('"Default" option sets "(.*)" font family') @step('"Default" option sets the expected font family')
def default_options_sets_expected_font_family(step, expected_font_family): def default_options_sets_expected_font_family(step): # pylint: disable=unused-argument, redefined-outer-name
fonts = get_available_fonts(get_fonts_list_panel(world)) fonts = get_available_fonts(get_fonts_list_panel(world))
assert_equal(fonts.get("Default", None), expected_font_family) fonts_found = fonts.get("Default", None)
expected_font_family = CUSTOM_FONTS.get('Default')
for expected_font in expected_font_family:
assert_in(expected_font, fonts_found)
@step('all standard tinyMCE fonts should be available') @step('all standard tinyMCE fonts should be available')
def check_standard_tinyMCE_fonts(step): def check_standard_tinyMCE_fonts(step):
fonts = get_available_fonts(get_fonts_list_panel(world)) fonts = get_available_fonts(get_fonts_list_panel(world))
for label, expected_font in TINYMCE_FONTS.items(): for label, expected_fonts in TINYMCE_FONTS.items():
assert_equal(fonts.get(label, None), expected_font) for expected_font in expected_fonts:
assert_in(expected_font, fonts.get(label, None))
TINYMCE_FONTS = OrderedDict([ TINYMCE_FONTS = OrderedDict([
("Andale Mono", "'andale mono', times"), ("Andale Mono", ['andale mono', 'times']),
("Arial", "arial, helvetica, sans-serif"), ("Arial", ['arial', 'helvetica', 'sans-serif']),
("Arial Black", "'arial black', 'avant garde'"), ("Arial Black", ['arial black', 'avant garde']),
("Book Antiqua", "'book antiqua', palatino"), ("Book Antiqua", ['book antiqua', 'palatino']),
("Comic Sans MS", "'comic sans ms', sans-serif"), ("Comic Sans MS", ['comic sans ms', 'sans-serif']),
("Courier New", "'courier new', courier"), ("Courier New", ['courier new', 'courier']),
("Georgia", "georgia, palatino"), ("Georgia", ['georgia', 'palatino']),
("Helvetica", "helvetica"), ("Helvetica", ['helvetica']),
("Impact", "impact, chicago"), ("Impact", ['impact', 'chicago']),
("Symbol", "symbol"), ("Symbol", ['symbol']),
("Tahoma", "tahoma, arial, helvetica, sans-serif"), ("Tahoma", ['tahoma', 'arial', 'helvetica', 'sans-serif']),
("Terminal", "terminal, monaco"), ("Terminal", ['terminal', 'monaco']),
("Times New Roman", "'times new roman', times"), ("Times New Roman", ['times new roman', 'times']),
("Trebuchet MS", "'trebuchet ms', geneva"), ("Trebuchet MS", ['trebuchet ms', 'geneva']),
("Verdana", "verdana, geneva"), ("Verdana", ['verdana', 'geneva']),
# tinyMCE does not set font-family on dropdown span for these two fonts # tinyMCE does not set font-family on dropdown span for these two fonts
("Webdings", ""), # webdings ("Webdings", [""]), # webdings
("Wingdings", ""), # wingdings, 'zapf dingbats' ("Wingdings", [""]), # wingdings, 'zapf dingbats'
]) ])
CUSTOM_FONTS = OrderedDict([ CUSTOM_FONTS = OrderedDict([
('Default', "'Open Sans', Verdana, Arial, Helvetica, sans-serif"), ('Default', ['Open Sans', 'Verdana', 'Arial', 'Helvetica', 'sans-serif']),
]) ])
......
...@@ -279,10 +279,9 @@ def after_each_step(step): ...@@ -279,10 +279,9 @@ def after_each_step(step):
@after.harvest @after.harvest
def teardown_browser(total): def saucelabs_status(total):
""" """
Quit the browser after executing the tests. Collect data for saucelabs.
""" """
if world.LETTUCE_SELENIUM_CLIENT == 'saucelabs': if world.LETTUCE_SELENIUM_CLIENT == 'saucelabs':
set_saucelabs_job_status(world.jobid, total.scenarios_ran == total.scenarios_passed) set_saucelabs_job_status(world.jobid, total.scenarios_ran == total.scenarios_passed)
world.browser.quit()
...@@ -56,12 +56,19 @@ def stop_video_server(_total): ...@@ -56,12 +56,19 @@ def stop_video_server(_total):
video_server.shutdown() video_server.shutdown()
@before.all # pylint: disable=no-member
def start_stub_servers():
"""
Start all stub servers
"""
for stub in SERVICES.keys():
start_stub(stub)
@before.each_scenario # pylint: disable=no-member @before.each_scenario # pylint: disable=no-member
def process_requires_tags(scenario): def skip_youtube_if_not_available(scenario):
""" """
Process the scenario tags to make sure that any
requirements are met prior to that scenario
being executed.
Scenario tags must be named with this convention: Scenario tags must be named with this convention:
@requires_stub_bar, where 'bar' is the name of the stub service to start @requires_stub_bar, where 'bar' is the name of the stub service to start
...@@ -85,7 +92,7 @@ def process_requires_tags(scenario): ...@@ -85,7 +92,7 @@ def process_requires_tags(scenario):
scenario.steps = [] scenario.steps = []
return return
start_stub(requires.group('server')) return
def start_stub(name): def start_stub(name):
...@@ -124,11 +131,13 @@ def is_youtube_available(urls): ...@@ -124,11 +131,13 @@ def is_youtube_available(urls):
return True return True
@after.each_scenario # pylint: disable=no-member @after.all # pylint: disable=no-member
def stop_stubs(_scenario): def stop_stubs(_scenario):
""" """
Shut down any stub services that were started up for the scenario. Shut down any stub services.
""" """
# close browser to ensure no open connections to the stub servers
world.browser.quit()
for name in SERVICES.keys(): for name in SERVICES.keys():
stub_server = getattr(world, name, None) stub_server = getattr(world, name, None)
if stub_server is not None: if stub_server is not None:
......
...@@ -3,6 +3,7 @@ Stub implementation of an HTTP service. ...@@ -3,6 +3,7 @@ Stub implementation of an HTTP service.
""" """
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import urllib import urllib
import urlparse import urlparse
import threading import threading
...@@ -233,7 +234,7 @@ class StubHttpRequestHandler(BaseHTTPRequestHandler, object): ...@@ -233,7 +234,7 @@ class StubHttpRequestHandler(BaseHTTPRequestHandler, object):
self.send_response(200) self.send_response(200)
class StubHttpService(HTTPServer, object): class StubHttpService(ThreadingMixIn, HTTPServer, object):
""" """
Stub HTTP service implementation. Stub HTTP service implementation.
""" """
......
...@@ -191,13 +191,13 @@ class StubLtiHandler(StubHttpRequestHandler): ...@@ -191,13 +191,13 @@ class StubLtiHandler(StubHttpRequestHandler):
if submit_url: if submit_url:
submit_form = textwrap.dedent(""" submit_form = textwrap.dedent("""
<form action="{submit_url}/grade" method="post"> <form action="{submit_url}/grade" method="post">
<input type="submit" name="submit-button" value="Submit"> <input type="submit" name="submit-button" value="Submit" id="submit-button">
</form> </form>
<form action="{submit_url}/lti2_outcome" method="post"> <form action="{submit_url}/lti2_outcome" method="post">
<input type="submit" name="submit-lti2-button" value="Submit"> <input type="submit" name="submit-lti2-button" value="Submit" id="submit-lti2-button">
</form> </form>
<form action="{submit_url}/lti2_delete" method="post"> <form action="{submit_url}/lti2_delete" method="post">
<input type="submit" name="submit-lti2-delete-button" value="Submit"> <input type="submit" name="submit-lti2-delete-button" value="Submit" id="submit-lti-delete-button">
</form> </form>
""").format(submit_url=submit_url) """).format(submit_url=submit_url)
else: else:
......
...@@ -359,7 +359,10 @@ def click_grade(_step, version): ...@@ -359,7 +359,10 @@ def click_grade(_step, version):
location = world.scenario_dict['LTI'].location.html_id() location = world.scenario_dict['LTI'].location.html_id()
iframe_name = 'ltiFrame-' + location iframe_name = 'ltiFrame-' + location
with world.browser.get_iframe(iframe_name) as iframe: with world.browser.get_iframe(iframe_name) as iframe:
iframe.find_by_name(version_map[version]['selector']).first.click() css_ele = version_map[version]['selector']
css_loc = '#' + css_ele
world.wait_for_visible(css_loc)
world.css_click(css_loc)
assert iframe.is_text_present(version_map[version]['expected_text']) assert iframe.is_text_present(version_map[version]['expected_text'])
......
...@@ -93,6 +93,8 @@ class AcceptanceTest(TestSuite): ...@@ -93,6 +93,8 @@ class AcceptanceTest(TestSuite):
report_file = self.report_dir / "{}.xml".format(self.system) report_file = self.report_dir / "{}.xml".format(self.system)
report_args = ["--xunit-file {}".format(report_file)] report_args = ["--xunit-file {}".format(report_file)]
return [ return [
# set DBUS_SESSION_BUS_ADDRESS to avoid hangs on Chrome
"DBUS_SESSION_BUS_ADDRESS=/dev/null",
"DEFAULT_STORE={}".format(self.default_store), "DEFAULT_STORE={}".format(self.default_store),
"./manage.py", "./manage.py",
self.system, self.system,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment