Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-ora2
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-ora2
Commits
476285c7
Commit
476285c7
authored
May 20, 2014
by
Stephen Sanchez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding front-end admin action to schedule training tasks.
parent
07e147ed
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
334 additions
and
16 deletions
+334
-16
apps/openassessment/templates/openassessmentblock/staff_debug/staff_debug.html
+7
-0
apps/openassessment/xblock/openassessmentblock.py
+16
-0
apps/openassessment/xblock/staff_info_mixin.py
+50
-4
apps/openassessment/xblock/static/css/openassessment.css
+0
-0
apps/openassessment/xblock/static/js/fixtures/templates.json
+15
-0
apps/openassessment/xblock/static/js/openassessment.min.js
+0
-0
apps/openassessment/xblock/static/js/spec/oa_staff_info.js
+75
-0
apps/openassessment/xblock/static/js/src/oa_server.js
+34
-0
apps/openassessment/xblock/static/js/src/oa_staff_info.js
+24
-0
apps/openassessment/xblock/static/sass/oa/utilities/_developer.scss
+7
-0
apps/openassessment/xblock/test/test_staff_info.py
+106
-12
No files found.
apps/openassessment/templates/openassessmentblock/staff_debug/staff_debug.html
View file @
476285c7
...
@@ -78,6 +78,13 @@
...
@@ -78,6 +78,13 @@
</table>
</table>
</div>
</div>
{% if display_schedule_training %}
<div
class=
"staff-info__status ui-staff__content__section"
>
<a
aria-role=
"button"
href=
""
id=
"schedule_training"
class=
"action--submit"
><span
class=
"copy"
>
{% trans "Schedule Example Based Assessment Training" %}
</span></a>
<div
id=
"schedule_training_message"
></div>
</div>
{% endif %}
<div
class=
"staff-info__student ui-staff__content__section"
>
<div
class=
"staff-info__student ui-staff__content__section"
>
<div
class=
"wrapper--input"
class=
"staff-info__student__form"
>
<div
class=
"wrapper--input"
class=
"staff-info__student__form"
>
<form
id=
"openassessment_student_info_form"
>
<form
id=
"openassessment_student_info_form"
>
...
...
apps/openassessment/xblock/openassessmentblock.py
View file @
476285c7
...
@@ -68,6 +68,7 @@ UI_MODELS = {
...
@@ -68,6 +68,7 @@ UI_MODELS = {
VALID_ASSESSMENT_TYPES
=
[
VALID_ASSESSMENT_TYPES
=
[
"student-training"
,
"student-training"
,
"example-based-assessment"
,
"peer-assessment"
,
"peer-assessment"
,
"self-assessment"
,
"self-assessment"
,
]
]
...
@@ -231,6 +232,19 @@ class OpenAssessmentBlock(
...
@@ -231,6 +232,19 @@ class OpenAssessmentBlock(
return
frag
return
frag
@property
@property
def
is_admin
(
self
):
"""
Check whether the user has global staff permissions.
Returns:
bool
"""
if
hasattr
(
self
,
'xmodule_runtime'
):
return
getattr
(
self
.
xmodule_runtime
,
'user_is_admin'
,
False
)
else
:
return
False
@property
def
is_course_staff
(
self
):
def
is_course_staff
(
self
):
"""
"""
Check whether the user has course staff permissions for this XBlock.
Check whether the user has course staff permissions for this XBlock.
...
@@ -243,6 +257,8 @@ class OpenAssessmentBlock(
...
@@ -243,6 +257,8 @@ class OpenAssessmentBlock(
else
:
else
:
return
False
return
False
@property
@property
def
in_studio_preview
(
self
):
def
in_studio_preview
(
self
):
"""
"""
...
...
apps/openassessment/xblock/staff_info_mixin.py
View file @
476285c7
...
@@ -6,10 +6,12 @@ import copy
...
@@ -6,10 +6,12 @@ import copy
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
openassessment.assessment.errors.ai
import
AIError
from
openassessment.xblock.resolve_dates
import
DISTANT_PAST
,
DISTANT_FUTURE
from
openassessment.xblock.resolve_dates
import
DISTANT_PAST
,
DISTANT_FUTURE
from
submissions
import
api
as
submission_api
from
submissions
import
api
as
submission_api
from
openassessment.assessment.api
import
peer
as
peer_api
from
openassessment.assessment.api
import
peer
as
peer_api
from
openassessment.assessment.api
import
self
as
self_api
from
openassessment.assessment.api
import
self
as
self_api
from
openassessment.assessment.api
import
ai
as
ai_api
class
StaffInfoMixin
(
object
):
class
StaffInfoMixin
(
object
):
...
@@ -29,8 +31,14 @@ class StaffInfoMixin(object):
...
@@ -29,8 +31,14 @@ class StaffInfoMixin(object):
return
self
.
render_error
(
_
(
return
self
.
render_error
(
_
(
u"You do not have permission to access staff information"
u"You do not have permission to access staff information"
))
))
student_item
=
self
.
get_student_item_dict
()
path
,
context
=
self
.
get_staff_path_and_context
()
context
=
dict
()
return
self
.
render_assessment
(
path
,
context
)
def
get_staff_path_and_context
(
self
):
"""
Gets the path and context for the staff section of the ORA XBlock.
"""
context
=
{}
path
=
'openassessmentblock/staff_debug/staff_debug.html'
path
=
'openassessmentblock/staff_debug/staff_debug.html'
# Calculate how many students are in each step of the workflow
# Calculate how many students are in each step of the workflow
...
@@ -38,6 +46,11 @@ class StaffInfoMixin(object):
...
@@ -38,6 +46,11 @@ class StaffInfoMixin(object):
context
[
'status_counts'
]
=
status_counts
context
[
'status_counts'
]
=
status_counts
context
[
'num_submissions'
]
=
num_submissions
context
[
'num_submissions'
]
=
num_submissions
# Show the schedule training button if example based assessment is
# configured, and the current user has admin privileges.
assessment
=
self
.
get_assessment_module
(
'example-based-assessment'
)
context
[
'display_schedule_training'
]
=
self
.
is_admin
and
assessment
# We need to display the new-style locations in the course staff
# We need to display the new-style locations in the course staff
# info, even if we're using old-style locations internally,
# info, even if we're using old-style locations internally,
# so course staff can use the locations to delete student state.
# so course staff can use the locations to delete student state.
...
@@ -57,8 +70,41 @@ class StaffInfoMixin(object):
...
@@ -57,8 +70,41 @@ class StaffInfoMixin(object):
'start'
:
start_date
if
start_date
>
DISTANT_PAST
else
None
,
'start'
:
start_date
if
start_date
>
DISTANT_PAST
else
None
,
'due'
:
due_date
if
due_date
<
DISTANT_FUTURE
else
None
,
'due'
:
due_date
if
due_date
<
DISTANT_FUTURE
else
None
,
})
})
return
path
,
context
return
self
.
render_assessment
(
path
,
context
)
@XBlock.json_handler
def
schedule_training
(
self
,
data
,
suffix
=
''
):
if
not
self
.
is_admin
or
self
.
in_studio_preview
:
return
{
'success'
:
False
,
'msg'
:
_
(
u"You do not have permission to schedule training"
)
}
assessment
=
self
.
get_assessment_module
(
'example-based-assessment'
)
if
assessment
:
examples
=
assessment
[
"examples"
]
try
:
workflow_uuid
=
ai_api
.
train_classifiers
(
self
.
rubric_criteria
,
examples
,
assessment
[
"algorithm_id"
]
)
return
{
'success'
:
True
,
'workflow_uuid'
:
workflow_uuid
,
'msg'
:
_
(
u"Training scheduled with new Workflow UUID: {}"
.
format
(
workflow_uuid
))
}
except
AIError
as
err
:
return
{
'success'
:
False
,
'msg'
:
_
(
u"An error occurred scheduling classifier training {}"
.
format
(
err
))
}
else
:
return
{
'success'
:
False
,
'msg'
:
_
(
u"Example Based Assessment is not configured for this location."
)
}
@XBlock.handler
@XBlock.handler
def
render_student_info
(
self
,
data
,
suffix
=
''
):
def
render_student_info
(
self
,
data
,
suffix
=
''
):
...
@@ -77,7 +123,7 @@ class StaffInfoMixin(object):
...
@@ -77,7 +123,7 @@ class StaffInfoMixin(object):
if
not
self
.
is_course_staff
or
self
.
in_studio_preview
:
if
not
self
.
is_course_staff
or
self
.
in_studio_preview
:
return
self
.
render_error
(
_
(
return
self
.
render_error
(
_
(
u"You do not have permission to access student information."
u"You do not have permission to access student information."
))
))
path
,
context
=
self
.
get_student_info_path_and_context
(
data
)
path
,
context
=
self
.
get_student_info_path_and_context
(
data
)
return
self
.
render_assessment
(
path
,
context
)
return
self
.
render_assessment
(
path
,
context
)
...
...
apps/openassessment/xblock/static/css/openassessment.css
View file @
476285c7
This diff is collapsed.
Click to expand it.
apps/openassessment/xblock/static/js/fixtures/templates.json
View file @
476285c7
...
@@ -345,5 +345,20 @@
...
@@ -345,5 +345,20 @@
"template"
:
"openassessmentblock/oa_edit.html"
,
"template"
:
"openassessmentblock/oa_edit.html"
,
"context"
:
{},
"context"
:
{},
"output"
:
"oa_edit.html"
"output"
:
"oa_edit.html"
},
{
"template"
:
"openassessmentblock/staff_debug/staff_debug.html"
,
"output"
:
"staff_debug.html"
,
"context"
:
{
"status_counts"
:
[
{
"status"
:
"peer"
,
"count"
:
0
}
],
"item_id"
:
".openassessment.d91.u0"
,
"display_schedule_training"
:
true
,
"num_submissions"
:
0
}
}
}
]
]
apps/openassessment/xblock/static/js/openassessment.min.js
View file @
476285c7
This diff is collapsed.
Click to expand it.
apps/openassessment/xblock/static/js/spec/oa_staff_info.js
0 → 100644
View file @
476285c7
/**
Tests for OpenAssessment Student Training view.
**/
describe
(
"OpenAssessment.StaffInfoView"
,
function
()
{
// Stub server
var
StubServer
=
function
()
{
var
successPromise
=
$
.
Deferred
(
function
(
defer
)
{
defer
.
resolve
();
}
).
promise
();
this
.
render
=
function
(
step
)
{
return
successPromise
;
};
this
.
scheduleTraining
=
function
()
{
var
server
=
this
;
return
$
.
Deferred
(
function
(
defer
)
{
defer
.
resolveWith
(
server
,
[
server
.
data
]);
}).
promise
();
};
this
.
data
=
{};
};
// Stub base view
var
StubBaseView
=
function
()
{
this
.
showLoadError
=
function
(
msg
)
{};
this
.
toggleActionError
=
function
(
msg
,
step
)
{};
this
.
setUpCollapseExpand
=
function
(
sel
)
{};
this
.
scrollToTop
=
function
()
{};
this
.
loadAssessmentModules
=
function
()
{};
};
// Stubs
var
baseView
=
null
;
var
server
=
null
;
// View under test
var
view
=
null
;
beforeEach
(
function
()
{
// Load the DOM fixture
jasmine
.
getFixtures
().
fixturesPath
=
'base/fixtures'
;
loadFixtures
(
'staff_debug.html'
);
// Create a new stub server
server
=
new
StubServer
();
// Create the stub base view
baseView
=
new
StubBaseView
();
// Create the object under test
var
el
=
$
(
"#openassessment-base"
).
get
(
0
);
view
=
new
OpenAssessment
.
StaffInfoView
(
el
,
server
,
baseView
);
view
.
installHandlers
();
});
it
(
"schedules training of AI classifiers"
,
function
()
{
server
.
data
=
{
"success"
:
true
,
"workflow_uuid"
:
"abc123"
,
"msg"
:
"Great success."
};
spyOn
(
server
,
'scheduleTraining'
).
andCallThrough
();
// Submit the assessment
view
.
scheduleTraining
();
// Expect that the assessment was sent to the server
expect
(
server
.
scheduleTraining
).
toHaveBeenCalled
();
});
});
apps/openassessment/xblock/static/js/src/oa_server.js
View file @
476285c7
...
@@ -337,6 +337,40 @@ OpenAssessment.Server.prototype = {
...
@@ -337,6 +337,40 @@ OpenAssessment.Server.prototype = {
},
},
/**
/**
Schedules classifier training for Example Based Assessment for this
Location.
Returns:
A JQuery promise, which resolves with a message indicating the results
of the scheduling request.
Example:
server.scheduleTraining().done(
function(msg) { console.log("Success!"); }
alert(msg);
).fail(
function(errorMsg) { console.log(errorMsg); }
);
**/
scheduleTraining
:
function
()
{
var
url
=
this
.
url
(
'schedule_training'
);
return
$
.
Deferred
(
function
(
defer
)
{
$
.
ajax
({
type
:
"POST"
,
url
:
url
,
data
:
"
\"\"
"
}).
done
(
function
(
data
)
{
if
(
data
.
success
)
{
defer
.
resolveWith
(
this
,
[
data
.
msg
]);
}
else
{
defer
.
rejectWith
(
this
,
[
data
.
msg
]);
}
}
).
fail
(
function
(
data
)
{
defer
.
rejectWith
(
this
,
[
gettext
(
'This assessment could not be submitted.'
)]);
});
});
},
/**
Load the XBlock's XML definition from the server.
Load the XBlock's XML definition from the server.
Returns:
Returns:
...
...
apps/openassessment/xblock/static/js/src/oa_staff_info.js
View file @
476285c7
...
@@ -81,5 +81,29 @@ OpenAssessment.StaffInfoView.prototype = {
...
@@ -81,5 +81,29 @@ OpenAssessment.StaffInfoView.prototype = {
view
.
loadStudentInfo
();
view
.
loadStudentInfo
();
}
}
);
);
// Install a click handler for scheduling AI classifier training
sel
.
find
(
'#schedule_training'
).
click
(
function
(
eventObject
)
{
eventObject
.
preventDefault
();
view
.
scheduleTraining
();
}
);
},
/**
Sends a request to the server to schedule the training of classifiers for
this problem's Example Based Assessments.
**/
scheduleTraining
:
function
()
{
var
view
=
this
;
this
.
server
.
scheduleTraining
().
done
(
function
(
msg
)
{
$
(
'#schedule_training_message'
,
this
.
element
).
text
(
msg
)
}
).
fail
(
function
(
errMsg
)
{
$
(
'#schedule_training_message'
,
this
.
element
).
text
(
errMsg
)
});
}
}
};
};
apps/openassessment/xblock/static/sass/oa/utilities/_developer.scss
View file @
476285c7
...
@@ -26,6 +26,13 @@
...
@@ -26,6 +26,13 @@
// --------------------
// --------------------
// Developer styles for Staff Section
// Developer styles for Staff Section
// --------------------
// --------------------
.staff-info__status
{
.action--submit
{
@extend
%btn--secondary
;
@extend
%action-2
;
margin
:
(
$baseline-v
/
2
)
(
$baseline-v
/
2
)
(
$baseline-v
/
2
)
(
$baseline-v
/
2
);
}
}
.staff-info__student
{
.staff-info__student
{
.label
{
.label
{
color
:
$heading-staff-color
;
color
:
$heading-staff-color
;
...
...
apps/openassessment/xblock/test/test_staff_info.py
View file @
476285c7
...
@@ -5,7 +5,9 @@ import json
...
@@ -5,7 +5,9 @@ import json
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
from
openassessment.assessment.api
import
peer
as
peer_api
from
openassessment.assessment.api
import
peer
as
peer_api
from
openassessment.assessment.api
import
self
as
self_api
from
openassessment.assessment.api
import
self
as
self_api
from
openassessment.assessment.api
import
ai
as
ai_api
from
openassessment.workflow
import
api
as
workflow_api
from
openassessment.workflow
import
api
as
workflow_api
from
openassessment.assessment.errors.ai
import
AIError
from
submissions
import
api
as
sub_api
from
submissions
import
api
as
sub_api
from
openassessment.xblock.test.base
import
scenario
,
XBlockHandlerTestCase
from
openassessment.xblock.test.base
import
scenario
,
XBlockHandlerTestCase
...
@@ -25,6 +27,38 @@ ASSESSMENT_DICT = {
...
@@ -25,6 +27,38 @@ ASSESSMENT_DICT = {
},
},
}
}
EXAMPLE_BASED_ASSESSMENT
=
{
"name"
:
"example-based-assessment"
,
"algorithm_id"
:
"1"
,
"examples"
:
[
{
"answer"
:
"Foo"
,
"options_selected"
:
[
{
"criterion"
:
"Ideas"
,
"option"
:
"Fair"
},
{
"criterion"
:
"Content"
,
"option"
:
"Good"
}
]
},
{
"answer"
:
"Bar"
,
"options_selected"
:
[
{
"criterion"
:
"Ideas"
,
"option"
:
"Poor"
},
{
"criterion"
:
"Content"
,
"option"
:
"Good"
}
]
}
]
}
class
TestCourseStaff
(
XBlockHandlerTestCase
):
class
TestCourseStaff
(
XBlockHandlerTestCase
):
"""
"""
...
@@ -50,7 +84,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -50,7 +84,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_course_staff_debug_info
(
self
,
xblock
):
def
test_course_staff_debug_info
(
self
,
xblock
):
# If we're not course staff, we shouldn't see the debug info
# If we're not course staff, we shouldn't see the debug info
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
False
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
False
,
False
,
"Bob"
)
)
resp
=
self
.
request
(
xblock
,
'render_staff_info'
,
json
.
dumps
({}))
resp
=
self
.
request
(
xblock
,
'render_staff_info'
,
json
.
dumps
({}))
self
.
assertNotIn
(
"course staff information"
,
resp
.
decode
(
'utf-8'
)
.
lower
())
self
.
assertNotIn
(
"course staff information"
,
resp
.
decode
(
'utf-8'
)
.
lower
())
...
@@ -64,7 +98,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -64,7 +98,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_course_student_debug_info
(
self
,
xblock
):
def
test_course_student_debug_info
(
self
,
xblock
):
# If we're not course staff, we shouldn't see the debug info
# If we're not course staff, we shouldn't see the debug info
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
False
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
False
,
False
,
"Bob"
)
)
resp
=
self
.
request
(
xblock
,
'render_student_info'
,
json
.
dumps
({}))
resp
=
self
.
request
(
xblock
,
'render_student_info'
,
json
.
dumps
({}))
self
.
assertIn
(
"you do not have permission"
,
resp
.
decode
(
'utf-8'
)
.
lower
())
self
.
assertIn
(
"you do not have permission"
,
resp
.
decode
(
'utf-8'
)
.
lower
())
...
@@ -81,7 +115,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -81,7 +115,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
# In this case, the runtime will tell us that we're staff,
# In this case, the runtime will tell us that we're staff,
# but no user ID will be set.
# but no user ID will be set.
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
)
resp
=
self
.
request
(
xblock
,
'render_staff_info'
,
json
.
dumps
({}))
resp
=
self
.
request
(
xblock
,
'render_staff_info'
,
json
.
dumps
({}))
self
.
assertNotIn
(
"course staff information"
,
resp
.
decode
(
'utf-8'
)
.
lower
())
self
.
assertNotIn
(
"course staff information"
,
resp
.
decode
(
'utf-8'
)
.
lower
())
...
@@ -90,7 +124,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -90,7 +124,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_staff_debug_dates_table
(
self
,
xblock
):
def
test_staff_debug_dates_table
(
self
,
xblock
):
# Simulate that we are course staff
# Simulate that we are course staff
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
)
# Verify that we can render without error
# Verify that we can render without error
...
@@ -111,7 +145,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -111,7 +145,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_staff_debug_dates_distant_past_and_future
(
self
,
xblock
):
def
test_staff_debug_dates_distant_past_and_future
(
self
,
xblock
):
# Simulate that we are course staff
# Simulate that we are course staff
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
)
# Verify that we can render without error
# Verify that we can render without error
...
@@ -123,7 +157,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -123,7 +157,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_staff_debug_student_info_no_submission
(
self
,
xblock
):
def
test_staff_debug_student_info_no_submission
(
self
,
xblock
):
# Simulate that we are course staff
# Simulate that we are course staff
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
)
request
=
namedtuple
(
'Request'
,
'params'
)
request
=
namedtuple
(
'Request'
,
'params'
)
request
.
params
=
{
"student_id"
:
"test_student"
}
request
.
params
=
{
"student_id"
:
"test_student"
}
...
@@ -135,7 +169,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -135,7 +169,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_staff_debug_student_info_peer_only
(
self
,
xblock
):
def
test_staff_debug_student_info_peer_only
(
self
,
xblock
):
# Simulate that we are course staff
# Simulate that we are course staff
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
)
bob_item
=
STUDENT_ITEM
.
copy
()
bob_item
=
STUDENT_ITEM
.
copy
()
...
@@ -175,7 +209,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -175,7 +209,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_staff_debug_student_info_self_only
(
self
,
xblock
):
def
test_staff_debug_student_info_self_only
(
self
,
xblock
):
# Simulate that we are course staff
# Simulate that we are course staff
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
)
bob_item
=
STUDENT_ITEM
.
copy
()
bob_item
=
STUDENT_ITEM
.
copy
()
...
@@ -206,7 +240,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -206,7 +240,7 @@ class TestCourseStaff(XBlockHandlerTestCase):
def
test_staff_debug_student_info_full_workflow
(
self
,
xblock
):
def
test_staff_debug_student_info_full_workflow
(
self
,
xblock
):
# Simulate that we are course staff
# Simulate that we are course staff
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
"Bob"
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
)
bob_item
=
STUDENT_ITEM
.
copy
()
bob_item
=
STUDENT_ITEM
.
copy
()
...
@@ -248,14 +282,75 @@ class TestCourseStaff(XBlockHandlerTestCase):
...
@@ -248,14 +282,75 @@ class TestCourseStaff(XBlockHandlerTestCase):
resp
=
xblock
.
render_student_info
(
request
)
resp
=
xblock
.
render_student_info
(
request
)
self
.
assertIn
(
"bob answer"
,
resp
.
body
.
lower
())
self
.
assertIn
(
"bob answer"
,
resp
.
body
.
lower
())
def
_create_mock_runtime
(
self
,
item_id
,
is_staff
,
anonymous_user_id
):
@scenario
(
'data/basic_scenario.xml'
,
user_id
=
'Bob'
)
def
test_display_schedule_training
(
self
,
xblock
):
xblock
.
rubric_assessments
.
append
(
EXAMPLE_BASED_ASSESSMENT
)
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
True
,
"Bob"
)
path
,
context
=
xblock
.
get_staff_path_and_context
()
self
.
assertEquals
(
'openassessmentblock/staff_debug/staff_debug.html'
,
path
)
self
.
assertTrue
(
context
[
'display_schedule_training'
])
@scenario
(
'data/basic_scenario.xml'
,
user_id
=
'Bob'
)
def
test_schedule_training
(
self
,
xblock
):
xblock
.
rubric_assessments
.
append
(
EXAMPLE_BASED_ASSESSMENT
)
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
True
,
"Bob"
)
response
=
self
.
request
(
xblock
,
'schedule_training'
,
json
.
dumps
({}),
response_format
=
'json'
)
self
.
assertTrue
(
response
[
'success'
])
self
.
assertTrue
(
'workflow_uuid'
in
response
)
@scenario
(
'data/basic_scenario.xml'
,
user_id
=
'Bob'
)
def
test_not_displaying_schedule_training
(
self
,
xblock
):
xblock
.
rubric_assessments
.
append
(
EXAMPLE_BASED_ASSESSMENT
)
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
path
,
context
=
xblock
.
get_staff_path_and_context
()
self
.
assertEquals
(
'openassessmentblock/staff_debug/staff_debug.html'
,
path
)
self
.
assertFalse
(
context
[
'display_schedule_training'
])
@scenario
(
'data/basic_scenario.xml'
,
user_id
=
'Bob'
)
def
test_admin_schedule_training_no_permissions
(
self
,
xblock
):
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
False
,
"Bob"
)
response
=
self
.
request
(
xblock
,
'schedule_training'
,
json
.
dumps
({}),
response_format
=
'json'
)
self
.
assertFalse
(
response
[
'success'
])
self
.
assertTrue
(
'permission'
in
response
[
'msg'
])
@patch.object
(
ai_api
,
"train_classifiers"
)
@scenario
(
'data/basic_scenario.xml'
,
user_id
=
'Bob'
)
def
test_admin_schedule_training_error
(
self
,
xblock
,
mock_api
):
mock_api
.
side_effect
=
AIError
(
"Oh no!"
)
xblock
.
rubric_assessments
.
append
(
EXAMPLE_BASED_ASSESSMENT
)
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
True
,
"Bob"
)
response
=
self
.
request
(
xblock
,
'schedule_training'
,
json
.
dumps
({}),
response_format
=
'json'
)
self
.
assertFalse
(
response
[
'success'
])
self
.
assertTrue
(
'error'
in
response
[
'msg'
])
@scenario
(
'data/basic_scenario.xml'
,
user_id
=
'Bob'
)
def
test_no_example_based_assessment
(
self
,
xblock
):
xblock
.
xmodule_runtime
=
self
.
_create_mock_runtime
(
xblock
.
scope_ids
.
usage_id
,
True
,
True
,
"Bob"
)
response
=
self
.
request
(
xblock
,
'schedule_training'
,
json
.
dumps
({}),
response_format
=
'json'
)
self
.
assertFalse
(
response
[
'success'
])
self
.
assertTrue
(
'not configured'
in
response
[
'msg'
])
def
_create_mock_runtime
(
self
,
item_id
,
is_staff
,
is_admin
,
anonymous_user_id
):
mock_runtime
=
Mock
(
mock_runtime
=
Mock
(
course_id
=
'test_course'
,
course_id
=
'test_course'
,
item_id
=
item_id
,
item_id
=
item_id
,
anonymous_student_id
=
'Bob'
,
anonymous_student_id
=
'Bob'
,
user_is_staff
=
is_staff
,
user_is_staff
=
is_staff
,
user_is_admin
=
is_admin
,
service
=
lambda
self
,
service
:
Mock
(
service
=
lambda
self
,
service
:
Mock
(
get_anonymous_student_id
=
lambda
user_id
,
course_id
:
anonymous_user_id
get_anonymous_student_id
=
lambda
user_id
,
course_id
:
anonymous_user_id
)
)
)
)
return
mock_runtime
return
mock_runtime
\ 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