Commit 2261bfdc by Renzo Lucioni

Merge pull request #703 from edx/renzo/fix-acceptance-tests

Fix acceptance/end-to-end tests
parents ca9f1c93 74dc1917
import requests import requests
from requests.auth import AuthBase from requests.auth import AuthBase
from acceptance_tests.config import ENROLLMENT_API_URL, ENROLLMENT_API_TOKEN from acceptance_tests.config import ACCESS_TOKEN, ENROLLMENT_API_URL
class BearerAuth(AuthBase): class BearerAuth(AuthBase):
...@@ -20,7 +20,7 @@ class BearerAuth(AuthBase): ...@@ -20,7 +20,7 @@ class BearerAuth(AuthBase):
class EnrollmentApiClient(object): class EnrollmentApiClient(object):
def __init__(self, host=None, key=None): def __init__(self, host=None, key=None):
self.host = host or ENROLLMENT_API_URL self.host = host or ENROLLMENT_API_URL
self.key = key or ENROLLMENT_API_TOKEN self.key = key or ACCESS_TOKEN
def get_enrollment_status(self, username, course_id): def get_enrollment_status(self, username, course_id):
""" """
......
import os import os
from acceptance_tests.utils import str2bool
def str2bool(s):
s = unicode(s)
return s.lower() in (u'yes', u'true', u't', u'1')
# GENERAL CONFIGURATION
ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN') ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN')
ENABLE_OAUTH2_TESTS = str2bool(os.environ.get('ENABLE_OAUTH2_TESTS', True))
HONOR_COURSE_ID = os.environ.get('HONOR_COURSE_ID', 'course-v1:edX+DemoX+Demo_Course')
VERIFIED_COURSE_ID = os.environ.get('VERIFIED_COURSE_ID', 'course-v1:BerkeleyX+ColWri.3.6x+3T2015')
PROFESSIONAL_COURSE_ID = os.environ.get('PROFESSIONAL_COURSE_ID', 'course-v1:UBCx+Marketing5501x+2T2015')
if ACCESS_TOKEN is None: if ACCESS_TOKEN is None:
raise RuntimeError('A valid OAuth2 access token is required to run acceptance tests.') raise RuntimeError('A valid OAuth2 access token is required.')
# END GENERAL CONFIGURATION
HONOR_COURSE_ID = os.environ.get('HONOR_COURSE_ID')
VERIFIED_COURSE_ID = os.environ.get('VERIFIED_COURSE_ID')
if not all([HONOR_COURSE_ID, VERIFIED_COURSE_ID]):
raise RuntimeError('IDs for courses with honor and verified modes are required.')
PROFESSIONAL_COURSE_ID = os.environ.get('PROFESSIONAL_COURSE_ID')
# OTTO CONFIGURATION
try: try:
ECOMMERCE_URL_ROOT = os.environ.get('ECOMMERCE_URL_ROOT').strip('/') ECOMMERCE_URL_ROOT = os.environ.get('ECOMMERCE_URL_ROOT').strip('/')
except AttributeError: except AttributeError:
raise RuntimeError('You must provide a valid URL root for the E-Commerce Service to run acceptance tests.') raise RuntimeError('A valid URL root for the E-Commerce Service is required.')
ECOMMERCE_API_URL = os.environ.get('ECOMMERCE_API_URL', ECOMMERCE_URL_ROOT + '/api/v2') ECOMMERCE_API_URL = os.environ.get('ECOMMERCE_API_URL', ECOMMERCE_URL_ROOT + '/api/v2')
ECOMMERCE_API_TOKEN = os.environ.get('ECOMMERCE_API_TOKEN', ACCESS_TOKEN)
MAX_COMPLETION_RETRIES = int(os.environ.get('MAX_COMPLETION_RETRIES', 3)) MAX_COMPLETION_RETRIES = int(os.environ.get('MAX_COMPLETION_RETRIES', 3))
PAYPAL_EMAIL = os.environ.get('PAYPAL_EMAIL') PAYPAL_EMAIL = os.environ.get('PAYPAL_EMAIL')
PAYPAL_PASSWORD = os.environ.get('PAYPAL_PASSWORD') PAYPAL_PASSWORD = os.environ.get('PAYPAL_PASSWORD')
# It can be a pain to set up CyberSource for local testing. This flag allows CyberSource
# tests to be disabled.
ENABLE_CYBERSOURCE_TESTS = str2bool(os.environ.get('ENABLE_CYBERSOURCE_TESTS', True)) ENABLE_CYBERSOURCE_TESTS = str2bool(os.environ.get('ENABLE_CYBERSOURCE_TESTS', True))
# END OTTO CONFIGURATION
# MARKETING CONFIGURATION
ENABLE_MARKETING_SITE = str2bool(os.environ.get('ENABLE_MARKETING_SITE', False))
MARKETING_URL_ROOT = os.environ.get('MARKETING_URL_ROOT').strip('/') if ENABLE_MARKETING_SITE else None
# These must correspond to the course IDs provided for each enrollment mode.
VERIFIED_COURSE_SLUG = os.environ.get(
'VERIFIED_COURSE_SLUG',
'dracula-stoker-berkeleyx-book-club-uc-berkeleyx-colwri3-6x'
)
PROFESSIONAL_COURSE_SLUG = os.environ.get(
'PROFESSIONAL_COURSE_SLUG',
'marketing-non-marketers-ubcx-marketing5501x'
)
# END MARKETING CONFIGURATION
try:
MARKETING_URL_ROOT = os.environ.get('MARKETING_URL_ROOT').strip('/')
except AttributeError:
MARKETING_URL_ROOT = None
# LMS CONFIGURATION
try: try:
LMS_URL_ROOT = os.environ.get('LMS_URL_ROOT').strip('/') LMS_URL_ROOT = os.environ.get('LMS_URL_ROOT').strip('/')
except AttributeError: except AttributeError:
raise RuntimeError('You must provide a valid URL root for the LMS to run acceptance tests.') raise RuntimeError('A valid LMS URL root is required.')
ENABLE_OAUTH2_TESTS = str2bool(os.environ.get('ENABLE_OAUTH2_TESTS', True))
LMS_USERNAME = os.environ.get('LMS_USERNAME') LMS_USERNAME = os.environ.get('LMS_USERNAME')
LMS_EMAIL = os.environ.get('LMS_EMAIL') LMS_EMAIL = os.environ.get('LMS_EMAIL')
LMS_PASSWORD = os.environ.get('LMS_PASSWORD') LMS_PASSWORD = os.environ.get('LMS_PASSWORD')
LMS_AUTO_AUTH = str2bool(os.environ.get('LMS_AUTO_AUTH', False)) LMS_AUTO_AUTH = str2bool(os.environ.get('LMS_AUTO_AUTH', False))
LMS_HTTPS = str2bool(os.environ.get('LMS_HTTPS', True)) LMS_HTTPS = str2bool(os.environ.get('LMS_HTTPS', True))
ENROLLMENT_API_URL = os.environ.get('ENROLLMENT_API_URL', LMS_URL_ROOT + '/api/enrollment/v1') ENROLLMENT_API_URL = os.environ.get('ENROLLMENT_API_URL', LMS_URL_ROOT + '/api/enrollment/v1')
ENROLLMENT_API_TOKEN = os.environ.get('ENROLLMENT_API_TOKEN', ACCESS_TOKEN)
BASIC_AUTH_USERNAME = os.environ.get('BASIC_AUTH_USERNAME') BASIC_AUTH_USERNAME = os.environ.get('BASIC_AUTH_USERNAME')
BASIC_AUTH_PASSWORD = os.environ.get('BASIC_AUTH_PASSWORD') BASIC_AUTH_PASSWORD = os.environ.get('BASIC_AUTH_PASSWORD')
if ENABLE_OAUTH2_TESTS and not (LMS_URL_ROOT and LMS_USERNAME and LMS_PASSWORD): if ENABLE_OAUTH2_TESTS and not all([LMS_URL_ROOT, LMS_USERNAME, LMS_PASSWORD]):
raise RuntimeError('Configuring LMS settings is required to run OAuth2 tests.') raise RuntimeError('LMS settings are required to run OAuth2 tests.')
# END LMS CONFIGURATION
ENABLE_COUPON_ADMIN_TESTS = str2bool(os.environ.get('ENABLE_COUPON_ADMIN_TESTS', False))
...@@ -20,7 +20,7 @@ from acceptance_tests.config import ( ...@@ -20,7 +20,7 @@ from acceptance_tests.config import (
BASIC_AUTH_PASSWORD, BASIC_AUTH_PASSWORD,
ECOMMERCE_API_URL, ECOMMERCE_API_URL,
LMS_USERNAME, LMS_USERNAME,
ECOMMERCE_API_TOKEN, ACCESS_TOKEN,
MAX_COMPLETION_RETRIES, MAX_COMPLETION_RETRIES,
PAYPAL_PASSWORD, PAYPAL_PASSWORD,
PAYPAL_EMAIL, PAYPAL_EMAIL,
...@@ -126,7 +126,7 @@ class EnrollmentApiMixin(object): ...@@ -126,7 +126,7 @@ class EnrollmentApiMixin(object):
class EcommerceApiMixin(object): class EcommerceApiMixin(object):
@property @property
def ecommerce_api_client(self): def ecommerce_api_client(self):
return EdxRestApiClient(ECOMMERCE_API_URL, oauth_access_token=ECOMMERCE_API_TOKEN) return EdxRestApiClient(ECOMMERCE_API_URL, oauth_access_token=ACCESS_TOKEN)
def assert_order_created_and_completed(self): def assert_order_created_and_completed(self):
orders = self.ecommerce_api_client.orders.get()['results'] orders = self.ecommerce_api_client.orders.get()['results']
...@@ -192,17 +192,29 @@ class PaymentMixin(object): ...@@ -192,17 +192,29 @@ class PaymentMixin(object):
# Click the payment button # Click the payment button
self.browser.find_element_by_css_selector('#paypal').click() self.browser.find_element_by_css_selector('#paypal').click()
# Wait for form to load # Wait for login form to load. PayPal's test environment is slow.
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.ID, 'loginFields'))) wait = WebDriverWait(self.browser, 30)
iframe_present = EC.presence_of_element_located((By.CSS_SELECTOR, '#injectedUnifiedLogin > iframe'))
iframe = wait.until(iframe_present)
# Log into PayPal # Log into PayPal
self.browser.switch_to.frame(iframe)
self.browser.find_element_by_css_selector('input#email').send_keys(PAYPAL_EMAIL) self.browser.find_element_by_css_selector('input#email').send_keys(PAYPAL_EMAIL)
self.browser.find_element_by_css_selector('input#password').send_keys(PAYPAL_PASSWORD) self.browser.find_element_by_css_selector('input#password').send_keys(PAYPAL_PASSWORD)
self.browser.find_element_by_css_selector('input[type="submit"]').click() self.browser.find_element_by_css_selector('button[type="submit"]').click()
self.browser.switch_to.default_content()
# Wait for the checkout form to load. PayPal's test environment is slow.
wait = WebDriverWait(self.browser, 30)
confirmation_button_present = EC.presence_of_element_located((By.ID, 'confirmButtonTop'))
confirmation_button = wait.until(confirmation_button_present)
# Wait for the checkout form to load, then submit it. # PayPal's loading spinner sticks around for longer than it should.
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.ID, 'confirmButtonTop'))) wait = WebDriverWait(self.browser, 2)
self.browser.find_element_by_css_selector('input#confirmButtonTop').click() spinner_invisibility = EC.invisibility_of_element_located((By.ID, 'spinner'))
wait.until(spinner_invisibility)
confirmation_button.click()
def checkout_with_cybersource(self, address): def checkout_with_cybersource(self, address):
""" Completes the checkout process via CyberSource. """ """ Completes the checkout process via CyberSource. """
...@@ -213,7 +225,9 @@ class PaymentMixin(object): ...@@ -213,7 +225,9 @@ class PaymentMixin(object):
self.dismiss_alert() self.dismiss_alert()
# Wait for form to load # Wait for form to load
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.ID, 'billing_details'))) wait = WebDriverWait(self.browser, 10)
billing_details_present = EC.presence_of_element_located((By.ID, 'billing_details'))
wait.until(billing_details_present)
# Select the credit card type (Visa) first since it triggers the display of additional fields # Select the credit card type (Visa) first since it triggers the display of additional fields
self.browser.find_element_by_css_selector('#card_type_001').click() # Visa self.browser.find_element_by_css_selector('#card_type_001').click() # Visa
...@@ -253,9 +267,24 @@ class PaymentMixin(object): ...@@ -253,9 +267,24 @@ class PaymentMixin(object):
def assert_receipt_page_loads(self): def assert_receipt_page_loads(self):
""" Verifies the receipt page loaded in the browser. """ """ Verifies the receipt page loaded in the browser. """
refresh = False
# Wait for the payment processor response to be processed, and the receipt page updated. # In a test environment, it can take a while for the payment processor to respond.
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'content-main'))) for _ in range(MAX_COMPLETION_RETRIES):
try:
if refresh:
self.browser.refresh()
WebDriverWait(self.browser, 2).until(EC.alert_is_present())
self.browser.switch_to.alert.accept()
# Wait for the payment processor response to be processed, and the receipt page updated.
wait = WebDriverWait(self.browser, 10)
receipt_loaded = EC.presence_of_element_located((By.CLASS_NAME, 'content-main'))
wait.until(receipt_loaded)
break
except TimeoutException:
refresh = True
# Verify we reach the receipt page. # Verify we reach the receipt page.
self.assertIn('receipt', self.browser.title.lower()) self.assertIn('receipt', self.browser.title.lower())
......
...@@ -5,6 +5,7 @@ import string # pylint: disable=deprecated-module ...@@ -5,6 +5,7 @@ import string # pylint: disable=deprecated-module
from bok_choy.javascript import wait_for_js from bok_choy.javascript import wait_for_js
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from acceptance_tests.config import VERIFIED_COURSE_ID from acceptance_tests.config import VERIFIED_COURSE_ID
...@@ -15,9 +16,18 @@ from acceptance_tests.pages.ecommerce import EcommerceAppPage ...@@ -15,9 +16,18 @@ from acceptance_tests.pages.ecommerce import EcommerceAppPage
def _get_coupon_name(is_discount): def _get_coupon_name(is_discount):
""" Returns an appropriate coupon name. """ """ Returns an appropriate coupon name. """
prefix = 'test-discount-code-' if is_discount else 'test-enrollment-code-' prefix = 'test-discount-code-' if is_discount else 'test-enrollment-code-'
postfix = ''.join(random.choice(string.ascii_letters) for _ in range(3)) suffix = ''.join(random.choice(string.ascii_letters) for _ in range(10))
return prefix + postfix return prefix + suffix
class verified_option_selected(object):
"""An expectation for checking that the verified option has been selected."""
def __init__(self, select):
self.select = select
def __call__(self, _):
return self.select.first_selected_option.text == 'Verified'
class BasketPage(EcommerceAppPage): class BasketPage(EcommerceAppPage):
...@@ -50,19 +60,32 @@ class CouponsCreatePage(EcommerceAppPage): ...@@ -50,19 +60,32 @@ class CouponsCreatePage(EcommerceAppPage):
self.q(css='input[name="title"]').fill(coupon_name) self.q(css='input[name="title"]').fill(coupon_name)
self.q(css=course_id_input).fill(VERIFIED_COURSE_ID) self.q(css=course_id_input).fill(VERIFIED_COURSE_ID)
self.wait_for_ajax() self.wait_for_ajax()
self.wait_for_element_presence(
'select[name="seat_type"] option[value="Verified"]', wait = WebDriverWait(self.browser, 5)
'Seat Type Drop-Down List is Present' verified_option_present = EC.presence_of_element_located(
(By.CSS_SELECTOR, 'select[name="seat_type"] option[value="Verified"]')
) )
wait.until(verified_option_present)
self.q(css="input[name='start_date']").fill(str(DEFAULT_START_DATE)) self.q(css="input[name='start_date']").fill(str(DEFAULT_START_DATE))
self.q(css="input[name='end_date']").fill(str(DEFAULT_END_DATE)) self.q(css="input[name='end_date']").fill(str(DEFAULT_END_DATE))
self.q(css="input[name='client']").fill('Test Client') self.q(css="input[name='client']").fill('Test Client')
self.q(css='select[name="seat_type"] option[value="Verified"]').first.click()
select = Select(self.browser.find_element_by_css_selector('select[name="seat_type"]'))
select.select_by_visible_text('Verified')
# This prevents the test from advancing before the seat type is selected.
wait = WebDriverWait(self.browser, 5)
wait.until(verified_option_selected)
if is_discount: if is_discount:
self.q(css='select[name="code_type"] option[value="Discount code"]').first.click() select = Select(self.browser.find_element_by_css_selector('select[name="code_type"]'))
self.wait_for_element_presence('input[name="benefit_value"]', 'Benefit Value Input is Present') select.select_by_visible_text('Discount Code')
wait = WebDriverWait(self.browser, 5)
benefit_input_present = EC.presence_of_element_located((By.CSS_SELECTOR, 'input[name="benefit_value"]'))
wait.until(benefit_input_present)
self.q(css="input[name='benefit_value']").fill('50') self.q(css="input[name='benefit_value']").fill('50')
self.q(css="div.form-actions > button.btn").click() self.q(css="div.form-actions > button.btn").click()
...@@ -90,7 +113,6 @@ class CouponsDetailsPage(EcommerceAppPage): ...@@ -90,7 +113,6 @@ class CouponsDetailsPage(EcommerceAppPage):
@wait_for_js @wait_for_js
def go_to_edit_coupon_form_page(self): def go_to_edit_coupon_form_page(self):
self.browser.find_element_by_id('CouponEdit').click() self.browser.find_element_by_id('CouponEdit').click()
# self.q(css='div.coupon-detail-view div.pull-right a.btn.btn-primary.btn-small').first.click()
self.wait_for_ajax() self.wait_for_ajax()
......
import urllib
from bok_choy.page_object import PageObject from bok_choy.page_object import PageObject
import requests
from acceptance_tests.config import MARKETING_URL_ROOT, BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD from acceptance_tests.config import MARKETING_URL_ROOT, BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD
class MarketingCourseAboutPage(PageObject): class MarketingCourseAboutPage(PageObject):
def __init__(self, browser, course_id):
super(MarketingCourseAboutPage, self).__init__(browser)
drupal_catalog_url = '{}/api/catalog/v2/courses/{}'.format(MARKETING_URL_ROOT, course_id)
response = requests.get(drupal_catalog_url)
data = response.json()
self.about_page_path = data['course_about_uri']
def is_browser_on_page(self): def is_browser_on_page(self):
return self.q(css='.js-enroll-btn').visible return self.q(css='.js-enroll-btn').visible
def _build_url(self, path): @property
url = '{}/{}'.format(MARKETING_URL_ROOT, path) def url(self):
url = '{}/{}'.format(MARKETING_URL_ROOT, self.about_page_path)
if BASIC_AUTH_USERNAME and BASIC_AUTH_PASSWORD: if BASIC_AUTH_USERNAME and BASIC_AUTH_PASSWORD:
url = url.replace('://', '://{}:{}@'.format(BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD)) url = url.replace('://', '://{}:{}@'.format(BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD))
return url return url
@property
def url(self):
path = 'course/{}'.format(urllib.quote_plus(self.slug))
return self._build_url(path)
def __init__(self, browser, slug):
super(MarketingCourseAboutPage, self).__init__(browser)
self.slug = slug
from datetime import date from datetime import date
from unittest import skipUnless
from bok_choy.web_app_test import WebAppTest from bok_choy.web_app_test import WebAppTest
from acceptance_tests.config import ENABLE_COUPON_ADMIN_TESTS
from acceptance_tests.constants import DEFAULT_END_DATE, DEFAULT_START_DATE from acceptance_tests.constants import DEFAULT_END_DATE, DEFAULT_START_DATE
from acceptance_tests.mixins import CouponMixin, LogistrationMixin from acceptance_tests.mixins import CouponMixin, LogistrationMixin
from acceptance_tests.pages import CouponsCreatePage, CouponsDetailsPage, CouponsListPage from acceptance_tests.pages import CouponsCreatePage, CouponsDetailsPage, CouponsListPage
@skipUnless(ENABLE_COUPON_ADMIN_TESTS, 'Coupon admin tests are disabled.')
class CouponAdministrationTests(CouponMixin, LogistrationMixin, WebAppTest): class CouponAdministrationTests(CouponMixin, LogistrationMixin, WebAppTest):
def setUp(self): def setUp(self):
""" Instantiate the page objects. """ """ Instantiate the page objects. """
......
...@@ -6,7 +6,7 @@ from selenium.webdriver.common.by import By ...@@ -6,7 +6,7 @@ from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from acceptance_tests.config import (VERIFIED_COURSE_ID, ENABLE_MARKETING_SITE, VERIFIED_COURSE_SLUG, from acceptance_tests.config import (VERIFIED_COURSE_ID, MARKETING_URL_ROOT,
PAYPAL_PASSWORD, PAYPAL_EMAIL, ENABLE_CYBERSOURCE_TESTS) PAYPAL_PASSWORD, PAYPAL_EMAIL, ENABLE_CYBERSOURCE_TESTS)
from acceptance_tests.constants import CYBERSOURCE_DATA1, CYBERSOURCE_DATA2 from acceptance_tests.constants import CYBERSOURCE_DATA1, CYBERSOURCE_DATA2
from acceptance_tests.mixins import (LogistrationMixin, EnrollmentApiMixin, EcommerceApiMixin, from acceptance_tests.mixins import (LogistrationMixin, EnrollmentApiMixin, EcommerceApiMixin,
...@@ -26,18 +26,17 @@ class VerifiedCertificatePaymentTests(UnenrollmentMixin, EcommerceApiMixin, Enro ...@@ -26,18 +26,17 @@ class VerifiedCertificatePaymentTests(UnenrollmentMixin, EcommerceApiMixin, Enro
""" Begin the checkout process for a verified certificate. """ """ Begin the checkout process for a verified certificate. """
self.login_with_lms(self.email, self.password) self.login_with_lms(self.email, self.password)
# If a slug is provided, use the marketing site. if MARKETING_URL_ROOT:
if ENABLE_MARKETING_SITE: course_about_page = MarketingCourseAboutPage(self.browser, self.course_id)
course_about_page = MarketingCourseAboutPage(self.browser, VERIFIED_COURSE_SLUG)
course_about_page.visit() course_about_page.visit()
# Click the first enroll button on the page to take the browser to the track selection page. # Click the first enroll button on the page to take the browser to the track selection page.
course_about_page.q(css='.js-enroll-btn').first.click() course_about_page.q(css='.js-enroll-btn').first.click()
# Wait for the track selection page to load. # Wait for the track selection page to load.
WebDriverWait(self.browser, 10).until( wait = WebDriverWait(self.browser, 10)
EC.presence_of_element_located((By.CLASS_NAME, 'form-register-choose')) track_selection_present = EC.presence_of_element_located((By.CLASS_NAME, 'form-register-choose'))
) wait.until(track_selection_present)
else: else:
course_modes_page = LMSCourseModePage(self.browser, self.course_id) course_modes_page = LMSCourseModePage(self.browser, self.course_id)
course_modes_page.visit() course_modes_page.visit()
...@@ -59,7 +58,6 @@ class VerifiedCertificatePaymentTests(UnenrollmentMixin, EcommerceApiMixin, Enro ...@@ -59,7 +58,6 @@ class VerifiedCertificatePaymentTests(UnenrollmentMixin, EcommerceApiMixin, Enro
def test_paypal(self): def test_paypal(self):
""" Test checkout with PayPal. """ """ Test checkout with PayPal. """
if not (PAYPAL_EMAIL and PAYPAL_PASSWORD): if not (PAYPAL_EMAIL and PAYPAL_PASSWORD):
self.fail('No PayPal credentials supplied!') self.fail('No PayPal credentials supplied!')
......
from unittest import skipUnless
from bok_choy.web_app_test import WebAppTest from bok_choy.web_app_test import WebAppTest
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from acceptance_tests.config import PROFESSIONAL_COURSE_ID, ENABLE_MARKETING_SITE, PROFESSIONAL_COURSE_SLUG from acceptance_tests.config import PROFESSIONAL_COURSE_ID, MARKETING_URL_ROOT
from acceptance_tests.mixins import LogistrationMixin, EnrollmentApiMixin from acceptance_tests.mixins import LogistrationMixin, EnrollmentApiMixin
from acceptance_tests.pages import LMSCourseModePage, MarketingCourseAboutPage from acceptance_tests.pages import LMSCourseModePage, MarketingCourseAboutPage
@skipUnless(PROFESSIONAL_COURSE_ID, 'Professional education tests are not enabled.')
class ProfessionalEducationEnrollmentTests(EnrollmentApiMixin, LogistrationMixin, WebAppTest): class ProfessionalEducationEnrollmentTests(EnrollmentApiMixin, LogistrationMixin, WebAppTest):
def test_payment_required(self): def test_payment_required(self):
"""Verify payment is required before enrolling in a professional education course.""" """Verify payment is required before enrolling in a professional education course."""
# Sign into LMS
username, password, email = self.get_lms_user() username, password, email = self.get_lms_user()
self.login_with_lms(email, password) self.login_with_lms(email, password)
if ENABLE_MARKETING_SITE: if MARKETING_URL_ROOT:
course_about_page = MarketingCourseAboutPage(self.browser, PROFESSIONAL_COURSE_SLUG) course_about_page = MarketingCourseAboutPage(self.browser, PROFESSIONAL_COURSE_ID)
course_about_page.visit() course_about_page.visit()
# Click the first enroll button on the page to take the browser to the track selection page, # Click the first enroll button on the page to take the browser to the track selection page,
# and allow it to load. # and allow it to load.
course_about_page.q(css='.js-enroll-btn').first.click() course_about_page.q(css='.js-enroll-btn').first.click()
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'make-payment-step'))) WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'basket')))
else: else:
# Visit the course mode page (where auto-enrollment normally occurs) # Visit the course mode page (where auto-enrollment normally occurs)
LMSCourseModePage(self.browser, PROFESSIONAL_COURSE_ID).visit() LMSCourseModePage(self.browser, PROFESSIONAL_COURSE_ID).visit()
......
"""Utilities for end-to-end tests."""
def str2bool(s):
s = unicode(s)
return s.lower() in (u'yes', u'true', u't', u'1')
...@@ -101,7 +101,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet): ...@@ -101,7 +101,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
raise NotImplementedError('Multi-use voucher types are not supported') raise NotImplementedError('Multi-use voucher types are not supported')
# When a black-listed course mode is received raise an exception. # When a black-listed course mode is received raise an exception.
# Audit modes do not have a certificate type and therefor will raise # Audit modes do not have a certificate type and therefore will raise
# an AttributeError exception. # an AttributeError exception.
seats = Product.objects.filter(stockrecords__id__in=stock_record_ids) seats = Product.objects.filter(stockrecords__id__in=stock_record_ids)
for seat in seats: for seat in seats:
......
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