initial change set. add org autocomplete
added unit tests and fixed JS tests added bok choy tests fixed broken botchoy tests fixed course discovery broken test removed monkey patch at class level changes after feedback from matte
This commit is contained in:
@@ -2,8 +2,10 @@
|
||||
Test view handler for rerun (and eventually create)
|
||||
"""
|
||||
import ddt
|
||||
from mock import patch
|
||||
|
||||
from django.test.client import RequestFactory
|
||||
from django.core.urlresolvers import reverse
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -15,6 +17,10 @@ from student.tests.factories import UserFactory
|
||||
from contentstore.tests.utils import AjaxEnabledTestClient, parse_json
|
||||
from datetime import datetime
|
||||
from xmodule.course_module import CourseFields
|
||||
from util.organizations_helpers import (
|
||||
add_organization,
|
||||
get_course_organizations,
|
||||
)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -33,7 +39,7 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
self.factory = RequestFactory()
|
||||
self.client = AjaxEnabledTestClient()
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
self.course_create_rerun_url = reverse('course_handler')
|
||||
source_course = CourseFactory.create(
|
||||
org='origin',
|
||||
number='the_beginning',
|
||||
@@ -57,7 +63,7 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
"""
|
||||
Just testing the functionality the view handler adds over the tasks tested in test_clone_course
|
||||
"""
|
||||
response = self.client.ajax_post('/course/', {
|
||||
response = self.client.ajax_post(self.course_create_rerun_url, {
|
||||
'source_course_key': unicode(self.source_course_key),
|
||||
'org': self.source_course_key.org, 'course': self.source_course_key.course, 'run': 'copy',
|
||||
'display_name': 'not the same old name',
|
||||
@@ -76,7 +82,7 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
Tests newly created course has web certs enabled by default.
|
||||
"""
|
||||
with modulestore().default_store(store):
|
||||
response = self.client.ajax_post('/course/', {
|
||||
response = self.client.ajax_post(self.course_create_rerun_url, {
|
||||
'org': 'orgX',
|
||||
'number': 'CS101',
|
||||
'display_name': 'Course with web certs enabled',
|
||||
@@ -87,3 +93,66 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
new_course_key = CourseKey.from_string(data['course_key'])
|
||||
course = self.store.get_course(new_course_key)
|
||||
self.assertTrue(course.cert_html_view_enabled)
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ORGANIZATIONS_APP': False})
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_course_creation_without_org_app_enabled(self, store):
|
||||
"""
|
||||
Tests course creation workflow should not create course to org
|
||||
link if organizations_app is not enabled.
|
||||
"""
|
||||
with modulestore().default_store(store):
|
||||
response = self.client.ajax_post(self.course_create_rerun_url, {
|
||||
'org': 'orgX',
|
||||
'number': 'CS101',
|
||||
'display_name': 'Course with web certs enabled',
|
||||
'run': '2015_T2'
|
||||
})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data = parse_json(response)
|
||||
new_course_key = CourseKey.from_string(data['course_key'])
|
||||
course_orgs = get_course_organizations(new_course_key)
|
||||
self.assertEqual(course_orgs, [])
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ORGANIZATIONS_APP': True})
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_course_creation_with_org_not_in_system(self, store):
|
||||
"""
|
||||
Tests course creation workflow when course organization does not exist
|
||||
in system.
|
||||
"""
|
||||
with modulestore().default_store(store):
|
||||
response = self.client.ajax_post(self.course_create_rerun_url, {
|
||||
'org': 'orgX',
|
||||
'number': 'CS101',
|
||||
'display_name': 'Course with web certs enabled',
|
||||
'run': '2015_T2'
|
||||
})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
data = parse_json(response)
|
||||
self.assertIn(u'Organization you selected does not exist in the system', data['error'])
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ORGANIZATIONS_APP': True})
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_course_creation_with_org_in_system(self, store):
|
||||
"""
|
||||
Tests course creation workflow when course organization exist in system.
|
||||
"""
|
||||
add_organization({
|
||||
'name': 'Test Organization',
|
||||
'short_name': 'orgX',
|
||||
'description': 'Testing Organization Description',
|
||||
})
|
||||
with modulestore().default_store(store):
|
||||
response = self.client.ajax_post(self.course_create_rerun_url, {
|
||||
'org': 'orgX',
|
||||
'number': 'CS101',
|
||||
'display_name': 'Course with web certs enabled',
|
||||
'run': '2015_T2'
|
||||
})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data = parse_json(response)
|
||||
new_course_key = CourseKey.from_string(data['course_key'])
|
||||
course_orgs = get_course_organizations(new_course_key)
|
||||
self.assertEqual(len(course_orgs), 1)
|
||||
self.assertEqual(course_orgs[0]['short_name'], 'orgX')
|
||||
|
||||
@@ -84,6 +84,11 @@ from util.milestones_helpers import (
|
||||
is_valid_course_key,
|
||||
set_prerequisite_courses,
|
||||
)
|
||||
from util.organizations_helpers import (
|
||||
add_organization_course,
|
||||
get_organization_by_short_name,
|
||||
organizations_enabled,
|
||||
)
|
||||
from util.string_utils import _has_non_ascii_characters
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.course_module import CourseFields
|
||||
@@ -738,8 +743,17 @@ def _create_new_course(request, org, number, run, fields):
|
||||
Returns the URL for the course overview page.
|
||||
Raises DuplicateCourseError if the course already exists
|
||||
"""
|
||||
org_data = get_organization_by_short_name(org)
|
||||
if not org_data and organizations_enabled():
|
||||
return JsonResponse(
|
||||
{'error': _('You must link this course to an organization in order to continue. '
|
||||
'Organization you selected does not exist in the system, '
|
||||
'you will need to add it to the system')},
|
||||
status=400
|
||||
)
|
||||
store_for_new_course = modulestore().default_modulestore.get_modulestore_type()
|
||||
new_course = create_new_course_in_store(store_for_new_course, request.user, org, number, run, fields)
|
||||
add_organization_course(org_data, new_course.id)
|
||||
return JsonResponse({
|
||||
'url': reverse_course_url('course_handler', new_course.id),
|
||||
'course_key': unicode(new_course.id),
|
||||
|
||||
23
cms/djangoapps/contentstore/views/organization.py
Normal file
23
cms/djangoapps/contentstore/views/organization.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""Organizations views for use with Studio."""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.generic import View
|
||||
from django.http import HttpResponse
|
||||
|
||||
from openedx.core.lib.js_utils import escape_json_dumps
|
||||
from util.organizations_helpers import get_organizations
|
||||
|
||||
|
||||
class OrganizationListView(View):
|
||||
"""View rendering organization list as json.
|
||||
|
||||
This view renders organization list json which is used in org
|
||||
autocomplete while creating new course.
|
||||
"""
|
||||
|
||||
@method_decorator(login_required)
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Returns organization list as json."""
|
||||
organizations = get_organizations()
|
||||
org_names_list = [(org["short_name"]) for org in organizations]
|
||||
return HttpResponse(escape_json_dumps(org_names_list), content_type='application/json; charset=utf-8')
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Tests covering the Organizations listing on the Studio home."""
|
||||
import json
|
||||
from mock import patch
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
from util.organizations_helpers import add_organization
|
||||
from student.tests.factories import UserFactory
|
||||
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ORGANIZATIONS_APP': True})
|
||||
class TestOrganizationListing(TestCase):
|
||||
"""Verify Organization listing behavior."""
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ORGANIZATIONS_APP': True})
|
||||
def setUp(self):
|
||||
super(TestOrganizationListing, self).setUp()
|
||||
self.staff = UserFactory(is_staff=True)
|
||||
self.client.login(username=self.staff.username, password='test')
|
||||
self.org_names_listing_url = reverse('organizations')
|
||||
self.org_short_names = ["alphaX", "betaX", "orgX"]
|
||||
for index, short_name in enumerate(self.org_short_names):
|
||||
add_organization(organization_data={
|
||||
'name': 'Test Organization %s' % index,
|
||||
'short_name': short_name,
|
||||
'description': 'Testing Organization %s Description' % index,
|
||||
})
|
||||
|
||||
def test_organization_list(self):
|
||||
"""Verify that the organization names list api returns list of organization short names."""
|
||||
response = self.client.get(self.org_names_listing_url, HTTP_ACCEPT='application/json')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
org_names = json.loads(response.content)
|
||||
self.assertEqual(org_names, self.org_short_names)
|
||||
Reference in New Issue
Block a user