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
a79a2907
Commit
a79a2907
authored
Mar 27, 2013
by
Victor Shnayder
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1755 from MITx/fix/brian/fix500v1
Fix/brian/fix500v1
parents
6d63d13f
c639799a
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
334 additions
and
295 deletions
+334
-295
lms/djangoapps/course_wiki/tests/tests.py
+2
-9
lms/djangoapps/courseware/tests/test_module_render.py
+36
-37
lms/djangoapps/courseware/tests/tests.py
+112
-104
lms/djangoapps/django_comment_client/forum/views.py
+17
-27
lms/djangoapps/django_comment_client/tests.py
+5
-66
lms/djangoapps/instructor/tests.py
+7
-19
lms/djangoapps/licenses/tests.py
+127
-9
lms/djangoapps/licenses/views.py
+13
-9
lms/djangoapps/open_ended_grading/tests.py
+15
-15
No files found.
lms/djangoapps/course_wiki/tests/tests.py
View file @
a79a2907
...
...
@@ -3,13 +3,11 @@ from django.test.utils import override_settings
import
xmodule.modulestore.django
from
courseware.tests.tests
import
PageLoader
,
TEST_DATA_XML_MODULESTORE
from
courseware.tests.tests
import
LoginEnrollmentTestCase
,
TEST_DATA_XML_MODULESTORE
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.xml_importer
import
import_from_xml
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
WikiRedirectTestCase
(
PageLoader
):
class
WikiRedirectTestCase
(
LoginEnrollmentTestCase
):
def
setUp
(
self
):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
courses
=
modulestore
()
.
get_courses
()
...
...
@@ -30,8 +28,6 @@ class WikiRedirectTestCase(PageLoader):
self
.
activate_user
(
self
.
student
)
self
.
activate_user
(
self
.
instructor
)
def
test_wiki_redirect
(
self
):
"""
Test that requesting wiki URLs redirect properly to or out of classes.
...
...
@@ -69,7 +65,6 @@ class WikiRedirectTestCase(PageLoader):
self
.
assertEqual
(
resp
.
status_code
,
302
)
self
.
assertEqual
(
resp
[
'Location'
],
'http://testserver'
+
destination
)
def
create_course_page
(
self
,
course
):
"""
Test that loading the course wiki page creates the wiki page.
...
...
@@ -98,7 +93,6 @@ class WikiRedirectTestCase(PageLoader):
self
.
assertTrue
(
"course info"
in
resp
.
content
.
lower
())
self
.
assertTrue
(
"courseware"
in
resp
.
content
.
lower
())
def
test_course_navigator
(
self
):
""""
Test that going from a course page to a wiki page contains the course navigator.
...
...
@@ -108,7 +102,6 @@ class WikiRedirectTestCase(PageLoader):
self
.
enroll
(
self
.
toy
)
self
.
create_course_page
(
self
.
toy
)
course_wiki_page
=
reverse
(
'wiki:get'
,
kwargs
=
{
'path'
:
self
.
toy
.
wiki_slug
+
'/'
})
referer
=
reverse
(
"courseware"
,
kwargs
=
{
'course_id'
:
self
.
toy
.
id
})
...
...
lms/djangoapps/courseware/tests/test_module_render.py
View file @
a79a2907
...
...
@@ -2,16 +2,16 @@ from mock import MagicMock
import
json
from
django.http
import
Http404
,
HttpResponse
from
django.core.urlresolvers
import
reverse
from
django.conf
import
settings
from
django.test
import
TestCase
from
django.test.client
import
RequestFactory
from
django.core.urlresolvers
import
reverse
from
django.test.utils
import
override_settings
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
import
courseware.module_render
as
render
from
xmodule.modulestore.django
import
modulestore
from
courseware.tests.tests
import
PageLoader
import
courseware.module_render
as
render
from
courseware.tests.tests
import
LoginEnrollmentTestCase
from
courseware.model_data
import
ModelDataCache
from
.factories
import
UserFactory
...
...
@@ -38,7 +38,7 @@ TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR)
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
ModuleRenderTestCase
(
PageLoader
):
class
ModuleRenderTestCase
(
LoginEnrollmentTestCase
):
def
setUp
(
self
):
self
.
location
=
[
'i4x'
,
'edX'
,
'toy'
,
'chapter'
,
'Overview'
]
self
.
course_id
=
'edX/toy/2012_Fall'
...
...
@@ -54,10 +54,9 @@ class ModuleRenderTestCase(PageLoader):
mock_request
=
MagicMock
()
mock_request
.
FILES
.
keys
.
return_value
=
[
'file_id'
]
mock_request
.
FILES
.
getlist
.
return_value
=
[
'file'
]
*
(
settings
.
MAX_FILEUPLOADS_PER_INPUT
+
1
)
self
.
assertEquals
(
render
.
modx_dispatch
(
mock_request
,
'dummy'
,
self
.
location
,
'dummy'
)
.
content
,
json
.
dumps
({
'success'
:
'Submission aborted! Maximum
%
d files may be submitted at once'
%
settings
.
MAX_FILEUPLOADS_PER_INPUT
}))
self
.
assertEquals
(
render
.
modx_dispatch
(
mock_request
,
'dummy'
,
self
.
location
,
'dummy'
)
.
content
,
json
.
dumps
({
'success'
:
'Submission aborted! Maximum
%
d files may be submitted at once'
%
settings
.
MAX_FILEUPLOADS_PER_INPUT
}))
mock_request_2
=
MagicMock
()
mock_request_2
.
FILES
.
keys
.
return_value
=
[
'file_id'
]
inputfile
=
Stub
()
...
...
@@ -68,7 +67,7 @@ class ModuleRenderTestCase(PageLoader):
self
.
assertEquals
(
render
.
modx_dispatch
(
mock_request_2
,
'dummy'
,
self
.
location
,
'dummy'
)
.
content
,
json
.
dumps
({
'success'
:
'Submission aborted! Your file "
%
s" is too large (max size:
%
d MB)'
%
(
inputfile
.
name
,
settings
.
STUDENT_FILEUPLOAD_MAX_SIZE
/
(
1000
**
2
))}))
(
inputfile
.
name
,
settings
.
STUDENT_FILEUPLOAD_MAX_SIZE
/
(
1000
**
2
))}))
mock_request_3
=
MagicMock
()
mock_request_3
.
POST
.
copy
.
return_value
=
{}
mock_request_3
.
FILES
=
False
...
...
@@ -79,10 +78,10 @@ class ModuleRenderTestCase(PageLoader):
self
.
assertRaises
(
ItemNotFoundError
,
render
.
modx_dispatch
,
mock_request_3
,
'dummy'
,
self
.
location
,
'toy'
)
self
.
assertRaises
(
Http404
,
render
.
modx_dispatch
,
mock_request_3
,
'dummy'
,
self
.
location
,
self
.
course_id
)
self
.
location
,
self
.
course_id
)
mock_request_3
.
POST
.
copy
.
return_value
=
{
'position'
:
1
}
self
.
assertIsInstance
(
render
.
modx_dispatch
(
mock_request_3
,
'goto_position'
,
self
.
location
,
self
.
course_id
),
HttpResponse
)
self
.
location
,
self
.
course_id
),
HttpResponse
)
def
test_get_score_bucket
(
self
):
self
.
assertEquals
(
render
.
get_score_bucket
(
0
,
10
),
'incorrect'
)
...
...
@@ -124,19 +123,19 @@ class TestTOC(TestCase):
self
.
toy_course
.
id
,
self
.
portal_user
,
self
.
toy_course
,
depth
=
2
)
expected
=
([{
'active'
:
True
,
'sections'
:
[{
'url_name'
:
'Toy_Videos'
,
'display_name'
:
u'Toy Videos'
,
'graded'
:
True
,
'format'
:
u'Lecture Sequence'
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'Welcome'
,
'display_name'
:
u'Welcome'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'video_123456789012'
,
'display_name'
:
'video 123456789012'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'video_4f66f493ac8f'
,
'display_name'
:
'video 4f66f493ac8f'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'Overview'
,
'display_name'
:
u'Overview'
},
{
'active'
:
False
,
'sections'
:
[{
'url_name'
:
'toyvideo'
,
'display_name'
:
'toyvideo'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'secret:magic'
,
'display_name'
:
'secret:magic'
}])
[{
'url_name'
:
'Toy_Videos'
,
'display_name'
:
u'Toy Videos'
,
'graded'
:
True
,
'format'
:
u'Lecture Sequence'
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'Welcome'
,
'display_name'
:
u'Welcome'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'video_123456789012'
,
'display_name'
:
'video 123456789012'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'video_4f66f493ac8f'
,
'display_name'
:
'video 4f66f493ac8f'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'Overview'
,
'display_name'
:
u'Overview'
},
{
'active'
:
False
,
'sections'
:
[{
'url_name'
:
'toyvideo'
,
'display_name'
:
'toyvideo'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'secret:magic'
,
'display_name'
:
'secret:magic'
}])
actual
=
render
.
toc_for_course
(
self
.
portal_user
,
request
,
self
.
toy_course
,
chapter
,
None
,
model_data_cache
)
self
.
assertEqual
(
expected
,
actual
)
...
...
@@ -151,19 +150,19 @@ class TestTOC(TestCase):
self
.
toy_course
.
id
,
self
.
portal_user
,
self
.
toy_course
,
depth
=
2
)
expected
=
([{
'active'
:
True
,
'sections'
:
[{
'url_name'
:
'Toy_Videos'
,
'display_name'
:
u'Toy Videos'
,
'graded'
:
True
,
'format'
:
u'Lecture Sequence'
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'Welcome'
,
'display_name'
:
u'Welcome'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
True
},
{
'url_name'
:
'video_123456789012'
,
'display_name'
:
'video 123456789012'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'video_4f66f493ac8f'
,
'display_name'
:
'video 4f66f493ac8f'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'Overview'
,
'display_name'
:
u'Overview'
},
{
'active'
:
False
,
'sections'
:
[{
'url_name'
:
'toyvideo'
,
'display_name'
:
'toyvideo'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'secret:magic'
,
'display_name'
:
'secret:magic'
}])
[{
'url_name'
:
'Toy_Videos'
,
'display_name'
:
u'Toy Videos'
,
'graded'
:
True
,
'format'
:
u'Lecture Sequence'
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'Welcome'
,
'display_name'
:
u'Welcome'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
True
},
{
'url_name'
:
'video_123456789012'
,
'display_name'
:
'video 123456789012'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
},
{
'url_name'
:
'video_4f66f493ac8f'
,
'display_name'
:
'video 4f66f493ac8f'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'Overview'
,
'display_name'
:
u'Overview'
},
{
'active'
:
False
,
'sections'
:
[{
'url_name'
:
'toyvideo'
,
'display_name'
:
'toyvideo'
,
'graded'
:
True
,
'format'
:
''
,
'due'
:
''
,
'active'
:
False
}],
'url_name'
:
'secret:magic'
,
'display_name'
:
'secret:magic'
}])
actual
=
render
.
toc_for_course
(
self
.
portal_user
,
request
,
self
.
toy_course
,
chapter
,
section
,
model_data_cache
)
self
.
assertEqual
(
expected
,
actual
)
lms/djangoapps/courseware/tests/tests.py
View file @
a79a2907
import
logging
log
=
logging
.
getLogger
(
"mitx."
+
__name__
)
import
json
import
time
from
urlparse
import
urlsplit
,
urlunsplit
from
django.contrib.auth.models
import
User
,
Group
...
...
@@ -29,29 +26,30 @@ from xmodule.modulestore.django import modulestore
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.modulestore.xml
import
XMLModuleStore
from
xmodule.timeparse
import
stringify_time
log
=
logging
.
getLogger
(
"mitx."
+
__name__
)
def
parse_json
(
response
):
"""Parse response, which is assumed to be json"""
return
json
.
loads
(
response
.
content
)
def
user
(
email
):
def
get_
user
(
email
):
'''look up a user by email'''
return
User
.
objects
.
get
(
email
=
email
)
def
registration
(
email
):
def
get_
registration
(
email
):
'''look up registration object by email'''
return
Registration
.
objects
.
get
(
user__email
=
email
)
# A bit of a hack--want mongo modulestore for these tests, until
# jump_to works with the xmlmodulestore or we have an even better solution
# NOTE: this means this test requires mongo to be running.
def
mongo_store_config
(
data_dir
):
'''
Defines default module store using MongoModuleStore
Use of this config requires mongo to be running
'''
return
{
'default'
:
{
'ENGINE'
:
'xmodule.modulestore.mongo.MongoModuleStore'
,
...
...
@@ -68,6 +66,7 @@ def mongo_store_config(data_dir):
def
draft_mongo_store_config
(
data_dir
):
'''Defines default module store using DraftMongoModuleStore'''
return
{
'default'
:
{
'ENGINE'
:
'xmodule.modulestore.mongo.DraftMongoModuleStore'
,
...
...
@@ -84,6 +83,7 @@ def draft_mongo_store_config(data_dir):
def
xml_store_config
(
data_dir
):
'''Defines default module store using XMLModuleStore'''
return
{
'default'
:
{
'ENGINE'
:
'xmodule.modulestore.xml.XMLModuleStore'
,
...
...
@@ -100,8 +100,8 @@ TEST_DATA_MONGO_MODULESTORE = mongo_store_config(TEST_DATA_DIR)
TEST_DATA_DRAFT_MONGO_MODULESTORE
=
draft_mongo_store_config
(
TEST_DATA_DIR
)
class
ActivateLogin
TestCase
(
TestCase
):
'''
Check that we can activate and log in
'''
class
LoginEnrollment
TestCase
(
TestCase
):
'''
Base TestCase providing support for user creation, activation, login, and course enrollment
'''
def
assertRedirectsNoFollow
(
self
,
response
,
expected_url
):
"""
...
...
@@ -117,32 +117,33 @@ class ActivateLoginTestCase(TestCase):
e_scheme
,
e_netloc
,
e_path
,
e_query
,
e_fragment
=
urlsplit
(
expected_url
)
if
not
(
e_scheme
or
e_netloc
):
expected_url
=
urlunsplit
((
'http'
,
'testserver'
,
e_path
,
e_query
,
e_fragment
))
expected_url
=
urlunsplit
((
'http'
,
'testserver'
,
e_path
,
e_query
,
e_fragment
))
self
.
assertEqual
(
url
,
expected_url
,
"Response redirected to '{0}', expected '{1}'"
.
format
(
url
,
expected_url
))
def
setUp
(
self
):
email
=
'view@test.com'
password
=
'foo'
self
.
create_account
(
'viewtest'
,
email
,
password
)
self
.
activate_user
(
email
)
self
.
login
(
email
,
password
)
def
setup_viewtest_user
(
self
):
'''create a user account, activate, and log in'''
self
.
viewtest_email
=
'view@test.com'
self
.
viewtest_password
=
'foo'
self
.
viewtest_username
=
'viewtest'
self
.
create_account
(
self
.
viewtest_username
,
self
.
viewtest_email
,
self
.
viewtest_password
)
self
.
activate_user
(
self
.
viewtest_email
)
self
.
login
(
self
.
viewtest_email
,
self
.
viewtest_password
)
# ============ User creation and login ==============
def
_login
(
self
,
email
,
p
w
):
def
_login
(
self
,
email
,
p
assword
):
'''Login. View should always return 200. The success/fail is in the
returned json'''
resp
=
self
.
client
.
post
(
reverse
(
'login'
),
{
'email'
:
email
,
'password'
:
p
w
})
{
'email'
:
email
,
'password'
:
p
assword
})
self
.
assertEqual
(
resp
.
status_code
,
200
)
return
resp
def
login
(
self
,
email
,
p
w
):
def
login
(
self
,
email
,
p
assword
):
'''Login, check that it worked.'''
resp
=
self
.
_login
(
email
,
p
w
)
resp
=
self
.
_login
(
email
,
p
assword
)
data
=
parse_json
(
resp
)
self
.
assertTrue
(
data
[
'success'
])
return
resp
...
...
@@ -154,34 +155,34 @@ class ActivateLoginTestCase(TestCase):
self
.
assertEqual
(
resp
.
status_code
,
302
)
return
resp
def
_create_account
(
self
,
username
,
email
,
p
w
):
def
_create_account
(
self
,
username
,
email
,
p
assword
):
'''Try to create an account. No error checking'''
resp
=
self
.
client
.
post
(
'/create_account'
,
{
'username'
:
username
,
'email'
:
email
,
'password'
:
p
w
,
'password'
:
p
assword
,
'name'
:
'Fred Weasley'
,
'terms_of_service'
:
'true'
,
'honor_code'
:
'true'
,
})
return
resp
def
create_account
(
self
,
username
,
email
,
p
w
):
def
create_account
(
self
,
username
,
email
,
p
assword
):
'''Create the account and check that it worked'''
resp
=
self
.
_create_account
(
username
,
email
,
p
w
)
resp
=
self
.
_create_account
(
username
,
email
,
p
assword
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
self
.
assertEqual
(
data
[
'success'
],
True
)
# Check both that the user is created, and inactive
self
.
assertFalse
(
user
(
email
)
.
is_active
)
self
.
assertFalse
(
get_
user
(
email
)
.
is_active
)
return
resp
def
_activate_user
(
self
,
email
):
'''Look up the activation key for the user, then hit the activate view.
No error checking'''
activation_key
=
registration
(
email
)
.
activation_key
activation_key
=
get_
registration
(
email
)
.
activation_key
# and now we try to activate
resp
=
self
.
client
.
get
(
reverse
(
'activate'
,
kwargs
=
{
'key'
:
activation_key
}))
...
...
@@ -191,19 +192,7 @@ class ActivateLoginTestCase(TestCase):
resp
=
self
.
_activate_user
(
email
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
# Now make sure that the user is now actually activated
self
.
assertTrue
(
user
(
email
)
.
is_active
)
def
test_activate_login
(
self
):
'''The setup function does all the work'''
pass
def
test_logout
(
self
):
'''Setup function does login'''
self
.
logout
()
class
PageLoader
(
ActivateLoginTestCase
):
''' Base class that adds a function to load all pages in a modulestore '''
self
.
assertTrue
(
get_user
(
email
)
.
is_active
)
def
_enroll
(
self
,
course
):
"""Post to the enrollment view, and return the parsed json response"""
...
...
@@ -240,8 +229,7 @@ class PageLoader(ActivateLoginTestCase):
"""
resp
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
resp
.
status_code
,
code
,
"got code {0} for url '{1}'. Expected code {2}"
.
format
(
resp
.
status_code
,
url
,
code
))
"got code {0} for url '{1}'. Expected code {2}"
.
format
(
resp
.
status_code
,
url
,
code
))
return
resp
def
check_for_post_code
(
self
,
code
,
url
,
data
=
{}):
...
...
@@ -251,10 +239,27 @@ class PageLoader(ActivateLoginTestCase):
"""
resp
=
self
.
client
.
post
(
url
,
data
)
self
.
assertEqual
(
resp
.
status_code
,
code
,
"got code {0} for url '{1}'. Expected code {2}"
.
format
(
resp
.
status_code
,
url
,
code
))
"got code {0} for url '{1}'. Expected code {2}"
.
format
(
resp
.
status_code
,
url
,
code
))
return
resp
class
ActivateLoginTest
(
LoginEnrollmentTestCase
):
'''Test logging in and logging out'''
def
setUp
(
self
):
self
.
setup_viewtest_user
()
def
test_activate_login
(
self
):
'''Test login -- the setup function does all the work'''
pass
def
test_logout
(
self
):
'''Test logout -- setup function does login'''
self
.
logout
()
class
PageLoaderTestCase
(
LoginEnrollmentTestCase
):
''' Base class that adds a function to load all pages in a modulestore '''
def
check_pages_load
(
self
,
module_store
):
"""Make all locations in course load"""
# enroll in the course before trying to access pages
...
...
@@ -264,14 +269,14 @@ class PageLoader(ActivateLoginTestCase):
self
.
enroll
(
course
)
course_id
=
course
.
id
n
=
0
n
um
=
0
num_bad
=
0
all_ok
=
True
for
descriptor
in
module_store
.
get_items
(
Location
(
None
,
None
,
None
,
None
,
None
)):
n
+=
1
n
um
+=
1
print
"Checking "
,
descriptor
.
location
.
url
()
# We have ancillary course information now as modules and we can't simply use 'jump_to' to view them
...
...
@@ -332,45 +337,43 @@ class PageLoader(ActivateLoginTestCase):
print
msg
self
.
assertTrue
(
all_ok
)
# fail fast
print
"{0}/{1} good"
.
format
(
n
-
num_bad
,
n
)
log
.
info
(
"{0}/{1} good"
.
format
(
n
-
num_bad
,
n
))
print
"{0}/{1} good"
.
format
(
n
um
-
num_bad
,
num
)
log
.
info
(
"{0}/{1} good"
.
format
(
n
um
-
num_bad
,
num
))
self
.
assertTrue
(
all_ok
)
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestCoursesLoadTestCase_XmlModulestore
(
PageLoader
):
'''Check that all pages in test courses load properly'''
class
TestCoursesLoadTestCase_XmlModulestore
(
PageLoader
TestCase
):
'''Check that all pages in test courses load properly
from XML
'''
def
setUp
(
self
):
ActivateLoginTestCase
.
setUp
(
self
)
self
.
setup_viewtest_user
(
)
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
def
test_toy_course_loads
(
self
):
module_store
=
XMLModuleStore
(
TEST_DATA_DIR
,
default_class
=
'xmodule.hidden_module.HiddenDescriptor'
,
course_dirs
=
[
'toy'
],
load_error_modules
=
True
,
module_store
=
XMLModuleStore
(
TEST_DATA_DIR
,
default_class
=
'xmodule.hidden_module.HiddenDescriptor'
,
course_dirs
=
[
'toy'
],
load_error_modules
=
True
,
)
self
.
check_pages_load
(
module_store
)
def
test_full_course_loads
(
self
):
module_store
=
XMLModuleStore
(
TEST_DATA_DIR
,
default_class
=
'xmodule.hidden_module.HiddenDescriptor'
,
course_dirs
=
[
'full'
],
load_error_modules
=
True
,
module_store
=
XMLModuleStore
(
TEST_DATA_DIR
,
default_class
=
'xmodule.hidden_module.HiddenDescriptor'
,
course_dirs
=
[
'full'
],
load_error_modules
=
True
,
)
self
.
check_pages_load
(
module_store
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
class
TestCoursesLoadTestCase_MongoModulestore
(
PageLoader
):
'''Check that all pages in test courses load properly'''
class
TestCoursesLoadTestCase_MongoModulestore
(
PageLoader
TestCase
):
'''Check that all pages in test courses load properly
from Mongo
'''
def
setUp
(
self
):
ActivateLoginTestCase
.
setUp
(
self
)
self
.
setup_viewtest_user
(
)
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
modulestore
()
.
collection
.
drop
()
...
...
@@ -386,7 +389,7 @@ class TestCoursesLoadTestCase_MongoModulestore(PageLoader):
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestNavigation
(
PageLoader
):
class
TestNavigation
(
LoginEnrollmentTestCase
):
"""Check that navigation state is saved properly"""
def
setUp
(
self
):
...
...
@@ -447,7 +450,7 @@ class TestDraftModuleStore(TestCase):
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestViewAuth
(
PageLoader
):
class
TestViewAuth
(
LoginEnrollmentTestCase
):
"""Check that view authentication works properly"""
# NOTE: setUpClass() runs before override_settings takes effect, so
...
...
@@ -492,7 +495,7 @@ class TestViewAuth(PageLoader):
'gradebook'
,
'grade_summary'
,)]
urls
.
append
(
reverse
(
'student_progress'
,
kwargs
=
{
'course_id'
:
course
.
id
,
'student_id'
:
user
(
self
.
student
)
.
id
}))
'student_id'
:
get_
user
(
self
.
student
)
.
id
}))
return
urls
# shouldn't be able to get to the instructor pages
...
...
@@ -502,8 +505,8 @@ class TestViewAuth(PageLoader):
# Make the instructor staff in the toy course
group_name
=
_course_staff_group_name
(
self
.
toy
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
user
(
self
.
instructor
))
g
roup
=
Group
.
objects
.
create
(
name
=
group_name
)
g
roup
.
user_set
.
add
(
get_
user
(
self
.
instructor
))
self
.
logout
()
self
.
login
(
self
.
instructor
,
self
.
password
)
...
...
@@ -518,9 +521,9 @@ class TestViewAuth(PageLoader):
self
.
check_for_get_code
(
404
,
url
)
# now also make the instructor staff
u
=
user
(
self
.
instructor
)
u
.
is_staff
=
True
u
.
save
()
instructor
=
get_
user
(
self
.
instructor
)
instructor
.
is_staff
=
True
instructor
.
save
()
# and now should be able to load both
for
url
in
instructor_urls
(
self
.
toy
)
+
instructor_urls
(
self
.
full
):
...
...
@@ -627,7 +630,7 @@ class TestViewAuth(PageLoader):
# to make access checking smarter and understand both the effective
# user (the student), and the requesting user (the prof)
url
=
reverse
(
'student_progress'
,
kwargs
=
{
'course_id'
:
course
.
id
,
'student_id'
:
user
(
self
.
student
)
.
id
})
'student_id'
:
get_
user
(
self
.
student
)
.
id
})
print
'checking for 404 on view-as-student: {0}'
.
format
(
url
)
self
.
check_for_get_code
(
404
,
url
)
...
...
@@ -648,8 +651,8 @@ class TestViewAuth(PageLoader):
print
'=== Testing course instructor access....'
# Make the instructor staff in the toy course
group_name
=
_course_staff_group_name
(
self
.
toy
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
user
(
self
.
instructor
))
g
roup
=
Group
.
objects
.
create
(
name
=
group_name
)
g
roup
.
user_set
.
add
(
get_
user
(
self
.
instructor
))
self
.
logout
()
self
.
login
(
self
.
instructor
,
self
.
password
)
...
...
@@ -663,9 +666,9 @@ class TestViewAuth(PageLoader):
print
'=== Testing staff access....'
# now also make the instructor staff
u
=
user
(
self
.
instructor
)
u
.
is_staff
=
True
u
.
save
()
instructor
=
get_
user
(
self
.
instructor
)
instructor
.
is_staff
=
True
instructor
.
save
()
# and now should be able to load both
check_staff
(
self
.
toy
)
...
...
@@ -698,8 +701,8 @@ class TestViewAuth(PageLoader):
print
'=== Testing course instructor access....'
# Make the instructor staff in the toy course
group_name
=
_course_staff_group_name
(
self
.
toy
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
user
(
self
.
instructor
))
g
roup
=
Group
.
objects
.
create
(
name
=
group_name
)
g
roup
.
user_set
.
add
(
get_
user
(
self
.
instructor
))
print
"logout/login"
self
.
logout
()
...
...
@@ -709,10 +712,10 @@ class TestViewAuth(PageLoader):
print
'=== Testing staff access....'
# now make the instructor global staff, but not in the instructor group
g
.
user_set
.
remove
(
user
(
self
.
instructor
))
u
=
user
(
self
.
instructor
)
u
.
is_staff
=
True
u
.
save
()
g
roup
.
user_set
.
remove
(
get_
user
(
self
.
instructor
))
instructor
=
get_
user
(
self
.
instructor
)
instructor
.
is_staff
=
True
instructor
.
save
()
# unenroll and try again
self
.
unenroll
(
self
.
toy
)
...
...
@@ -726,8 +729,8 @@ class TestViewAuth(PageLoader):
# Make courses start in the future
tomorrow
=
time
.
time
()
+
24
*
3600
nextday
=
tomorrow
+
24
*
3600
yesterday
=
time
.
time
()
-
24
*
3600
#
nextday = tomorrow + 24 * 3600
#
yesterday = time.time() - 24 * 3600
# toy course's hasn't started
self
.
toy
.
lms
.
start
=
time
.
gmtime
(
tomorrow
)
...
...
@@ -737,20 +740,20 @@ class TestViewAuth(PageLoader):
self
.
toy
.
lms
.
days_early_for_beta
=
2
# student user shouldn't see it
student_user
=
user
(
self
.
student
)
student_user
=
get_
user
(
self
.
student
)
self
.
assertFalse
(
has_access
(
student_user
,
self
.
toy
,
'load'
))
# now add the student to the beta test group
group_name
=
course_beta_test_group_name
(
self
.
toy
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
student_user
)
g
roup
=
Group
.
objects
.
create
(
name
=
group_name
)
g
roup
.
user_set
.
add
(
student_user
)
# now the student should see it
self
.
assertTrue
(
has_access
(
student_user
,
self
.
toy
,
'load'
))
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestCourseGrader
(
PageLoader
):
class
TestCourseGrader
(
LoginEnrollmentTestCase
):
"""Check that a course gets graded properly"""
# NOTE: setUpClass() runs before override_settings takes effect, so
...
...
@@ -773,35 +776,39 @@ class TestCourseGrader(PageLoader):
self
.
activate_user
(
self
.
student
)
self
.
enroll
(
self
.
graded_course
)
self
.
student_user
=
user
(
self
.
student
)
self
.
student_user
=
get_
user
(
self
.
student
)
self
.
factory
=
RequestFactory
()
def
get_grade_summary
(
self
):
'''calls grades.grade for current user and course'''
model_data_cache
=
ModelDataCache
.
cache_for_descriptor_descendents
(
self
.
graded_course
.
id
,
self
.
student_user
,
self
.
graded_course
)
fake_request
=
self
.
factory
.
get
(
reverse
(
'progress'
,
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
}))
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
}))
return
grades
.
grade
(
self
.
student_user
,
fake_request
,
self
.
graded_course
,
model_data_cache
)
def
get_homework_scores
(
self
):
'''get scores for homeworks'''
return
self
.
get_grade_summary
()[
'totaled_scores'
][
'Homework'
]
def
get_progress_summary
(
self
):
'''return progress summary structure for current user and course'''
model_data_cache
=
ModelDataCache
.
cache_for_descriptor_descendents
(
self
.
graded_course
.
id
,
self
.
student_user
,
self
.
graded_course
)
fake_request
=
self
.
factory
.
get
(
reverse
(
'progress'
,
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
}))
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
}))
progress_summary
=
grades
.
progress_summary
(
self
.
student_user
,
fake_request
,
self
.
graded_course
,
model_data_cache
)
return
progress_summary
def
check_grade_percent
(
self
,
percent
):
'''assert that percent grade is as expected'''
grade_summary
=
self
.
get_grade_summary
()
self
.
assertEqual
(
grade_summary
[
'percent'
],
percent
)
...
...
@@ -816,10 +823,9 @@ class TestCourseGrader(PageLoader):
problem_location
=
"i4x://edX/graded/problem/{0}"
.
format
(
problem_url_name
)
modx_url
=
reverse
(
'modx_dispatch'
,
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
,
'location'
:
problem_location
,
'dispatch'
:
'problem_check'
,
})
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
,
'location'
:
problem_location
,
'dispatch'
:
'problem_check'
,
})
resp
=
self
.
client
.
post
(
modx_url
,
{
'input_i4x-edX-graded-problem-{0}_2_1'
.
format
(
problem_url_name
):
responses
[
0
],
...
...
@@ -831,16 +837,17 @@ class TestCourseGrader(PageLoader):
return
resp
def
problem_location
(
self
,
problem_url_name
):
'''Get location string for problem, assuming hardcoded course_id'''
return
"i4x://edX/graded/problem/{0}"
.
format
(
problem_url_name
)
def
reset_question_answer
(
self
,
problem_url_name
):
'''resets specified problem for current user'''
problem_location
=
self
.
problem_location
(
problem_url_name
)
modx_url
=
reverse
(
'modx_dispatch'
,
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
,
'location'
:
problem_location
,
'dispatch'
:
'problem_reset'
,
})
kwargs
=
{
'course_id'
:
self
.
graded_course
.
id
,
'location'
:
problem_location
,
'dispatch'
:
'problem_reset'
,
})
resp
=
self
.
client
.
post
(
modx_url
)
return
resp
...
...
@@ -855,6 +862,7 @@ class TestCourseGrader(PageLoader):
return
[
s
.
earned
for
s
in
self
.
get_homework_scores
()]
def
score_for_hw
(
hw_url_name
):
"""returns list of scores for a given url"""
hw_section
=
[
section
for
section
in
self
.
get_progress_summary
()[
0
][
'sections'
]
if
section
.
get
(
'url_name'
)
==
hw_url_name
][
0
]
...
...
lms/djangoapps/django_comment_client/forum/views.py
View file @
a79a2907
import
json
import
logging
import
xml.sax.saxutils
as
saxutils
from
django.contrib.auth.decorators
import
login_required
from
django.views.decorators.http
import
require_POST
from
django.http
import
HttpResponse
,
Http404
from
django.utils
import
simplejson
from
django.http
import
Http404
from
django.core.context_processors
import
csrf
from
django.core.urlresolvers
import
reverse
from
django.contrib.auth.models
import
User
from
mitxmako.shortcuts
import
render_to_response
,
render_to_string
from
courseware.courses
import
get_course_with_access
from
course_groups.cohorts
import
is_course_cohorted
,
get_cohort_id
,
is_commentable_cohorted
,
get_cohorted_commentables
,
get_cohort
,
get_course_cohorts
,
get_cohort_by_id
from
course_groups.cohorts
import
(
is_course_cohorted
,
get_cohort_id
,
is_commentable_cohorted
,
get_cohorted_commentables
,
get_course_cohorts
,
get_cohort_by_id
)
from
courseware.access
import
has_access
from
urllib
import
urlencode
from
operator
import
methodcaller
from
django_comment_client.permissions
import
check_permissions_by_view
,
cached_has_permission
from
django_comment_client.utils
import
(
merge_dict
,
extract
,
strip_none
,
strip_blank
,
get_courseware_context
)
from
django_comment_client.permissions
import
cached_has_permission
from
django_comment_client.utils
import
(
merge_dict
,
extract
,
strip_none
,
get_courseware_context
)
import
django_comment_client.utils
as
utils
import
comment_client
as
cc
import
xml.sax.saxutils
as
saxutils
THREADS_PER_PAGE
=
20
INLINE_THREADS_PER_PAGE
=
20
...
...
@@ -31,6 +25,7 @@ escapedict = {'"': '"'}
log
=
logging
.
getLogger
(
"edx.discussions"
)
@login_required
def
get_threads
(
request
,
course_id
,
discussion_id
=
None
,
per_page
=
THREADS_PER_PAGE
):
"""
This may raise cc.utils.CommentClientError or
...
...
@@ -60,7 +55,6 @@ def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAG
cc_user
.
default_sort_key
=
request
.
GET
.
get
(
'sort_key'
)
cc_user
.
save
()
#there are 2 dimensions to consider when executing a search with respect to group id
#is user a moderator
#did the user request a group
...
...
@@ -91,18 +85,17 @@ def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAG
#now add the group name if the thread has a group id
for
thread
in
threads
:
if
thread
.
get
(
'group_id'
):
thread
[
'group_name'
]
=
get_cohort_by_id
(
course_id
,
thread
.
get
(
'group_id'
))
.
name
thread
[
'group_string'
]
=
"This post visible only to Group
%
s."
%
(
thread
[
'group_name'
])
else
:
thread
[
'group_name'
]
=
""
thread
[
'group_string'
]
=
"This post visible to everyone."
#patch for backward compatibility to comments service
if
not
'pinned'
in
thread
:
thread
[
'pinned'
]
=
False
query_params
[
'page'
]
=
page
query_params
[
'num_pages'
]
=
num_pages
...
...
@@ -110,6 +103,7 @@ def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAG
return
threads
,
query_params
@login_required
def
inline_discussion
(
request
,
course_id
,
discussion_id
):
"""
Renders JSON for DiscussionModules
...
...
@@ -142,14 +136,14 @@ def inline_discussion(request, course_id, discussion_id):
cohorts_list
=
list
()
if
is_cohorted
:
cohorts_list
.
append
({
'name'
:
'All Groups'
,
'id'
:
None
})
cohorts_list
.
append
({
'name'
:
'All Groups'
,
'id'
:
None
})
#if you're a mod, send all cohorts and let you pick
if
is_moderator
:
cohorts
=
get_course_cohorts
(
course_id
)
for
c
in
cohorts
:
cohorts_list
.
append
({
'name'
:
c
.
name
,
'id'
:
c
.
id
})
cohorts_list
.
append
({
'name'
:
c
.
name
,
'id'
:
c
.
id
})
else
:
#students don't get to choose
...
...
@@ -216,9 +210,6 @@ def forum_form_discussion(request, course_id):
user_cohort_id
=
get_cohort_id
(
request
.
user
,
course_id
)
context
=
{
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'course'
:
course
,
...
...
@@ -242,6 +233,7 @@ def forum_form_discussion(request, course_id):
return
render_to_response
(
'discussion/index.html'
,
context
)
@login_required
def
single_thread
(
request
,
course_id
,
discussion_id
,
thread_id
):
course
=
get_course_with_access
(
request
.
user
,
course_id
,
'load'
)
...
...
@@ -250,11 +242,11 @@ def single_thread(request, course_id, discussion_id, thread_id):
try
:
thread
=
cc
.
Thread
.
find
(
thread_id
)
.
retrieve
(
recursive
=
True
,
user_id
=
request
.
user
.
id
)
#patch for backward compatibility with comments service
if
not
'pinned'
in
thread
.
attributes
:
thread
[
'pinned'
]
=
False
except
(
cc
.
utils
.
CommentClientError
,
cc
.
utils
.
CommentClientUnknownError
)
as
err
:
log
.
error
(
"Error loading single thread."
)
raise
Http404
...
...
@@ -352,7 +344,7 @@ def user_profile(request, course_id, user_id):
query_params
=
{
'page'
:
request
.
GET
.
get
(
'page'
,
1
),
'per_page'
:
THREADS_PER_PAGE
,
# more than threads_per_page to show more activities
}
}
threads
,
page
,
num_pages
=
profiled_user
.
active_threads
(
query_params
)
query_params
[
'page'
]
=
page
...
...
@@ -369,8 +361,6 @@ def user_profile(request, course_id, user_id):
'annotated_content_info'
:
saxutils
.
escape
(
json
.
dumps
(
annotated_content_info
),
escapedict
),
})
else
:
context
=
{
'course'
:
course
,
'user'
:
request
.
user
,
...
...
@@ -426,5 +416,5 @@ def followed_threads(request, course_id, user_id):
}
return
render_to_response
(
'discussion/user_profile.html'
,
context
)
except
(
cc
.
utils
.
CommentClientError
,
cc
.
utils
.
CommentClientUnknownError
)
as
err
:
except
(
cc
.
utils
.
CommentClientError
,
cc
.
utils
.
CommentClientUnknownError
):
raise
Http404
lms/djangoapps/django_comment_client/tests.py
View file @
a79a2907
from
django.contrib.auth.models
import
User
,
Group
from
django.core.urlresolvers
import
reverse
from
django.test
import
TestCase
from
django.test.client
import
RequestFactory
from
django.conf
import
settings
from
mock
import
Mock
from
django.test.utils
import
override_settings
import
xmodule.modulestore.django
from
student.models
import
CourseEnrollment
from
django.db.models.signals
import
m2m_changed
,
pre_delete
,
pre_save
,
post_delete
,
post_save
from
django.dispatch.dispatcher
import
_make_id
import
string
import
random
from
.permissions
import
has_permission
from
.models
import
Role
,
Permission
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.modulestore.xml
import
XMLModuleStore
import
comment_client
from
courseware.tests.tests
import
PageLoader
,
TEST_DATA_XML_MODULESTORE
#@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE)
#class TestCohorting(PageLoader):
# """Check that cohorting works properly"""
#
# def setUp(self):
# xmodule.modulestore.django._MODULESTORES = {}
#
# # Assume courses are there
# self.toy = modulestore().get_course("edX/toy/2012_Fall")
#
# # Create two accounts
# self.student = 'view@test.com'
# self.student2 = 'view2@test.com'
# self.password = 'foo'
# self.create_account('u1', self.student, self.password)
# self.create_account('u2', self.student2, self.password)
# self.activate_user(self.student)
# self.activate_user(self.student2)
#
# def test_create_thread(self):
# my_save = Mock()
# comment_client.perform_request = my_save
#
# resp = self.client.post(
# reverse('django_comment_client.base.views.create_thread',
# kwargs={'course_id': 'edX/toy/2012_Fall',
# 'commentable_id': 'General'}),
# {'some': "some",
# 'data': 'data'})
# self.assertTrue(my_save.called)
#
# #self.assertEqual(resp.status_code, 200)
# #self.assertEqual(my_save.something, "expected", "complaint if not true")
#
# self.toy.cohort_config = {"cohorted": True}
#
# # call the view again ...
#
# # assert that different things happened
from
django.contrib.auth.models
import
User
from
django.test
import
TestCase
from
student.models
import
CourseEnrollment
from
django_comment_client.permissions
import
has_permission
from
django_comment_client.models
import
Role
class
PermissionsTestCase
(
TestCase
):
...
...
lms/djangoapps/instructor/tests.py
View file @
a79a2907
...
...
@@ -8,13 +8,6 @@ Notes for running by hand:
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/instructor
"""
import
courseware.tests.tests
as
ct
import
json
from
nose
import
SkipTest
from
mock
import
patch
,
Mock
from
django.test.utils
import
override_settings
# Need access to internal func to put users in the right group
...
...
@@ -26,13 +19,13 @@ from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, \
from
django_comment_client.utils
import
has_forum_access
from
courseware.access
import
_course_staff_group_name
import
courseware.tests.tests
as
ct
from
courseware.tests.tests
import
LoginEnrollmentTestCase
,
TEST_DATA_XML_MODULESTORE
,
get_user
from
xmodule.modulestore.django
import
modulestore
import
xmodule.modulestore.django
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestInstructorDashboardGradeDownloadCSV
(
ct
.
PageLoader
):
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestInstructorDashboardGradeDownloadCSV
(
LoginEnrollmentTestCase
):
'''
Check for download of csv
'''
...
...
@@ -55,7 +48,7 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
def
make_instructor
(
course
):
group_name
=
_course_staff_group_name
(
course
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
ct
.
user
(
self
.
instructor
))
g
.
user_set
.
add
(
get_
user
(
self
.
instructor
))
make_instructor
(
self
.
toy
)
...
...
@@ -63,7 +56,6 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
self
.
login
(
self
.
instructor
,
self
.
password
)
self
.
enroll
(
self
.
toy
)
def
test_download_grades_csv
(
self
):
course
=
self
.
toy
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
...
...
@@ -101,9 +93,8 @@ def action_name(operation, rolename):
return
'{0} forum {1}'
.
format
(
operation
,
FORUM_ADMIN_ACTION_SUFFIX
[
rolename
])
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestInstructorDashboardForumAdmin
(
ct
.
PageLoader
):
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestInstructorDashboardForumAdmin
(
LoginEnrollmentTestCase
):
'''
Check for change in forum admin role memberships
'''
...
...
@@ -112,7 +103,6 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
courses
=
modulestore
()
.
get_courses
()
self
.
course_id
=
"edX/toy/2012_Fall"
self
.
toy
=
modulestore
()
.
get_course
(
self
.
course_id
)
...
...
@@ -127,14 +117,12 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
group_name
=
_course_staff_group_name
(
self
.
toy
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
ct
.
user
(
self
.
instructor
))
g
.
user_set
.
add
(
get_
user
(
self
.
instructor
))
self
.
logout
()
self
.
login
(
self
.
instructor
,
self
.
password
)
self
.
enroll
(
self
.
toy
)
def
initialize_roles
(
self
,
course_id
):
self
.
admin_role
=
Role
.
objects
.
get_or_create
(
name
=
FORUM_ROLE_ADMINISTRATOR
,
course_id
=
course_id
)[
0
]
self
.
moderator_role
=
Role
.
objects
.
get_or_create
(
name
=
FORUM_ROLE_MODERATOR
,
course_id
=
course_id
)[
0
]
...
...
lms/djangoapps/licenses/tests.py
View file @
a79a2907
"""Tests for License package"""
import
logging
import
json
from
uuid
import
uuid4
from
random
import
shuffle
from
tempfile
import
NamedTemporaryFile
from
factory
import
Factory
,
SubFactory
from
django.test
import
TestCase
from
django.core.management
import
call_command
from
.models
import
CourseSoftware
,
UserLicense
from
django.core.urlresolvers
import
reverse
from
licenses.models
import
CourseSoftware
,
UserLicense
from
courseware.tests.tests
import
LoginEnrollmentTestCase
,
get_user
COURSE_1
=
'edX/toy/2012_Fall'
SOFTWARE_1
=
'matlab'
SOFTWARE_2
=
'stata'
SERIAL_1
=
'123456abcde'
log
=
logging
.
getLogger
(
__name__
)
class
CourseSoftwareFactory
(
Factory
):
'''Factory for generating CourseSoftware objects in database'''
FACTORY_FOR
=
CourseSoftware
name
=
SOFTWARE_1
full_name
=
SOFTWARE_1
url
=
SOFTWARE_1
course_id
=
COURSE_1
class
UserLicenseFactory
(
Factory
):
'''
Factory for generating UserLicense objects in database
By default, the user assigned is null, indicating that the
serial number has not yet been assigned.
'''
FACTORY_FOR
=
UserLicense
software
=
SubFactory
(
CourseSoftwareFactory
)
serial
=
SERIAL_1
class
LicenseTestCase
(
LoginEnrollmentTestCase
):
'''Tests for licenses.views'''
def
setUp
(
self
):
'''creates a user and logs in'''
self
.
setup_viewtest_user
()
self
.
software
=
CourseSoftwareFactory
()
def
test_get_license
(
self
):
UserLicenseFactory
(
user
=
get_user
(
self
.
viewtest_email
),
software
=
self
.
software
)
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'software'
:
SOFTWARE_1
,
'generate'
:
'false'
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
,
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
COURSE_1
))
self
.
assertEqual
(
200
,
response
.
status_code
)
json_returned
=
json
.
loads
(
response
.
content
)
self
.
assertFalse
(
'error'
in
json_returned
)
self
.
assertTrue
(
'serial'
in
json_returned
)
self
.
assertEquals
(
json_returned
[
'serial'
],
SERIAL_1
)
def
test_get_nonexistent_license
(
self
):
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'software'
:
SOFTWARE_1
,
'generate'
:
'false'
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
,
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
COURSE_1
))
self
.
assertEqual
(
200
,
response
.
status_code
)
json_returned
=
json
.
loads
(
response
.
content
)
self
.
assertFalse
(
'serial'
in
json_returned
)
self
.
assertTrue
(
'error'
in
json_returned
)
def
test_create_nonexistent_license
(
self
):
'''Should not assign a license to an unlicensed user when none are available'''
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'software'
:
SOFTWARE_1
,
'generate'
:
'true'
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
,
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
COURSE_1
))
self
.
assertEqual
(
200
,
response
.
status_code
)
json_returned
=
json
.
loads
(
response
.
content
)
self
.
assertFalse
(
'serial'
in
json_returned
)
self
.
assertTrue
(
'error'
in
json_returned
)
def
test_create_license
(
self
):
'''Should assign a license to an unlicensed user if one is unassigned'''
# create an unassigned license
UserLicenseFactory
(
software
=
self
.
software
)
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'software'
:
SOFTWARE_1
,
'generate'
:
'true'
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
,
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
COURSE_1
))
self
.
assertEqual
(
200
,
response
.
status_code
)
json_returned
=
json
.
loads
(
response
.
content
)
self
.
assertFalse
(
'error'
in
json_returned
)
self
.
assertTrue
(
'serial'
in
json_returned
)
self
.
assertEquals
(
json_returned
[
'serial'
],
SERIAL_1
)
def
test_get_license_from_wrong_course
(
self
):
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'software'
:
SOFTWARE_1
,
'generate'
:
'false'
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
,
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
'some/other/course'
))
self
.
assertEqual
(
404
,
response
.
status_code
)
def
test_get_license_from_non_ajax
(
self
):
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'software'
:
SOFTWARE_1
,
'generate'
:
'false'
},
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
COURSE_1
))
self
.
assertEqual
(
404
,
response
.
status_code
)
def
test_get_license_without_software
(
self
):
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'generate'
:
'false'
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
,
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
COURSE_1
))
self
.
assertEqual
(
404
,
response
.
status_code
)
def
test_get_license_without_login
(
self
):
self
.
logout
()
response
=
self
.
client
.
post
(
reverse
(
'user_software_license'
),
{
'software'
:
SOFTWARE_1
,
'generate'
:
'false'
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
,
HTTP_REFERER
=
'/courses/{0}/some_page'
.
format
(
COURSE_1
))
# if we're not logged in, we should be referred to the login page
self
.
assertEqual
(
302
,
response
.
status_code
)
class
CommandTest
(
TestCase
):
'''Test management command for importing serial numbers'''
def
test_import_serial_numbers
(
self
):
size
=
20
...
...
@@ -51,31 +167,33 @@ class CommandTest(TestCase):
licenses_count
=
UserLicense
.
objects
.
all
()
.
count
()
self
.
assertEqual
(
3
*
size
,
licenses_count
)
cs
=
CourseSoftware
.
objects
.
get
(
pk
=
1
)
software
=
CourseSoftware
.
objects
.
get
(
pk
=
1
)
lics
=
UserLicense
.
objects
.
filter
(
software
=
cs
)[:
size
]
lics
=
UserLicense
.
objects
.
filter
(
software
=
software
)[:
size
]
known_serials
=
list
(
l
.
serial
for
l
in
lics
)
known_serials
.
extend
(
generate_serials
(
10
))
shuffle
(
known_serials
)
log
.
debug
(
'Adding some new and old serials to {0}'
.
format
(
SOFTWARE_1
))
with
NamedTemporaryFile
()
as
f
:
f
.
write
(
'
\n
'
.
join
(
known_serials
))
f
.
flush
()
args
=
[
COURSE_1
,
SOFTWARE_1
,
f
.
name
]
with
NamedTemporaryFile
()
as
tmpfile
:
tmpfile
.
write
(
'
\n
'
.
join
(
known_serials
))
tmpfile
.
flush
()
args
=
[
COURSE_1
,
SOFTWARE_1
,
tmpfile
.
name
]
call_command
(
'import_serial_numbers'
,
*
args
)
log
.
debug
(
'Check if we added only the new ones'
)
licenses_count
=
UserLicense
.
objects
.
filter
(
software
=
cs
)
.
count
()
licenses_count
=
UserLicense
.
objects
.
filter
(
software
=
software
)
.
count
()
self
.
assertEqual
((
2
*
size
)
+
10
,
licenses_count
)
def
generate_serials
(
size
=
20
):
'''generate a list of serial numbers'''
return
[
str
(
uuid4
())
for
_
in
range
(
size
)]
def
generate_serials_file
(
size
=
20
):
'''output list of generated serial numbers to a temp file'''
serials
=
generate_serials
(
size
)
temp_file
=
NamedTemporaryFile
()
...
...
lms/djangoapps/licenses/views.py
View file @
a79a2907
...
...
@@ -7,12 +7,13 @@ from collections import namedtuple, defaultdict
from
mitxmako.shortcuts
import
render_to_string
from
django.contrib.auth.decorators
import
login_required
from
django.contrib.auth.models
import
User
from
django.http
import
HttpResponse
,
Http404
from
django.views.decorators.csrf
import
requires_csrf_token
,
csrf_protect
from
django.views.decorators.csrf
import
requires_csrf_token
from
.models
import
CourseSoftware
from
.models
import
get_courses_licenses
,
get_or_create_license
,
get_license
from
licenses
.models
import
CourseSoftware
from
licenses
.models
import
get_courses_licenses
,
get_or_create_license
,
get_license
log
=
logging
.
getLogger
(
"mitx.licenses"
)
...
...
@@ -44,6 +45,7 @@ def get_licenses_by_course(user, courses):
return
data_by_course
@login_required
@requires_csrf_token
def
user_software_license
(
request
):
if
request
.
method
!=
'POST'
or
not
request
.
is_ajax
():
...
...
@@ -65,19 +67,21 @@ def user_software_license(request):
try
:
software
=
CourseSoftware
.
objects
.
get
(
name
=
software_name
,
course_id
=
course_id
)
print
software
except
CourseSoftware
.
DoesNotExist
:
raise
Http404
user
=
User
.
objects
.
get
(
id
=
user_id
)
try
:
user
=
User
.
objects
.
get
(
id
=
user_id
)
except
User
.
DoesNotExist
:
raise
Http404
if
generate
:
license
=
get_or_create_license
(
user
,
software
)
software_
license
=
get_or_create_license
(
user
,
software
)
else
:
license
=
get_license
(
user
,
software
)
software_
license
=
get_license
(
user
,
software
)
if
license
:
response
=
{
'serial'
:
license
.
serial
}
if
software_
license
:
response
=
{
'serial'
:
software_
license
.
serial
}
else
:
response
=
{
'error'
:
'No serial number found'
}
...
...
lms/djangoapps/open_ended_grading/tests.py
View file @
a79a2907
...
...
@@ -4,22 +4,22 @@ Tests for open ended grading interfaces
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/open_ended_grading
"""
from
django.test
import
TestCase
from
open_ended_grading
import
staff_grading_service
from
xmodule.open_ended_grading_classes
import
peer_grading_service
from
xmodule
import
peer_grading_module
import
json
from
mock
import
MagicMock
from
django.core.urlresolvers
import
reverse
from
django.contrib.auth.models
import
Group
from
mitxmako.shortcuts
import
render_to_string
from
courseware.access
import
_course_staff_group_nam
e
import
courseware.tests.tests
as
ct
from
xmodule.open_ended_grading_classes
import
peer_grading_servic
e
from
xmodule
import
peer_grading_module
from
xmodule.modulestore.django
import
modulestore
import
xmodule.modulestore.django
from
nose
import
SkipTest
from
mock
import
patch
,
Mock
,
MagicMock
import
json
from
xmodule.x_module
import
ModuleSystem
from
mitxmako.shortcuts
import
render_to_string
from
open_ended_grading
import
staff_grading_service
from
courseware.access
import
_course_staff_group_name
from
courseware.tests.tests
import
LoginEnrollmentTestCase
,
TEST_DATA_XML_MODULESTORE
,
get_user
import
logging
...
...
@@ -30,8 +30,8 @@ from django.http import QueryDict
from
xmodule.tests
import
test_util_open_ended
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestStaffGradingService
(
ct
.
PageLoader
):
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestStaffGradingService
(
LoginEnrollmentTestCase
):
'''
Check that staff grading service proxy works. Basically just checking the
access control and error handling logic -- all the actual work is on the
...
...
@@ -56,7 +56,7 @@ class TestStaffGradingService(ct.PageLoader):
def
make_instructor
(
course
):
group_name
=
_course_staff_group_name
(
course
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
ct
.
user
(
self
.
instructor
))
g
.
user_set
.
add
(
get_
user
(
self
.
instructor
))
make_instructor
(
self
.
toy
)
...
...
@@ -126,8 +126,8 @@ class TestStaffGradingService(ct.PageLoader):
self
.
assertIsNotNone
(
d
[
'problem_list'
])
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestPeerGradingService
(
ct
.
PageLoader
):
@override_settings
(
MODULESTORE
=
TEST_DATA_XML_MODULESTORE
)
class
TestPeerGradingService
(
LoginEnrollmentTestCase
):
'''
Check that staff grading service proxy works. Basically just checking the
access control and error handling logic -- all the actual work is on the
...
...
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