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
50d7e616
Commit
50d7e616
authored
Dec 03, 2012
by
Don Mitchell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move models from common to cms.
Add unit tests.
parent
8379e303
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
223 additions
and
8 deletions
+223
-8
cms/djangoapps/__init__.py
+0
-0
cms/djangoapps/contentstore/tests/test_course_settings.py
+194
-0
cms/djangoapps/contentstore/views.py
+1
-2
cms/djangoapps/models/__init__.py
+0
-0
cms/djangoapps/models/settings/course_details.py
+0
-2
cms/djangoapps/models/settings/course_faculty.py
+23
-0
common/djangoapps/util/converters.py
+5
-4
No files found.
cms/djangoapps/__init__.py
0 → 100644
View file @
50d7e616
cms/djangoapps/contentstore/tests/test_course_settings.py
0 → 100644
View file @
50d7e616
from
django.test.testcases
import
TestCase
import
datetime
import
time
from
django.contrib.auth.models
import
User
import
xmodule
from
django.test.client
import
Client
from
django.core.urlresolvers
import
reverse
from
xmodule.modulestore
import
Location
from
cms.djangoapps.models.settings.course_details
import
CourseDetails
,
\
CourseDetailsEncoder
import
json
from
common.djangoapps.util
import
converters
# YYYY-MM-DDThh:mm:ss.s+/-HH:MM
class
ConvertersTestCase
(
TestCase
):
def
struct_to_datetime
(
self
,
struct_time
):
return
datetime
.
datetime
(
struct_time
.
tm_year
,
struct_time
.
tm_mon
,
struct_time
.
tm_mday
,
struct_time
.
tm_hour
,
struct_time
.
tm_min
,
struct_time
.
tm_sec
)
def
compare_dates
(
self
,
date1
,
date2
,
expected_delta
):
dt1
=
self
.
struct_to_datetime
(
date1
)
dt2
=
self
.
struct_to_datetime
(
date2
)
self
.
assertEqual
(
dt1
-
dt2
,
expected_delta
,
str
(
date1
)
+
"-"
+
str
(
date2
)
+
"!="
+
str
(
expected_delta
))
def
test_iso_to_struct
(
self
):
self
.
compare_dates
(
converters
.
jsdate_to_time
(
"2013-01-01"
),
converters
.
jsdate_to_time
(
"2012-12-31"
),
datetime
.
timedelta
(
days
=
1
))
self
.
compare_dates
(
converters
.
jsdate_to_time
(
"2013-01-01T00"
),
converters
.
jsdate_to_time
(
"2012-12-31T23"
),
datetime
.
timedelta
(
hours
=
1
))
self
.
compare_dates
(
converters
.
jsdate_to_time
(
"2013-01-01T00:00"
),
converters
.
jsdate_to_time
(
"2012-12-31T23:59"
),
datetime
.
timedelta
(
minutes
=
1
))
self
.
compare_dates
(
converters
.
jsdate_to_time
(
"2013-01-01T00:00:00"
),
converters
.
jsdate_to_time
(
"2012-12-31T23:59:59"
),
datetime
.
timedelta
(
seconds
=
1
))
class
CourseDetailsTestCase
(
TestCase
):
def
setUp
(
self
):
uname
=
'testuser'
email
=
'test+courses@edx.org'
password
=
'foo'
# Create the use so we can log them in.
self
.
user
=
User
.
objects
.
create_user
(
uname
,
email
,
password
)
# Note that we do not actually need to do anything
# for registration if we directly mark them active.
self
.
user
.
is_active
=
True
# Staff has access to view all courses
self
.
user
.
is_staff
=
True
self
.
user
.
save
()
# Flush and initialize the module store
# It needs the templates because it creates new records
# by cloning from the template.
# Note that if your test module gets in some weird state
# (though it shouldn't), do this manually
# from the bash shell to drop it:
# $ mongo test_xmodule --eval "db.dropDatabase()"
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
xmodule
.
modulestore
.
django
.
modulestore
()
.
collection
.
drop
()
xmodule
.
templates
.
update_templates
()
self
.
client
=
Client
()
self
.
client
.
login
(
username
=
uname
,
password
=
password
)
self
.
course_data
=
{
'template'
:
'i4x://edx/templates/course/Empty'
,
'org'
:
'MITx'
,
'number'
:
'999'
,
'display_name'
:
'Robot Super Course'
,
}
self
.
course_location
=
Location
(
'i4x'
,
'MITx'
,
'999'
,
'course'
,
'Robot_Super_Course'
)
self
.
create_course
()
def
tearDown
(
self
):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
xmodule
.
modulestore
.
django
.
modulestore
()
.
collection
.
drop
()
def
create_course
(
self
):
"""Create new course"""
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
def
test_virgin_fetch
(
self
):
details
=
CourseDetails
.
fetch
(
self
.
course_location
)
self
.
assertEqual
(
details
.
course_location
,
self
.
course_location
,
"Location not copied into"
)
self
.
assertIsNone
(
details
.
end_date
,
"end date somehow initialized "
+
str
(
details
.
end_date
))
self
.
assertIsNone
(
details
.
enrollment_start
,
"enrollment_start date somehow initialized "
+
str
(
details
.
enrollment_start
))
self
.
assertIsNone
(
details
.
enrollment_end
,
"enrollment_end date somehow initialized "
+
str
(
details
.
enrollment_end
))
self
.
assertIsNone
(
details
.
syllabus
,
"syllabus somehow initialized"
+
str
(
details
.
syllabus
))
self
.
assertEqual
(
details
.
overview
,
""
,
"overview somehow initialized"
+
details
.
overview
)
self
.
assertIsNone
(
details
.
intro_video
,
"intro_video somehow initialized"
+
str
(
details
.
intro_video
))
self
.
assertIsNone
(
details
.
effort
,
"effort somehow initialized"
+
str
(
details
.
effort
))
def
test_encoder
(
self
):
details
=
CourseDetails
.
fetch
(
self
.
course_location
)
jsondetails
=
json
.
dumps
(
details
,
cls
=
CourseDetailsEncoder
)
jsondetails
=
json
.
loads
(
jsondetails
)
self
.
assertTupleEqual
(
Location
(
jsondetails
[
'course_location'
]),
self
.
course_location
,
"Location !="
)
# Note, start_date is being initialized someplace. I'm not sure why b/c the default will make no sense.
self
.
assertIsNone
(
jsondetails
[
'end_date'
],
"end date somehow initialized "
)
self
.
assertIsNone
(
jsondetails
[
'enrollment_start'
],
"enrollment_start date somehow initialized "
)
self
.
assertIsNone
(
jsondetails
[
'enrollment_end'
],
"enrollment_end date somehow initialized "
)
self
.
assertIsNone
(
jsondetails
[
'syllabus'
],
"syllabus somehow initialized"
)
self
.
assertEqual
(
jsondetails
[
'overview'
],
""
,
"overview somehow initialized"
)
self
.
assertIsNone
(
jsondetails
[
'intro_video'
],
"intro_video somehow initialized"
)
self
.
assertIsNone
(
jsondetails
[
'effort'
],
"effort somehow initialized"
)
def
test_update_and_fetch
(
self
):
## NOTE: I couldn't figure out how to validly test time setting w/ all the conversions
jsondetails
=
CourseDetails
.
fetch
(
self
.
course_location
)
jsondetails
.
syllabus
=
"<a href='foo'>bar</a>"
self
.
assertEqual
(
CourseDetails
.
update_from_json
(
jsondetails
.
__dict__
)
.
syllabus
,
jsondetails
.
syllabus
,
"After set syllabus"
)
jsondetails
.
overview
=
"Overview"
self
.
assertEqual
(
CourseDetails
.
update_from_json
(
jsondetails
.
__dict__
)
.
overview
,
jsondetails
.
overview
,
"After set overview"
)
jsondetails
.
intro_video
=
"intro_video"
self
.
assertEqual
(
CourseDetails
.
update_from_json
(
jsondetails
.
__dict__
)
.
intro_video
,
jsondetails
.
intro_video
,
"After set intro_video"
)
jsondetails
.
effort
=
"effort"
self
.
assertEqual
(
CourseDetails
.
update_from_json
(
jsondetails
.
__dict__
)
.
effort
,
jsondetails
.
effort
,
"After set effort"
)
class
CourseDetailsViewTest
(
TestCase
):
def
setUp
(
self
):
uname
=
'testuser'
email
=
'test+courses@edx.org'
password
=
'foo'
# Create the use so we can log them in.
self
.
user
=
User
.
objects
.
create_user
(
uname
,
email
,
password
)
# Note that we do not actually need to do anything
# for registration if we directly mark them active.
self
.
user
.
is_active
=
True
# Staff has access to view all courses
self
.
user
.
is_staff
=
True
self
.
user
.
save
()
# Flush and initialize the module store
# It needs the templates because it creates new records
# by cloning from the template.
# Note that if your test module gets in some weird state
# (though it shouldn't), do this manually
# from the bash shell to drop it:
# $ mongo test_xmodule --eval "db.dropDatabase()"
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
xmodule
.
modulestore
.
django
.
modulestore
()
.
collection
.
drop
()
xmodule
.
templates
.
update_templates
()
self
.
client
=
Client
()
self
.
client
.
login
(
username
=
uname
,
password
=
password
)
self
.
course_data
=
{
'template'
:
'i4x://edx/templates/course/Empty'
,
'org'
:
'MITx'
,
'number'
:
'999'
,
'display_name'
:
'Robot Super Course'
,
}
self
.
course_location
=
Location
(
'i4x'
,
'MITx'
,
'999'
,
'course'
,
'Robot_Super_Course'
)
self
.
create_course
()
def
tearDown
(
self
):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
xmodule
.
modulestore
.
django
.
modulestore
()
.
collection
.
drop
()
def
create_course
(
self
):
"""Create new course"""
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
def
alter_field
(
self
,
url
,
details
,
field
,
val
):
details
[
field
]
=
val
jsondetails
=
json
.
dumps
(
details
,
cls
=
CourseDetailsEncoder
)
resp
=
self
.
client
.
post
(
url
,
jsondetails
)
self
.
assertDictEqual
(
json
.
loads
(
resp
),
details
,
field
+
val
)
def
test_update_and_fetch
(
self
):
details
=
CourseDetails
.
fetch
(
self
.
course_location
)
details_loc
=
self
.
course_location
.
dict
()
.
copy
()
details_loc
[
'section'
]
=
'details'
resp
=
self
.
client
.
get
(
reverse
(
'contentstore.views.get_course_settings'
,
kwargs
=
self
.
course_location
.
dict
()))
self
.
assertContains
(
resp
,
'<li><a href="#" class="is-shown" data-section="details">Course Details</a></li>'
,
status_code
=
200
,
html
=
True
)
# resp s/b json from here on
url
=
reverse
(
'contentstore.views.course_settings_updates'
,
kwargs
=
details_loc
)
resp
=
self
.
client
.
get
(
url
)
jsondetails
=
json
.
dumps
(
details
,
cls
=
CourseDetailsEncoder
)
self
.
assertDictEqual
(
resp
,
jsondetails
,
"virgin get"
)
self
.
alter_field
(
url
,
details
,
'start_date'
,
time
.
time
()
*
1000
)
self
.
alter_field
(
url
,
details
,
'start_date'
,
time
.
time
()
*
1000
+
60
*
60
*
24
)
self
.
alter_field
(
url
,
details
,
'end_date'
,
time
.
time
()
*
1000
+
60
*
60
*
24
*
100
)
self
.
alter_field
(
url
,
details
,
'enrollment_start'
,
time
.
time
()
*
1000
)
self
.
alter_field
(
url
,
details
,
'enrollment_end'
,
time
.
time
()
*
1000
+
60
*
60
*
24
*
8
)
self
.
alter_field
(
url
,
details
,
'syllabus'
,
"<a href='foo'>bar</a>"
)
self
.
alter_field
(
url
,
details
,
'overview'
,
"Overview"
)
self
.
alter_field
(
url
,
details
,
'intro_video'
,
"intro_video"
)
self
.
alter_field
(
url
,
details
,
'effort'
,
"effort"
)
cms/djangoapps/contentstore/views.py
View file @
50d7e616
...
...
@@ -955,8 +955,7 @@ def get_course_settings(request, org, course, name):
return
render_to_response
(
'settings.html'
,
{
'active_tab'
:
'settings-tab'
,
'context_course'
:
course_module
,
'course_details'
:
json
.
dumps
(
course_details
,
cls
=
CourseDetailsEncoder
),
'video_editor_html'
:
preview_component
(
request
,
course_details
.
intro_video_loc
)
'course_details'
:
json
.
dumps
(
course_details
,
cls
=
CourseDetailsEncoder
)
})
@expect_json
...
...
cms/djangoapps/models/__init__.py
0 → 100644
View file @
50d7e616
cms/djangoapps/models/settings/course_details.py
View file @
50d7e616
...
...
@@ -17,7 +17,6 @@ class CourseDetails:
self
.
syllabus
=
None
# a pdf file asset
self
.
overview
=
""
# html to render as the overview
self
.
intro_video
=
None
# a video pointer
self
.
intro_video_loc
=
None
# a video pointer
self
.
effort
=
None
# int hours/week
@classmethod
...
...
@@ -58,7 +57,6 @@ class CourseDetails:
temploc
=
temploc
.
_replace
(
name
=
'video'
)
try
:
course
.
intro_video
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
definition
[
'data'
]
course
.
intro_video_loc
=
temploc
except
ItemNotFoundError
:
pass
...
...
cms/djangoapps/models/settings/course_faculty.py
0 → 100644
View file @
50d7e616
from
xmodule.modulestore
import
Location
class
CourseFaculty
:
def
__init__
(
self
,
location
):
if
not
isinstance
(
location
,
Location
):
location
=
Location
(
location
)
# course_location is used so that updates know where to get the relevant data
self
.
course_location
=
location
self
.
first_name
=
""
self
.
last_name
=
""
self
.
photo
=
None
self
.
bio
=
""
@classmethod
def
fetch
(
cls
,
course_location
):
"""
Fetch a list of faculty for the course
"""
if
not
isinstance
(
course_location
,
Location
):
course_location
=
Location
(
course_location
)
# Must always have at least one faculty member (possibly empty)
\ No newline at end of file
common/djangoapps/util/converters.py
View file @
50d7e616
...
...
@@ -10,12 +10,12 @@ def time_to_date(time_obj):
def
jsdate_to_time
(
field
):
"""
Convert a
true universal time (msec since epoch) from a string
to a time obj
Convert a
universal time (iso format) or msec since epoch
to a time obj
"""
if
field
is
None
:
return
field
elif
isinstance
(
field
,
unicode
):
# iso format but ignores time zone assuming it's Z
d
=
datetime
.
datetime
(
*
map
(
int
,
re
.
split
(
'[^
\
d]'
,
field
)[:
-
1
]))
elif
isinstance
(
field
,
unicode
)
or
isinstance
(
field
,
str
)
:
# iso format but ignores time zone assuming it's Z
d
=
datetime
.
datetime
(
*
map
(
int
,
re
.
split
(
'[^
\
d]'
,
field
)[:
6
]))
# stop after seconds. Debatable
return
d
.
utctimetuple
()
elif
isinstance
(
field
,
int
):
elif
isinstance
(
field
,
int
)
or
isinstance
(
field
,
float
)
:
return
time
.
gmtime
(
field
/
1000
)
\ No newline at end of file
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