Detached pages from XML courses are set to appropriate descriptor class (LMS-2094)
Add tests
This commit is contained in:
@@ -18,10 +18,9 @@ from xmodule.error_module import ErrorDescriptor
|
||||
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
|
||||
@@ -222,6 +221,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
|
||||
# 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)
|
||||
@@ -509,6 +509,9 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
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(
|
||||
@@ -570,9 +573,9 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
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
|
||||
|
||||
47
common/test/data/2014/about/overview.html
Normal file
47
common/test/data/2014/about/overview.html
Normal file
@@ -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
common/test/data/2014/course.xml
Normal file
1
common/test/data/2014/course.xml
Normal file
@@ -0,0 +1 @@
|
||||
<course url_name="2014" org="edX" course="detached_pages"/>
|
||||
1
common/test/data/2014/course/2014.xml
Normal file
1
common/test/data/2014/course/2014.xml
Normal file
@@ -0,0 +1 @@
|
||||
<course display_name="detached_pages" end="2014-01-22T05:00:00Z" start="2013-01-01T00:00:00Z"/>
|
||||
1
common/test/data/2014/info/handouts.html
Normal file
1
common/test/data/2014/info/handouts.html
Normal file
@@ -0,0 +1 @@
|
||||
<ol></ol>
|
||||
1
common/test/data/2014/info/updates.html
Normal file
1
common/test/data/2014/info/updates.html
Normal file
@@ -0,0 +1 @@
|
||||
<ol><li><h2>January 29, 2014</h2>course info 463139</li></ol>
|
||||
1
common/test/data/2014/policies/2014/grading_policy.json
Normal file
1
common/test/data/2014/policies/2014/grading_policy.json
Normal file
@@ -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
common/test/data/2014/policies/2014/policy.json
Normal file
39
common/test/data/2014/policies/2014/policy.json
Normal file
@@ -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
common/test/data/2014/policies/assets.json
Normal file
1
common/test/data/2014/policies/assets.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
<p>static 463139</p>
|
||||
@@ -25,5 +25,6 @@ MAPPINGS = {
|
||||
'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)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Test the about xblock
|
||||
"""
|
||||
import mock
|
||||
from django.test.utils import override_settings
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
@@ -18,6 +19,10 @@ class AboutTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
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()
|
||||
@@ -31,3 +36,18 @@ class AboutTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
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)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Test the course_info xblock
|
||||
"""
|
||||
import mock
|
||||
from django.test.utils import override_settings
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
@@ -18,6 +19,10 @@ class CourseInfoTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
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()
|
||||
@@ -31,3 +36,18 @@ class CourseInfoTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
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)
|
||||
|
||||
@@ -155,6 +155,11 @@ class StaticTabDateTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
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()
|
||||
@@ -169,6 +174,21 @@ class StaticTabDateTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
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):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user