Files
edx-platform/common/test/acceptance/pages/common/utils.py
Amit 8649385861 INCR-244: Make compatible with Python 3.x without breaking Python 2.7… (#20531)
* INCR-244: Make compatible with Python 3.x without breaking Python 2.7 support on common/test/acceptance/pages [common, xblock]

* INCR-244: Add missing module docstring and fix for six import

* INCR-244: Update module docstring
2019-05-14 11:10:25 -04:00

151 lines
5.7 KiB
Python

"""
Utility methods common to Studio and the LMS.
"""
from __future__ import absolute_import
import six
from bok_choy.promise import BrokenPromise
from selenium.webdriver.common.action_chains import ActionChains
from common.test.acceptance.pages.lms.create_mode import ModeCreationPage
from common.test.acceptance.pages.lms.pay_and_verify import FakePaymentPage, PaymentAndVerificationFlow
from common.test.acceptance.pages.lms.track_selection import TrackSelectionPage
from common.test.acceptance.tests.helpers import disable_animations
def sync_on_notification(page, style='default', wait_for_hide=False):
"""
Sync on notifications but do not raise errors.
A BrokenPromise in the wait_for probably means that we missed it.
We should just swallow this error and not raise it for reasons including:
* We are not specifically testing this functionality
* This functionality is covered by unit tests
* This verification method is prone to flakiness
and browser version dependencies
See classes in edx-platform:
lms/static/sass/elements/_system-feedback.scss
"""
hiding_class = 'is-hiding'
shown_class = 'is-shown'
def notification_has_class(style, el_class):
"""
Return a boolean representing whether
the notification has the class applied.
"""
if style == 'mini':
css_string = '.wrapper-notification-mini.{}'
else:
css_string = '.wrapper-notification-confirmation.{}'
return page.q(css=css_string.format(el_class)).present
# Wait for the notification to show.
# This notification appears very quickly and maybe missed. Don't raise an error.
try:
page.wait_for(
lambda: notification_has_class(style, shown_class),
'Notification should have been shown.',
timeout=5
)
except BrokenPromise as _err:
pass
# Now wait for it to hide.
# This is not required for web page interaction, so not really needed.
if wait_for_hide:
page.wait_for(
lambda: notification_has_class(style, hiding_class),
'Notification should have hidden.'
)
def click_css(page, css, source_index=0, require_notification=True):
"""
Click the button/link with the given css and index on the specified page (subclass of PageObject).
Will only consider elements that are displayed and have a height and width greater than zero.
If require_notification is False (default value is True), the method will return immediately.
Otherwise, it will wait for the "mini-notification" to appear and disappear.
"""
def _is_visible(element):
"""Is the given element visible?"""
# Only make the call to size once (instead of once for the height and once for the width)
# because otherwise you will trigger a extra query on a remote element.
return element.is_displayed() and all(size > 0 for size in six.itervalues(element.size))
# Disable all animations for faster testing with more reliable synchronization
disable_animations(page)
# Click on the element in the browser
page.q(css=css).filter(_is_visible).nth(source_index).click()
if require_notification:
sync_on_notification(page)
# Some buttons trigger ajax posts
# (e.g. .add-missing-groups-button as configured in split_test_author_view.js)
# so after you click anything wait for the ajax call to finish
page.wait_for_ajax()
def confirm_prompt(page, cancel=False, require_notification=None):
"""
Ensures that a modal prompt and confirmation button are visible, then clicks the button. The prompt is canceled iff
cancel is True.
"""
page.wait_for_element_visibility('.prompt', 'Prompt is visible')
confirmation_button_css = '.prompt .action-' + ('secondary' if cancel else 'primary')
page.wait_for_element_visibility(confirmation_button_css, 'Confirmation button is visible')
require_notification = (not cancel) if require_notification is None else require_notification
click_css(page, confirmation_button_css, require_notification=require_notification)
def hover(browser, element):
"""
Hover over an element.
"""
ActionChains(browser).move_to_element(element).perform()
def enroll_user_track(browser, course_id, track):
"""
Utility method to enroll a user in the audit or verified user track. Creates and connects to the
necessary pages. Selects the track and handles payment for verified.
Supported tracks are 'verified' or 'audit'.
"""
payment_and_verification_flow = PaymentAndVerificationFlow(browser, course_id)
fake_payment_page = FakePaymentPage(browser, course_id)
track_selection = TrackSelectionPage(browser, course_id)
# Select track and process payment
track_selection.visit()
track_selection.enroll(track)
if track == 'verified':
payment_and_verification_flow.proceed_to_payment()
fake_payment_page.submit_payment()
def add_enrollment_course_modes(browser, course_id, tracks):
"""
Add the specified array of tracks to the given course.
Supported tracks are `verified` and `audit` (all others will be ignored),
and display names assigned are `Verified` and `Audit`, respectively.
"""
for track in tracks:
if track == 'audit':
# Add an audit mode to the course
ModeCreationPage(
browser,
course_id, mode_slug='audit',
mode_display_name='Audit'
).visit()
elif track == 'verified':
# Add a verified mode to the course
ModeCreationPage(
browser, course_id, mode_slug='verified',
mode_display_name='Verified', min_price=10
).visit()