Commit 5e69050a by Will Daly

Elminated unused functions from courseware/features/courses.py

and moved the rest to common.py
parent c12e1fb1
......@@ -6,6 +6,9 @@ from student.models import CourseEnrollment
from xmodule.modulestore import Location
from xmodule.modulestore.django import _MODULESTORES, modulestore
from xmodule.templates import update_templates
from xmodule.course_module import CourseDescriptor
from courseware.courses import get_course_by_id
from xmodule import seq_module, vertical_module
from logging import getLogger
logger = getLogger(__name__)
......@@ -94,3 +97,87 @@ def section_location(course_num):
course=course_num,
category='sequential',
name=TEST_SECTION_NAME.replace(" ", "_"))
def get_courses():
'''
Returns dict of lists of courses available, keyed by course.org (ie university).
Courses are sorted by course.number.
'''
courses = [c for c in modulestore().get_courses()
if isinstance(c, CourseDescriptor)]
courses = sorted(courses, key=lambda course: course.number)
return courses
def get_courseware_with_tabs(course_id):
"""
Given a course_id (string), return a courseware array of dictionaries for the
top three levels of navigation. Same as get_courseware() except include
the tabs on the right hand main navigation page.
This hides the appropriate courseware as defined by the hide_from_toc field:
chapter.lms.hide_from_toc
Example:
[{
'chapter_name': 'Overview',
'sections': [{
'clickable_tab_count': 0,
'section_name': 'Welcome',
'tab_classes': []
}, {
'clickable_tab_count': 1,
'section_name': 'System Usage Sequence',
'tab_classes': ['VerticalDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Lab0: Using the tools',
'tab_classes': ['HtmlDescriptor', 'HtmlDescriptor', 'CapaDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Circuit Sandbox',
'tab_classes': []
}]
}, {
'chapter_name': 'Week 1',
'sections': [{
'clickable_tab_count': 4,
'section_name': 'Administrivia and Circuit Elements',
'tab_classes': ['VerticalDescriptor', 'VerticalDescriptor', 'VerticalDescriptor', 'VerticalDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Basic Circuit Analysis',
'tab_classes': ['CapaDescriptor', 'CapaDescriptor', 'CapaDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Resistor Divider',
'tab_classes': []
}, {
'clickable_tab_count': 0,
'section_name': 'Week 1 Tutorials',
'tab_classes': []
}]
}, {
'chapter_name': 'Midterm Exam',
'sections': [{
'clickable_tab_count': 2,
'section_name': 'Midterm Exam',
'tab_classes': ['VerticalDescriptor', 'VerticalDescriptor']
}]
}]
"""
course = get_course_by_id(course_id)
chapters = [chapter for chapter in course.get_children() if not chapter.lms.hide_from_toc]
courseware = [{'chapter_name': c.display_name_with_default,
'sections': [{'section_name': s.display_name_with_default,
'clickable_tab_count': len(s.get_children()) if (type(s) == seq_module.SequenceDescriptor) else 0,
'tabs': [{'children_count': len(t.get_children()) if (type(t) == vertical_module.VerticalDescriptor) else 0,
'class': t.__class__.__name__}
for t in s.get_children()]}
for s in c.get_children() if not s.lms.hide_from_toc]}
for c in chapters]
return courseware
from lettuce import world
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.django import modulestore
from courseware.courses import get_course_by_id
from xmodule import seq_module, vertical_module
from logging import getLogger
logger = getLogger(__name__)
## support functions
def get_courses():
'''
Returns dict of lists of courses available, keyed by course.org (ie university).
Courses are sorted by course.number.
'''
courses = [c for c in modulestore().get_courses()
if isinstance(c, CourseDescriptor)]
courses = sorted(courses, key=lambda course: course.number)
return courses
def get_courseware_with_tabs(course_id):
"""
Given a course_id (string), return a courseware array of dictionaries for the
top three levels of navigation. Same as get_courseware() except include
the tabs on the right hand main navigation page.
This hides the appropriate courseware as defined by the hide_from_toc field:
chapter.lms.hide_from_toc
Example:
[{
'chapter_name': 'Overview',
'sections': [{
'clickable_tab_count': 0,
'section_name': 'Welcome',
'tab_classes': []
}, {
'clickable_tab_count': 1,
'section_name': 'System Usage Sequence',
'tab_classes': ['VerticalDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Lab0: Using the tools',
'tab_classes': ['HtmlDescriptor', 'HtmlDescriptor', 'CapaDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Circuit Sandbox',
'tab_classes': []
}]
}, {
'chapter_name': 'Week 1',
'sections': [{
'clickable_tab_count': 4,
'section_name': 'Administrivia and Circuit Elements',
'tab_classes': ['VerticalDescriptor', 'VerticalDescriptor', 'VerticalDescriptor', 'VerticalDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Basic Circuit Analysis',
'tab_classes': ['CapaDescriptor', 'CapaDescriptor', 'CapaDescriptor']
}, {
'clickable_tab_count': 0,
'section_name': 'Resistor Divider',
'tab_classes': []
}, {
'clickable_tab_count': 0,
'section_name': 'Week 1 Tutorials',
'tab_classes': []
}]
}, {
'chapter_name': 'Midterm Exam',
'sections': [{
'clickable_tab_count': 2,
'section_name': 'Midterm Exam',
'tab_classes': ['VerticalDescriptor', 'VerticalDescriptor']
}]
}]
"""
course = get_course_by_id(course_id)
chapters = [chapter for chapter in course.get_children() if not chapter.lms.hide_from_toc]
courseware = [{'chapter_name': c.display_name_with_default,
'sections': [{'section_name': s.display_name_with_default,
'clickable_tab_count': len(s.get_children()) if (type(s) == seq_module.SequenceDescriptor) else 0,
'tabs': [{'children_count': len(t.get_children()) if (type(t) == vertical_module.VerticalDescriptor) else 0,
'class': t.__class__.__name__}
for t in s.get_children()]}
for s in c.get_children() if not s.lms.hide_from_toc]}
for c in chapters]
return courseware
def process_section(element, num_tabs=0):
'''
Process section reads through whatever is in 'course-content' and classifies it according to sequence module type.
This function is recursive
There are 6 types, with 6 actions.
Sequence Module
-contains one child module
Vertical Module
-contains other modules
-process it and get its children, then process them
Capa Module
-problem type, contains only one problem
-for this, the most complex type, we created a separate method, process_problem
Video Module
-video type, contains only one video
-we only check to ensure that a section with class of video exists
HTML Module
-html text
-we do not check anything about it
Custom Tag Module
-a custom 'hack' module type
-there is a large variety of content that could go in a custom tag module, so we just pass if it is of this unusual type
can be used like this:
e = world.browser.find_by_css('section.course-content section')
process_section(e)
'''
if element.has_class('xmodule_display xmodule_SequenceModule'):
logger.debug('####### Processing xmodule_SequenceModule')
child_modules = element.find_by_css("div>div>section[class^='xmodule']")
for mod in child_modules:
process_section(mod)
elif element.has_class('xmodule_display xmodule_VerticalModule'):
logger.debug('####### Processing xmodule_VerticalModule')
vert_list = element.find_by_css("li section[class^='xmodule']")
for item in vert_list:
process_section(item)
elif element.has_class('xmodule_display xmodule_CapaModule'):
logger.debug('####### Processing xmodule_CapaModule')
assert element.find_by_css("section[id^='problem']"), "No problems found in Capa Module"
p = element.find_by_css("section[id^='problem']").first
p_id = p['id']
logger.debug('####################')
logger.debug('id is "%s"' % p_id)
logger.debug('####################')
process_problem(p, p_id)
elif element.has_class('xmodule_display xmodule_VideoModule'):
logger.debug('####### Processing xmodule_VideoModule')
assert element.find_by_css("section[class^='video']"), "No video found in Video Module"
elif element.has_class('xmodule_display xmodule_HtmlModule'):
logger.debug('####### Processing xmodule_HtmlModule')
pass
elif element.has_class('xmodule_display xmodule_CustomTagModule'):
logger.debug('####### Processing xmodule_CustomTagModule')
pass
else:
assert False, "Class for element not recognized!!"
def process_problem(element, problem_id):
'''
Process problem attempts to
1) scan all the input fields and reset them
2) click the 'check' button and look for an incorrect response (p.status text should be 'incorrect')
3) click the 'show answer' button IF it exists and IF the answer is not already displayed
4) enter the correct answer in each input box
5) click the 'check' button and verify that answers are correct
Because of all the ajax calls happening, sometimes the test fails because objects disconnect from the DOM.
The basic functionality does exist, though, and I'm hoping that someone can take it over and make it super effective.
'''
prob_xmod = element.find_by_css("section.problem").first
input_fields = prob_xmod.find_by_css("section[id^='input']")
## clear out all input to ensure an incorrect result
for field in input_fields:
field.find_by_css("input").first.fill('')
## because of cookies or the application, only click the 'check' button if the status is not already 'incorrect'
# This would need to be reworked because multiple choice problems don't have this status
# if prob_xmod.find_by_css("p.status").first.text.strip().lower() != 'incorrect':
prob_xmod.find_by_css("section.action input.check").first.click()
## all elements become disconnected after the click
## grab element and prob_xmod because the dom has changed (some classes/elements became hidden and changed the hierarchy)
# Wait for the ajax reload
assert world.browser.is_element_present_by_css("section[id='%s']" % problem_id, wait_time=5)
element = world.browser.find_by_css("section[id='%s']" % problem_id).first
prob_xmod = element.find_by_css("section.problem").first
input_fields = prob_xmod.find_by_css("section[id^='input']")
for field in input_fields:
assert field.find_by_css("div.incorrect"), "The 'check' button did not work for %s" % (problem_id)
show_button = element.find_by_css("section.action input.show").first
## this logic is to ensure we do not accidentally hide the answers
if show_button.value.lower() == 'show answer':
show_button.click()
else:
pass
## grab element and prob_xmod because the dom has changed (some classes/elements became hidden and changed the hierarchy)
assert world.browser.is_element_present_by_css("section[id='%s']" % problem_id, wait_time=5)
element = world.browser.find_by_css("section[id='%s']" % problem_id).first
prob_xmod = element.find_by_css("section.problem").first
input_fields = prob_xmod.find_by_css("section[id^='input']")
## in each field, find the answer, and send it to the field.
## Note that this does not work if the answer type is a strange format, e.g. "either a or b"
for field in input_fields:
field.find_by_css("input").first.fill(field.find_by_css("p[id^='answer']").first.text)
prob_xmod.find_by_css("section.action input.check").first.click()
## assert that we entered the correct answers
## grab element and prob_xmod because the dom has changed (some classes/elements became hidden and changed the hierarchy)
assert world.browser.is_element_present_by_css("section[id='%s']" % problem_id, wait_time=5)
element = world.browser.find_by_css("section[id='%s']" % problem_id).first
prob_xmod = element.find_by_css("section.problem").first
input_fields = prob_xmod.find_by_css("section[id^='input']")
for field in input_fields:
## if you don't use 'starts with ^=' the test will fail because the actual class is 'correct ' (with a space)
assert field.find_by_css("div[class^='correct']"), "The check answer values were not correct for %s" % problem_id
......@@ -2,7 +2,7 @@ from lettuce import world, step
from re import sub
from nose.tools import assert_equals
from xmodule.modulestore.django import modulestore
from courses import *
from common import *
from logging import getLogger
logger = getLogger(__name__)
......
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