diff --git a/common/lib/xmodule/xmodule/conditional_module.py b/common/lib/xmodule/xmodule/conditional_module.py
index b3e0e0e06b..2433a143ed 100644
--- a/common/lib/xmodule/xmodule/conditional_module.py
+++ b/common/lib/xmodule/xmodule/conditional_module.py
@@ -125,7 +125,8 @@ class ConditionalModule(ConditionalFields, XModule):
an AJAX call.
"""
if not self.is_condition_satisfied():
- message = self.descriptor.xml_attributes.get('message')
+ defmsg = "{link} must be attempted before this will become visible."
+ message = self.descriptor.xml_attributes.get('message', defmsg)
context = {'module': self,
'message': message}
html = self.system.render_template('conditional_module.html',
diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py
index ed5a37e580..4712bbe426 100644
--- a/common/lib/xmodule/xmodule/course_module.py
+++ b/common/lib/xmodule/xmodule/course_module.py
@@ -652,7 +652,12 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
@property
def end_date_text(self):
- return time.strftime("%b %d, %Y", self.end)
+ """
+ Returns the end date for the course formatted as a string.
+
+ If the course does not have an end date set (course.end is None), an empty string will be returned.
+ """
+ return '' if self.end is None else time.strftime("%b %d, %Y", self.end)
@property
def forum_posts_allowed(self):
diff --git a/common/lib/xmodule/xmodule/tests/test_course_module.py b/common/lib/xmodule/xmodule/tests/test_course_module.py
index 17930f1b89..15bab32c14 100644
--- a/common/lib/xmodule/xmodule/tests/test_course_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_course_module.py
@@ -54,7 +54,7 @@ class IsNewCourseTestCase(unittest.TestCase):
self.addCleanup(datetime_patcher.stop)
@staticmethod
- def get_dummy_course(start, announcement=None, is_new=None, advertised_start=None):
+ def get_dummy_course(start, announcement=None, is_new=None, advertised_start=None, end=None):
"""Get a dummy course"""
system = DummySystem(load_error_modules=True)
@@ -65,6 +65,7 @@ class IsNewCourseTestCase(unittest.TestCase):
is_new = to_attrb('is_new', is_new)
announcement = to_attrb('announcement', announcement)
advertised_start = to_attrb('advertised_start', advertised_start)
+ end = to_attrb('end', end)
start_xml = '''
+ {advertised_start}
+ {end}>
Two houses, ...
'''.format(org=ORG, course=COURSE, start=start, is_new=is_new,
- announcement=announcement, advertised_start=advertised_start)
+ announcement=announcement, advertised_start=advertised_start, end=end)
return system.process_xml(start_xml)
@@ -161,3 +163,11 @@ class IsNewCourseTestCase(unittest.TestCase):
descriptor = self.get_dummy_course(start='2012-12-31T12:00')
assert(descriptor.is_newish is True)
+
+ def test_end_date_text(self):
+ # No end date set, returns empty string.
+ d = self.get_dummy_course('2012-12-02T12:00')
+ self.assertEqual('', d.end_date_text)
+
+ d = self.get_dummy_course('2012-12-02T12:00', end='2014-9-04T12:00')
+ self.assertEqual('Sep 04, 2014', d.end_date_text)
diff --git a/common/test/data/test_about_blob_end_date/README.md b/common/test/data/test_about_blob_end_date/README.md
new file mode 100644
index 0000000000..69cb3b7cb7
--- /dev/null
+++ b/common/test/data/test_about_blob_end_date/README.md
@@ -0,0 +1,5 @@
+Test course for checking the end date displayed on the course about page.
+This course has both an end_date HTML "blob", and it also has a course end date set.
+The end_date "blob" has higher precedence and will show.
+
+See also test_end course.
diff --git a/common/test/data/test_about_blob_end_date/about/end_date.html b/common/test/data/test_about_blob_end_date/about/end_date.html
new file mode 100644
index 0000000000..918737595e
--- /dev/null
+++ b/common/test/data/test_about_blob_end_date/about/end_date.html
@@ -0,0 +1 @@
+Learning never ends
diff --git a/common/test/data/test_about_blob_end_date/course.xml b/common/test/data/test_about_blob_end_date/course.xml
new file mode 100644
index 0000000000..e6ffae8481
--- /dev/null
+++ b/common/test/data/test_about_blob_end_date/course.xml
@@ -0,0 +1 @@
+
diff --git a/common/test/data/test_about_blob_end_date/course/2012_Fall.xml b/common/test/data/test_about_blob_end_date/course/2012_Fall.xml
new file mode 100644
index 0000000000..c9d2e8702d
--- /dev/null
+++ b/common/test/data/test_about_blob_end_date/course/2012_Fall.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/common/test/data/test_about_blob_end_date/policies/2012_Fall.json b/common/test/data/test_about_blob_end_date/policies/2012_Fall.json
new file mode 100644
index 0000000000..7df05a1392
--- /dev/null
+++ b/common/test/data/test_about_blob_end_date/policies/2012_Fall.json
@@ -0,0 +1,9 @@
+{
+ "course/2012_Fall": {
+ "graceperiod": "2 days 5 hours 59 minutes 59 seconds",
+ "start": "2015-07-17T12:00",
+ "end": "2015-09-17T12:00",
+ "display_name": "Test About Blob End Date",
+ "graded": "true"
+ }
+}
diff --git a/common/test/data/test_end/README.md b/common/test/data/test_end/README.md
new file mode 100644
index 0000000000..6fc2f28728
--- /dev/null
+++ b/common/test/data/test_end/README.md
@@ -0,0 +1,5 @@
+Test course for checking the end date displayed on the course about page.
+This course does not have an end_date HTML "blob", but it does have a course end date set.
+Therefore the course end date should show on the course about page.
+
+See also test_about_blob_end_date course.
diff --git a/common/test/data/test_end/course.xml b/common/test/data/test_end/course.xml
new file mode 100644
index 0000000000..3071ba09ea
--- /dev/null
+++ b/common/test/data/test_end/course.xml
@@ -0,0 +1 @@
+
diff --git a/common/test/data/test_end/course/2012_Fall.xml b/common/test/data/test_end/course/2012_Fall.xml
new file mode 100644
index 0000000000..c9d2e8702d
--- /dev/null
+++ b/common/test/data/test_end/course/2012_Fall.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/common/test/data/test_end/policies/2012_Fall.json b/common/test/data/test_end/policies/2012_Fall.json
new file mode 100644
index 0000000000..a114f23465
--- /dev/null
+++ b/common/test/data/test_end/policies/2012_Fall.json
@@ -0,0 +1,9 @@
+{
+ "course/2012_Fall": {
+ "graceperiod": "2 days 5 hours 59 minutes 59 seconds",
+ "start": "2015-07-17T12:00",
+ "end": "2015-09-17T12:00",
+ "display_name": "Test End",
+ "graded": "true"
+ }
+}
diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index 979f347d1f..1d3166893e 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -1,26 +1,19 @@
-import logging
-from mock import MagicMock, patch
+from mock import MagicMock
import datetime
-import factory
-import unittest
-import os
from django.test import TestCase
-from django.http import Http404, HttpResponse
+from django.http import Http404
from django.conf import settings
from django.test.utils import override_settings
from django.contrib.auth.models import User
from django.test.client import RequestFactory
from student.models import CourseEnrollment
-from xmodule.modulestore.django import modulestore, _MODULESTORES
-from xmodule.modulestore.exceptions import InvalidLocationError,\
- ItemNotFoundError, NoPathToItem
+from xmodule.modulestore.django import modulestore
+
import courseware.views as views
from xmodule.modulestore import Location
-from .factories import UserFactory
-
class Stub():
pass
@@ -55,7 +48,6 @@ class TestJumpTo(TestCase):
def test_jumpto_invalid_location(self):
location = Location('i4x', 'edX', 'toy', 'NoSuchPlace', None)
jumpto_url = '%s/%s/jump_to/%s' % ('/courses', self.course_name, location)
- expected = 'courses/edX/toy/2012_Fall/courseware/Overview/'
response = self.client.get(jumpto_url)
self.assertEqual(response.status_code, 404)
@@ -124,3 +116,26 @@ class ViewsTestCase(TestCase):
request, 'bar', ())
self.assertRaisesRegexp(Http404, 'No data*', views.jump_to, request,
'dummy', self.location)
+
+ def test_no_end_on_about_page(self):
+ # Toy course has no course end date or about/end_date blob
+ self.verify_end_date(self.course_id)
+
+ def test_no_end_about_blob(self):
+ # test_end has a course end date, no end_date HTML blob
+ self.verify_end_date("edX/test_end/2012_Fall", "Sep 17, 2015")
+
+ def test_about_blob_end_date(self):
+ # test_about_blob_end_date has both a course end date and an end_date HTML blob.
+ # HTML blob wins
+ self.verify_end_date("edX/test_about_blob_end_date/2012_Fall", "Learning never ends")
+
+ def verify_end_date(self, course_id, expected_end_text=None):
+ request = self.request_factory.get("foo")
+ request.user = self.user
+ result = views.course_about(request, course_id)
+ if expected_end_text is not None:
+ self.assertContains(result, "Classes End")
+ self.assertContains(result, expected_end_text)
+ else:
+ self.assertNotContains(result, "Classes End")
diff --git a/lms/templates/courseware/course_about.html b/lms/templates/courseware/course_about.html
index b35c7a1b6f..dc1dc17532 100644
--- a/lms/templates/courseware/course_about.html
+++ b/lms/templates/courseware/course_about.html
@@ -144,10 +144,20 @@
Course Number
${course.number}
Classes Start
${course.start_date_text}
- ## End date should come from course.xml, but this is a quick hack
- % if get_course_about_section(course, "end_date"):
- Classes End
${get_course_about_section(course, "end_date")}
- % endif
+ ## We plan to ditch end_date (which is not stored in course metadata),
+ ## but for backwards compatibility, show about/end_date blob if it exists.
+ % if get_course_about_section(course, "end_date") or course.end:
+
+
+ Classes End
+ % if get_course_about_section(course, "end_date"):
+ ${get_course_about_section(course, "end_date")}
+ % else:
+ ${course.end_date_text}
+ % endif
+
+
+ % endif
% if get_course_about_section(course, "effort"):
Estimated Effort
${get_course_about_section(course, "effort")}