Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-proctoring
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
OpenEdx
edx-proctoring
Commits
ac0115f7
Commit
ac0115f7
authored
Jul 08, 2015
by
chrisndodge
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #19 from edx/cdodge/add-get-exams-for-course
Add API method to get a list of all exams for a course
parents
b17b841b
90853b76
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
64 additions
and
2 deletions
+64
-2
edx_proctoring/api.py
+19
-0
edx_proctoring/models.py
+7
-0
edx_proctoring/tests/test_api.py
+38
-2
No files found.
edx_proctoring/api.py
View file @
ac0115f7
...
@@ -219,6 +219,17 @@ def stop_exam_attempt(exam_id, user_id):
...
@@ -219,6 +219,17 @@ def stop_exam_attempt(exam_id, user_id):
return
exam_attempt_obj
.
id
return
exam_attempt_obj
.
id
def
get_all_exams_for_course
(
course_id
):
"""
This method will return all exams for a course. This will return a list
of dictionaries, whose schema is the same as what is returned in
get_exam_by_id
"""
exams
=
ProctoredExam
.
get_all_exams_for_course
(
course_id
)
return
[
ProctoredExamSerializer
(
proctored_exam
)
.
data
for
proctored_exam
in
exams
]
def
get_active_exams_for_user
(
user_id
,
course_id
=
None
):
def
get_active_exams_for_user
(
user_id
,
course_id
=
None
):
"""
"""
This method will return a list of active exams for the user,
This method will return a list of active exams for the user,
...
@@ -277,9 +288,17 @@ def get_student_view(user_id, course_id, content_id, context):
...
@@ -277,9 +288,17 @@ def get_student_view(user_id, course_id, content_id, context):
exam_id
=
None
exam_id
=
None
try
:
try
:
exam
=
get_exam_by_content_id
(
course_id
,
content_id
)
exam
=
get_exam_by_content_id
(
course_id
,
content_id
)
if
not
exam
[
'is_active'
]:
# Exam is no longer active
# Note, we don't hard delete exams since we need to retain
# data
return
None
exam_id
=
exam
[
'id'
]
exam_id
=
exam
[
'id'
]
is_proctored
=
exam
[
'is_proctored'
]
is_proctored
=
exam
[
'is_proctored'
]
except
ProctoredExamNotFoundException
:
except
ProctoredExamNotFoundException
:
# This really shouldn't happen
# as Studio will be setting this up
is_proctored
=
context
.
get
(
'is_proctored'
,
False
)
is_proctored
=
context
.
get
(
'is_proctored'
,
False
)
exam_id
=
create_exam
(
exam_id
=
create_exam
(
course_id
=
course_id
,
course_id
=
course_id
,
...
...
edx_proctoring/models.py
View file @
ac0115f7
...
@@ -65,6 +65,13 @@ class ProctoredExam(TimeStampedModel):
...
@@ -65,6 +65,13 @@ class ProctoredExam(TimeStampedModel):
proctored_exam
=
None
proctored_exam
=
None
return
proctored_exam
return
proctored_exam
@classmethod
def
get_all_exams_for_course
(
cls
,
course_id
):
"""
Returns all exams for a give course
"""
return
cls
.
objects
.
filter
(
course_id
=
course_id
)
class
ProctoredExamStudentAttempt
(
TimeStampedModel
):
class
ProctoredExamStudentAttempt
(
TimeStampedModel
):
"""
"""
...
...
edx_proctoring/tests/test_api.py
View file @
ac0115f7
...
@@ -16,6 +16,7 @@ from edx_proctoring.api import (
...
@@ -16,6 +16,7 @@ from edx_proctoring.api import (
get_exam_attempt
,
get_exam_attempt
,
create_exam_attempt
,
create_exam_attempt
,
get_student_view
,
get_student_view
,
get_all_exams_for_course
,
)
)
from
edx_proctoring.exceptions
import
(
from
edx_proctoring.exceptions
import
(
ProctoredExamAlreadyExists
,
ProctoredExamAlreadyExists
,
...
@@ -48,12 +49,14 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -48,12 +49,14 @@ class ProctoredExamApiTests(LoggedInTestCase):
self
.
default_time_limit
=
21
self
.
default_time_limit
=
21
self
.
course_id
=
'test_course'
self
.
course_id
=
'test_course'
self
.
content_id
=
'test_content_id'
self
.
content_id
=
'test_content_id'
self
.
disabled_content_id
=
'test_disabled_content_id'
self
.
exam_name
=
'Test Exam'
self
.
exam_name
=
'Test Exam'
self
.
user_id
=
1
self
.
user_id
=
1
self
.
key
=
'Test Key'
self
.
key
=
'Test Key'
self
.
value
=
'Test Value'
self
.
value
=
'Test Value'
self
.
external_id
=
'test_external_id'
self
.
external_id
=
'test_external_id'
self
.
proctored_exam_id
=
self
.
_create_proctored_exam
()
self
.
proctored_exam_id
=
self
.
_create_proctored_exam
()
self
.
disabled_exam_id
=
self
.
_create_disabled_exam
()
# Messages for get_student_view
# Messages for get_student_view
self
.
start_an_exam_msg
=
'Would you like to take
%
s as a Proctored Exam?'
self
.
start_an_exam_msg
=
'Would you like to take
%
s as a Proctored Exam?'
...
@@ -72,6 +75,18 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -72,6 +75,18 @@ class ProctoredExamApiTests(LoggedInTestCase):
time_limit_mins
=
self
.
default_time_limit
time_limit_mins
=
self
.
default_time_limit
)
)
def
_create_disabled_exam
(
self
):
"""
Calls the api's create_exam to create an exam object.
"""
return
create_exam
(
course_id
=
self
.
course_id
,
content_id
=
self
.
disabled_content_id
,
exam_name
=
self
.
exam_name
,
time_limit_mins
=
self
.
default_time_limit
,
is_active
=
False
)
def
_create_unstarted_exam_attempt
(
self
):
def
_create_unstarted_exam_attempt
(
self
):
"""
"""
Creates the ProctoredExamStudentAttempt object.
Creates the ProctoredExamStudentAttempt object.
...
@@ -135,7 +150,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -135,7 +150,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
which will throw the exception
which will throw the exception
"""
"""
with
self
.
assertRaises
(
ProctoredExamNotFoundException
):
with
self
.
assertRaises
(
ProctoredExamNotFoundException
):
update_exam
(
2
,
exam_name
=
'Updated Exam Name'
,
time_limit_mins
=
30
)
update_exam
(
0
,
exam_name
=
'Updated Exam Name'
,
time_limit_mins
=
30
)
def
test_get_proctored_exam
(
self
):
def
test_get_proctored_exam
(
self
):
"""
"""
...
@@ -152,6 +167,9 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -152,6 +167,9 @@ class ProctoredExamApiTests(LoggedInTestCase):
self
.
assertEqual
(
proctored_exam
[
'content_id'
],
self
.
content_id
)
self
.
assertEqual
(
proctored_exam
[
'content_id'
],
self
.
content_id
)
self
.
assertEqual
(
proctored_exam
[
'exam_name'
],
self
.
exam_name
)
self
.
assertEqual
(
proctored_exam
[
'exam_name'
],
self
.
exam_name
)
exams
=
get_all_exams_for_course
(
self
.
course_id
)
self
.
assertEqual
(
len
(
exams
),
2
)
def
test_get_invalid_proctored_exam
(
self
):
def
test_get_invalid_proctored_exam
(
self
):
"""
"""
test to get the exam by the invalid exam_id which will
test to get the exam by the invalid exam_id which will
...
@@ -159,7 +177,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -159,7 +177,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
"""
"""
with
self
.
assertRaises
(
ProctoredExamNotFoundException
):
with
self
.
assertRaises
(
ProctoredExamNotFoundException
):
get_exam_by_id
(
2
)
get_exam_by_id
(
0
)
with
self
.
assertRaises
(
ProctoredExamNotFoundException
):
with
self
.
assertRaises
(
ProctoredExamNotFoundException
):
get_exam_by_content_id
(
'teasd'
,
'tewasda'
)
get_exam_by_content_id
(
'teasd'
,
'tewasda'
)
...
@@ -321,6 +339,24 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -321,6 +339,24 @@ class ProctoredExamApiTests(LoggedInTestCase):
self
.
assertIn
(
'data-exam-id="
%
d"'
%
self
.
proctored_exam_id
,
rendered_response
)
self
.
assertIn
(
'data-exam-id="
%
d"'
%
self
.
proctored_exam_id
,
rendered_response
)
self
.
assertIn
(
self
.
start_an_exam_msg
%
self
.
exam_name
,
rendered_response
)
self
.
assertIn
(
self
.
start_an_exam_msg
%
self
.
exam_name
,
rendered_response
)
def
test_get_disabled_student_view
(
self
):
"""
Assert that a disabled proctored exam will not override the
student_view
"""
self
.
assertIsNone
(
get_student_view
(
user_id
=
self
.
user_id
,
course_id
=
self
.
course_id
,
content_id
=
self
.
disabled_content_id
,
context
=
{
'is_proctored'
:
True
,
'display_name'
:
self
.
exam_name
,
'default_time_limit_mins'
:
90
}
)
)
def
test_getstudentview_timedexam
(
self
):
def
test_getstudentview_timedexam
(
self
):
"""
"""
Test for get_student_view Timed exam which is not proctored.
Test for get_student_view Timed exam which is not proctored.
...
...
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