react gb: implement 'message students who'
closes CNVS-22024 test plan: verify the 'Message Students Who...' dialog works in the react gradebook AND in the normal gradebook Change-Id: Iec1201cc0a95816b9b9497a53a3d0c2c1406cacc Reviewed-on: https://gerrit.instructure.com/64376 Tested-by: Jenkins Reviewed-by: Dylan Ross <dross@instructure.com> QA-Review: Jason Carter <jcarter@instructure.com> Product-Review: Spencer Olson <solson@instructure.com>
This commit is contained in:
parent
da6bcd1019
commit
05f776837c
|
@ -10,12 +10,13 @@ define [
|
|||
'jst/re_upload_submissions_form'
|
||||
'underscore'
|
||||
'compiled/behaviors/authenticity_token'
|
||||
'jsx/gradebook/grid/helpers/messageStudentsWhoHelper'
|
||||
'jquery.instructure_forms'
|
||||
'jqueryui/dialog'
|
||||
'jquery.instructure_misc_helpers'
|
||||
'jquery.instructure_misc_plugins'
|
||||
'compiled/jquery.kylemenu'
|
||||
], (I18n, $, messageStudents, AssignmentDetailsDialog, AssignmentMuter, SetDefaultGradeDialog, CurveGradesDialog, gradebookHeaderMenuTemplate, re_upload_submissions_form, _, authenticity_token) ->
|
||||
], (I18n, $, messageStudents, AssignmentDetailsDialog, AssignmentMuter, SetDefaultGradeDialog, CurveGradesDialog, gradebookHeaderMenuTemplate, re_upload_submissions_form, _, authenticity_token, MessageStudentsWhoHelper) ->
|
||||
|
||||
class GradebookHeaderMenu
|
||||
constructor: (@assignment, @$trigger, @gradebook) ->
|
||||
|
@ -85,48 +86,8 @@ define [
|
|||
score: sub?.score
|
||||
submitted_at: sub?.submitted_at
|
||||
|
||||
submissionTypes = assignment.submission_types
|
||||
hasSubmission = true
|
||||
if submissionTypes.length == 0
|
||||
hasSubmission = false
|
||||
else if submissionTypes.length == 1
|
||||
hasSubmission = not _.include(["none", "on_paper"], submissionTypes[0])
|
||||
options = [
|
||||
{text: I18n.t("students_who.havent_submitted_yet", "Haven't submitted yet")}
|
||||
{text: I18n.t("students_who.havent_been_graded", "Haven't been graded")}
|
||||
{text: I18n.t("students_who.scored_less_than", "Scored less than"), cutoff: true}
|
||||
{text: I18n.t("students_who.scored_more_than", "Scored more than"), cutoff: true}
|
||||
]
|
||||
options.splice 0, 1 unless hasSubmission
|
||||
|
||||
window.messageStudents
|
||||
options: options
|
||||
title: assignment.name
|
||||
points_possible: assignment.points_possible
|
||||
students: students
|
||||
context_code: "course_"+assignment.course_id
|
||||
callback: (selected, cutoff, students) ->
|
||||
students = $.grep students, ($student, idx) ->
|
||||
student = $student.user_data
|
||||
if selected == I18n.t("students_who.havent_submitted_yet", "Haven't submitted yet")
|
||||
!student.submitted_at
|
||||
else if selected == I18n.t("students_who.havent_been_graded", "Haven't been graded")
|
||||
!student.score?
|
||||
else if selected == I18n.t("students_who.scored_less_than", "Scored less than")
|
||||
student.score? and student.score != "" and cutoff? and student.score < cutoff
|
||||
else if selected == I18n.t("students_who.scored_more_than", "Scored more than")
|
||||
student.score? and student.score != "" and cutoff? and student.score > cutoff
|
||||
$.map students, (student) -> student.user_data.id
|
||||
subjectCallback: (selected, cutoff) =>
|
||||
cutoff = cutoff || ''
|
||||
if selected == I18n.t('students_who.not_submitted_yet', "Haven't submitted yet")
|
||||
I18n.t('students_who.no_submission_for', 'No submission for %{assignment}', assignment: assignment.name)
|
||||
else if selected == I18n.t("students_who.havent_been_graded", "Haven't been graded")
|
||||
I18n.t('students_who.no_grade_for', 'No grade for %{assignment}', assignment: assignment.name)
|
||||
else if selected == I18n.t('students_who.scored_less_than', "Scored less than")
|
||||
I18n.t('students_who.scored_less_than_on', 'Scored less than %{cutoff} on %{assignment}', assignment: assignment.name, cutoff: cutoff)
|
||||
else if selected == I18n.t('students_who.scored_more_than', "Scored more than")
|
||||
I18n.t('students_who.scored_more_than_on', 'Scored more than %{cutoff} on %{assignment}', assignment: assignment.name, cutoff: cutoff)
|
||||
settings = MessageStudentsWhoHelper.settings(assignment, students)
|
||||
messageStudents(settings)
|
||||
|
||||
setDefaultGrade: (opts={
|
||||
assignment:@assignment,
|
||||
|
|
|
@ -92,6 +92,7 @@ define([
|
|||
var columnType = columnData.columnType,
|
||||
assignment = columnData.assignment,
|
||||
enrollments = columnData.enrollments,
|
||||
submissions = columnData.submissions,
|
||||
key, dropdownOptionsId;
|
||||
if (assignment) {
|
||||
key = 'assignment-' + assignment.id;
|
||||
|
@ -101,7 +102,8 @@ define([
|
|||
idToAppendTo='gradebook_grid' screenreaderText={I18n.t('Assignment Options')}
|
||||
defaultClassNames='gradebook-header-drop' options={{ noButton: true }}>
|
||||
<AssignmentHeaderDropdownOptions key={dropdownOptionsId}
|
||||
idAttribute={dropdownOptionsId} assignment={assignment} enrollments={enrollments}/>
|
||||
idAttribute={dropdownOptionsId} assignment={assignment}
|
||||
enrollments={enrollments} submissions={submissions}/>
|
||||
</GradebookKyleMenu>
|
||||
);
|
||||
} else if (columnType === 'total') {
|
||||
|
|
|
@ -5,13 +5,15 @@ define([
|
|||
'jsx/gradebook/grid/components/dropdown_components/headerDropdownOption',
|
||||
'jsx/gradebook/grid/constants',
|
||||
'jsx/gradebook/grid/components/dropdown_components/setDefaultGradeOption',
|
||||
'jsx/gradebook/grid/components/dropdown_components/muteAssignmentOption'
|
||||
], function (React, _, I18n, HeaderDropdownOption, GradebookConstants, SetDefaultGradeOption, MuteAssignmentOption) {
|
||||
'jsx/gradebook/grid/components/dropdown_components/muteAssignmentOption',
|
||||
'jsx/gradebook/grid/components/dropdown_components/messageStudentsWhoOption'
|
||||
], function (React, _, I18n, HeaderDropdownOption, GradebookConstants, SetDefaultGradeOption, MuteAssignmentOption, MessageStudentsWhoOption) {
|
||||
|
||||
var AssignmentHeaderDropdownOptions = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
assignment: React.PropTypes.object.isRequired,
|
||||
submissions: React.PropTypes.object.isRequired,
|
||||
idAttribute: React.PropTypes.string.isRequired,
|
||||
enrollments: React.PropTypes.array.isRequired
|
||||
},
|
||||
|
@ -35,7 +37,7 @@ define([
|
|||
dropdownOptions.push(downloadSubmissionsOption);
|
||||
}
|
||||
|
||||
if (GradebookConstants.gradebook_is_editable &&assignment.submissions_downloads > 0 ) {
|
||||
if (GradebookConstants.gradebook_is_editable && assignment.submissions_downloads > 0 ) {
|
||||
reuploadSubmissionsOption = { title: I18n.t('Re-Upload Submissions'), action: 'reuploadSubmissions' };
|
||||
dropdownOptions.push(reuploadSubmissionsOption);
|
||||
}
|
||||
|
@ -53,6 +55,7 @@ define([
|
|||
var options = this.getDropdownOptions(),
|
||||
assignment = this.props.assignment,
|
||||
enrollments = this.props.enrollments,
|
||||
submissions = this.props.submissions,
|
||||
key;
|
||||
return (
|
||||
<ul id={this.props.idAttribute} className="gradebook-header-menu">
|
||||
|
@ -70,6 +73,12 @@ define([
|
|||
enrollments={enrollments}
|
||||
contextId={GradebookConstants.context_id}/>
|
||||
);
|
||||
} else if (listItem.action === 'messageStudentsWho') {
|
||||
return (
|
||||
<MessageStudentsWhoOption
|
||||
key={key} title={listItem.title} assignment={assignment}
|
||||
enrollments={enrollments} submissions={submissions}/>
|
||||
);
|
||||
} else {
|
||||
return(
|
||||
<HeaderDropdownOption
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
define([
|
||||
'react',
|
||||
'underscore',
|
||||
'jsx/gradebook/grid/components/dropdown_components/headerDropdownOption',
|
||||
'jsx/gradebook/grid/helpers/submissionsHelper',
|
||||
'timezone',
|
||||
'jsx/gradebook/grid/helpers/messageStudentsWhoHelper',
|
||||
'message_students'
|
||||
], function (React, _, HeaderDropdownOption, SubmissionsHelper, tz, MessageStudentsWhoHelper) {
|
||||
|
||||
var MessageStudentsWhoOption = React.createClass({
|
||||
propTypes: {
|
||||
title: React.PropTypes.string.isRequired,
|
||||
assignment: React.PropTypes.object.isRequired,
|
||||
enrollments: React.PropTypes.array.isRequired,
|
||||
submissions: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
openDialog() {
|
||||
var submissions = SubmissionsHelper.
|
||||
submissionsForAssignment(this.props.submissions, this.props.assignment.id);
|
||||
|
||||
var students = _.map(submissions, (submission) => {
|
||||
submission.submitted_at = tz.parse(submission.submitted_at);
|
||||
var enrollment = _.find(
|
||||
this.props.enrollments,
|
||||
enrollment => enrollment.user_id === submission.user_id
|
||||
);
|
||||
if(enrollment) submission.name = enrollment.user.name;
|
||||
return submission;
|
||||
});
|
||||
|
||||
var settings = MessageStudentsWhoHelper.settings(this.props.assignment, students);
|
||||
messageStudents(settings);
|
||||
},
|
||||
|
||||
render() {
|
||||
return(
|
||||
<HeaderDropdownOption
|
||||
handleClick={this.openDialog}
|
||||
key={'messageStudentsWho' + this.props.assignment.id}
|
||||
title={this.props.title}/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return MessageStudentsWhoOption;
|
||||
});
|
|
@ -21,7 +21,8 @@ define([
|
|||
'jsx/gradebook/grid/stores/tableStore',
|
||||
'jsx/gradebook/grid/actions/sectionsActions',
|
||||
'jsx/gradebook/grid/helpers/columnArranger',
|
||||
'vendor/spin'
|
||||
'vendor/spin',
|
||||
'jsx/gradebook/grid/helpers/submissionsHelper'
|
||||
], function (
|
||||
React,
|
||||
FixedDataTable,
|
||||
|
@ -45,7 +46,8 @@ define([
|
|||
TableStore,
|
||||
SectionsActions,
|
||||
ColumnArranger,
|
||||
Spinner
|
||||
Spinner,
|
||||
SubmissionsHelper
|
||||
){
|
||||
var Table = FixedDataTable.Table,
|
||||
Column = FixedDataTable.Column,
|
||||
|
@ -150,12 +152,14 @@ define([
|
|||
var columnIdentifier = columnId || columnType,
|
||||
columnWidth = this.getColumnWidth(columnIdentifier),
|
||||
enrollments = this.state.tableData.students,
|
||||
submissions = this.state.tableData.submissions,
|
||||
columnData = {
|
||||
columnType: columnType,
|
||||
activeCell: this.state.currentCellIndex,
|
||||
setActiveCell: KeyboardNavigationActions.setActiveCell,
|
||||
assignment: assignment,
|
||||
enrollments: enrollments
|
||||
enrollments: enrollments,
|
||||
submissions: submissions
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
define([
|
||||
'underscore',
|
||||
'i18n!gradebook2',
|
||||
], function (_, I18n) {
|
||||
var MessageStudentsWhoHelper = {
|
||||
settings: function(assignment, students) {
|
||||
return {
|
||||
options: this.options(assignment),
|
||||
title: assignment.name,
|
||||
points_possible: assignment.points_possible,
|
||||
students: students,
|
||||
context_code: "course_" + assignment.course_id,
|
||||
callback: this.callbackFn.bind(this),
|
||||
subjectCallback: this.generateSubjectCallbackFn(assignment)
|
||||
}
|
||||
},
|
||||
|
||||
options: function(assignment) {
|
||||
var options = this.allOptions();
|
||||
var noSubmissions = !this.hasSubmission(assignment);
|
||||
if(noSubmissions) options.splice(0,1);
|
||||
return options;
|
||||
},
|
||||
|
||||
allOptions: function() {
|
||||
return [
|
||||
{
|
||||
text: I18n.t("students_who.havent_submitted_yet", "Haven't submitted yet"),
|
||||
subjectFn: (assignment) => I18n.t('students_who.no_submission_for', 'No submission for %{assignment}', { assignment: assignment.name }),
|
||||
criteriaFn: (student) => !student.submitted_at
|
||||
},
|
||||
{
|
||||
text: I18n.t("students_who.havent_been_graded", "Haven't been graded"),
|
||||
subjectFn: (assignment) => I18n.t('students_who.no_grade_for', 'No grade for %{assignment}', { assignment: assignment.name }),
|
||||
criteriaFn: (student) => !this.exists(student.score)
|
||||
},
|
||||
{
|
||||
text: I18n.t("students_who.scored_less_than", "Scored less than"),
|
||||
cutoff: true,
|
||||
subjectFn: (assignment, cutoff) => I18n.t('students_who.scored_less_than_on', 'Scored less than %{cutoff} on %{assignment}', { assignment: assignment.name, cutoff: cutoff }),
|
||||
criteriaFn: (student, cutoff) => this.scoreWithCutoff(student, cutoff) && student.score < cutoff
|
||||
},
|
||||
{
|
||||
text: I18n.t("students_who.scored_more_than", "Scored more than"),
|
||||
cutoff: true,
|
||||
subjectFn: (assignment, cutoff) => I18n.t('students_who.scored_more_than_on', 'Scored more than %{cutoff} on %{assignment}', { assignment: assignment.name, cutoff: cutoff }),
|
||||
criteriaFn: (student, cutoff) => this.scoreWithCutoff(student, cutoff) && student.score > cutoff
|
||||
}
|
||||
];
|
||||
},
|
||||
|
||||
hasSubmission: function(assignment) {
|
||||
var submissionTypes = assignment.submission_types;
|
||||
if(submissionTypes.length === 0) return false;
|
||||
|
||||
return _.any(submissionTypes, (submissionType) => {
|
||||
return submissionType !== 'none' && submissionType !== 'on_paper';
|
||||
});
|
||||
},
|
||||
|
||||
exists: function(value) {
|
||||
return !_.isUndefined(value) && !_.isNull(value);
|
||||
},
|
||||
|
||||
scoreWithCutoff: function(student, cutoff) {
|
||||
return this.exists(student.score)
|
||||
&& student.score !== ''
|
||||
&& this.exists(cutoff);
|
||||
},
|
||||
|
||||
callbackFn: function(selected, cutoff, students) {
|
||||
var criteriaFn = this.findOptionByText(selected).criteriaFn;
|
||||
var students = _.filter(students, student => criteriaFn(student.user_data, cutoff));
|
||||
return _.map(students, student => student.user_data.id);
|
||||
},
|
||||
|
||||
findOptionByText: function(text) {
|
||||
return _.find(this.allOptions(), option => option.text === text);
|
||||
},
|
||||
|
||||
generateSubjectCallbackFn: function(assignment) {
|
||||
return (selected, cutoff) => {
|
||||
var cutoffString = cutoff || '';
|
||||
var subjectFn = this.findOptionByText(selected).subjectFn;
|
||||
return subjectFn(assignment, cutoffString);
|
||||
}
|
||||
}
|
||||
};
|
||||
return MessageStudentsWhoHelper;
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
define([
|
||||
'underscore',
|
||||
], function (_) {
|
||||
var SubmissionsHelper = {
|
||||
submissionsForAssignment: function(submissionGroups, assignmentId) {
|
||||
var submissions = this.extractSubmissions(submissionGroups);
|
||||
return _.filter(
|
||||
submissions,
|
||||
submission => submission.assignment_id.toString() === assignmentId.toString()
|
||||
);
|
||||
},
|
||||
|
||||
extractSubmissions: function(submissionGroups) {
|
||||
return _.chain(submissionGroups)
|
||||
.values()
|
||||
.flatten()
|
||||
.pluck('submissions')
|
||||
.flatten()
|
||||
.value();
|
||||
}
|
||||
};
|
||||
return SubmissionsHelper;
|
||||
});
|
|
@ -54,7 +54,8 @@ define [
|
|||
deepEqual displayedDueDate(component), 'No due date'
|
||||
|
||||
test 'displays the override due date if the assignment has no due date and one' +
|
||||
'override with a due date', ->
|
||||
' override with a due date', ->
|
||||
@stub($, 'sameYear').returns(true)
|
||||
props = defaultProps()
|
||||
props.columnData.assignment.due_at = null
|
||||
props.columnData.assignment.overrides = [
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
define [
|
||||
'jsx/gradebook/grid/components/dropdown_components/messageStudentsWhoOption'
|
||||
'jsx/gradebook/grid/helpers/submissionsHelper'
|
||||
'jsx/gradebook/grid/helpers/messageStudentsWhoHelper'
|
||||
'timezone'
|
||||
], (MessageStudentsWhoOption, SubmissionsHelper, MessageStudentsWhoHelper, tz) ->
|
||||
|
||||
wrapper = document.getElementById('fixtures')
|
||||
|
||||
renderComponent = ->
|
||||
assignment = { id: '1', }
|
||||
props =
|
||||
title: 'Message Students Who...'
|
||||
assignment: assignment
|
||||
enrollments: [{ course_id: '1', user_id: '3', user: { id: '3', name: 'Dora' } }]
|
||||
submissions: {}
|
||||
componentFactory = React.createFactory(MessageStudentsWhoOption)
|
||||
React.render(componentFactory(props), wrapper)
|
||||
|
||||
module 'MessageStudentsWhoOption',
|
||||
setup: ->
|
||||
@component = renderComponent()
|
||||
teardown: ->
|
||||
React.unmountComponentAtNode wrapper
|
||||
|
||||
test 'mounts on build', ->
|
||||
ok renderComponent().isMounted()
|
||||
|
||||
test 'openDialog calls MessageStudentsWhoHelper#settings with the correct arguments', ->
|
||||
@stub SubmissionsHelper, 'submissionsForAssignment', ->
|
||||
[{ user_id: '3', submitted_at: '2014-04-20T00:00:00Z' }]
|
||||
@stub window, 'messageStudents'
|
||||
settingsStub = @stub MessageStudentsWhoHelper, 'settings'
|
||||
@component.openDialog()
|
||||
ok settingsStub.calledOnce
|
||||
expectedStudents = [{ user_id: "3", submitted_at: tz.parse('2014-04-20T00:00:00Z'), name: "Dora" }]
|
||||
deepEqual settingsStub.args[0][0], @component.props.assignment
|
||||
deepEqual settingsStub.args[0][1], expectedStudents
|
|
@ -1,8 +1,7 @@
|
|||
define [
|
||||
'react'
|
||||
'jsx/gradebook/grid/helpers/datesHelper'
|
||||
'underscore'
|
||||
], (React, DatesHelper, _) ->
|
||||
], (DatesHelper, _) ->
|
||||
|
||||
defaultAssignment = ->
|
||||
{
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
define [
|
||||
'jsx/gradebook/grid/helpers/messageStudentsWhoHelper'
|
||||
'underscore'
|
||||
], (MessageStudentsWhoHelper, _) ->
|
||||
|
||||
module "messageStudentsWhoHelper#options",
|
||||
setup: ->
|
||||
@assignment = { id: '1', name: 'Shootbags'}
|
||||
|
||||
test "Includes the 'Haven't been graded' option if there are submissions", ->
|
||||
@stub(MessageStudentsWhoHelper, 'hasSubmission', -> true)
|
||||
options = MessageStudentsWhoHelper.options(@assignment)
|
||||
deepEqual options[1].text, "Haven't been graded"
|
||||
|
||||
test "Does not include the 'Haven't been graded' option if there are no submissions", ->
|
||||
@stub(MessageStudentsWhoHelper, 'hasSubmission', -> false)
|
||||
options = MessageStudentsWhoHelper.options(@assignment)
|
||||
deepEqual options[1].text, "Scored less than"
|
||||
|
||||
module "messageStudentsWhoHelper#hasSubmission"
|
||||
|
||||
test "returns false if there are no submission types", ->
|
||||
assignment = { id: '1', name: 'Shootbags', submission_types: [] }
|
||||
hasSubmission = MessageStudentsWhoHelper.hasSubmission(assignment)
|
||||
deepEqual hasSubmission, false
|
||||
|
||||
test "returns false if the only submission type is 'none'", ->
|
||||
assignment = { id: '1', name: 'Shootbags', submission_types: ['none'] }
|
||||
hasSubmission = MessageStudentsWhoHelper.hasSubmission(assignment)
|
||||
deepEqual hasSubmission, false
|
||||
|
||||
test "returns false if the only submission type is 'on_paper'", ->
|
||||
assignment = { id: '1', name: 'Shootbags', submission_types: ['on_paper'] }
|
||||
hasSubmission = MessageStudentsWhoHelper.hasSubmission(assignment)
|
||||
deepEqual hasSubmission, false
|
||||
|
||||
test "returns false if the only submission types are 'none' and 'on_paper'", ->
|
||||
assignment = { id: '1', name: 'Shootbags', submission_types: ['none', 'on_paper'] }
|
||||
hasSubmission = MessageStudentsWhoHelper.hasSubmission(assignment)
|
||||
deepEqual hasSubmission, false
|
||||
|
||||
test "returns true if there is at least one submission that is not of type 'non' or 'on_paper'", ->
|
||||
assignment = { id: '1', name: 'Shootbags', submission_types: ['online_quiz'] }
|
||||
hasSubmission = MessageStudentsWhoHelper.hasSubmission(assignment)
|
||||
deepEqual hasSubmission, true
|
||||
|
||||
module "messageStudentsWhoHelper#scoreWithCutoff"
|
||||
|
||||
test "returns true if the student has a non-empty-string score and a cutoff", ->
|
||||
student = { score: 6 }
|
||||
cutoff = 5
|
||||
scoreWithCutoff = MessageStudentsWhoHelper.scoreWithCutoff(student, cutoff)
|
||||
deepEqual scoreWithCutoff, true
|
||||
|
||||
test "returns false if the student has an empty-string score", ->
|
||||
student = { score: '' }
|
||||
cutoff = 5
|
||||
scoreWithCutoff = MessageStudentsWhoHelper.scoreWithCutoff(student, cutoff)
|
||||
deepEqual scoreWithCutoff, false
|
||||
|
||||
test "returns false if the student score is null or undefined", ->
|
||||
student = {}
|
||||
cutoff = 5
|
||||
scoreWithCutoff = MessageStudentsWhoHelper.scoreWithCutoff(student, cutoff)
|
||||
deepEqual scoreWithCutoff, false
|
||||
student.score = null
|
||||
scoreWithCutoff = MessageStudentsWhoHelper.scoreWithCutoff(student, cutoff)
|
||||
deepEqual scoreWithCutoff, false
|
||||
|
||||
test "returns false if the cutoff is null or undefined", ->
|
||||
student = { score: 5 }
|
||||
scoreWithCutoff = MessageStudentsWhoHelper.scoreWithCutoff(student, cutoff)
|
||||
deepEqual scoreWithCutoff, false
|
||||
cutoff = null
|
||||
scoreWithCutoff = MessageStudentsWhoHelper.scoreWithCutoff(student, cutoff)
|
||||
deepEqual scoreWithCutoff, false
|
||||
|
||||
module 'messageStudentsWhoHelper#callbackFn'
|
||||
|
||||
test "returns the student ids filtered by the correct criteria", ->
|
||||
option = { criteriaFn: (student, cutoff) -> student.score > cutoff }
|
||||
@stub(MessageStudentsWhoHelper, 'findOptionByText', -> option)
|
||||
students = [{ user_data: { id: '1', score: 8 } }, { user_data: { id: '2', score: 4 } }]
|
||||
cutoff = 5
|
||||
selected = "Scored more than"
|
||||
filteredStudents = MessageStudentsWhoHelper.callbackFn(selected, cutoff, students)
|
||||
deepEqual filteredStudents.length, 1
|
||||
deepEqual filteredStudents[0], '1'
|
||||
|
||||
|
||||
module 'messageStudentsWhoHelper#generateSubjectCallbackFn'
|
||||
|
||||
test "generates a function that returns the subject string", ->
|
||||
option = { subjectFn: (assignment, cutoff) -> 'name: ' + assignment.name + ', cutoff: ' + cutoff }
|
||||
@stub(MessageStudentsWhoHelper, 'findOptionByText', -> option)
|
||||
assignment = { id: '1', name: 'Shootbags' }
|
||||
cutoff = 5
|
||||
subjectCallbackFn = MessageStudentsWhoHelper.generateSubjectCallbackFn(assignment)
|
||||
deepEqual subjectCallbackFn(assignment,cutoff), 'name: Shootbags, cutoff: 5'
|
||||
|
||||
module 'messageStudentsWhoHelper#settings'
|
||||
|
||||
test "returns an object with the expected settings", ->
|
||||
assignment =
|
||||
id: '1'
|
||||
name: 'Shootbags'
|
||||
points_possible: 5
|
||||
course_id: '5'
|
||||
students = [{ id: '1', name: 'Dora' }]
|
||||
self =
|
||||
options: -> 'stuff'
|
||||
callbackFn: -> 'call me back!'
|
||||
generateSubjectCallbackFn: -> -> 'function inception'
|
||||
settingsFn = MessageStudentsWhoHelper.settings.bind(self)
|
||||
settings = settingsFn(assignment, students)
|
||||
|
||||
settingsKeys = _.keys settings
|
||||
expectedKeys = ["options", "title", "points_possible",
|
||||
"students", "context_code", "callback", "subjectCallback"]
|
||||
|
||||
deepEqual settingsKeys, expectedKeys
|
Loading…
Reference in New Issue