Commit c2afd442 by Ned Batchelder Committed by GitHub

Merge pull request #14593 from edx/estute/xenial-and-browser-updates-for-testing

Estute/xenial and browser updates for testing
parents 52fc790c 3cbdf962
......@@ -110,7 +110,7 @@ Feature: CMS.HTML Editor
When I edit the page
And I click font selection dropdown
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
# Skipping in master due to brittleness JZ 05/22/2014
......
......@@ -229,41 +229,45 @@ def font_selector_dropdown_is_shown(step):
assert_equal(actual_fonts, expected_fonts)
@step('"Default" option sets "(.*)" font family')
def default_options_sets_expected_font_family(step, expected_font_family):
@step('"Default" option sets the 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))
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')
def check_standard_tinyMCE_fonts(step):
fonts = get_available_fonts(get_fonts_list_panel(world))
for label, expected_font in TINYMCE_FONTS.items():
assert_equal(fonts.get(label, None), expected_font)
for label, expected_fonts in TINYMCE_FONTS.items():
for expected_font in expected_fonts:
assert_in(expected_font, fonts.get(label, None))
TINYMCE_FONTS = OrderedDict([
("Andale Mono", "'andale mono', times"),
("Arial", "arial, helvetica, sans-serif"),
("Arial Black", "'arial black', 'avant garde'"),
("Book Antiqua", "'book antiqua', palatino"),
("Comic Sans MS", "'comic sans ms', sans-serif"),
("Courier New", "'courier new', courier"),
("Georgia", "georgia, palatino"),
("Helvetica", "helvetica"),
("Impact", "impact, chicago"),
("Symbol", "symbol"),
("Tahoma", "tahoma, arial, helvetica, sans-serif"),
("Terminal", "terminal, monaco"),
("Times New Roman", "'times new roman', times"),
("Trebuchet MS", "'trebuchet ms', geneva"),
("Verdana", "verdana, geneva"),
("Andale Mono", ['andale mono', 'times']),
("Arial", ['arial', 'helvetica', 'sans-serif']),
("Arial Black", ['arial black', 'avant garde']),
("Book Antiqua", ['book antiqua', 'palatino']),
("Comic Sans MS", ['comic sans ms', 'sans-serif']),
("Courier New", ['courier new', 'courier']),
("Georgia", ['georgia', 'palatino']),
("Helvetica", ['helvetica']),
("Impact", ['impact', 'chicago']),
("Symbol", ['symbol']),
("Tahoma", ['tahoma', 'arial', 'helvetica', 'sans-serif']),
("Terminal", ['terminal', 'monaco']),
("Times New Roman", ['times new roman', 'times']),
("Trebuchet MS", ['trebuchet ms', 'geneva']),
("Verdana", ['verdana', 'geneva']),
# tinyMCE does not set font-family on dropdown span for these two fonts
("Webdings", ""), # webdings
("Wingdings", ""), # wingdings, 'zapf dingbats'
("Webdings", [""]), # webdings
("Wingdings", [""]), # wingdings, 'zapf dingbats'
])
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):
@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':
set_saucelabs_job_status(world.jobid, total.scenarios_ran == total.scenarios_passed)
world.browser.quit()
......@@ -56,12 +56,19 @@ def stop_video_server(_total):
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
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:
@requires_stub_bar, where 'bar' is the name of the stub service to start
......@@ -85,7 +92,7 @@ def process_requires_tags(scenario):
scenario.steps = []
return
start_stub(requires.group('server'))
return
def start_stub(name):
......@@ -124,11 +131,13 @@ def is_youtube_available(urls):
return True
@after.each_scenario # pylint: disable=no-member
@after.all # pylint: disable=no-member
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():
stub_server = getattr(world, name, None)
if stub_server is not None:
......
......@@ -3,6 +3,7 @@ Stub implementation of an HTTP service.
"""
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import urllib
import urlparse
import threading
......@@ -233,7 +234,7 @@ class StubHttpRequestHandler(BaseHTTPRequestHandler, object):
self.send_response(200)
class StubHttpService(HTTPServer, object):
class StubHttpService(ThreadingMixIn, HTTPServer, object):
"""
Stub HTTP service implementation.
"""
......
......@@ -191,13 +191,13 @@ class StubLtiHandler(StubHttpRequestHandler):
if submit_url:
submit_form = textwrap.dedent("""
<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 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 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>
""").format(submit_url=submit_url)
else:
......
......@@ -269,7 +269,8 @@ class VideoStudentViewHandlers(object):
headerlist=[
('Content-Disposition', 'attachment; filename="{}"'.format(transcript_filename.encode('utf8'))),
('Content-Language', self.transcript_language),
]
],
charset='utf8'
)
response.content_type = transcript_mime_type
......
......@@ -5,6 +5,7 @@ import datetime
from bok_choy.page_object import PageObject
from bok_choy.promise import EmptyPromise
from bok_choy.javascript import js_defined, wait_for_js
from selenium.webdriver import ActionChains
from selenium.webdriver.support.ui import Select
......@@ -18,6 +19,7 @@ from common.test.acceptance.pages.studio.container import ContainerPage
from common.test.acceptance.pages.studio.utils import set_input_value_and_save, set_input_value
@js_defined('jQuery')
class CourseOutlineItem(object):
"""
A mixin class for any :class:`PageObject` shown in a course outline.
......@@ -174,6 +176,7 @@ class CourseOutlineItem(object):
element = self.q(css=self._bounded_selector(".status-grading-value")) # pylint: disable=no-member
return element.first.text[0] if element.present else None
@wait_for_js
def publish(self):
"""
Publish the unit.
......
......@@ -436,6 +436,7 @@ class CoursewareMultipleVerticalsTest(UniqueCourseTest, EventsTestMixin):
self.courseware_page.visit()
self.course_nav = CourseNavPage(self.browser)
@flaky # TODO: fix this, see TNL-5762
def test_navigation_buttons(self):
# start in first section
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 0, next_enabled=True, prev_enabled=False)
......
......@@ -274,6 +274,7 @@ class EdxNotesDefaultInteractionsTest(EdxNotesTestMixin):
components = self.note_unit_page.components
self.assert_notes_are_removed(components)
@flaky # TODO: fix this, see TNL-6494
def test_can_create_note_with_tags(self):
"""
Scenario: a user of notes can define one with tags
......@@ -1061,6 +1062,7 @@ class EdxNotesPageTest(EventsTestMixin, EdxNotesTestMixin):
self.assertNotIn(u"Search Results", self.notes_page.tabs)
self.assertEqual(len(self.notes_page.notes), 5)
@flaky # TODO: fix this, see TNL-6493
def test_open_note_when_accessed_from_notes_page(self):
"""
Scenario: Ensure that the link to the Unit opens a note only once.
......@@ -1115,6 +1117,7 @@ class EdxNotesPageTest(EventsTestMixin, EdxNotesTestMixin):
note = self.note_unit_page.notes[0]
self.assertFalse(note.is_visible)
self.courseware_page.go_to_sequential_position(1)
self.courseware_page.wait_for_ajax()
note = self.note_unit_page.notes[0]
self.assertFalse(note.is_visible)
......
......@@ -5,9 +5,9 @@ progress page.
"""
import ddt
from bok_choy.javascript import js_defined
from contextlib import contextmanager
from nose.plugins.attrib import attr
from flaky import flaky
from ..helpers import (
UniqueCourseTest, auto_auth, create_multiple_choice_problem, create_multiple_choice_xml, get_modal_alert
......@@ -126,7 +126,6 @@ class ProgressPageBaseTest(UniqueCourseTest):
@attr(shard=9)
@ddt.ddt
@js_defined('window.jQuery')
class PersistentGradesTest(ProgressPageBaseTest):
"""
Test that grades for completed assessments are persisted
......@@ -228,6 +227,7 @@ class PersistentGradesTest(ProgressPageBaseTest):
_change_subsection_structure,
_change_weight_for_problem
)
@flaky # TODO: fix this, see TNL-6040
def test_content_changes_do_not_change_score(self, edit):
with self._logged_in_session():
self.courseware_page.visit()
......
......@@ -359,7 +359,10 @@ def click_grade(_step, version):
location = world.scenario_dict['LTI'].location.html_id()
iframe_name = 'ltiFrame-' + location
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'])
......
......@@ -14,10 +14,10 @@ from mock import patch
from polib import pofile
from pytz import UTC
from i18n import config
from i18n import dummy
from i18n import extract
from i18n import generate
from i18n import dummy
from i18n.config import CONFIGURATION
class TestGenerate(TestCase):
......@@ -57,6 +57,8 @@ class TestGenerate(TestCase):
def setUp(self):
super(TestGenerate, self).setUp()
self.configuration = config.Configuration()
# Subtract 1 second to help comparisons with file-modify time succeed,
# since os.path.getmtime() is not millisecond-accurate
self.start_time = datetime.now(UTC) - timedelta(seconds=1)
......@@ -65,13 +67,11 @@ class TestGenerate(TestCase):
"""
Tests merge script on English source files.
"""
filename = os.path.join(CONFIGURATION.source_messages_dir, random_name())
generate.merge(CONFIGURATION.source_locale, target=filename)
filename = os.path.join(self.configuration.source_messages_dir, random_name())
generate.merge(self.configuration, self.configuration.source_locale, target=filename)
self.assertTrue(os.path.exists(filename))
os.remove(filename)
# Patch dummy_locales to not have esperanto present
@patch.object(CONFIGURATION, 'dummy_locales', ['fake2'])
def test_main(self):
"""
Runs generate.main() which should merge source files,
......@@ -80,11 +80,14 @@ class TestGenerate(TestCase):
.mo files should exist, and be recently created (modified
after start of test suite)
"""
# Change dummy_locales to not have Esperanto present.
self.configuration.dummy_locales = ['fake2']
generate.main(verbosity=0, strict=False)
for locale in CONFIGURATION.translated_locales:
for locale in self.configuration.translated_locales:
for filename in ('django', 'djangojs'):
mofile = filename + '.mo'
path = os.path.join(CONFIGURATION.get_messages_dir(locale), mofile)
path = os.path.join(self.configuration.get_messages_dir(locale), mofile)
exists = os.path.exists(path)
self.assertTrue(exists, msg='Missing file in locale %s: %s' % (locale, mofile))
self.assertGreaterEqual(
......@@ -108,7 +111,7 @@ class TestGenerate(TestCase):
# #-#-#-#-# django-partial.po (0.1a) #-#-#-#-#
"""
path = os.path.join(CONFIGURATION.get_messages_dir(locale), 'django.po')
path = os.path.join(self.configuration.get_messages_dir(locale), 'django.po')
pof = pofile(path)
pattern = re.compile('^#-#-#-#-#', re.M)
match = pattern.findall(pof.header)
......
......@@ -93,6 +93,8 @@ class AcceptanceTest(TestSuite):
report_file = self.report_dir / "{}.xml".format(self.system)
report_args = ["--xunit-file {}".format(report_file)]
return [
# set DBUS_SESSION_BUS_ADDRESS to avoid hangs on Chrome
"DBUS_SESSION_BUS_ADDRESS=/dev/null",
"DEFAULT_STORE={}".format(self.default_store),
"./manage.py",
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