Commit 82092bdd by Christina Roberts

Merge pull request #1697 from edx/christina/i4x_test

Test HTML returned from view methods for "i4X".
parents 729f2e3b f01b36b5
#pylint: disable=E1101 #pylint: disable=E1101
import json
import shutil import shutil
import mock import mock
...@@ -15,6 +14,7 @@ from fs.osfs import OSFS ...@@ -15,6 +14,7 @@ from fs.osfs import OSFS
import copy import copy
from json import loads from json import loads
from datetime import timedelta from datetime import timedelta
from django.test import TestCase
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.dispatch import Signal from django.dispatch import Signal
...@@ -53,6 +53,7 @@ from pytz import UTC ...@@ -53,6 +53,7 @@ from pytz import UTC
from uuid import uuid4 from uuid import uuid4
from pymongo import MongoClient from pymongo import MongoClient
from student.models import CourseEnrollment from student.models import CourseEnrollment
import re
from contentstore.utils import delete_course_and_groups from contentstore.utils import delete_course_and_groups
from xmodule.modulestore.django import loc_mapper from xmodule.modulestore.django import loc_mapper
...@@ -135,6 +136,8 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -135,6 +136,8 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
resp = self.client.get_html(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) resp = self.client.get_html(reverse('edit_unit', kwargs={'location': descriptor.location.url()}))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment after edit_unit no longer using locations.
# _test_no_locations(self, resp)
for expected in expected_types: for expected in expected_types:
self.assertIn(expected, resp.content) self.assertIn(expected, resp.content)
...@@ -160,15 +163,21 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -160,15 +163,21 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
resp = self.client.get_html(reverse('edit_unit', kwargs={'location': location.url()})) resp = self.client.get_html(reverse('edit_unit', kwargs={'location': location.url()}))
self.assertEqual(resp.status_code, 400) self.assertEqual(resp.status_code, 400)
_test_no_locations(self, resp, status_code=400)
def check_edit_unit(self, test_course_name): def check_edit_unit(self, test_course_name):
import_from_xml(modulestore('direct'), 'common/test/data/', [test_course_name]) import_from_xml(modulestore('direct'), 'common/test/data/', [test_course_name])
for descriptor in modulestore().get_items(Location(None, None, 'vertical', None, None)): items = modulestore().get_items(Location('i4x', 'edX', test_course_name, 'vertical', None, None))
# Assert is here to make sure that the course being tested actually has verticals.
self.assertGreater(len(items), 0)
for descriptor in items:
print "Checking ", descriptor.location.url() print "Checking ", descriptor.location.url()
print descriptor.__class__, descriptor.location print descriptor.__class__, descriptor.location
resp = self.client.get_html(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) resp = self.client.get_html(reverse('edit_unit', kwargs={'location': descriptor.location.url()}))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment after edit_unit not using locations.
# _test_no_locations(self, resp)
def lockAnAsset(self, content_store, course_location): def lockAnAsset(self, content_store, course_location):
""" """
...@@ -483,6 +492,8 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -483,6 +492,8 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
) )
resp = self.client.get_html(locator.url_reverse('xblock')) resp = self.client.get_html(locator.url_reverse('xblock'))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment when preview no longer has locations being returned.
# _test_no_locations(self, resp)
return resp return resp
def test_delete(self): def test_delete(self):
...@@ -841,6 +852,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -841,6 +852,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
def test_bad_contentstore_request(self): def test_bad_contentstore_request(self):
resp = self.client.get_html('http://localhost:8001/c4x/CDX/123123/asset/&images_circuits_Lab7Solution2.png') resp = self.client.get_html('http://localhost:8001/c4x/CDX/123123/asset/&images_circuits_Lab7Solution2.png')
self.assertEqual(resp.status_code, 400) self.assertEqual(resp.status_code, 400)
_test_no_locations(self, resp, 400)
def test_rewrite_nonportable_links_on_import(self): def test_rewrite_nonportable_links_on_import(self):
module_store = modulestore('direct') module_store = modulestore('direct')
...@@ -1026,12 +1038,11 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -1026,12 +1038,11 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
items = module_store.get_items(stub_location.replace(category='vertical', name=None)) items = module_store.get_items(stub_location.replace(category='vertical', name=None))
self.assertGreater(len(items), 0) self.assertGreater(len(items), 0)
for descriptor in items: for descriptor in items:
# don't try to look at private verticals. Right now we're running
# the service in non-draft aware
if getattr(descriptor, 'is_draft', False):
print "Checking {0}....".format(descriptor.location.url()) print "Checking {0}....".format(descriptor.location.url())
resp = self.client.get_html(reverse('edit_unit', kwargs={'location': descriptor.location.url()})) resp = self.client.get_html(reverse('edit_unit', kwargs={'location': descriptor.location.url()}))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment when edit_unit no longer has locations.
# _test_no_locations(self, resp)
# verify that we have the content in the draft store as well # verify that we have the content in the draft store as well
vertical = draft_store.get_item( vertical = draft_store.get_item(
...@@ -1508,6 +1519,7 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -1508,6 +1519,7 @@ class ContentStoreTest(ModuleStoreTestCase):
status_code=200, status_code=200,
html=True html=True
) )
_test_no_locations(self, resp)
def test_course_factory(self): def test_course_factory(self):
"""Test that the course factory works correctly.""" """Test that the course factory works correctly."""
...@@ -1530,6 +1542,8 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -1530,6 +1542,8 @@ class ContentStoreTest(ModuleStoreTestCase):
status_code=200, status_code=200,
html=True html=True
) )
# TODO: uncomment when course index no longer has locations being returned.
# _test_no_locations(self, resp)
def test_course_overview_view_with_course(self): def test_course_overview_view_with_course(self):
"""Test viewing the course overview page with an existing course""" """Test viewing the course overview page with an existing course"""
...@@ -1589,6 +1603,13 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -1589,6 +1603,13 @@ class ContentStoreTest(ModuleStoreTestCase):
Import and walk through some common URL endpoints. This just verifies non-500 and no other Import and walk through some common URL endpoints. This just verifies non-500 and no other
correct behavior, so it is not a deep test correct behavior, so it is not a deep test
""" """
def test_get_html(page):
# Helper function for getting HTML for a page in Studio and
# checking that it does not error.
resp = self.client.get_html(new_location.url_reverse(page))
self.assertEqual(resp.status_code, 200)
_test_no_locations(self, resp)
import_from_xml(modulestore('direct'), 'common/test/data/', ['simple']) import_from_xml(modulestore('direct'), 'common/test/data/', ['simple'])
loc = Location(['i4x', 'edX', 'simple', 'course', '2012_Fall', None]) loc = Location(['i4x', 'edX', 'simple', 'course', '2012_Fall', None])
new_location = loc_mapper().translate_location(loc.course_id, loc, False, True) new_location = loc_mapper().translate_location(loc.course_id, loc, False, True)
...@@ -1598,42 +1619,46 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -1598,42 +1619,46 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertContains(resp, 'Chapter 2') self.assertContains(resp, 'Chapter 2')
# go to various pages # go to various pages
test_get_html('import')
test_get_html('export')
test_get_html('course_team')
test_get_html('course_info')
test_get_html('checklists')
test_get_html('assets')
# import page # settings_details
resp = self.client.get_html(new_location.url_reverse('import/', '')) resp = self.client.get_html(reverse('settings_details',
self.assertEqual(resp.status_code, 200) kwargs={'org': loc.org,
'course': loc.course,
# export page 'name': loc.name}))
resp = self.client.get_html(new_location.url_reverse('export/', ''))
self.assertEqual(resp.status_code, 200)
# course team
url = new_location.url_reverse('course_team/', '')
resp = self.client.get_html(url)
self.assertEqual(resp.status_code, 200)
# course info
resp = self.client.get(new_location.url_reverse('course_info'))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
_test_no_locations(self, resp)
# settings_details # settings_details
resp = self.client.get(reverse('settings_details', resp = self.client.get_html(reverse('settings_grading',
kwargs={'org': loc.org, kwargs={'org': loc.org,
'course': loc.course, 'course': loc.course,
'name': loc.name})) 'name': loc.name}))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment when grading is not using old locations.
# _test_no_locations(self, resp)
# settings_details # advanced settings
resp = self.client.get(reverse('settings_grading', resp = self.client.get_html(reverse('course_advanced_settings',
kwargs={'org': loc.org, kwargs={'org': loc.org,
'course': loc.course, 'course': loc.course,
'name': loc.name})) 'name': loc.name}))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment when advanced settings not using old locations.
# _test_no_locations(self, resp)
# assets_handler (HTML for full page content) # textbook index
url = new_location.url_reverse('assets/', '') resp = self.client.get_html(reverse('textbook_index',
resp = self.client.get_html(url) kwargs={'org': loc.org,
'course': loc.course,
'name': loc.name}))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
_test_no_locations(self, resp)
# go look at a subsection page # go look at a subsection page
subsection_location = loc.replace(category='sequential', name='test_sequence') subsection_location = loc.replace(category='sequential', name='test_sequence')
...@@ -1641,12 +1666,23 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -1641,12 +1666,23 @@ class ContentStoreTest(ModuleStoreTestCase):
reverse('edit_subsection', kwargs={'location': subsection_location.url()}) reverse('edit_subsection', kwargs={'location': subsection_location.url()})
) )
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment when grading and outline not using old locations.
# _test_no_locations(self, resp)
# go look at the Edit page # go look at the Edit page
unit_location = loc.replace(category='vertical', name='test_vertical') unit_location = loc.replace(category='vertical', name='test_vertical')
resp = self.client.get_html( resp = self.client.get_html(
reverse('edit_unit', kwargs={'location': unit_location.url()})) reverse('edit_unit', kwargs={'location': unit_location.url()}))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# TODO: uncomment when edit_unit not using old locations.
# _test_no_locations(self, resp)
resp = self.client.get_html(reverse('edit_tabs',
kwargs={'org': loc.org,
'course': loc.course,
'coursename': loc.name}))
self.assertEqual(resp.status_code, 200)
_test_no_locations(self, resp)
def delete_item(category, name): def delete_item(category, name):
""" Helper method for testing the deletion of an xblock item. """ """ Helper method for testing the deletion of an xblock item. """
...@@ -1654,6 +1690,7 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -1654,6 +1690,7 @@ class ContentStoreTest(ModuleStoreTestCase):
del_location = loc_mapper().translate_location(loc.course_id, del_loc, False, True) del_location = loc_mapper().translate_location(loc.course_id, del_loc, False, True)
resp = self.client.delete(del_location.url_reverse('xblock')) resp = self.client.delete(del_location.url_reverse('xblock'))
self.assertEqual(resp.status_code, 204) self.assertEqual(resp.status_code, 204)
_test_no_locations(self, resp, status_code=204, html=False)
# delete a component # delete a component
delete_item(category='html', name='test_html') delete_item(category='html', name='test_html')
...@@ -1853,7 +1890,10 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -1853,7 +1890,10 @@ class ContentStoreTest(ModuleStoreTestCase):
Show the course overview page. Show the course overview page.
""" """
new_location = loc_mapper().translate_location(location.course_id, location, False, True) new_location = loc_mapper().translate_location(location.course_id, location, False, True)
return self.client.get_html(new_location.url_reverse('course/', '')) resp = self.client.get_html(new_location.url_reverse('course/', ''))
# TODO: uncomment when i4x no longer in overview.
# _test_no_locations(self, resp)
return resp
@override_settings(MODULESTORE=TEST_MODULESTORE) @override_settings(MODULESTORE=TEST_MODULESTORE)
...@@ -1920,6 +1960,32 @@ class MetadataSaveTestCase(ModuleStoreTestCase): ...@@ -1920,6 +1960,32 @@ class MetadataSaveTestCase(ModuleStoreTestCase):
pass pass
class EntryPageTestCase(TestCase):
"""
Tests entry pages that aren't specific to a course.
"""
def setUp(self):
self.client = AjaxEnabledTestClient()
def _test_page(self, page, status_code=200):
resp = self.client.get_html(reverse(page))
self.assertEqual(resp.status_code, status_code)
_test_no_locations(self, resp, status_code)
def test_how_it_works(self):
self._test_page("howitworks")
def test_signup(self):
self._test_page("signup")
def test_login(self):
self._test_page("login")
def test_logout(self):
# Logout redirects.
self._test_page("logout", 302)
def _create_course(test, course_data): def _create_course(test, course_data):
""" """
Creates a course via an AJAX request and verifies the URL returned in the response. Creates a course via an AJAX request and verifies the URL returned in the response.
...@@ -1945,3 +2011,21 @@ def _course_factory_create_course(): ...@@ -1945,3 +2011,21 @@ def _course_factory_create_course():
def _get_course_id(test_course_data): def _get_course_id(test_course_data):
"""Returns the course ID (org/number/run).""" """Returns the course ID (org/number/run)."""
return "{org}/{number}/{run}".format(**test_course_data) return "{org}/{number}/{run}".format(**test_course_data)
def _test_no_locations(test, resp, status_code=200, html=True):
"""
Verifies that "i4x", which appears in old locations, but not
new locators, does not appear in the HTML response output.
Used to verify that database refactoring is complete.
"""
test.assertNotContains(resp, 'i4x', status_code=status_code, html=html)
if html:
# For HTML pages, it is nice to call the method with html=True because
# it checks that the HTML properly parses. However, it won't find i4x usages
# in JavaScript blocks.
content = resp.content
num_jump_to = len(re.findall(r"8000(\S)*jump_to/i4x", content))
total_i4x = len(re.findall(r"i4x", content))
test.assertEqual(total_i4x - num_jump_to, 0, "i4x found outside of LMS jump-to links")
...@@ -5,12 +5,9 @@ define(["backbone"], function(Backbone) { ...@@ -5,12 +5,9 @@ define(["backbone"], function(Backbone) {
url: '', url: '',
defaults: { defaults: {
"courseId": "", // the location url
"updates" : null, // UpdateCollection "updates" : null, // UpdateCollection
"handouts": null // HandoutCollection "handouts": null // HandoutCollection
}, }
idAttribute : "courseId"
}); });
return CourseInfo; return CourseInfo;
}); });
...@@ -187,7 +187,7 @@ require(["domReady", "jquery", "gettext", "js/models/asset", "js/collections/ass ...@@ -187,7 +187,7 @@ require(["domReady", "jquery", "gettext", "js/models/asset", "js/collections/ass
<a href="#" class="close-button"><i class="icon-remove-sign"></i> <span class="sr">${_('close')}</span></a> <a href="#" class="close-button"><i class="icon-remove-sign"></i> <span class="sr">${_('close')}</span></a>
<div class="modal-body"> <div class="modal-body">
<h1 class="title">${_("Upload New File")}</h1> <h1 class="title">${_("Upload New File")}</h1>
<p class="file-name"></a> <p class="file-name">
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-fill"></div> <div class="progress-fill"></div>
</div> </div>
......
...@@ -33,7 +33,6 @@ require(["domReady!", "jquery", "js/collections/course_update", "js/models/modul ...@@ -33,7 +33,6 @@ require(["domReady!", "jquery", "js/collections/course_update", "js/models/modul
var editor = new CourseInfoEditView({ var editor = new CourseInfoEditView({
el: $('.main-wrapper'), el: $('.main-wrapper'),
model : new CourseInfoModel({ model : new CourseInfoModel({
courseId : '${context_course.location}',
updates : course_updates, updates : course_updates,
base_asset_url : '${base_asset_url}', base_asset_url : '${base_asset_url}',
handouts : course_handouts handouts : course_handouts
......
...@@ -87,7 +87,7 @@ require(["domReady!", "jquery", "js/models/settings/course_details", "js/views/s ...@@ -87,7 +87,7 @@ require(["domReady!", "jquery", "js/models/settings/course_details", "js/views/s
<div class="note note-promotion note-promotion-courseURL has-actions"> <div class="note note-promotion note-promotion-courseURL has-actions">
<h3 class="title">${_("Course Summary Page")} <span class="tip">${_("(for student enrollment and access)")}</span></h3> <h3 class="title">${_("Course Summary Page")} <span class="tip">${_("(for student enrollment and access)")}</span></h3>
<div class="copy"> <div class="copy">
<p><a class="link-courseURL" rel="external" href="https:${utils.get_lms_link_for_about_page(course_location)}" />https:${utils.get_lms_link_for_about_page(course_location)}</a></p> <p><a class="link-courseURL" rel="external" href="https:${utils.get_lms_link_for_about_page(course_location)}" >https:${utils.get_lms_link_for_about_page(course_location)}</a></p>
</div> </div>
<ul class="list-actions"> <ul class="list-actions">
......
<%!
from xmodule.modulestore.django import loc_mapper
%>
% if context_course:
<%
ctx_loc = context_course.location
locator = loc_mapper().translate_location(ctx_loc.course_id, ctx_loc, False, True)
%>
% endif
% if settings.MITX_FEATURES.get('SEGMENT_IO'): % if settings.MITX_FEATURES.get('SEGMENT_IO'):
<!-- begin Segment.io --> <!-- begin Segment.io -->
<script type="text/javascript"> <script type="text/javascript">
// if inside course, inject the course location into the JS namespace // if inside course, inject the course location into the JS namespace
%if context_course: %if context_course:
var course_location_analytics = "${context_course.location}"; var course_location_analytics = "${locator}";
%endif %endif
var analytics=analytics||[];analytics.load=function(e){var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src=("https:"===document.location.protocol?"https://":"http://")+"d2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/"+e+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);var r=function(e){return function(){analytics.push([e].concat(Array.prototype.slice.call(arguments,0)))}},i=["identify","track","trackLink","trackForm","trackClick","trackSubmit","pageview","ab","alias","ready"];for(var s=0;s<i.length;s++)analytics[i[s]]=r(i[s])}; var analytics=analytics||[];analytics.load=function(e){var t=document.createElement("script");t.type="text/javascript",t.async=!0,t.src=("https:"===document.location.protocol?"https://":"http://")+"d2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/"+e+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);var r=function(e){return function(){analytics.push([e].concat(Array.prototype.slice.call(arguments,0)))}},i=["identify","track","trackLink","trackForm","trackClick","trackSubmit","pageview","ab","alias","ready"];for(var s=0;s<i.length;s++)analytics[i[s]]=r(i[s])};
...@@ -22,7 +33,7 @@ ...@@ -22,7 +33,7 @@
<!-- dummy segment.io --> <!-- dummy segment.io -->
<script type="text/javascript"> <script type="text/javascript">
%if context_course: %if context_course:
var course_location_analytics = "${context_course.location}"; var course_location_analytics = "${locator}";
%endif %endif
var analytics = { var analytics = {
"track": function() {} "track": function() {}
......
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