Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
5e69050a
Commit
5e69050a
authored
Mar 22, 2013
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Elminated unused functions from courseware/features/courses.py
and moved the rest to common.py
parent
c12e1fb1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
88 additions
and
235 deletions
+88
-235
lms/djangoapps/courseware/features/common.py
+87
-0
lms/djangoapps/courseware/features/courses.py
+0
-234
lms/djangoapps/courseware/features/smart-accordion.py
+1
-1
No files found.
lms/djangoapps/courseware/features/common.py
View file @
5e69050a
...
...
@@ -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
lms/djangoapps/courseware/features/courses.py
deleted
100644 → 0
View file @
c12e1fb1
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
lms/djangoapps/courseware/features/smart-accordion.py
View file @
5e69050a
...
...
@@ -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
co
urses
import
*
from
co
mmon
import
*
from
logging
import
getLogger
logger
=
getLogger
(
__name__
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment