Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions common/lib/xmodule/xmodule/modulestore/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
from xmodule.errortracker import make_error_tracker, exc_info_to_str
from xmodule.course_module import CourseDescriptor
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.x_module import XMLParsingSystem, prefer_xmodules, policy_key
from xmodule.x_module import XMLParsingSystem, policy_key

from xmodule.html_module import HtmlDescriptor
from xblock.core import XBlock
from xblock.fields import ScopeIds
from xblock.field_data import DictFieldData
from xblock.runtime import DictKeyValueStore, IdReader, IdGenerator
Expand Down Expand Up @@ -222,6 +221,7 @@ def fallback_name(orig_name=None):
# load_item should actually be get_instance, because it expects the course-specific
# policy to be loaded. For now, just add the course_id here...
def load_item(location):
"""Return the XBlock for the specified location"""
return xmlstore.get_instance(course_id, Location(location))

resources_fs = OSFS(xmlstore.data_dir / course_dir)
Expand Down Expand Up @@ -509,6 +509,9 @@ def load_course(self, course_dir, tracker):
course_id = CourseDescriptor.make_id(org, course, url_name)

def get_policy(usage_id):
"""
Return the policy dictionary to be applied to the specified XBlock usage
"""
return policy.get(policy_key(usage_id), {})

system = ImportSystem(
Expand Down Expand Up @@ -570,9 +573,9 @@ def _load_extra_content(self, system, course_descriptor, category, path, course_
html = f.read().decode('utf-8')
# tabs are referenced in policy.json through a 'slug' which is just the filename without the .html suffix
slug = os.path.splitext(os.path.basename(filepath))[0]
loc = course_descriptor.scope_ids.usage_id._replace(category=category, name=slug)
module = system.construct_xblock_from_class(
HtmlDescriptor,
loc = course_descriptor.scope_ids.usage_id.replace(category=category, name=slug)
module = system.construct_xblock(
category,
# We're loading a descriptor, so student_id is meaningless
# We also don't have separate notions of definition and usage ids yet,
# so we use the location for both
Expand Down
47 changes: 47 additions & 0 deletions common/test/data/2014/about/overview.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<section class="about">
<h2>About This Course</h2>
<p>Include your long course description here. The long course description should contain 150-400 words. about page 463139</p>

<p>This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.</p>
</section>

<section class="prerequisites">
<h2>Prerequisites</h2>
<p>Add information about course prerequisites here.</p>
</section>

<section class="course-staff">
<h2>Course Staff</h2>
<article class="teacher">
<div class="teacher-image">
<img src="/static/images/pl-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #1">
</div>

<h3>Staff Member #1</h3>
<p>Biography of instructor/staff member #1</p>
</article>

<article class="teacher">
<div class="teacher-image">
<img src="/static/images/pl-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #2">
</div>

<h3>Staff Member #2</h3>
<p>Biography of instructor/staff member #2</p>
</article>
</section>

<section class="faq">
<section class="responses">
<h2>Frequently Asked Questions</h2>
<article class="response">
<h3>Do I need to buy a textbook?</h3>
<p>No, a free online version of Chemistry: Principles, Patterns, and Applications, First Edition by Bruce Averill and Patricia Eldredge will be available, though you can purchase a printed version (published by FlatWorld Knowledge) if you’d like.</p>
</article>

<article class="response">
<h3>Question #2</h3>
<p>Your answer would be displayed here.</p>
</article>
</section>
</section>
1 change: 1 addition & 0 deletions common/test/data/2014/course.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<course url_name="2014" org="edX" course="detached_pages"/>
1 change: 1 addition & 0 deletions common/test/data/2014/course/2014.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<course display_name="detached_pages" end="2014-01-22T05:00:00Z" start="2013-01-01T00:00:00Z"/>
1 change: 1 addition & 0 deletions common/test/data/2014/info/handouts.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ol></ol>
1 change: 1 addition & 0 deletions common/test/data/2014/info/updates.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ol><li><h2>January 29, 2014</h2>course info 463139</li></ol>
1 change: 1 addition & 0 deletions common/test/data/2014/policies/2014/grading_policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"GRADER": [{"short_label": "HW", "min_count": 12, "type": "Homework", "drop_count": 2, "weight": 0.15}, {"min_count": 12, "type": "Lab", "drop_count": 2, "weight": 0.15}, {"short_label": "Midterm", "min_count": 1, "type": "Midterm Exam", "drop_count": 0, "weight": 0.3}, {"short_label": "Final", "min_count": 1, "type": "Final Exam", "drop_count": 0, "weight": 0.4}], "GRADE_CUTOFFS": {"Pass": 0.5}}
39 changes: 39 additions & 0 deletions common/test/data/2014/policies/2014/policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"course/2014": {
"discussion_topics": {
"General": {
"id": "i4x-edX-detached_pages-course-2014"
}
},
"display_name": "detached_pages",
"end": "2014-01-22T05:00:00Z",
"start": "2013-01-01T00:00:00Z",
"tabs": [
{
"name": "Courseware",
"type": "courseware"
},
{
"name": "Course Info",
"type": "course_info"
},
{
"name": "Discussion",
"type": "discussion"
},
{
"name": "Wiki",
"type": "wiki"
},
{
"name": "Progress",
"type": "progress"
},
{
"name": "Empty",
"type": "static_tab",
"url_slug": "8e4cce2b4aaf4ba28b1220804619e41f"
}
]
}
}
1 change: 1 addition & 0 deletions common/test/data/2014/policies/assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>static 463139</p>
4 changes: 2 additions & 2 deletions lms/djangoapps/bulk_email/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def _get_source_address(course_id, course_title):
invalid_chars = re.compile(r"[^\w.-]")
course_num = invalid_chars.sub('_', course_num)

from_addr = '"{0}" Course Staff <{1}-{2}>'.format(course_title_no_quotes, course_num, settings.BULK_EMAIL_DEFAULT_FROM_EMAIL)
from_addr = u'"{0}" Course Staff <{1}-{2}>'.format(course_title_no_quotes, course_num, settings.BULK_EMAIL_DEFAULT_FROM_EMAIL)
return from_addr


Expand Down Expand Up @@ -677,5 +677,5 @@ def _statsd_tag(course_title):
"""
Calculate the tag we will use for DataDog.
"""
tag = "course_email:{0}".format(course_title)
tag = u"course_email:{0}".format(course_title)
return tag[:200]
4 changes: 3 additions & 1 deletion lms/djangoapps/bulk_email/tests/test_course_optout.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Unit tests for student optouts from course email
"""
Expand Down Expand Up @@ -26,7 +27,8 @@ class TestOptoutCourseEmails(ModuleStoreTestCase):
"""

def setUp(self):
self.course = CourseFactory.create()
course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ"
self.course = CourseFactory.create(display_name=course_title)
self.instructor = AdminFactory.create()
self.student = UserFactory.create()
CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
Expand Down
3 changes: 2 additions & 1 deletion lms/djangoapps/bulk_email/tests/test_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ class TestEmailSendFromDashboard(ModuleStoreTestCase):

@patch.dict(settings.FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True, 'REQUIRE_COURSE_EMAIL_AUTH': False})
def setUp(self):
self.course = CourseFactory.create()
course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ"
self.course = CourseFactory.create(display_name=course_title)

self.instructor = InstructorFactory(course=self.course.location)

Expand Down
4 changes: 3 additions & 1 deletion lms/djangoapps/bulk_email/tests/test_err_handling.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Unit tests for handling email sending errors
"""
Expand Down Expand Up @@ -43,7 +44,8 @@ class TestEmailErrors(ModuleStoreTestCase):
"""

def setUp(self):
self.course = CourseFactory.create()
course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ"
self.course = CourseFactory.create(display_name=course_title)
self.instructor = AdminFactory.create()
self.client.login(username=self.instructor.username, password="test")

Expand Down
5 changes: 3 additions & 2 deletions lms/djangoapps/bulk_email/tests/test_forms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Unit tests for bulk-email-related forms.
"""
Expand All @@ -23,8 +24,8 @@ class CourseAuthorizationFormTest(ModuleStoreTestCase):
"""Test the CourseAuthorizationAdminForm form for Mongo-backed courses."""

def setUp(self):
# Make a mongo course
self.course = CourseFactory.create()
course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ"
self.course = CourseFactory.create(display_name=course_title)

def tearDown(self):
"""
Expand Down
1 change: 1 addition & 0 deletions lms/djangoapps/courseware/tests/modulestore_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
'edX/open_ended/2012_Fall': 'xml',
'edX/due_date/2013_fall': 'xml',
'edX/open_ended_nopath/2012_Fall': 'xml',
'edX/detached_pages/2014': 'xml',
}
TEST_DATA_MIXED_MODULESTORE = mixed_store_config(TEST_DATA_DIR, MAPPINGS)
20 changes: 20 additions & 0 deletions lms/djangoapps/courseware/tests/test_about.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Test the about xblock
"""
import mock
from django.test.utils import override_settings
from django.core.urlresolvers import reverse

Expand All @@ -18,6 +19,10 @@ def setUp(self):
category="about", parent_location=self.course.location,
data="OOGIE BLOOGIE", display_name="overview"
)
# The following XML course is closed; we're testing that
# an about page still appears when the course is already closed
self.xml_course_id = 'edX/detached_pages/2014'
self.xml_data = "about page 463139"

def test_logged_in(self):
self.setup_user()
Expand All @@ -31,3 +36,18 @@ def test_anonymous_user(self):
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn("OOGIE BLOOGIE", resp.content)

@mock.patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_logged_in_xml(self):
self.setup_user()
url = reverse('about_course', args=[self.xml_course_id])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(self.xml_data, resp.content)

@mock.patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_anonymous_user_xml(self):
url = reverse('about_course', args=[self.xml_course_id])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(self.xml_data, resp.content)
20 changes: 20 additions & 0 deletions lms/djangoapps/courseware/tests/test_course_info.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Test the course_info xblock
"""
import mock
from django.test.utils import override_settings
from django.core.urlresolvers import reverse

Expand All @@ -18,6 +19,10 @@ def setUp(self):
category="course_info", parent_location=self.course.location,
data="OOGIE BLOOGIE", display_name="updates"
)
# The following XML course is closed; we're testing that
# a course info page still appears when the course is already closed
self.xml_data = "course info 463139"
self.xml_course_id = "edX/detached_pages/2014"

def test_logged_in(self):
self.setup_user()
Expand All @@ -31,3 +36,18 @@ def test_anonymous_user(self):
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertNotIn("OOGIE BLOOGIE", resp.content)

@mock.patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_logged_in_xml(self):
self.setup_user()
url = reverse('info', args=[self.xml_course_id])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(self.xml_data, resp.content)

@mock.patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_anonymous_user_xml(self):
url = reverse('info', args=[self.xml_course_id])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertNotIn(self.xml_data, resp.content)
20 changes: 20 additions & 0 deletions lms/djangoapps/courseware/tests/test_tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ def setUp(self):
category="static_tab", parent_location=self.course.location,
data="OOGIE BLOOGIE", display_name="new_tab"
)
# The following XML course is closed; we're testing that
# static tabs still appear when the course is already closed
self.xml_data = "static 463139"
self.xml_url = "8e4cce2b4aaf4ba28b1220804619e41f"
self.xml_course_id = 'edX/detached_pages/2014'

def test_logged_in(self):
self.setup_user()
Expand All @@ -169,6 +174,21 @@ def test_anonymous_user(self):
self.assertEqual(resp.status_code, 200)
self.assertIn("OOGIE BLOOGIE", resp.content)

@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_logged_in_xml(self):
self.setup_user()
url = reverse('static_tab', args=[self.xml_course_id, self.xml_url])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(self.xml_data, resp.content)

@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_anonymous_user_xml(self):
url = reverse('static_tab', args=[self.xml_course_id, self.xml_url])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(self.xml_data, resp.content)


class TextbooksTestCase(TestCase):

Expand Down