Commit 6ff61480 by Clinton Blackburn Committed by Clinton Blackburn

Updated auto_auth endpoint to always return JSON

Defaulting to a plaintext response makes no sense for an endpoint that is intended to be used by machines for testing. The endpoint now returns JSON only unless a redirect action is triggered.
parent c285b4f3
...@@ -5,13 +5,15 @@ from django.conf import settings ...@@ -5,13 +5,15 @@ from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.test import TestCase from django.test import TestCase
from django.test.client import Client from django.test.client import Client
from mock import Mock, patch from mock import patch, Mock
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locator import CourseLocator from opaque_keys.edx.locator import CourseLocator
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_STUDENT, Role from django_comment_common.models import (
Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_STUDENT
)
from django_comment_common.utils import seed_permissions_roles from django_comment_common.utils import seed_permissions_roles
from student.models import CourseEnrollment, UserProfile, anonymous_id_for_user from student.models import anonymous_id_for_user, CourseAccessRole, CourseEnrollment, UserProfile
from util.testing import UrlResetMixin from util.testing import UrlResetMixin
...@@ -169,18 +171,16 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase): ...@@ -169,18 +171,16 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase):
course_roles[FORUM_ROLE_MODERATOR], course_roles[FORUM_ROLE_MODERATOR],
course_roles[FORUM_ROLE_ADMINISTRATOR]])) course_roles[FORUM_ROLE_ADMINISTRATOR]]))
@ddt.data(*COURSE_IDS_DDT) def test_json_response(self):
@ddt.unpack """ The view should return JSON. """
def test_json_response(self, course_id, course_key): # pylint: disable=unused-argument response = self._auto_auth()
"""Verify that we can get JSON back from the auto_auth page."""
response = self._auto_auth(HTTP_ACCEPT='application/json')
response_data = json.loads(response.content) response_data = json.loads(response.content)
for key in ['created_status', 'username', 'email', 'password', 'user_id', 'anonymous_id']: for key in ['created_status', 'username', 'email', 'password', 'user_id', 'anonymous_id']:
self.assertIn(key, response_data) self.assertIn(key, response_data)
user = User.objects.get(username=response_data['username']) user = User.objects.get(username=response_data['username'])
self.assertDictContainsSubset( self.assertDictContainsSubset(
{ {
'created_status': "Logged in", 'created_status': 'Logged in',
'anonymous_id': anonymous_id_for_user(user, None), 'anonymous_id': anonymous_id_for_user(user, None),
}, },
response_data response_data
...@@ -237,23 +237,23 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase): ...@@ -237,23 +237,23 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase):
self.assertTrue(response.url.endswith(url_pattern)) # pylint: disable=no-member self.assertTrue(response.url.endswith(url_pattern)) # pylint: disable=no-member
def _auto_auth(self, params=None, status_code=None, **kwargs): def _auto_auth(self, params=None, status_code=200, **kwargs):
""" """
Make a request to the auto-auth end-point and check Make a request to the auto-auth end-point and check
that the response is successful. that the response is successful.
Arguments: Arguments:
params (dict): Dict of params to pass to the auto_auth view params (dict): Dict of params to pass to the auto_auth view
status_code (int): Expected response status code
kwargs: Passed directly to the test client's get method. kwargs: Passed directly to the test client's get method.
Returns Returns:
response: The response object for the auto_auth page. Response: The response object for the auto_auth page.
""" """
params = params or {} params = params or {}
response = self.client.get(self.url, params, **kwargs) response = self.client.get(self.url, params, **kwargs)
expected_status_code = status_code if status_code else 200 self.assertEqual(response.status_code, status_code)
self.assertEqual(response.status_code, expected_status_code)
# Check that session and CSRF are set in the response # Check that session and CSRF are set in the response
for cookie in ['csrftoken', 'sessionid']: for cookie in ['csrftoken', 'sessionid']:
...@@ -270,6 +270,26 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase): ...@@ -270,6 +270,26 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase):
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertEqual(response.status_code, 403) self.assertEqual(response.status_code, 403)
def test_course_access_roles(self):
""" Passing role names via the course_access_roles query string parameter should create CourseAccessRole
objects associated with the user.
"""
expected_roles = ['finance_admin', 'sales_admin']
course_key = CourseLocator.from_string(self.COURSE_ID_SPLIT)
params = {
'course_id': str(course_key),
'course_access_roles': ','.join(expected_roles)
}
response = self._auto_auth(params)
user_info = json.loads(response.content)
for role in expected_roles:
self.assertTrue(
CourseAccessRole.objects.filter(
user__id=user_info['user_id'], course_id=course_key, org=course_key.org, role=role
).exists()
)
class AutoAuthDisabledTestCase(AutoAuthTestCase): class AutoAuthDisabledTestCase(AutoAuthTestCase):
""" """
......
""" """
Student Views Student Views
""" """
import datetime import datetime
import json import json
import logging import logging
import uuid import uuid
import warnings import warnings
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from urlparse import parse_qs, urljoin, urlsplit, urlunsplit from urlparse import parse_qs, urlsplit, urlunsplit
import analytics import analytics
import edx_oauth2_provider import edx_oauth2_provider
...@@ -25,7 +26,7 @@ from django.core.validators import ValidationError, validate_email ...@@ -25,7 +26,7 @@ from django.core.validators import ValidationError, validate_email
from django.db import IntegrityError, transaction from django.db import IntegrityError, transaction
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import Signal, receiver from django.dispatch import Signal, receiver
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseServerError from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
from django.shortcuts import redirect from django.shortcuts import redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils.encoding import force_bytes, force_text from django.utils.encoding import force_bytes, force_text
...@@ -35,6 +36,7 @@ from django.utils.translation import get_language, ungettext ...@@ -35,6 +36,7 @@ from django.utils.translation import get_language, ungettext
from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
from django.views.decorators.http import require_GET, require_POST from django.views.decorators.http import require_GET, require_POST
from django.views.generic import TemplateView from django.views.generic import TemplateView
from eventtracking import tracker
from ipware.ip import get_ip from ipware.ip import get_ip
from opaque_keys import InvalidKeyError from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
...@@ -62,9 +64,8 @@ from certificates.models import ( # pylint: disable=import-error ...@@ -62,9 +64,8 @@ from certificates.models import ( # pylint: disable=import-error
from course_modes.models import CourseMode from course_modes.models import CourseMode
from courseware.access import has_access from courseware.access import has_access
from courseware.courses import get_courses, sort_by_announcement, sort_by_start_date # pylint: disable=import-error from courseware.courses import get_courses, sort_by_announcement, sort_by_start_date # pylint: disable=import-error
from django_comment_common.models import Role from django_comment_common.models import assign_role
from edxmako.shortcuts import render_to_response, render_to_string from edxmako.shortcuts import render_to_response, render_to_string
from eventtracking import tracker
from lms.djangoapps.commerce.utils import EcommerceService # pylint: disable=import-error from lms.djangoapps.commerce.utils import EcommerceService # pylint: disable=import-error
from lms.djangoapps.grades.new.course_grade_factory import CourseGradeFactory from lms.djangoapps.grades.new.course_grade_factory import CourseGradeFactory
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification # pylint: disable=import-error from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification # pylint: disable=import-error
...@@ -99,11 +100,11 @@ from student.helpers import ( ...@@ -99,11 +100,11 @@ from student.helpers import (
) )
from student.models import ( from student.models import (
ALLOWEDTOENROLL_TO_ENROLLED, ALLOWEDTOENROLL_TO_ENROLLED,
CourseAccessRole,
CourseEnrollment, CourseEnrollment,
CourseEnrollmentAllowed, CourseEnrollmentAllowed,
CourseEnrollmentAttribute, CourseEnrollmentAttribute,
DashboardConfiguration, DashboardConfiguration,
EnrollStatusChange,
LinkedInAddToProfileConfiguration, LinkedInAddToProfileConfiguration,
LoginFailures, LoginFailures,
LogoutViewConfiguration, LogoutViewConfiguration,
...@@ -2131,6 +2132,27 @@ def create_account(request, post_override=None): ...@@ -2131,6 +2132,27 @@ def create_account(request, post_override=None):
return response return response
def str2bool(s):
s = str(s)
return s.lower() in ('yes', 'true', 't', '1')
def _clean_roles(roles):
""" Clean roles.
Strips whitespace from roles, and removes empty items.
Args:
roles (str[]): List of role names.
Returns:
str[]
"""
roles = [role.strip() for role in roles]
roles = [role for role in roles if role]
return roles
def auto_auth(request): def auto_auth(request):
""" """
Create or configure a user account, then log in as that user. Create or configure a user account, then log in as that user.
...@@ -2154,29 +2176,27 @@ def auto_auth(request): ...@@ -2154,29 +2176,27 @@ def auto_auth(request):
""" """
# Generate a unique name to use if none provided # Generate a unique name to use if none provided
unique_name = uuid.uuid4().hex[0:30] generated_username = uuid.uuid4().hex[0:30]
# Use the params from the request, otherwise use these defaults # Use the params from the request, otherwise use these defaults
username = request.GET.get('username', unique_name) username = request.GET.get('username', generated_username)
password = request.GET.get('password', unique_name) password = request.GET.get('password', username)
email = request.GET.get('email', unique_name + "@example.com") email = request.GET.get('email', username + "@example.com")
full_name = request.GET.get('full_name', username) full_name = request.GET.get('full_name', username)
is_staff = request.GET.get('staff', None) is_staff = str2bool(request.GET.get('staff', False))
is_superuser = request.GET.get('superuser', None) is_superuser = str2bool(request.GET.get('superuser', False))
course_id = request.GET.get('course_id', None) course_id = request.GET.get('course_id')
redirect_to = request.GET.get('redirect_to', None) redirect_to = request.GET.get('redirect_to')
active_status = request.GET.get('is_active') is_active = str2bool(request.GET.get('is_active', True))
# mode has to be one of 'honor'/'professional'/'verified'/'audit'/'no-id-professional'/'credit' # Valid modes: audit, credit, honor, no-id-professional, professional, verified
enrollment_mode = request.GET.get('enrollment_mode', 'honor') enrollment_mode = request.GET.get('enrollment_mode', 'honor')
active_status = (not active_status or active_status == 'true') # Parse roles, stripping whitespace, and filtering out empty strings
roles = _clean_roles(request.GET.get('roles', '').split(','))
course_access_roles = _clean_roles(request.GET.get('course_access_roles', '').split(','))
course_key = None redirect_when_done = str2bool(request.GET.get('redirect', '')) or redirect_to
if course_id:
course_key = CourseLocator.from_string(course_id)
role_names = [v.strip() for v in request.GET.get('roles', '').split(',') if v.strip()]
redirect_when_done = request.GET.get('redirect', '').lower() == 'true' or redirect_to
login_when_done = 'no_login' not in request.GET login_when_done = 'no_login' not in request.GET
form = AccountCreationForm( form = AccountCreationForm(
...@@ -2199,23 +2219,18 @@ def auto_auth(request): ...@@ -2199,23 +2219,18 @@ def auto_auth(request):
user = User.objects.get(username=username) user = User.objects.get(username=username)
user.email = email user.email = email
user.set_password(password) user.set_password(password)
user.is_active = active_status user.is_active = is_active
user.save() user.save()
profile = UserProfile.objects.get(user=user) profile = UserProfile.objects.get(user=user)
reg = Registration.objects.get(user=user) reg = Registration.objects.get(user=user)
except PermissionDenied: except PermissionDenied:
return HttpResponseForbidden(_("Account creation not allowed.")) return HttpResponseForbidden(_('Account creation not allowed.'))
# Set the user's global staff bit user.is_staff = is_staff
if is_staff is not None: user.is_superuser = is_superuser
user.is_staff = (is_staff == "true") user.save()
user.save()
if is_superuser is not None: if is_active:
user.is_superuser = (is_superuser == "true")
user.save()
if active_status:
reg.activate() reg.activate()
reg.save() reg.save()
...@@ -2226,13 +2241,17 @@ def auto_auth(request): ...@@ -2226,13 +2241,17 @@ def auto_auth(request):
profile.save() profile.save()
# Enroll the user in a course # Enroll the user in a course
if course_key is not None: course_key = None
if course_id:
course_key = CourseLocator.from_string(course_id)
CourseEnrollment.enroll(user, course_key, mode=enrollment_mode) CourseEnrollment.enroll(user, course_key, mode=enrollment_mode)
# Apply the roles # Apply the roles
for role_name in role_names: for role in roles:
role = Role.objects.get(name=role_name, course_id=course_key) assign_role(course_key, user, role)
user.roles.add(role)
for role in course_access_roles:
CourseAccessRole.objects.update_or_create(user=user, course_id=course_key, org=course_key.org, role=role)
# Log in as the user # Log in as the user
if login_when_done: if login_when_done:
...@@ -2241,50 +2260,33 @@ def auto_auth(request): ...@@ -2241,50 +2260,33 @@ def auto_auth(request):
create_comments_service_user(user) create_comments_service_user(user)
# Provide the user with a valid CSRF token
# then return a 200 response unless redirect is true
if redirect_when_done: if redirect_when_done:
# Redirect to specific page if specified
if redirect_to: if redirect_to:
# Redirect to page specified by the client
redirect_url = redirect_to redirect_url = redirect_to
# Redirect to course home page if course_id is known
elif course_id: elif course_id:
# Redirect to the course homepage (in LMS) or outline page (in Studio)
try: try:
# redirect to course home page in LMS redirect_url = reverse(course_home_url_name(request), kwargs={'course_id': course_id})
redirect_url = reverse(
course_home_url_name(request),
kwargs={'course_id': course_id}
)
except NoReverseMatch: except NoReverseMatch:
# redirect to course outline page in Studio redirect_url = reverse('course_handler', kwargs={'course_key_string': course_id})
redirect_url = reverse(
'course_handler',
kwargs={'course_key_string': course_id}
)
else: else:
# Redirect to the learner dashboard (in LMS) or homepage (in Studio)
try: try:
# redirect to dashboard for LMS
redirect_url = reverse('dashboard') redirect_url = reverse('dashboard')
except NoReverseMatch: except NoReverseMatch:
# redirect to home for Studio
redirect_url = reverse('home') redirect_url = reverse('home')
return redirect(redirect_url) return redirect(redirect_url)
elif request.META.get('HTTP_ACCEPT') == 'application/json': else:
response = JsonResponse({ response = JsonResponse({
'created_status': u"Logged in" if login_when_done else "Created", 'created_status': 'Logged in' if login_when_done else 'Created',
'username': username, 'username': username,
'email': email, 'email': email,
'password': password, 'password': password,
'user_id': user.id, # pylint: disable=no-member 'user_id': user.id, # pylint: disable=no-member
'anonymous_id': anonymous_id_for_user(user, None), 'anonymous_id': anonymous_id_for_user(user, None),
}) })
else:
success_msg = u"{} user {} ({}) with password {} and user_id {}".format(
u"Logged in" if login_when_done else "Created",
username, email, password, user.id # pylint: disable=no-member
)
response = HttpResponse(success_msg)
response.set_cookie('csrftoken', csrf(request)['csrf_token']) response.set_cookie('csrftoken', csrf(request)['csrf_token'])
return response return response
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
Common code shared by course and library fixtures. Common code shared by course and library fixtures.
""" """
import json import json
import re
import requests import requests
from lazy import lazy from lazy import lazy
...@@ -33,22 +32,20 @@ class StudioApiFixture(object): ...@@ -33,22 +32,20 @@ class StudioApiFixture(object):
""" """
# Use auto-auth to retrieve the session for a logged in user # Use auto-auth to retrieve the session for a logged in user
session = requests.Session() session = requests.Session()
response = session.get(STUDIO_BASE_URL + "/auto_auth?staff=true") response = session.get(STUDIO_BASE_URL + '/auto_auth?staff=true')
# Return the session from the request # Return the session from the request
if response.ok: if response.ok:
# auto_auth returns information about the newly created user # Capture the details of the authenticated user
# capture this so it can be used by by the testcases. self.user = response.json()
user_pattern = re.compile(r'Logged in user {0} \({1}\) with password {2} and user_id {3}'.format(
r'(?P<username>\S+)', r'(?P<email>[^\)]+)', r'(?P<password>\S+)', r'(?P<user_id>\d+)')) if not self.user:
user_matches = re.match(user_pattern, response.text) raise StudioApiLoginError('Auto-auth failed. Response was: {}'.format(self.user))
if user_matches:
self.user = user_matches.groupdict()
return session return session
else: else:
msg = "Could not log in to use Studio restful API. Status code: {0}".format(response.status_code) msg = 'Could not log in to use Studio restful API. Status code: {0}'.format(response.status_code)
raise StudioApiLoginError(msg) raise StudioApiLoginError(msg)
@lazy @lazy
......
""" """
Auto-auth page (used to automatically log in during testing). Auto-auth page (used to automatically log in during testing).
""" """
import json
import re import os
import urllib import urllib
from bok_choy.page_object import XSS_INJECTION, PageObject, unguarded from bok_choy.page_object import XSS_INJECTION, PageObject, unguarded
from common.test.acceptance.pages.lms import AUTH_BASE_URL # The URL used for user auth in testing
AUTH_BASE_URL = os.environ.get('test_url', 'http://localhost:8031')
class AutoAuthPage(PageObject): class AutoAuthPage(PageObject):
""" """
The automatic authorization page. The automatic authorization page.
When allowed via the django settings file, visiting
this url will create a user and log them in. When enabled via the Django settings file, visiting this url will create a user and log them in.
""" """
CONTENT_REGEX = r'.+? user (?P<username>\S+) \((?P<email>.+?)\) with password \S+ and user_id (?P<user_id>\d+)$' # Internal cache for parsed user info.
_user_info = None
def __init__(self, browser, username=None, email=None, password=None, full_name=None, staff=None, course_id=None, def __init__(self, browser, username=None, email=None, password=None, full_name=XSS_INJECTION, staff=False, course_id=None,
enrollment_mode=None, roles=None, is_active=None): enrollment_mode=None, roles=None, no_login=False, is_active=True, course_access_roles=None):
""" """
Auto-auth is an end-point for HTTP GET requests. Auto-auth is an end-point for HTTP GET requests.
By default, it will create accounts with random user credentials, By default, it will create accounts with random user credentials,
...@@ -39,33 +41,36 @@ class AutoAuthPage(PageObject): ...@@ -39,33 +41,36 @@ class AutoAuthPage(PageObject):
# This will eventually hold the details about the user account # This will eventually hold the details about the user account
self._user_info = None self._user_info = None
# Create query string parameters if provided course_access_roles = course_access_roles or []
self._params = {} course_access_roles = ','.join(course_access_roles)
if username is not None: self._params = {
self._params['username'] = username 'full_name': full_name,
'staff': staff,
'is_active': is_active,
'course_access_roles': course_access_roles,
}
self._params['full_name'] = full_name if full_name is not None else XSS_INJECTION if username:
self._params['username'] = username
if email is not None: if email:
self._params['email'] = email self._params['email'] = email
if password is not None: if password:
self._params['password'] = password self._params['password'] = password
if staff is not None: if course_id:
self._params['staff'] = "true" if staff else "false"
if course_id is not None:
self._params['course_id'] = course_id self._params['course_id'] = course_id
if enrollment_mode: if enrollment_mode:
self._params['enrollment_mode'] = enrollment_mode self._params['enrollment_mode'] = enrollment_mode
if roles is not None: if roles:
self._params['roles'] = roles self._params['roles'] = roles
if is_active is not None: if no_login:
self._params['is_active'] = "true" if is_active else "false" self._params['no_login'] = True
@property @property
def url(self): def url(self):
...@@ -81,27 +86,16 @@ class AutoAuthPage(PageObject): ...@@ -81,27 +86,16 @@ class AutoAuthPage(PageObject):
return url return url
def is_browser_on_page(self): def is_browser_on_page(self):
return True if self.get_user_info() is not None else False return bool(self.user_info)
@unguarded
def get_user_info(self):
"""Parse the auto auth page body to extract relevant details about the user that was logged in."""
message = self.q(css='BODY').text[0]
match = re.match(self.CONTENT_REGEX, message)
if not match:
return None
else:
user_info = match.groupdict()
user_info['user_id'] = int(user_info['user_id'])
return user_info
@property @property
@unguarded
def user_info(self): def user_info(self):
"""A dictionary containing details about the user account.""" """A dictionary containing details about the user account."""
if self._user_info is None: if not self._user_info:
user_info = self.get_user_info() body = self.q(css='BODY').text[0]
if user_info is not None: self._user_info = json.loads(body)
self._user_info = self.get_user_info()
return self._user_info return self._user_info
def get_user_id(self): def get_user_id(self):
......
...@@ -2,6 +2,3 @@ import os ...@@ -2,6 +2,3 @@ import os
# Get the URL of the instance under test # Get the URL of the instance under test
BASE_URL = os.environ.get('test_url', 'http://localhost:8003') BASE_URL = os.environ.get('test_url', 'http://localhost:8003')
# The URL used for user auth in testing
AUTH_BASE_URL = os.environ.get('test_url', 'http://localhost:8031')
""" """
Courseware Boomarks Courseware Boomarks
""" """
from common.test.acceptance.pages.common.paging import PaginatedUIMixin from common.test.acceptance.pages.common.paging import PaginatedUIMixin
from common.test.acceptance.pages.lms.course_page import CoursePage from common.test.acceptance.pages.lms.course_page import CoursePage
......
"""
Auto-auth page (used to automatically log in during testing).
"""
import re
import urllib
from bok_choy.page_object import PageObject
from common.test.acceptance.pages.studio import BASE_URL
class AutoAuthPage(PageObject):
"""
The automatic authorization page.
When allowed via the django settings file, visiting
this url will create/update a user and log them in.
"""
def __init__(self, browser, username=None, email=None, password=None,
staff=None, course_id=None, roles=None, no_login=None, is_active=None):
"""
Auto-auth is an end-point for HTTP GET requests.
By default, it will create accounts with random user credentials,
but you can also specify credentials using querystring parameters.
Can be used to update an account, call to this end-point with already
made account's credentials along with values to update will result into
an account update.
`username`, `email`, and `password` are the user's credentials (strings)
`staff` is a boolean indicating whether the user is global staff.
`course_id` is the ID of the course to enroll the student in.
`is_active` activation status of user
Currently, this has the form "org/number/run"
Note that "global staff" is NOT the same as course staff.
"""
super(AutoAuthPage, self).__init__(browser)
# Create query string parameters if provided
self._params = {}
if username is not None:
self._params['username'] = username
if email is not None:
self._params['email'] = email
if password is not None:
self._params['password'] = password
if staff is not None:
self._params['staff'] = "true" if staff else "false"
if course_id is not None:
self._params['course_id'] = course_id
if roles is not None:
self._params['roles'] = roles
if no_login:
self._params['no_login'] = True
if is_active is not None:
self._params['is_active'] = 'true' if is_active else 'false'
@property
def url(self):
"""
Construct the URL.
"""
url = BASE_URL + "/auto_auth"
query_str = urllib.urlencode(self._params)
if query_str:
url += "?" + query_str
return url
def is_browser_on_page(self):
message = self.q(css='BODY').text[0]
match = re.search(r'(Logged in|Created) user ([^$]+) with password ([^$]+) and user_id ([^$]+)$', message)
return True if match else False
def get_user_id(self):
message = self.q(css='BODY').text[0].strip()
match = re.search(r' user_id ([^$]+)$', message)
return match.groups()[0] if match else None
...@@ -5,8 +5,8 @@ from bok_choy.web_app_test import with_cache ...@@ -5,8 +5,8 @@ from bok_choy.web_app_test import with_cache
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, CourseUpdateDesc, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, CourseUpdateDesc, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage from common.test.acceptance.pages.lms.course_info import CourseInfoPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.dashboard import DashboardPage from common.test.acceptance.pages.lms.dashboard import DashboardPage
......
...@@ -4,7 +4,7 @@ Single page performance tests for Studio. ...@@ -4,7 +4,7 @@ Single page performance tests for Studio.
from bok_choy.web_app_test import with_cache from bok_choy.web_app_test import with_cache
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from ..tests.helpers import AcceptanceTest from ..tests.helpers import AcceptanceTest
......
...@@ -3,22 +3,22 @@ ...@@ -3,22 +3,22 @@
End-to-end tests related to the cohort management on the LMS Instructor Dashboard End-to-end tests related to the cohort management on the LMS Instructor Dashboard
""" """
import os
import uuid
from datetime import datetime from datetime import datetime
from pytz import UTC, utc import unicodecsv
from bok_choy.promise import EmptyPromise from bok_choy.promise import EmptyPromise
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.tests.discussion.helpers import CohortTestMixin from pytz import UTC, utc
from common.test.acceptance.tests.helpers import UniqueCourseTest, EventsTestMixin, create_user_partition_json
from xmodule.partitions.partitions import Group
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage, DataDownloadPage from common.test.acceptance.pages.lms.instructor_dashboard import DataDownloadPage, InstructorDashboardPage
from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage
from common.test.acceptance.tests.discussion.helpers import CohortTestMixin
import os from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest, create_user_partition_json
import unicodecsv from xmodule.partitions.partitions import Group
import uuid
@attr(shard=8) @attr(shard=8)
......
...@@ -6,7 +6,7 @@ from uuid import uuid4 ...@@ -6,7 +6,7 @@ from uuid import uuid4
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.discussion import DiscussionTabSingleThreadPage, InlineDiscussionPage from common.test.acceptance.pages.lms.discussion import DiscussionTabSingleThreadPage, InlineDiscussionPage
from common.test.acceptance.tests.discussion.helpers import BaseDiscussionMixin, BaseDiscussionTestCase, CohortTestMixin from common.test.acceptance.tests.discussion.helpers import BaseDiscussionMixin, BaseDiscussionTestCase, CohortTestMixin
......
...@@ -20,7 +20,7 @@ from common.test.acceptance.fixtures.discussion import ( ...@@ -20,7 +20,7 @@ from common.test.acceptance.fixtures.discussion import (
Thread, Thread,
UserProfileViewFixture UserProfileViewFixture
) )
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.discussion import ( from common.test.acceptance.pages.lms.discussion import (
DiscussionSortPreferencePage, DiscussionSortPreferencePage,
......
...@@ -2,42 +2,40 @@ ...@@ -2,42 +2,40 @@
Test helper functions and base classes. Test helper functions and base classes.
""" """
import functools
import inspect import inspect
import json import json
import unittest
import functools
import operator import operator
import pprint
import requests
import os import os
import pprint
import unittest
import urlparse import urlparse
from contextlib import contextmanager from contextlib import contextmanager
from datetime import datetime from datetime import datetime
from path import Path as path from unittest import TestCase
import requests
from bok_choy.javascript import js_defined from bok_choy.javascript import js_defined
from bok_choy.web_app_test import WebAppTest
from bok_choy.promise import EmptyPromise, Promise
from bok_choy.page_object import XSS_INJECTION from bok_choy.page_object import XSS_INJECTION
from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory from bok_choy.promise import EmptyPromise, Promise
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from bok_choy.web_app_test import WebAppTest
from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from opaque_keys.edx.locator import CourseLocator from opaque_keys.edx.locator import CourseLocator
from pymongo import MongoClient, ASCENDING from path import Path as path
from openedx.core.lib.tests.assertions.events import assert_event_matches, is_matching_event, EventMatchTolerates from pymongo import ASCENDING, MongoClient
from xmodule.partitions.partitions import UserPartition
from selenium.common.exceptions import StaleElementReferenceException from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from unittest import TestCase
from openedx.core.release import doc_version, RELEASE_LINE
from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.common import BASE_URL from common.test.acceptance.pages.common import BASE_URL
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from openedx.core.lib.tests.assertions.events import EventMatchTolerates, assert_event_matches, is_matching_event
from openedx.core.release import RELEASE_LINE, doc_version
from xmodule.partitions.partitions import UserPartition
MAX_EVENTS_IN_FAILURE_OUTPUT = 20 MAX_EVENTS_IN_FAILURE_OUTPUT = 20
......
...@@ -9,8 +9,8 @@ from bok_choy.page_object import XSS_INJECTION ...@@ -9,8 +9,8 @@ from bok_choy.page_object import XSS_INJECTION
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from pytz import timezone, utc from pytz import timezone, utc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.dashboard import DashboardPage from common.test.acceptance.pages.lms.dashboard import DashboardPage
from common.test.acceptance.tests.helpers import AcceptanceTest, EventsTestMixin from common.test.acceptance.tests.helpers import AcceptanceTest, EventsTestMixin
......
...@@ -9,12 +9,11 @@ from nose.plugins.attrib import attr ...@@ -9,12 +9,11 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common import BASE_URL from common.test.acceptance.pages.common import BASE_URL
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage as LmsAutoAuthPage
from common.test.acceptance.pages.lms.bookmarks import BookmarksPage from common.test.acceptance.pages.lms.bookmarks import BookmarksPage
from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest, is_404_page from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest, is_404_page
...@@ -56,7 +55,7 @@ class BookmarksTestMixin(EventsTestMixin, UniqueCourseTest): ...@@ -56,7 +55,7 @@ class BookmarksTestMixin(EventsTestMixin, UniqueCourseTest):
self.create_course_fixture(num_chapters) self.create_course_fixture(num_chapters)
# Auto-auth register for the course. # Auto-auth register for the course.
LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit() AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()
self.courseware_page.visit() self.courseware_page.visit()
...@@ -159,7 +158,7 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -159,7 +158,7 @@ class BookmarksTest(BookmarksTestMixin):
# Logout and login as staff # Logout and login as staff
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id, staff=True self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id, staff=True
).visit() ).visit()
...@@ -171,7 +170,7 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -171,7 +170,7 @@ class BookmarksTest(BookmarksTestMixin):
# Logout and login as a student. # Logout and login as a student.
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit() AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()
# Visit courseware as a student. # Visit courseware as a student.
self.courseware_page.visit() self.courseware_page.visit()
...@@ -349,7 +348,7 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -349,7 +348,7 @@ class BookmarksTest(BookmarksTestMixin):
self._verify_breadcrumbs(num_units=1) self._verify_breadcrumbs(num_units=1)
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
LmsAutoAuthPage( AutoAuthPage(
self.browser, self.browser,
username=self.USERNAME, username=self.USERNAME,
email=self.EMAIL, email=self.EMAIL,
...@@ -361,7 +360,7 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -361,7 +360,7 @@ class BookmarksTest(BookmarksTestMixin):
self.update_and_publish_block_display_name(modified_name) self.update_and_publish_block_display_name(modified_name)
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit() AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()
self.bookmarks_page.visit() self.bookmarks_page.visit()
self._verify_breadcrumbs(num_units=1, modified_name=modified_name) self._verify_breadcrumbs(num_units=1, modified_name=modified_name)
......
...@@ -5,7 +5,7 @@ End-to-end tests for the CCX dashboard. ...@@ -5,7 +5,7 @@ End-to-end tests for the CCX dashboard.
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture from common.test.acceptance.fixtures.course import CourseFixture
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.ccx_dashboard_page import CoachDashboardPage from common.test.acceptance.pages.lms.ccx_dashboard_page import CoachDashboardPage
from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest
......
...@@ -5,7 +5,7 @@ from nose.plugins.attrib import attr ...@@ -5,7 +5,7 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.certificates import CertificateConfigFixture from common.test.acceptance.fixtures.certificates import CertificateConfigFixture
from common.test.acceptance.fixtures.course import CourseFixture, CourseUpdateDesc, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, CourseUpdateDesc, XBlockFixtureDesc
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.certificate_page import CertificatePage from common.test.acceptance.pages.lms.certificate_page import CertificatePage
from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage from common.test.acceptance.pages.lms.course_info import CourseInfoPage
......
...@@ -4,10 +4,10 @@ Bok choy acceptance tests for conditionals in the LMS ...@@ -4,10 +4,10 @@ Bok choy acceptance tests for conditionals in the LMS
from capa.tests.response_xml_factory import StringResponseXMLFactory from capa.tests.response_xml_factory import StringResponseXMLFactory
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.conditional import POLL_ANSWER, ConditionalPage from common.test.acceptance.pages.lms.conditional import POLL_ANSWER, ConditionalPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.problem import ProblemPage from common.test.acceptance.pages.lms.problem import ProblemPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.tests.helpers import UniqueCourseTest
......
...@@ -7,9 +7,9 @@ from datetime import datetime ...@@ -7,9 +7,9 @@ from datetime import datetime
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.dashboard import DashboardPage from common.test.acceptance.pages.lms.dashboard import DashboardPage
from common.test.acceptance.pages.lms.learner_profile import LearnerProfilePage from common.test.acceptance.pages.lms.learner_profile import LearnerProfilePage
from common.test.acceptance.tests.helpers import AcceptanceTest, EventsTestMixin from common.test.acceptance.tests.helpers import AcceptanceTest, EventsTestMixin
......
...@@ -9,11 +9,11 @@ from nose.plugins.attrib import attr ...@@ -9,11 +9,11 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.fixtures.library import LibraryFixture from common.test.acceptance.fixtures.library import LibraryFixture
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.library import LibraryContentXBlockWrapper from common.test.acceptance.pages.lms.library import LibraryContentXBlockWrapper
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.library import StudioLibraryContainerXBlockWrapper, StudioLibraryContentEditor from common.test.acceptance.pages.studio.library import StudioLibraryContainerXBlockWrapper, StudioLibraryContentEditor
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.tests.helpers import TestWithSearchIndexMixin, UniqueCourseTest from common.test.acceptance.tests.helpers import TestWithSearchIndexMixin, UniqueCourseTest
......
...@@ -13,11 +13,11 @@ from flaky import flaky ...@@ -13,11 +13,11 @@ from flaky import flaky
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, CourseUpdateDesc, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, CourseUpdateDesc, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.common.utils import enroll_user_track from common.test.acceptance.pages.common.utils import enroll_user_track
from common.test.acceptance.pages.lms import BASE_URL from common.test.acceptance.pages.lms import BASE_URL
from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage from common.test.acceptance.pages.lms.course_info import CourseInfoPage
from common.test.acceptance.pages.lms.course_wiki import ( from common.test.acceptance.pages.lms.course_wiki import (
......
...@@ -6,7 +6,7 @@ End-to-end tests for the LMS. ...@@ -6,7 +6,7 @@ End-to-end tests for the LMS.
from unittest import expectedFailure from unittest import expectedFailure
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.xblock.acid import AcidView from common.test.acceptance.pages.xblock.acid import AcidView
from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.tests.helpers import UniqueCourseTest
......
...@@ -9,11 +9,11 @@ from nose.plugins.attrib import attr ...@@ -9,11 +9,11 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures import LMS_BASE_URL from common.test.acceptance.fixtures import LMS_BASE_URL
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage
from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage
from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage
from common.test.acceptance.pages.studio.component_editor import ComponentVisibilityEditorView from common.test.acceptance.pages.studio.component_editor import ComponentVisibilityEditorView
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage
...@@ -54,21 +54,21 @@ class CoursewareSearchCohortTest(ContainerBase): ...@@ -54,21 +54,21 @@ class CoursewareSearchCohortTest(ContainerBase):
# Create a student who will be in "Cohort A" # Create a student who will be in "Cohort A"
self.cohort_a_student_username = "cohort_a_" + str(uuid.uuid4().hex)[:12] self.cohort_a_student_username = "cohort_a_" + str(uuid.uuid4().hex)[:12]
self.cohort_a_student_email = self.cohort_a_student_username + "@example.com" self.cohort_a_student_email = self.cohort_a_student_username + "@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.cohort_a_student_username, email=self.cohort_a_student_email, no_login=True self.browser, username=self.cohort_a_student_username, email=self.cohort_a_student_email, no_login=True
).visit() ).visit()
# Create a student who will be in "Cohort B" # Create a student who will be in "Cohort B"
self.cohort_b_student_username = "cohort_b_" + str(uuid.uuid4().hex)[:12] self.cohort_b_student_username = "cohort_b_" + str(uuid.uuid4().hex)[:12]
self.cohort_b_student_email = self.cohort_b_student_username + "@example.com" self.cohort_b_student_email = self.cohort_b_student_username + "@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.cohort_b_student_username, email=self.cohort_b_student_email, no_login=True self.browser, username=self.cohort_b_student_username, email=self.cohort_b_student_email, no_login=True
).visit() ).visit()
# Create a student who will end up in the default cohort group # Create a student who will end up in the default cohort group
self.cohort_default_student_username = "cohort_default_student" self.cohort_default_student_username = "cohort_default_student"
self.cohort_default_student_email = "cohort_default_student@example.com" self.cohort_default_student_email = "cohort_default_student@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.cohort_default_student_username, self.browser, username=self.cohort_default_student_username,
email=self.cohort_default_student_email, no_login=True email=self.cohort_default_student_email, no_login=True
).visit() ).visit()
...@@ -89,8 +89,8 @@ class CoursewareSearchCohortTest(ContainerBase): ...@@ -89,8 +89,8 @@ class CoursewareSearchCohortTest(ContainerBase):
Logout and login with given credentials. Logout and login with given credentials.
""" """
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
StudioAutoAuthPage(self.browser, username=username, email=email, AutoAuthPage(self.browser, username=username, email=email,
course_id=self.course_id, staff=staff).visit() course_id=self.course_id, staff=staff).visit()
def _studio_reindex(self): def _studio_reindex(self):
""" """
......
...@@ -6,9 +6,9 @@ import json ...@@ -6,9 +6,9 @@ import json
import uuid import uuid
from common.test.acceptance.fixtures.course import CourseFixture from common.test.acceptance.fixtures.course import CourseFixture
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.discovery import CourseDiscoveryPage from common.test.acceptance.pages.lms.discovery import CourseDiscoveryPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.tests.helpers import AcceptanceTest, remove_file from common.test.acceptance.tests.helpers import AcceptanceTest, remove_file
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
""" """
End-to-end tests for the LMS that utilize the course home page and course outline. End-to-end tests for the LMS that utilize the course home page and course outline.
""" """
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from ...fixtures.course import CourseFixture, XBlockFixtureDesc from ...fixtures.course import CourseFixture, XBlockFixtureDesc
......
...@@ -11,6 +11,7 @@ from flaky import flaky ...@@ -11,6 +11,7 @@ from flaky import flaky
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from ...fixtures.course import CourseFixture, XBlockFixtureDesc from ...fixtures.course import CourseFixture, XBlockFixtureDesc
from ...pages.common.auto_auth import AutoAuthPage
from ...pages.common.logout import LogoutPage from ...pages.common.logout import LogoutPage
from ...pages.lms.course_home import CourseHomePage from ...pages.lms.course_home import CourseHomePage
from ...pages.lms.courseware import CoursewarePage, CoursewareSequentialTabPage from ...pages.lms.courseware import CoursewarePage, CoursewareSequentialTabPage
...@@ -21,7 +22,6 @@ from ...pages.lms.problem import ProblemPage ...@@ -21,7 +22,6 @@ from ...pages.lms.problem import ProblemPage
from ...pages.lms.progress import ProgressPage from ...pages.lms.progress import ProgressPage
from ...pages.lms.staff_view import StaffCoursewarePage from ...pages.lms.staff_view import StaffCoursewarePage
from ...pages.lms.track_selection import TrackSelectionPage from ...pages.lms.track_selection import TrackSelectionPage
from ...pages.studio.auto_auth import AutoAuthPage
from ...pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from ...pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from ..helpers import EventsTestMixin, UniqueCourseTest, auto_auth, create_multiple_choice_problem from ..helpers import EventsTestMixin, UniqueCourseTest, auto_auth, create_multiple_choice_problem
......
...@@ -7,10 +7,10 @@ from flaky import flaky ...@@ -7,10 +7,10 @@ from flaky import flaky
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.common.utils import click_css from common.test.acceptance.pages.common.utils import click_css
from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.container import ContainerPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror
......
...@@ -7,7 +7,7 @@ import datetime ...@@ -7,7 +7,7 @@ import datetime
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture from common.test.acceptance.fixtures.course import CourseFixture
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.dashboard import DashboardPage from common.test.acceptance.pages.lms.dashboard import DashboardPage
from common.test.acceptance.tests.helpers import UniqueCourseTest, generate_course_key from common.test.acceptance.tests.helpers import UniqueCourseTest, generate_course_key
......
...@@ -5,10 +5,10 @@ import json ...@@ -5,10 +5,10 @@ import json
import os import os
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.common.utils import click_css from common.test.acceptance.pages.common.utils import click_css
from common.test.acceptance.pages.lms.dashboard_search import DashboardSearchPage from common.test.acceptance.pages.lms.dashboard_search import DashboardSearchPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.container import ContainerPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror
......
...@@ -11,7 +11,7 @@ from nose.plugins.attrib import attr ...@@ -11,7 +11,7 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.fixtures.edxnotes import EdxNotesFixture, Note, Range from common.test.acceptance.fixtures.edxnotes import EdxNotesFixture, Note, Range
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.edxnotes import EdxNotesPage, EdxNotesPageNoContent, EdxNotesUnitPage from common.test.acceptance.pages.lms.edxnotes import EdxNotesPage, EdxNotesPageNoContent, EdxNotesUnitPage
......
...@@ -5,10 +5,10 @@ Bok choy acceptance tests for Entrance exams in the LMS ...@@ -5,10 +5,10 @@ Bok choy acceptance tests for Entrance exams in the LMS
from textwrap import dedent from textwrap import dedent
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.problem import ProblemPage from common.test.acceptance.pages.lms.problem import ProblemPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.tests.helpers import UniqueCourseTest
......
...@@ -5,11 +5,11 @@ End-to-end tests for the gating feature. ...@@ -5,11 +5,11 @@ End-to-end tests for the gating feature.
from textwrap import dedent from textwrap import dedent
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.problem import ProblemPage from common.test.acceptance.pages.lms.problem import ProblemPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.tests.helpers import UniqueCourseTest
......
...@@ -9,9 +9,9 @@ from nose.plugins.attrib import attr ...@@ -9,9 +9,9 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.certificates import CertificateConfigFixture from common.test.acceptance.fixtures.certificates import CertificateConfigFixture
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.common.utils import enroll_user_track from common.test.acceptance.pages.common.utils import enroll_user_track
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.create_mode import ModeCreationPage from common.test.acceptance.pages.lms.create_mode import ModeCreationPage
from common.test.acceptance.pages.lms.dashboard import DashboardPage from common.test.acceptance.pages.lms.dashboard import DashboardPage
...@@ -36,13 +36,24 @@ class BaseInstructorDashboardTest(EventsTestMixin, UniqueCourseTest): ...@@ -36,13 +36,24 @@ class BaseInstructorDashboardTest(EventsTestMixin, UniqueCourseTest):
""" """
Mixin class for testing the instructor dashboard. Mixin class for testing the instructor dashboard.
""" """
def log_in_as_instructor(self): def log_in_as_instructor(self, course_access_roles=None):
""" """
Logs in as an instructor and returns the id. Login with an instructor account.
Args:
course_access_roles (str[]): List of course access roles that should be assigned to the user.
Returns
username (str)
user_id (int)
""" """
username = "test_instructor_{uuid}".format(uuid=self.unique_id[0:6]) course_access_roles = course_access_roles or []
auto_auth_page = AutoAuthPage(self.browser, username=username, course_id=self.course_id, staff=True) auto_auth_page = AutoAuthPage(
return username, auto_auth_page.visit().get_user_id() self.browser, course_id=self.course_id, staff=True, course_access_roles=course_access_roles
)
auto_auth_page.visit()
user_info = auto_auth_page.user_info
return user_info['username'], user_info['user_id']
def visit_instructor_dashboard(self): def visit_instructor_dashboard(self):
""" """
...@@ -1257,23 +1268,11 @@ class EcommerceTest(BaseInstructorDashboardTest): ...@@ -1257,23 +1268,11 @@ class EcommerceTest(BaseInstructorDashboardTest):
) )
course_fixture.install() course_fixture.install()
def log_in_as_unique_user(self):
"""
Log in as a valid lms user.
"""
AutoAuthPage(
self.browser,
username="test_instructor",
email="test_instructor@example.com",
password="password",
course_id=self.course_id
).visit()
def visit_ecommerce_section(self): def visit_ecommerce_section(self):
""" """
Log in to visit Instructor dashboard and click E-commerce tab Log in to visit Instructor dashboard and click E-commerce tab
""" """
self.log_in_as_unique_user() self.log_in_as_instructor(course_access_roles=['finance_admin'])
instructor_dashboard_page = self.visit_instructor_dashboard() instructor_dashboard_page = self.visit_instructor_dashboard()
return instructor_dashboard_page.select_ecommerce_tab() return instructor_dashboard_page.select_ecommerce_tab()
......
...@@ -9,10 +9,10 @@ from textwrap import dedent ...@@ -9,10 +9,10 @@ from textwrap import dedent
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.login_and_register import CombinedLoginAndRegisterPage from common.test.acceptance.pages.lms.login_and_register import CombinedLoginAndRegisterPage
from common.test.acceptance.pages.lms.problem import ProblemPage from common.test.acceptance.pages.lms.problem import ProblemPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest
......
...@@ -4,20 +4,16 @@ Test courseware search ...@@ -4,20 +4,16 @@ Test courseware search
import json import json
from common.test.acceptance.tests.helpers import remove_file
from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage
from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.tests.helpers import create_user_partition_json
from xmodule.partitions.partitions import Group
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.tests.helpers import create_user_partition_json, remove_file
from common.test.acceptance.tests.studio.base_studio_test import ContainerBase from common.test.acceptance.tests.studio.base_studio_test import ContainerBase
from xmodule.partitions.partitions import Group
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage
@attr(shard=1) @attr(shard=1)
...@@ -58,8 +54,7 @@ class SplitTestCoursewareSearchTest(ContainerBase): ...@@ -58,8 +54,7 @@ class SplitTestCoursewareSearchTest(ContainerBase):
Logout and login with given credentials. Logout and login with given credentials.
""" """
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
StudioAutoAuthPage(self.browser, username=username, email=email, AutoAuthPage(self.browser, username=username, email=email, course_id=self.course_id, staff=staff).visit()
course_id=self.course_id, staff=staff).visit()
def _studio_reindex(self): def _studio_reindex(self):
""" """
......
...@@ -4,17 +4,17 @@ Tests the "preview" selector in the LMS that allows changing between Staff, Lear ...@@ -4,17 +4,17 @@ Tests the "preview" selector in the LMS that allows changing between Staff, Lear
""" """
from textwrap import dedent
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.tests.helpers import UniqueCourseTest, create_user_partition_json from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage
from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.tests.helpers import UniqueCourseTest, create_user_partition_json
from bok_choy.promise import EmptyPromise from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID, Group
from xmodule.partitions.partitions import (Group, ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID)
from textwrap import dedent
@attr(shard=10) @attr(shard=10)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
from urlparse import parse_qsl, urlparse from urlparse import parse_qsl, urlparse
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.oauth2_confirmation import OAuth2Confirmation from common.test.acceptance.pages.lms.oauth2_confirmation import OAuth2Confirmation
from common.test.acceptance.tests.helpers import AcceptanceTest from common.test.acceptance.tests.helpers import AcceptanceTest
......
...@@ -4,7 +4,7 @@ from nose.plugins.attrib import attr ...@@ -4,7 +4,7 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.catalog import CatalogFixture, CatalogIntegrationMixin from common.test.acceptance.fixtures.catalog import CatalogFixture, CatalogIntegrationMixin
from common.test.acceptance.fixtures.course import CourseFixture from common.test.acceptance.fixtures.course import CourseFixture
from common.test.acceptance.fixtures.programs import ProgramsConfigMixin from common.test.acceptance.fixtures.programs import ProgramsConfigMixin
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.catalog import CacheProgramsPage from common.test.acceptance.pages.lms.catalog import CacheProgramsPage
from common.test.acceptance.pages.lms.programs import ProgramDetailsPage, ProgramListingPage from common.test.acceptance.pages.lms.programs import ProgramDetailsPage, ProgramListingPage
from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.tests.helpers import UniqueCourseTest
......
...@@ -14,8 +14,8 @@ from selenium.common.exceptions import TimeoutException ...@@ -14,8 +14,8 @@ from selenium.common.exceptions import TimeoutException
from common.test.acceptance.fixtures import LMS_BASE_URL from common.test.acceptance.fixtures import LMS_BASE_URL
from common.test.acceptance.fixtures.course import CourseFixture from common.test.acceptance.fixtures.course import CourseFixture
from common.test.acceptance.fixtures.discussion import ForumsConfigMixin, MultipleThreadFixture, Thread from common.test.acceptance.fixtures.discussion import ForumsConfigMixin, MultipleThreadFixture, Thread
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.utils import confirm_prompt from common.test.acceptance.pages.common.utils import confirm_prompt
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage from common.test.acceptance.pages.lms.course_info import CourseInfoPage
from common.test.acceptance.pages.lms.learner_profile import LearnerProfilePage from common.test.acceptance.pages.lms.learner_profile import LearnerProfilePage
from common.test.acceptance.pages.lms.tab_nav import TabNavPage from common.test.acceptance.pages.lms.tab_nav import TabNavPage
......
...@@ -5,7 +5,7 @@ from bok_choy.page_object import XSS_INJECTION ...@@ -5,7 +5,7 @@ from bok_choy.page_object import XSS_INJECTION
from common.test.acceptance.fixtures.course import CourseFixture from common.test.acceptance.fixtures.course import CourseFixture
from common.test.acceptance.fixtures.library import LibraryFixture from common.test.acceptance.fixtures.library import LibraryFixture
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from common.test.acceptance.pages.studio.utils import verify_ordering from common.test.acceptance.pages.studio.utils import verify_ordering
from common.test.acceptance.tests.helpers import AcceptanceTest, UniqueCourseTest from common.test.acceptance.tests.helpers import AcceptanceTest, UniqueCourseTest
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Acceptance tests for Studio related to the acid xblock. Acceptance tests for Studio related to the acid xblock.
""" """
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from common.test.acceptance.pages.xblock.acid import AcidView from common.test.acceptance.pages.xblock.acid import AcidView
from common.test.acceptance.tests.helpers import AcceptanceTest from common.test.acceptance.tests.helpers import AcceptanceTest
......
...@@ -4,26 +4,23 @@ The container page is used both for displaying units, and ...@@ -4,26 +4,23 @@ The container page is used both for displaying units, and
for displaying containers within units. for displaying containers within units.
""" """
import datetime import datetime
from unittest import skip
import ddt import ddt
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from unittest import skip
from base_studio_test import ContainerBase from base_studio_test import ContainerBase
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.create_mode import ModeCreationPage from common.test.acceptance.pages.lms.create_mode import ModeCreationPage
from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage
from common.test.acceptance.pages.studio.component_editor import ComponentEditorView, ComponentVisibilityEditorView from common.test.acceptance.pages.studio.component_editor import ComponentEditorView, ComponentVisibilityEditorView
from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.container import ContainerPage
from common.test.acceptance.pages.studio.html_component_editor import HtmlComponentEditorView from common.test.acceptance.pages.studio.html_component_editor import HtmlComponentEditorView
from common.test.acceptance.pages.studio.move_xblock import MoveModalView from common.test.acceptance.pages.studio.move_xblock import MoveModalView
from common.test.acceptance.pages.studio.utils import add_discussion, drag from common.test.acceptance.pages.studio.utils import add_discussion, drag
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage
from common.test.acceptance.tests.helpers import create_user_partition_json from common.test.acceptance.tests.helpers import create_user_partition_json
from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID, Group
from xmodule.partitions.partitions import (
Group, ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID
)
class NestedVerticalTest(ContainerBase): class NestedVerticalTest(ContainerBase):
......
...@@ -5,7 +5,7 @@ import uuid ...@@ -5,7 +5,7 @@ import uuid
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.index import DashboardPage from common.test.acceptance.pages.studio.index import DashboardPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from common.test.acceptance.tests.helpers import AcceptanceTest from common.test.acceptance.tests.helpers import AcceptanceTest
......
...@@ -4,7 +4,7 @@ Acceptance Tests for Course Information ...@@ -4,7 +4,7 @@ Acceptance Tests for Course Information
from common.test.acceptance.pages.studio.course_info import CourseUpdatesPage from common.test.acceptance.pages.studio.course_info import CourseUpdatesPage
from common.test.acceptance.tests.studio.base_studio_test import StudioCourseTest from common.test.acceptance.tests.studio.base_studio_test import StudioCourseTest
from ...pages.studio.auto_auth import AutoAuthPage from ...pages.common.auto_auth import AutoAuthPage
from ...pages.studio.index import DashboardPage from ...pages.studio.index import DashboardPage
......
...@@ -3,7 +3,7 @@ Acceptance tests for course in studio ...@@ -3,7 +3,7 @@ Acceptance tests for course in studio
""" """
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.index import DashboardPage from common.test.acceptance.pages.studio.index import DashboardPage
from common.test.acceptance.pages.studio.users import CourseTeamPage from common.test.acceptance.pages.studio.users import CourseTeamPage
from common.test.acceptance.tests.studio.base_studio_test import StudioCourseTest from common.test.acceptance.tests.studio.base_studio_test import StudioCourseTest
......
...@@ -5,8 +5,8 @@ import uuid ...@@ -5,8 +5,8 @@ import uuid
from base_studio_test import StudioCourseTest from base_studio_test import StudioCourseTest
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.asset_index import AssetIndexPage from common.test.acceptance.pages.studio.asset_index import AssetIndexPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.course_info import CourseUpdatesPage from common.test.acceptance.pages.studio.course_info import CourseUpdatesPage
from common.test.acceptance.pages.studio.edit_tabs import PagesPage from common.test.acceptance.pages.studio.edit_tabs import PagesPage
from common.test.acceptance.pages.studio.import_export import ExportCoursePage, ImportCoursePage from common.test.acceptance.pages.studio.import_export import ExportCoursePage, ImportCoursePage
......
...@@ -7,8 +7,8 @@ from unittest import skip ...@@ -7,8 +7,8 @@ from unittest import skip
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.asset_index import AssetIndexPage from common.test.acceptance.pages.studio.asset_index import AssetIndexPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.course_info import CourseUpdatesPage from common.test.acceptance.pages.studio.course_info import CourseUpdatesPage
from common.test.acceptance.pages.studio.edit_tabs import PagesPage from common.test.acceptance.pages.studio.edit_tabs import PagesPage
from common.test.acceptance.pages.studio.import_export import ( from common.test.acceptance.pages.studio.import_export import (
......
...@@ -6,8 +6,8 @@ from uuid import uuid4 ...@@ -6,8 +6,8 @@ from uuid import uuid4
from flaky import flaky from flaky import flaky
from opaque_keys.edx.locator import LibraryLocator from opaque_keys.edx.locator import LibraryLocator
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.index import DashboardPage from common.test.acceptance.pages.studio.index import DashboardPage
from common.test.acceptance.pages.studio.library import LibraryEditPage from common.test.acceptance.pages.studio.library import LibraryEditPage
from common.test.acceptance.tests.helpers import AcceptanceTest, get_selected_option_text, select_option_by_text from common.test.acceptance.tests.helpers import AcceptanceTest, get_selected_option_text, select_option_by_text
......
...@@ -5,7 +5,7 @@ from ddt import data, ddt ...@@ -5,7 +5,7 @@ from ddt import data, ddt
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.library import LibraryEditPage from common.test.acceptance.pages.studio.library import LibraryEditPage
from common.test.acceptance.pages.studio.users import LibraryUsersPage from common.test.acceptance.pages.studio.users import LibraryUsersPage
from common.test.acceptance.pages.studio.utils import add_component from common.test.acceptance.pages.studio.utils import add_component
......
...@@ -3,10 +3,9 @@ ...@@ -3,10 +3,9 @@
Acceptance tests for Studio's Setting pages Acceptance tests for Studio's Setting pages
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import os
from mock import patch import os
from nose.plugins.attrib import attr from textwrap import dedent
from bok_choy.promise import EmptyPromise from bok_choy.promise import EmptyPromise
from mock import patch from mock import patch
...@@ -14,16 +13,14 @@ from nose.plugins.attrib import attr ...@@ -14,16 +13,14 @@ from nose.plugins.attrib import attr
from base_studio_test import StudioCourseTest from base_studio_test import StudioCourseTest
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.tests.helpers import create_user_partition_json, element_has_text from common.test.acceptance.pages.common.utils import add_enrollment_course_modes
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from common.test.acceptance.pages.studio.settings import SettingsPage from common.test.acceptance.pages.studio.settings import SettingsPage
from common.test.acceptance.pages.studio.settings_advanced import AdvancedSettingsPage from common.test.acceptance.pages.studio.settings_advanced import AdvancedSettingsPage
from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.studio.utils import get_input_value from common.test.acceptance.pages.studio.utils import get_input_value
from common.test.acceptance.pages.common.utils import add_enrollment_course_modes from common.test.acceptance.tests.helpers import create_user_partition_json, element_has_text
from textwrap import dedent
from xmodule.partitions.partitions import Group from xmodule.partitions.partitions import Group
......
...@@ -4,25 +4,23 @@ Acceptance tests for Studio related to the split_test module. ...@@ -4,25 +4,23 @@ Acceptance tests for Studio related to the split_test module.
import math import math
from unittest import skip from unittest import skip
from bok_choy.promise import Promise
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from selenium.webdriver.support.ui import Select from selenium.webdriver.support.ui import Select
from xmodule.partitions.partitions import Group from base_studio_test import StudioCourseTest
from bok_choy.promise import Promise, EmptyPromise
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.studio.component_editor import ComponentEditorView from common.test.acceptance.pages.studio.component_editor import ComponentEditorView
from common.test.acceptance.pages.studio.overview import CourseOutlinePage, CourseOutlineUnit
from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.container import ContainerPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage, CourseOutlineUnit
from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage
from common.test.acceptance.pages.studio.utils import add_advanced_component from common.test.acceptance.pages.studio.utils import add_advanced_component
from common.test.acceptance.pages.xblock.utils import wait_for_xblock_initialization from common.test.acceptance.pages.xblock.utils import wait_for_xblock_initialization
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.tests.helpers import create_user_partition_json from common.test.acceptance.tests.helpers import create_user_partition_json
from base_studio_test import StudioCourseTest
from test_studio_container import ContainerBase from test_studio_container import ContainerBase
from xmodule.partitions.partitions import Group
class SplitTestMixin(object): class SplitTestMixin(object):
......
...@@ -6,9 +6,9 @@ E2E tests for the LMS. ...@@ -6,9 +6,9 @@ E2E tests for the LMS.
from textwrap import dedent from textwrap import dedent
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.annotation_component import AnnotationComponentPage from common.test.acceptance.pages.lms.annotation_component import AnnotationComponentPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.tests.helpers import UniqueCourseTest, disable_animations from common.test.acceptance.tests.helpers import UniqueCourseTest, disable_animations
......
...@@ -9,11 +9,10 @@ from nose.plugins.attrib import attr ...@@ -9,11 +9,10 @@ from nose.plugins.attrib import attr
from common.test.acceptance.fixtures import LMS_BASE_URL from common.test.acceptance.fixtures import LMS_BASE_URL
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.utils import add_enrollment_course_modes, enroll_user_track from common.test.acceptance.pages.common.utils import add_enrollment_course_modes, enroll_user_track
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage as LmsAutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage
from common.test.acceptance.pages.studio.component_editor import ComponentVisibilityEditorView from common.test.acceptance.pages.studio.component_editor import ComponentVisibilityEditorView
from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage
from common.test.acceptance.tests.lms.test_lms_user_preview import verify_expected_problem_visibility from common.test.acceptance.tests.lms.test_lms_user_preview import verify_expected_problem_visibility
...@@ -43,21 +42,21 @@ class EndToEndCohortedCoursewareTest(ContainerBase): ...@@ -43,21 +42,21 @@ class EndToEndCohortedCoursewareTest(ContainerBase):
# Create a student who will be in "Cohort A" # Create a student who will be in "Cohort A"
self.cohort_a_student_username = "cohort_a_student" self.cohort_a_student_username = "cohort_a_student"
self.cohort_a_student_email = "cohort_a_student@example.com" self.cohort_a_student_email = "cohort_a_student@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.cohort_a_student_username, email=self.cohort_a_student_email, no_login=True self.browser, username=self.cohort_a_student_username, email=self.cohort_a_student_email, no_login=True
).visit() ).visit()
# Create a student who will be in "Cohort B" # Create a student who will be in "Cohort B"
self.cohort_b_student_username = "cohort_b_student" self.cohort_b_student_username = "cohort_b_student"
self.cohort_b_student_email = "cohort_b_student@example.com" self.cohort_b_student_email = "cohort_b_student@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.cohort_b_student_username, email=self.cohort_b_student_email, no_login=True self.browser, username=self.cohort_b_student_username, email=self.cohort_b_student_email, no_login=True
).visit() ).visit()
# Create a Verified Student # Create a Verified Student
self.cohort_verified_student_username = "cohort_verified_student" self.cohort_verified_student_username = "cohort_verified_student"
self.cohort_verified_student_email = "cohort_verified_student@example.com" self.cohort_verified_student_email = "cohort_verified_student@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, self.browser,
username=self.cohort_verified_student_username, username=self.cohort_verified_student_username,
email=self.cohort_verified_student_email, email=self.cohort_verified_student_email,
...@@ -67,7 +66,7 @@ class EndToEndCohortedCoursewareTest(ContainerBase): ...@@ -67,7 +66,7 @@ class EndToEndCohortedCoursewareTest(ContainerBase):
# Create audit student # Create audit student
self.cohort_audit_student_username = "cohort_audit_student" self.cohort_audit_student_username = "cohort_audit_student"
self.cohort_audit_student_email = "cohort_audit_student@example.com" self.cohort_audit_student_email = "cohort_audit_student@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, self.browser,
username=self.cohort_audit_student_username, username=self.cohort_audit_student_username,
email=self.cohort_audit_student_email, email=self.cohort_audit_student_email,
...@@ -77,13 +76,13 @@ class EndToEndCohortedCoursewareTest(ContainerBase): ...@@ -77,13 +76,13 @@ class EndToEndCohortedCoursewareTest(ContainerBase):
# Create a student who will end up in the default cohort group # Create a student who will end up in the default cohort group
self.cohort_default_student_username = "cohort_default_student" self.cohort_default_student_username = "cohort_default_student"
self.cohort_default_student_email = "cohort_default_student@example.com" self.cohort_default_student_email = "cohort_default_student@example.com"
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.cohort_default_student_username, self.browser, username=self.cohort_default_student_username,
email=self.cohort_default_student_email, no_login=True email=self.cohort_default_student_email, no_login=True
).visit() ).visit()
# Start logged in as the staff user. # Start logged in as the staff user.
StudioAutoAuthPage( AutoAuthPage(
self.browser, username=self.staff_user["username"], email=self.staff_user["email"] self.browser, username=self.staff_user["username"], email=self.staff_user["email"]
).visit() ).visit()
...@@ -194,7 +193,7 @@ class EndToEndCohortedCoursewareTest(ContainerBase): ...@@ -194,7 +193,7 @@ class EndToEndCohortedCoursewareTest(ContainerBase):
courseware_page = CoursewarePage(self.browser, self.course_id) courseware_page = CoursewarePage(self.browser, self.course_id)
def login_and_verify_visible_problems(username, email, expected_problems, track=None): def login_and_verify_visible_problems(username, email, expected_problems, track=None):
LmsAutoAuthPage( AutoAuthPage(
self.browser, username=username, email=email, course_id=self.course_id self.browser, username=username, email=email, course_id=self.course_id
).visit() ).visit()
if track is not None: if track is not None:
......
...@@ -10,7 +10,7 @@ from mock import patch ...@@ -10,7 +10,7 @@ from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from common.test.acceptance.pages.studio.video.video import VideoComponentPage from common.test.acceptance.pages.studio.video.video import VideoComponentPage
from common.test.acceptance.tests.helpers import UniqueCourseTest, YouTubeStubConfig, is_youtube_available from common.test.acceptance.tests.helpers import UniqueCourseTest, YouTubeStubConfig, is_youtube_available
......
...@@ -14,7 +14,7 @@ from selenium.webdriver.common.action_chains import ActionChains ...@@ -14,7 +14,7 @@ from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage from common.test.acceptance.pages.lms.course_info import CourseInfoPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.tab_nav import TabNavPage from common.test.acceptance.pages.lms.tab_nav import TabNavPage
......
...@@ -4,8 +4,8 @@ Javascript tests for the crowdsourcehinter xblock ...@@ -4,8 +4,8 @@ Javascript tests for the crowdsourcehinter xblock
from textwrap import dedent from textwrap import dedent
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.xblock.crowdsourcehinter_problem import CrowdsourcehinterProblemPage from common.test.acceptance.pages.xblock.crowdsourcehinter_problem import CrowdsourcehinterProblemPage
from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.tests.helpers import UniqueCourseTest
......
[
{
"pk": 1,
"model": "auth.user",
"fields": {
"username": "test_instructor",
"email":"test_instructor@example.com",
"password": "password",
"is_staff": true,
"is_active": true
}
},
{
"pk": 1,
"model": "student.userprofile",
"fields": {
"user": 1,
"name": "test instructor",
"courseware": "course.xml"
}
},
{
"pk": 1,
"model": "student.registration",
"fields": {
"user": 1,
"activation_key": "52bfac10384d49219385dcd4cc17177q"
}
},
{
"pk": 1,
"model": "student.courseaccessrole",
"fields": {
"id": "1",
"org": "test_org",
"course_id": "course-v1:test_org+34039497242734583224814321005482849780+test_run",
"role": "finance_admin",
"user_id": "1"
}
},
{
"pk": 2,
"model": "student.courseaccessrole",
"fields": {
"id": "2",
"org": "test_org",
"course_id": "course-v1:test_org+34039497242734583224814321005482849781+test_run",
"role": "finance_admin",
"user_id": "1"
}
},
{
"pk": 3,
"model": "student.courseaccessrole",
"fields": {
"id": "3",
"org": "test_org",
"course_id": "course-v1:test_org+34039497242734583224814321005482849782+test_run",
"role": "finance_admin",
"user_id": "1"
}
},
{
"pk": 4,
"model": "student.courseaccessrole",
"fields": {
"id": "4",
"org": "test_org",
"course_id": "course-v1:test_org+34039497242734583224814321005482849783+test_run",
"role": "finance_admin",
"user_id": "1"
}
}
]
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