stop using anonymous moderated marking feature flag

fixes GRADE-976

test plan:
* Make sure the AMM flag is off
* All AMM features should be visible and work
* The Anonymous Marking and Moderated feature flags should be visible
* Toggling the AMM feature flag should do nothing

Change-Id: Ie0c52c23748389c6f5df5b85e8580bdf474c0a52
Reviewed-on: https://gerrit.instructure.com/152067
Reviewed-by: Adrian Packel <apackel@instructure.com>
Tested-by: Jenkins
Reviewed-by: Derek Bender <djbender@instructure.com>
QA-Review: James Butters <jbutters@instructure.com>
Product-Review: Keith T. Garner <kgarner@instructure.com>
This commit is contained in:
Neil Gupta 2018-05-31 14:58:50 -05:00
parent 587e64616e
commit 6a659fbaa8
113 changed files with 1072 additions and 2870 deletions

View File

@ -101,7 +101,7 @@ export default class SubmissionDetailsDialog {
buildSpeedGraderUrl = () => {
const assignmentParam = `assignment_id=${this.assignment.id}`
const speedGraderUrlParams = this.options.anonymous_moderated_marking_enabled && this.assignment.anonymous_grading
const speedGraderUrlParams = this.assignment.anonymous_grading
? assignmentParam
: `${assignmentParam}#{"student_id":"${this.student.id}"}`
return encodeURI(`${this.options.context_url}/gradebook/speed_grader?${speedGraderUrlParams}`)

View File

@ -819,7 +819,6 @@ define [
hasGradingPeriods: !!@has_grading_periods
selectedGradingPeriodID: @get('selectedGradingPeriod.id') || '0'
isAdmin: ENV.current_user_roles && _.contains(ENV.current_user_roles, "admin")
anonymousModeratedMarkingEnabled: ENV.GRADEBOOK_OPTIONS.anonymous_moderated_marking_enabled
)
map.setup(@get('students').toArray(), @get('assignmentsFromGroups.content').toArray())
@set('submissionStateMap', map)

View File

@ -317,9 +317,8 @@ define [
for assignment in group.assignments
assignment.assignment_group = group
assignment.due_at = tz.parse(assignment.due_at)
if @options.anonymous_moderated_marking_enabled
assignment.moderation_in_progress = assignment.moderated_grading and !assignment.grades_published
assignment.hide_grades_when_muted = assignment.anonymous_grading
assignment.moderation_in_progress = assignment.moderated_grading and !assignment.grades_published
assignment.hide_grades_when_muted = assignment.anonymous_grading
@updateAssignmentEffectiveDueDates(assignment)
@assignments[assignment.id] = assignment

View File

@ -182,8 +182,7 @@ define [
canUnmute: =>
not (
@gradebook.options.anonymous_moderated_marking_enabled and
@assignment.muted and
@assignment.moderated_grading and
not @assignment.grades_published
@assignment?.muted and
@assignment?.moderated_grading and
not @assignment?.grades_published
)

View File

@ -1186,7 +1186,6 @@ define [
hasGradingPeriods: @gradingPeriodSet?
selectedGradingPeriodID: @getGradingPeriodToShow()
isAdmin: isAdmin()
anonymousModeratedMarkingEnabled: @options.anonymous_moderated_marking_enabled
initPostGradesStore: ->
@postGradesStore = PostGradesStore
@ -2159,7 +2158,6 @@ define [
submissionState = @submissionStateMap.getSubmissionState({ user_id: studentId, assignment_id: assignmentId })
isGroupWeightZero = @assignmentGroups[assignment.assignment_group_id].group_weight == 0
anonymousModeratedMarkingEnabled: @options.anonymous_moderated_marking_enabled
assignment: ConvertCase.camelize(assignment)
colors: @getGridColors()
comments: comments
@ -2681,8 +2679,7 @@ define [
manager = new AssignmentMuterDialogManager(
assignment,
"#{@options.context_url}/assignments/#{assignmentId}/mute",
@contentLoadStates.submissionsLoaded,
@options.anonymous_moderated_marking_enabled
@contentLoadStates.submissionsLoaded
)
{

View File

@ -382,7 +382,6 @@ define [
conditionalReleaseServiceEnabled: ENV?.CONDITIONAL_RELEASE_SERVICE_ENABLED or false
lockedItems: @lockedItems
anonymousGradingEnabled: ENV?.ANONYMOUS_GRADING_ENABLED or false
anonymousModeratedMarkingEnabled: ENV.ANONYMOUS_MODERATED_MARKING_ENABLED or false
_attachEditorToDescription: =>
return if @lockedItems.content
@ -520,9 +519,8 @@ define [
errors = @_validateSubmissionTypes data, errors
errors = @_validateAllowedExtensions data, errors
errors = @assignmentGroupSelector.validateBeforeSave(data, errors)
if ENV.ANONYMOUS_MODERATED_MARKING_ENABLED
Object.assign(errors, @validateFinalGrader(data))
Object.assign(errors, @validateGraderCount(data))
Object.assign(errors, @validateFinalGrader(data))
Object.assign(errors, @validateGraderCount(data))
unless ENV?.IS_LARGE_ROSTER
errors = @groupCategorySelector.validateBeforeSave(data, errors)
errors = @_validatePointsPossible(data, errors)

View File

@ -2206,17 +2206,14 @@ class ApplicationController < ActionController::Base
js_env hash
end
def set_js_assignment_data(include_assignment_permissions: false)
def set_js_assignment_data
rights = [:manage_assignments, :manage_grades, :read_grades, :manage]
permissions = @context.rights_status(@current_user, *rights)
permissions[:manage_course] = permissions[:manage]
permissions[:manage] = permissions[:manage_assignments]
if include_assignment_permissions
permissions[:by_assignment_id] = @context.assignments.map do |assignment|
[assignment.id, {update: assignment.user_can_update?(@current_user, session)}]
end.to_h
end
permissions[:by_assignment_id] = @context.assignments.map do |assignment|
[assignment.id, {update: assignment.user_can_update?(@current_user, session)}]
end.to_h
js_env({
:URLS => {

View File

@ -52,10 +52,7 @@ class AssignmentsController < ApplicationController
# because of course import/copy.
@context.require_assignment_group
set_js_assignment_data(
include_assignment_permissions: @context.root_account.feature_enabled?(:anonymous_moderated_marking)
)
set_js_assignment_data
set_tutorial_js_env
hash = {
WEIGHT_FINAL_GRADES: @context.apply_group_weights?,
@ -192,21 +189,13 @@ class AssignmentsController < ApplicationController
add_crumb(@assignment.title, polymorphic_url([@context, @assignment]))
add_crumb(t('Moderate'))
if @assignment.root_account.feature_enabled?(:anonymous_moderated_marking)
css_bundle :assignment_grade_summary
js_bundle :assignment_grade_summary
js_env(new_moderate_env)
css_bundle :assignment_grade_summary
js_bundle :assignment_grade_summary
js_env(new_moderate_env)
@page_title = @assignment.title
@page_title = @assignment.title
render html: "", layout: true
else
js_env(old_moderate_env)
respond_to do |format|
format.html { render }
end
end
render html: "", layout: true
end
def downloadable_submissions?(current_user, context, assignment)
@ -366,10 +355,7 @@ class AssignmentsController < ApplicationController
@assignment = @context.assignments.active.find(params[:assignment_id])
toggle_value = params[:status] == 'true'
unless toggle_value
return render_unauthorized_action if !@assignment.grades_published? && @assignment.root_account.feature_enabled?(:anonymous_moderated_marking)
end
return render_unauthorized_action if !toggle_value && !@assignment.grades_published?
method = toggle_value ? :mute! : :unmute!
@ -477,7 +463,6 @@ class AssignmentsController < ApplicationController
post_to_sis = Assignment.sis_grade_export_enabled?(@context)
hash = {
ANONYMOUS_MODERATED_MARKING_ENABLED: @context.root_account.feature_enabled?(:anonymous_moderated_marking),
ASSIGNMENT_GROUPS: json_for_assignment_groups,
ASSIGNMENT_INDEX_URL: polymorphic_url([@context, :assignments]),
ASSIGNMENT_OVERRIDES: assignment_overrides_json(
@ -530,11 +515,9 @@ class AssignmentsController < ApplicationController
hash[:active_grading_periods] = GradingPeriod.json_for(@context, @current_user)
end
hash[:ANONYMOUS_GRADING_ENABLED] =
hash[:ANONYMOUS_MODERATED_MARKING_ENABLED] && @context.feature_enabled?(:anonymous_marking)
hash[:ANONYMOUS_GRADING_ENABLED] = @context.feature_enabled?(:anonymous_marking)
hash[:MODERATED_GRADING_ENABLED] =
hash[:ANONYMOUS_MODERATED_MARKING_ENABLED] && @context.feature_enabled?(:moderated_grading)
hash[:MODERATED_GRADING_ENABLED] = @context.feature_enabled?(:moderated_grading)
append_sis_data(hash)
if context.is_a?(Course)
@ -586,31 +569,6 @@ class AssignmentsController < ApplicationController
}
end
def old_moderate_env
can_edit_grades = @context.grants_right?(@current_user, :manage_grades)
{
ANONYMOUS_MODERATED_MARKING_ENABLED: false,
ASSIGNMENT_MUTED: @assignment.muted?,
ASSIGNMENT_TITLE: @assignment.title,
COURSE_ID: @context.id,
GRADES_PUBLISHED: @assignment.grades_published?,
PERMISSIONS: {
edit_grades: can_edit_grades,
view_grades: can_edit_grades || @context.grants_right?(@current_user, :view_all_grades)
},
STUDENT_CONTEXT_CARDS_ENABLED: @domain_root_account.feature_enabled?(:student_context_cards),
URLS: {
add_moderated_students: api_v1_add_moderated_students_url({course_id: @context.id, assignment_id: @assignment.id}),
assignment_speedgrader_url: speed_grader_course_gradebook_url({course_id: @context.id, assignment_id: @assignment.id}),
list_gradeable_students: api_v1_course_assignment_gradeable_students_url({course_id: @context.id, assignment_id: @assignment.id}) + "?include[]=provisional_grades&per_page=50",
provisional_grades_base_url: polymorphic_url([:api_v1, @context, @assignment]) + "/provisional_grades",
publish_grades_url: api_v1_publish_provisional_grades_url({course_id: @context.id, assignment_id: @assignment.id}),
student_submissions_url: polymorphic_url([:api_v1, @context, @assignment, :submissions]) + "?include[]=user_summary&include[]=provisional_grades",
unmute_assignment_url: course_assignment_mute_url(course_id: @context.id, assignment_id: @assignment.id, status: 'false')
}
}
end
def tool_eula_url
@assignment.tool_settings_tool.try(:tool_proxy)&.find_service(Assignment::LTI_EULA_SERVICE, 'GET')&.endpoint
end

View File

@ -71,8 +71,6 @@ class CanvadocSessionsController < ApplicationController
private
def anonymous_grading_enabled?(attachment)
return false unless @domain_root_account.feature_enabled?(:anonymous_moderated_marking)
Assignment.joins(submissions: :attachment_associations).
where(
submissions: {attachment_associations: {context_type: 'Submission', attachment: attachment}},

View File

@ -1754,9 +1754,7 @@ class CoursesController < ApplicationController
@padless = true
when 'assignments'
add_crumb(t('#crumbs.assignments', "Assignments"))
set_js_assignment_data(
include_assignment_permissions: @context.root_account.feature_enabled?(:anonymous_moderated_marking)
)
set_js_assignment_data
js_env(:SIS_NAME => AssignmentUtil.post_to_sis_friendly_name(@context))
js_env(:COURSE_HOME => true)
@upcoming_assignments = get_upcoming_assignments(@context)

View File

@ -307,7 +307,6 @@ class GradebooksController < ApplicationController
GRADEBOOK_OPTIONS: {
api_max_per_page: per_page,
chunk_size: Setting.get('gradebook2.submissions_chunk_size', '10').to_i,
anonymous_moderated_marking_enabled: anonymous_moderated_marking_enabled?,
assignment_groups_url: api_v1_course_assignment_groups_url(
@context,
include: ag_includes,
@ -447,7 +446,7 @@ class GradebooksController < ApplicationController
# decorate submissions with user_ids if not present
submissions_without_user_ids = submissions.select {|s| s[:user_id].blank?}
if submissions_without_user_ids.present? && anonymous_moderated_marking_enabled?
if submissions_without_user_ids.present?
submissions = populate_user_ids(submissions_without_user_ids)
end
@ -563,7 +562,7 @@ class GradebooksController < ApplicationController
def submissions_json(submissions:, assignments:)
submissions.map do |sub|
assignment = assignments[sub[:assignment_id].to_i]
omitted_field = assignment.anonymous_grading? && anonymous_moderated_marking_enabled? ? :user_id : :anonymous_id
omitted_field = assignment.anonymous_grading? ? :user_id : :anonymous_id
json_params = {
include: { submission_history: { methods: %i[late missing], except: omitted_field } },
except: omitted_field
@ -627,14 +626,13 @@ class GradebooksController < ApplicationController
end
@can_comment_on_submission = !@context.completed? && !@context_enrollment.try(:completed?)
@disable_unmute_assignment = @assignment.muted && !@assignment.grades_published? && anonymous_moderated_marking_enabled?
@disable_unmute_assignment = @assignment.muted && !@assignment.grades_published?
respond_to do |format|
format.html do
rubric = @assignment&.rubric_association&.rubric
@headers = false
@outer_frame = true
@anonymous_moderated_marking_enabled = anonymous_moderated_marking_enabled?
log_asset_access([ "speed_grader", @context ], "grades", "other")
env = {
CONTEXT_ACTION_SOURCE: :speed_grader,
@ -645,7 +643,6 @@ class GradebooksController < ApplicationController
lti_retrieve_url: retrieve_course_external_tools_url(
@context.id, assignment_id: @assignment.id, display: 'borderless'
),
anonymous_moderated_marking_enabled: @anonymous_moderated_marking_enabled,
course_id: @context.id,
assignment_id: @assignment.id,
assignment_title: @assignment.title,
@ -669,8 +666,7 @@ class GradebooksController < ApplicationController
append_sis_data(env)
js_env(env)
anonymous_grading = @assignment.anonymous_grading? && @anonymous_moderated_marking_enabled
render :speed_grader, locals: { anonymous_grading: anonymous_grading }
render :speed_grader, locals: { anonymous_grading: @assignment.anonymous_grading? }
end
format.json do
@ -762,10 +758,6 @@ class GradebooksController < ApplicationController
end
end
def anonymous_moderated_marking_enabled?
@context.root_account.feature_enabled?(:anonymous_moderated_marking)
end
def new_gradebook_env
graded_late_submissions_exist = @context.submissions.graded.late.exists?

View File

@ -33,9 +33,7 @@ class ProvisionalGradesBaseController < ApplicationController
return render json: { message: "Assignment grades have already been published" }, status: :bad_request
end
# in theory we could apply visibility here, but for now we would rather be performant
# e.g. @assignment.students_with_visibility(@context.students_visible_to(@current_user)).find(params[:student_id])
json = {needs_provisional_grade: @assignment.student_needs_provisional_grade?(@student)}
json = {needs_provisional_grade: @assignment.can_be_moderated_grader?(@current_user)}
return render json: json unless submission_updated?

View File

@ -51,10 +51,7 @@ module Submissions
if redirect?
redirect_to(named_context_url(@context, redirect_path_name, @assignment.quiz.id, redirect_params))
else
anonymous_grading = @assignment.anonymous_grading? &&
@context.root_account.feature_enabled?(:anonymous_moderated_marking)
render 'submissions/show_preview', locals: { anonymous_grading: anonymous_grading }
render 'submissions/show_preview', locals: { anonymous_grading: @assignment.anonymous_grading? }
end
end
end

View File

@ -25,22 +25,14 @@ module GradebooksHelper
!!anonymous_assignment
end
def anonymous_grading_required?(assignment)
if assignment.root_account.feature_enabled?(:anonymous_moderated_marking)
assignment.anonymous_grading?
else
assignment.course.feature_enabled?(:anonymous_grading)
end
end
def force_anonymous_grading?(assignment)
anonymous_assignment?(assignment) || anonymous_grading_required?(assignment)
anonymous_assignment?(assignment) || assignment.anonymous_grading?
end
def force_anonymous_grading_reason(assignment)
if anonymous_assignment?(assignment)
I18n.t("Student names must be hidden because this is an anonymous survey.")
elsif anonymous_grading_required?(assignment)
elsif assignment.anonymous_grading?
I18n.t("Student names must be hidden because anonymous grading is required.")
else
""

View File

@ -77,7 +77,6 @@ export default React.createClass({
<FlashMessageHolder {...this.state.flashMessage} />
<h1 className="screenreader-only">{I18n.t('Moderate %{assignment_name}', {assignment_name: this.state.assignment.title})}</h1>
<Header
anonymousModeratedMarkingEnabled={this.state.assignment.anonymousModeratedMarkingEnabled}
onPublishClick={
() => {
this.props.store.dispatch(Actions.publishStarted());

View File

@ -24,7 +24,6 @@ import I18n from 'i18n!moderated_grading'
displayName: 'Header',
propTypes: {
anonymousModeratedMarkingEnabled: PropTypes.bool.isRequired,
muted: PropTypes.bool.isRequired,
onPublishClick: PropTypes.func.isRequired,
onReviewClick: PropTypes.func.isRequired,
@ -111,7 +110,7 @@ import I18n from 'i18n!moderated_grading'
},
render () {
const showUnmuteButton = this.props.anonymousModeratedMarkingEnabled && this.props.permissions.editGrades
const showUnmuteButton = this.props.permissions.editGrades
return (
<div>

View File

@ -38,7 +38,6 @@ const store = configureStore({
unmute: false
},
assignment: {
anonymousModeratedMarkingEnabled: window.ENV.ANONYMOUS_MODERATED_MARKING_ENABLED,
muted: window.ENV.ASSIGNMENT_MUTED,
published: window.ENV.GRADES_PUBLISHED,
title: window.ENV.ASSIGNMENT_TITLE,

View File

@ -36,10 +36,9 @@ import GradingPeriodsHelper from '../grading/helpers/GradingPeriodsHelper'
student,
hasGradingPeriods,
selectedGradingPeriodID,
isAdmin,
anonymousModeratedMarkingEnabled
isAdmin
) {
if (assignment.anonymous_grading && assignment.muted && anonymousModeratedMarkingEnabled) {
if (assignment.anonymous_grading && assignment.muted) {
return { locked: true, hideGrade: true };
} else if (!visibleToStudent(assignment, student)) {
return { locked: true, hideGrade: true, tooltip: TOOLTIP_KEYS.NONE };
@ -74,11 +73,10 @@ import GradingPeriodsHelper from '../grading/helpers/GradingPeriodsHelper'
}
class SubmissionState {
constructor({ hasGradingPeriods, selectedGradingPeriodID, isAdmin, anonymousModeratedMarkingEnabled }) {
constructor({ hasGradingPeriods, selectedGradingPeriodID, isAdmin }) {
this.hasGradingPeriods = hasGradingPeriods;
this.selectedGradingPeriodID = selectedGradingPeriodID;
this.isAdmin = isAdmin;
this.anonymousModeratedMarkingEnabled = anonymousModeratedMarkingEnabled;
this.submissionCellMap = {};
this.submissionMap = {};
}
@ -100,8 +98,7 @@ import GradingPeriodsHelper from '../grading/helpers/GradingPeriodsHelper'
student,
this.hasGradingPeriods,
this.selectedGradingPeriodID,
this.isAdmin,
this.anonymousModeratedMarkingEnabled
this.isAdmin
];
this.submissionCellMap[student.id][assignment.id] = cellMapForSubmission(...params);

View File

@ -65,12 +65,12 @@ function cellMappingsForMultipleGradingPeriods (assignment, student, selectedGra
return { ...cellMapping, ...gradingPeriodInfo };
}
function cellMapForSubmission (assignment, student, hasGradingPeriods, selectedGradingPeriodID, isAdmin, anonymousModeratedMarkingEnabled) {
function cellMapForSubmission (assignment, student, hasGradingPeriods, selectedGradingPeriodID, isAdmin) {
if (!assignment.published) {
return { locked: true, hideGrade: true };
} else if (assignment.moderated_grading && !assignment.grades_published && anonymousModeratedMarkingEnabled) {
} else if (assignment.moderated_grading && !assignment.grades_published) {
return { locked: true, hideGrade: false };
} else if (assignment.anonymous_grading && assignment.muted && anonymousModeratedMarkingEnabled) {
} else if (assignment.anonymous_grading && assignment.muted) {
return { locked: true, hideGrade: true };
} else if (!visibleToStudent(assignment, student)) {
return { locked: true, hideGrade: true };
@ -98,11 +98,10 @@ function missingSubmission (student, assignment) {
}
class SubmissionStateMap {
constructor ({ hasGradingPeriods, selectedGradingPeriodID, isAdmin, anonymousModeratedMarkingEnabled }) {
constructor ({ hasGradingPeriods, selectedGradingPeriodID, isAdmin }) {
this.hasGradingPeriods = hasGradingPeriods;
this.selectedGradingPeriodID = selectedGradingPeriodID;
this.isAdmin = isAdmin;
this.anonymousModeratedMarkingEnabled = anonymousModeratedMarkingEnabled;
this.submissionCellMap = {};
this.submissionMap = {};
}
@ -124,8 +123,7 @@ class SubmissionStateMap {
student,
this.hasGradingPeriods,
this.selectedGradingPeriodID,
this.isAdmin,
this.anonymousModeratedMarkingEnabled
this.isAdmin
];
this.submissionCellMap[student.id][assignment.id] = cellMapForSubmission(...params);

View File

@ -62,7 +62,7 @@ function getProps (column, gradebook, options) {
addGradebookElement: gradebook.keyboardNav.addGradebookElement,
assignment: {
anonymousGrading: assignment.anonymous_grading && gradebook.options.anonymous_moderated_marking_enabled,
anonymousGrading: assignment.anonymous_grading,
courseId: assignment.course_id,
htmlUrl: assignment.html_url,
id: assignment.id,

View File

@ -65,7 +65,6 @@ export default class SubmissionTray extends React.Component {
};
static propTypes = {
anonymousModeratedMarkingEnabled: bool.isRequired,
assignment: shape({
name: string.isRequired,
htmlUrl: string.isRequired,
@ -199,7 +198,7 @@ export default class SubmissionTray extends React.Component {
renderSpeedGraderLink (speedGraderProps) {
const buttonProps = { variant: 'link', href: speedGraderProps.speedGraderUrl }
if (this.props.anonymousModeratedMarkingEnabled && speedGraderProps.anonymousGrading) {
if (speedGraderProps.anonymousGrading) {
buttonProps.onClick = (e) => {
e.preventDefault();
this.props.onAnonymousSpeedGraderClick(speedGraderProps.speedGraderUrl);
@ -219,7 +218,7 @@ export default class SubmissionTray extends React.Component {
const { name, avatarUrl } = this.props.student;
const assignmentParam = `assignment_id=${this.props.submission.assignmentId}`;
const studentParam = `#{"student_id":"${this.props.student.id}"}`;
const speedGraderUrlParams = this.props.anonymousModeratedMarkingEnabled && this.props.assignment.anonymousGrading
const speedGraderUrlParams = this.props.assignment.anonymousGrading
? assignmentParam
: `${assignmentParam}${studentParam}`
const speedGraderUrl = encodeURI(`/courses/${this.props.courseId}/gradebook/speed_grader?${speedGraderUrlParams}`)

View File

@ -19,11 +19,10 @@
import AssignmentMuter from 'compiled/AssignmentMuter'
export default class AssignmentMuterDialogManager {
constructor(assignment, url, submissionsLoaded, anonymousModeratedMarkingEnabled) {
constructor(assignment, url, submissionsLoaded) {
this.assignment = assignment
this.url = url
this.submissionsLoaded = submissionsLoaded
this.anonymousModeratedMarkingEnabled = anonymousModeratedMarkingEnabled
this.showDialog = this.showDialog.bind(this)
this.isDialogEnabled = this.isDialogEnabled.bind(this)
@ -41,11 +40,7 @@ export default class AssignmentMuterDialogManager {
return false
}
if (
this.assignment.muted &&
this.anonymousModeratedMarkingEnabled &&
this.assignment.moderated_grading
) {
if (this.assignment.muted && this.assignment.moderated_grading) {
return this.assignment.grades_published
}

View File

@ -100,17 +100,13 @@ class Assignment < ActiveRecord::Base
validate :assignment_name_length_ok?
validates :lti_context_id, presence: true, uniqueness: true
before_create do
self.muted = true if moderated_grading? && anonymous_moderated_marking?
end
with_options unless: :moderated_grading? do
validates :graders_anonymous_to_graders, absence: true
validates :grader_section, absence: true
validates :final_grader, absence: true
end
with_options if: -> { moderated_grading? && anonymous_moderated_marking? } do
with_options if: -> { moderated_grading? } do
validates :grader_count, numericality: { greater_than: 0, message: "Number of graders must be positive" }
validate :grader_section_ok?
validate :final_grader_ok?
@ -454,7 +450,8 @@ class Assignment < ActiveRecord::Base
:default_values,
:maintain_group_category_attribute,
:validate_assignment_overrides,
:mute_if_changed_to_anonymous
:mute_if_changed_to_anonymous,
:mute_if_changed_to_moderated
after_save :update_submissions_and_grades_if_details_changed,
@ -1387,11 +1384,10 @@ class Assignment < ActiveRecord::Base
def user_can_update?(user, session=nil)
return false unless context.grants_right?(user, session, :manage_assignments)
return true unless moderated_grading? && root_account.feature_enabled?(:anonymous_moderated_marking)
return true unless moderated_grading?
# When Anonymous Moderated Marking is on, a moderated assignment may only be
# edited by the assignment's moderator (assuming one has been specified) or
# by an account admin with 'Select Final Grader for Moderation' privileges.
# a moderated assignment may only be edited by the assignment's moderator (assuming one has
# been specified) or by an account admin with 'Select Final Grader for Moderation' privileges.
final_grader_id.blank? || permits_moderation?(user)
end
@ -1737,7 +1733,7 @@ class Assignment < ActiveRecord::Base
opts[:assessment_request].complete unless opts[:assessment_request].rubric_association
end
ensure_grader_can_adjudicate(grader: opts[:commenter], provisional: opts[:provisional]) do
ensure_grader_can_adjudicate(grader: opts[:author], provisional: opts[:provisional]) do
if opts[:comment] && Canvas::Plugin.value_to_boolean(opts[:group_comment])
uuid = CanvasSlug.generate_securish_uuid
res = find_or_create_submissions(students) do |submission|
@ -1864,25 +1860,6 @@ class Assignment < ActiveRecord::Base
!moderated_grading? || grades_published_at.present?
end
def student_needs_provisional_grade?(student, preloaded_counts=nil)
# For Anonymous Moderated Marking, we aren't concerned with the assignment's
# moderation set or the hard-coded provisional grade limit. Instead we
# check (elsewhere) that we're below the assignment's max grader count.
return true if anonymous_moderated_marking?
pg_count = if preloaded_counts
preloaded_counts[student.id] || 0
else
self.provisional_grades.not_final.where(:submissions => {:user_id => student}).count
end
in_moderation_set = if self.moderated_grading_selections.loaded?
self.moderated_grading_selections.detect{|s| s.student_id == student.id}.present?
else
self.moderated_grading_selections.where(:student_id => student).exists?
end
pg_count < (in_moderation_set ? 2 : 1)
end
def sections_with_visibility(user)
return context.active_course_sections unless self.differentiated_assignments_applies?
@ -2665,7 +2642,7 @@ class Assignment < ActiveRecord::Base
def unmute!
return unless muted?
return super unless !grades_published? && anonymous_moderated_marking? && anonymous_grading?
return super unless !grades_published? && anonymous_grading?
errors.add :muted, I18n.t("Anonymous moderated assignments cannot be unmuted until grades are posted")
false
end
@ -2773,11 +2750,7 @@ class Assignment < ActiveRecord::Base
end
def permits_moderation?(user)
if anonymous_moderated_marking?
final_grader_id == user.id || context.account_membership_allows(user, :select_final_grade)
else
context.grants_right?(user, :moderate_grades)
end
final_grader_id == user.id || context.account_membership_allows(user, :select_final_grade)
end
def available_moderators
@ -2804,7 +2777,7 @@ class Assignment < ActiveRecord::Base
end
def moderated_grader_limit_reached?
moderated_grading? && anonymous_moderated_marking? && provisional_moderation_graders.count >= grader_count
moderated_grading? && provisional_moderation_graders.count >= grader_count
end
def can_be_moderated_grader?(user)
@ -2820,7 +2793,7 @@ class Assignment < ActiveRecord::Base
def can_view_other_grader_identities?(user)
return false unless context.grants_any_right?(user, :manage_grades, :view_all_grades)
return true unless anonymous_moderated_marking? && moderated_grading?
return true unless moderated_grading?
return grader_names_visible_to_final_grader? if final_grader_id == user.id
return true if context.account_membership_allows(user, :select_final_grade)
@ -2831,7 +2804,7 @@ class Assignment < ActiveRecord::Base
def can_view_other_grader_comments?(user)
return false unless context.grants_any_right?(user, :manage_grades, :view_all_grades)
return true unless anonymous_moderated_marking? && moderated_grading?
return true unless moderated_grading?
return true if final_grader_id == user.id || context.account_membership_allows(user, :select_final_grade)
@ -2845,9 +2818,7 @@ class Assignment < ActiveRecord::Base
end
def can_view_student_names?(user)
return false unless context.grants_any_right?(user, :manage_grades, :view_all_grades)
return true unless anonymous_moderated_marking?
!anonymous_grading?
!anonymous_grading && context.grants_any_right?(user, :manage_grades, :view_all_grades)
end
private
@ -2855,7 +2826,13 @@ class Assignment < ActiveRecord::Base
def mute_if_changed_to_anonymous
return unless anonymous_grading_changed?
self.muted = true if anonymous_grading? && anonymous_moderated_marking?
self.muted = true if anonymous_grading?
end
def mute_if_changed_to_moderated
return unless moderated_grading_changed?
self.muted = true if moderated_grading?
end
def due_date_ok?
@ -2925,10 +2902,6 @@ class Assignment < ActiveRecord::Base
end
end
def anonymous_moderated_marking?
root_account.feature_enabled?(:anonymous_moderated_marking)
end
def clear_moderated_grading_attributes(assignment)
assignment.final_grader_id = nil
assignment.grader_count = nil
@ -2940,7 +2913,7 @@ class Assignment < ActiveRecord::Base
def create_moderation_grader_if_needed(grader:)
return false if moderation_graders.where(user: grader).exists?
if provisional_moderation_graders.count >= grader_count
if moderated_grader_limit_reached?
raise MaxGradersReachedError unless grader.id == final_grader_id
end
@ -2960,13 +2933,12 @@ class Assignment < ActiveRecord::Base
end
# This is a helper method intended to ensure the number of provisional graders
# for a moderated assignment (if Anonymous Moderated Marking is enabled) doesn't
# exceed the prescribed maximum. Currently, it is used for submitting grades and
# comments via SpeedGrader. If the assignment is not moderated, the grade/comment
# being issued is not provisional, or Anonymous Moderated Marking is off, this
# for a moderated assignment doesn't exceed the prescribed maximum. Currently,
# it is used for submitting grades and comments via SpeedGrader. If the assignment
# is not moderated or the grade/comment being issued is not provisional, this
# method will simply execute the provided block without any additional checks.
def ensure_grader_can_adjudicate(grader:, provisional: false)
unless provisional && moderated_grading? && anonymous_moderated_marking?
unless provisional && moderated_grading?
yield and return
end

View File

@ -75,8 +75,6 @@ class Assignment
all_provisional_rubric_assessments = @grading_role == :moderator &&
(@assignment.visible_rubric_assessments_for(@user, :provisional_moderator => true) || [])
# if we're a provisional grader, calculate whether the student needs a grade
preloaded_pg_counts = is_provisional && @assignment.provisional_grades.not_final.group("submissions.user_id").count
ActiveRecord::Associations::Preloader.new.preload(@assignment, :moderated_grading_selections) if is_provisional
includes = [{ versions: :versionable }, :quiz_submission, :user, :attachment_associations, :assignment, :originality_reports]
@ -90,11 +88,7 @@ class Assignment
res[:context][:students] = @students.map do |student|
json = student.as_json(include_root: false, methods: submission_comment_methods, only: student_json_fields)
json[:anonymous_id] = student_ids_to_anonymous_ids[student.id.to_s] if anonymous_students?
if preloaded_pg_counts
json[:needs_provisional_grade] = @assignment.student_needs_provisional_grade?(student, preloaded_pg_counts)
end
json[:needs_provisional_grade] = @assignment.can_be_moderated_grader?(@user) if is_provisional
json[:rubric_assessments] = rubric_assessements_to_json(current_user_rubric_assessments.select {|assessment| assessment.user_id == student.id})
json
end

View File

@ -3181,8 +3181,6 @@ class Course < ActiveRecord::Base
end
def moderators
return [] unless root_account.feature_enabled?(:anonymous_moderated_marking)
active_instructors = users.merge(Enrollment.active_or_pending.of_instructor_type)
active_instructors.select { |user| grants_right?(user, :select_final_grade) }
end

View File

@ -1440,7 +1440,6 @@ class Enrollment < ActiveRecord::Base
def remove_user_as_final_grader?
instructor? &&
root_account.feature_enabled?(:anonymous_moderated_marking) &&
!other_enrollments_of_type(['TaEnrollment', 'TeacherEnrollment']).exists?
end

View File

@ -288,7 +288,7 @@ module Importers
[:peer_reviews,
:automatic_peer_reviews, :anonymous_peer_reviews,
:grade_group_students_individually, :allowed_extensions,
:position, :peer_review_count, :moderated_grading,
:position, :peer_review_count,
:omit_from_final_grade, :intra_group_peer_reviews, :post_to_sis
].each do |prop|
item.send("#{prop}=", hash[prop]) unless hash[prop].nil?

View File

@ -45,7 +45,7 @@ class ModeratedGrading::ProvisionalGrade < ActiveRecord::Base
scope :not_final, -> { where(:final => false)}
def must_be_final_or_student_in_need_of_provisional_grade
if !self.final && !self.submission.assignment.student_needs_provisional_grade?(self.submission.user)
if !self.final && !self.submission.assignment.can_be_moderated_grader?(self.scorer)
raise(Assignment::GradeError, "Student already has the maximum number of provisional grades")
end
end

View File

@ -910,14 +910,12 @@ class RoleOverride < ActiveRecord::Base
:select_final_grade => {
:label => -> { t('Select final grade for moderation') },
:true_for => %w(AccountAdmin TeacherEnrollment TaEnrollment),
:available_to => %w(AccountAdmin AccountMembership TeacherEnrollment TaEnrollment),
:account_allows => lambda {|a| a.feature_enabled?(:anonymous_moderated_marking)}
:available_to => %w(AccountAdmin AccountMembership TeacherEnrollment TaEnrollment)
},
:view_audit_trail => {
:label => -> { t('View audit trail') },
:true_for => %w(TeacherEnrollment AccountAdmin),
:available_to => %w(TeacherEnrollment AccountAdmin AccountMembership),
:account_allows => lambda {|a| a.feature_enabled?(:anonymous_moderated_marking)}
:available_to => %w(TeacherEnrollment AccountAdmin AccountMembership)
}
})

View File

@ -462,7 +462,6 @@ class Submission < ActiveRecord::Base
end
def can_view_details?(user)
return true unless self.assignment.root_account.feature_enabled?(:anonymous_moderated_marking)
return true unless self.assignment.anonymous_grading && self.assignment.muted
user == self.user || Account.site_admin.grants_right?(user, :update)
end
@ -1509,9 +1508,7 @@ class Submission < ActiveRecord::Base
def can_grade_symbolic_status(user = nil)
user ||= grader
if assignment.root_account&.feature_enabled?(:anonymous_moderated_marking)
return :moderation_in_progress unless assignment.grades_published? || grade_posting_in_progress
end
return :moderation_in_progress unless assignment.grades_published? || grade_posting_in_progress || assignment.permits_moderation?(user)
return :not_applicable if deleted?
return :unpublished unless assignment.published?

View File

@ -53,31 +53,7 @@
</span>
</button>
<% unless @anonymous_moderated_marking_enabled %>
<button id="keyboard-shortcut-info-icon" class="Button Button--icon-action gradebookActions__Button" type="button" title="<%= t('Keyboard Shortcuts') %>">
<i class="icon-keyboard-shortcuts" aria-hidden="true"></i>
<span class="screenreader-only" aria-hidden="true"><%= t('Keyboard Shortcuts') %></span>
</button>
<% end %>
<% if help_link && !@anonymous_moderated_marking_enabled %>
<%= link_to help_link_url,
class: help_link_classes(["Button Button--icon-action gradebookActions__Button exclude_external_icon"]),
title: help_link_name,
data: help_link_data do %>
<span class="gradebookActions__Svg" role="presentation"><%= svg_icon help_link_icon %></span>
<span class="screenreader-only" aria-hidden="true"><%= help_link_name %></span>
<% end %>
<% end %>
<% if @anonymous_moderated_marking_enabled %>
<span id="speedgrader-settings"></span>
<% else %>
<button id="settings_link" class="Button Button--icon-action gradebookActions__Button" type="button" title="<%= t('Settings') %>">
<i class="icon-settings" aria-hidden="true"></i>
<span class="screenreader-only" aria-hidden="true"><%= t('SpeedGrader Settings') %></span>
</button>
<% end %>
<span id="speedgrader-settings"></span>
</div>
<div class="assignmentDetails">
<a id="assignment_url" href="<%= context_url(@context, :context_assignment_url, @assignment.id) %>">
@ -280,10 +256,7 @@
<% if can_do(@context, @current_user, :manage_grades) || (@context.concluded? && can_do(@context, @current_user, :read_as_admin)) %>
<div id="grade_container">
<%= render partial: "grading_box_extended",
locals: {
assignment: @assignment,
anonymous_moderated_marking_enabled: @anonymous_moderated_marking_enabled
}
locals: {assignment: @assignment}
%>
<span class="turnitin_score_container"></span>
<a href="#" id="submit_same_score"><br><%= t('links.submit_same_score', "Use this same grade for the resubmission") %></a>

View File

@ -161,22 +161,7 @@
{{/if}}
{{#unless isQuizLTIAssignment}}
{{#if anonymousModeratedMarkingEnabled}}
<span data-component="ModeratedGradingFormFieldGroup"></span>
{{else}}
<fieldset>
<div class="form-column-left">{{#t}}Moderated Grading{{/t}}</div>
<div class="form-column-right" style="margin-top: 14px;">
<label class="checkbox">
{{checkbox "moderatedGrading"
id="assignment_moderated_grading"
name="moderated_grading"
}}
{{#t}}Allow a moderator to review multiple independent grades for selected submissions{{/t}}
</label>
</div>
</fieldset>
{{/if}}
<span data-component="ModeratedGradingFormFieldGroup"></span>
{{/unless}}
{{#if anonymousGradingEnabled}}

View File

@ -682,7 +682,7 @@ module Api::V1::Assignment
assignment.moderated_grading = value_to_boolean(assignment_params['moderated_grading'])
end
grader_changes = final_grader_changes(assignment, context, assignment_params)
grader_changes = final_grader_changes(assignment, assignment_params)
assignment.final_grader_id = grader_changes.grader_id if grader_changes.grader_changed?
if assignment_params.key?('anonymous_grading') && assignment.course.feature_enabled?(:anonymous_marking)
@ -773,10 +773,9 @@ module Api::V1::Assignment
private
def final_grader_changes(assignment, course, assignment_params)
def final_grader_changes(assignment, assignment_params)
no_changes = OpenStruct.new(grader_changed?: false)
return no_changes unless assignment.moderated_grading && assignment_params.key?('final_grader_id')
return no_changes unless course.root_account.feature_enabled?(:anonymous_moderated_marking)
final_grader_id = assignment_params.fetch("final_grader_id")
return OpenStruct.new(grader_changed?: true, grader_id: nil) if final_grader_id.blank?

View File

@ -69,7 +69,7 @@ class Feature
# display_name: -> { I18n.t('features.automatic_essay_grading', 'Automatic Essay Grading') },
# description: -> { I18n.t('features.automatic_essay_grading_description, 'Popup text describing the feature goes here') },
# applies_to: 'Course', # or 'RootAccount' or 'Account' or 'User'
# state: 'allowed', # or 'off', 'on', 'hidden', or 'hidden_in_prod'
# state: 'allowed', # or 'on', 'hidden', or 'hidden_in_prod'
# # - 'hidden' means the feature must be set by a site admin before it will be visible
# # (in that context and below) to other users
# # - 'hidden_in_prod' registers 'hidden' in production environments or 'allowed' elsewhere

View File

@ -25,31 +25,21 @@ Feature.register(
DESCRIPTION
},
applies_to: 'Account',
state: 'allowed',
state: 'hidden',
root_opt_in: true,
beta: true,
development: false
development: true
},
anonymous_marking: {
display_name: -> { I18n.t 'Anonymous Marking' },
description: -> {
I18n.t <<~DESCRIPTION
Enable anonymous marking of assignments. Only relevant if the Anonymous Moderated Marking flag is enabled.
Enable anonymous marking of assignments.
DESCRIPTION
},
applies_to: 'Course',
state: 'allowed',
root_opt_in: true,
beta: true,
development: false,
visible_on: ->(context) do
if context.is_a?(Account)
context.feature_enabled?(:anonymous_moderated_marking)
elsif context.is_a?(Course)
context.root_account.feature_enabled?(:anonymous_moderated_marking)
else
false
end
end
beta: true
}
)

View File

@ -21,22 +21,12 @@ Feature.register(
display_name: -> { I18n.t 'Moderated Grading' },
description: -> {
I18n.t <<~DESCRIPTION
Enable moderated grading. Only relevant if the Anonymous Moderated Marking flag is enabled.
Enable moderated grading.
DESCRIPTION
},
applies_to: 'Course',
state: 'allowed',
root_opt_in: true,
beta: true,
development: false,
visible_on: ->(context) do
if context.is_a?(Account)
context.feature_enabled?(:anonymous_moderated_marking)
elsif context.is_a?(Course)
context.root_account.feature_enabled?(:anonymous_moderated_marking)
else
false
end
end
beta: true
}
)

View File

@ -21,7 +21,7 @@ require 'csv'
class GradebookImporter
ASSIGNMENT_PRELOADED_FIELDS = %i/
id title points_possible grading_type updated_at context_id context_type group_category_id
created_at due_at only_visible_to_overrides
created_at due_at only_visible_to_overrides moderated_grading
/.freeze
class NegativeId

View File

@ -18,7 +18,7 @@
module Moderation
def create_moderation_selections_for_assignment(assignment_id, student_ids, student_context)
assignment = Assignment.find(assignment_id)
return unless assignment.root_account.feature_enabled?(:anonymous_moderated_marking) && assignment.moderated_grading
return unless assignment.moderated_grading
# Add selections for students in Student IDs
already_moderated_ids = assignment.moderated_grading_selections.pluck(:student_id)

View File

@ -45,7 +45,6 @@ import htmlEscape from './str/htmlEscape';
import rubricAssessment from './rubric_assessment';
import SpeedgraderSelectMenu from './speed_grader_select_menu';
import SpeedgraderHelpers, {
isAnonymousModeratedMarkingEnabled,
setupAnonymizableId,
setupAnonymizableStudentId,
setupAnonymizableUserId,
@ -471,13 +470,7 @@ function setupHeader () {
modal: $('#unmute_dialog')
},
nav: $gradebook_header.find('#prev-student-button, #next-student-button'),
settings: {
form: $('#settings_form'),
link: $('#settings_link')
},
keyinfo: {
icon: $('#keyboard-shortcut-info-icon')
}
settings: { form: $('#settings_form') }
},
courseId: utils.getParam('courses'),
assignmentId: utils.getParam('assignment_id'),
@ -492,10 +485,6 @@ function setupHeader () {
this.elements.mute.link.click($.proxy(this.onMuteClick, this));
this.elements.settings.form.submit(this.submitSettingsForm.bind(this));
if (!isAnonymous) {
this.elements.settings.link.click(this.showSettingsModal.bind(this));
}
this.elements.keyinfo.icon.click(this.keyboardShortcutInfoModal.bind(this));
},
createModals () {
this.elements.settings.form.dialog({
@ -1346,20 +1335,18 @@ EG = {
}
if (ENV.grading_role == "moderator") {
this.current_prov_grade_index = null;
this.handleModerationTabs(0); // sets up tabs and loads first grade
this.removeModerationBarAndShowSubmission();
if (isAnonymousModeratedMarkingEnabled()) {
this.renderProvisionalGradeSelector({showingNewStudent: true})
this.renderProvisionalGradeSelector({showingNewStudent: true})
const selectedGrade = currentStudentProvisionalGrades().find(grade => grade.selected);
if (selectedGrade) {
this.setActiveProvisionalGradeFields({
label: provisionalGraderDisplayNames[selectedGrade.provisional_grade_id],
grade: selectedGrade
});
} else {
this.setActiveProvisionalGradeFields();
}
const selectedGrade = currentStudentProvisionalGrades().find(grade => grade.selected);
if (selectedGrade) {
this.setActiveProvisionalGradeFields({
label: provisionalGraderDisplayNames[selectedGrade.provisional_grade_id],
grade: selectedGrade
});
} else {
this.setActiveProvisionalGradeFields();
}
} else {
// showSubmissionOverride is optionally set if the user is
@ -1387,94 +1374,6 @@ EG = {
this.setReadOnly(false)
},
handleModerationTabs: function(index_to_load) {
if (isAnonymousModeratedMarkingEnabled()) {
this.removeModerationBarAndShowSubmission()
return
}
var prov_grades = this.currentStudent.submission && this.currentStudent.submission.provisional_grades;
var final_grade = this.currentStudent.submission && this.currentStudent.submission.final_provisional_grade;
if (prov_grades && prov_grades.length == 1 && !final_grade && !prov_grades[0].readonly) {
$full_width_container.removeClass("with_moderation_tabs");
$moderation_bar.hide();
EG.showProvisionalGrade(0);
} else if (prov_grades && prov_grades.length > 0) {
if (prov_grades.length == 1) {
// hide and disable second mark tab
$moderation_tab_2nd.hide();
$moderation_tabs_div.tabs('disable', 1);
if (this.currentStudent.needs_provisional_grade || final_grade) {
$new_mark_container.show();
$new_mark_copy_link2_menu_item.hide(); // hide copy 2nd mark
if (final_grade) {
$new_mark_link_menu_item.hide();
} else {
EG.can_add_review = true;
$new_mark_link_menu_item.show();
}
} else {
$new_mark_container.hide(); // hide new mark dropdown if not selected for moderation
}
} else if (prov_grades.length == 2) {
// enable and show second mark tab
$moderation_tabs_div.tabs('enable', 1);
$moderation_tab_2nd.show();
$new_mark_container.show();
$new_mark_link_menu_item.hide();
if (prov_grades[1].provisional_grade_id) {
$new_mark_copy_link2_menu_item.show(); // show copy 2nd mark
} else {
$new_mark_copy_link2_menu_item.hide(); // don't show if it's a new unsaved mark
}
}
if (final_grade) {
$moderation_tabs_div.tabs('enable', 2);
$moderation_tab_final.show();
$new_mark_final_link_menu_item.hide();
} else {
$moderation_tabs_div.tabs('disable', 2);
$moderation_tab_final.hide();
$new_mark_final_link_menu_item.show();
}
$full_width_container.addClass("with_moderation_tabs");
$moderation_bar.show();
if (this.add_review && this.can_add_review) {
this.add_review = false;
this.newProvisionalGrade('new', 1);
} else {
if (this.selected_provisional_grade_id) {
var selected_id = this.selected_provisional_grade_id;
// load provisional grade id from anchor hash
if (final_grade && final_grade.provisional_grade_id == selected_id) {
index_to_load = 'final'; // final mark
} else {
$.each(prov_grades, function (idx, pg) {
if (pg.provisional_grade_id == selected_id) {
index_to_load = idx;
}
});
}
this.selected_provisional_grade_id = null; // don't load it again
}
if (index_to_load == 'final') {
$moderation_tab_final.find('a').click();
} else {
$moderation_tabs.eq(index_to_load).find('a').click(); // show a grade
}
}
} else {
this.removeModerationBarAndShowSubmission()
}
},
updateModerationTabs: function() {
if (!this.currentStudent.submission) return;
var prov_grades = this.currentStudent.submission.provisional_grades;
@ -1547,11 +1446,10 @@ EG = {
};
if (index == 1) {
this.currentStudent.submission.provisional_grades.push(new_mark);
this.handleModerationTabs(1);
} else if (index == 'final') {
this.currentStudent.submission.final_provisional_grade = new_mark;
this.handleModerationTabs('final');
}
this.removeModerationBarAndShowSubmission();
} else if (type == 'copy') {
if (!this.currentStudent.submission.final_provisional_grade ||
confirm(I18n.t("Are you sure you want to copy to the final mark? This will overwrite the existing mark."))) {
@ -1564,7 +1462,7 @@ EG = {
EG.currentStudent.submission_state =
SpeedgraderHelpers.submissionState(EG.currentStudent, ENV.grading_role);
EG.current_prov_grade_index = null;
EG.handleModerationTabs('final');
this.removeModerationBarAndShowSubmission();
EG.updateModerationTabs();
$moderation_tab_final.focus();
})
@ -2648,11 +2546,7 @@ EG = {
$multiple_submissions.change();
EG.showGrade();
if (
isAnonymousModeratedMarkingEnabled() &&
ENV.grading_role === 'moderator' &&
currentStudentProvisionalGrades().length > 0
) {
if (ENV.grading_role === 'moderator' && currentStudentProvisionalGrades().length > 0) {
// This is the ID of the possibly-new grade that the server returned
const newProvisionalGradeId = submissions[0].submission.provisional_grade_id;
const existingGrade = currentStudentProvisionalGrades().find(
@ -3201,10 +3095,7 @@ function currentStudentProvisionalGrades () {
export default {
setup () {
setupSelectors()
if (isAnonymousModeratedMarkingEnabled()) {
renderSettingsMenu()
}
renderSettingsMenu()
function registerQuizzesNext (overriddenShowSubmission) {
showSubmissionOverride = overriddenShowSubmission;

View File

@ -22,12 +22,8 @@ import I18n from 'i18n!gradebook'
import './jquery.instructure_date_and_time'
import './jquery.instructure_misc_helpers'
export function isAnonymousModeratedMarkingEnabled () {
return !!ENV.anonymous_moderated_marking_enabled
}
export function setupIsAnonymous ({anonymous_grading}) {
return isAnonymousModeratedMarkingEnabled() && anonymous_grading
return anonymous_grading
}
export function setupAnonymizableId (isAnonymous) {
@ -168,8 +164,7 @@ export function setupAnonymizableUserId (isAnonymous) {
setupIsAnonymous,
setupAnonymizableId,
setupAnonymizableUserId,
setupAnonymizableStudentId,
isAnonymousModeratedMarkingEnabled
setupAnonymizableStudentId
}
export default speedgraderHelpers

View File

@ -59,7 +59,6 @@ module Lti
create: "/api/lti/assignments/#{@assignment.id}/submissions/#{@submission.id}/originality_report"
}
allow_any_instance_of(Account).to receive(:feature_enabled?).with(:anonymous_moderated_marking).and_return(false)
allow_any_instance_of(Account).to receive(:feature_enabled?).with(:plagiarism_detection_platform).and_return(true)
end

View File

@ -26,7 +26,7 @@ describe 'Anonymous Provisional Grades API', type: :request do
course_with_teacher(active_all: true)
ta_in_course(active_all: true)
@student = student_in_course(active_all: true).user
@assignment = @course.assignments.create!(moderated_grading: true)
@assignment = @course.assignments.create!(moderated_grading: true, grader_count: 1)
@submission = @assignment.submit_homework(@student, body: 'EHLO')
@path = "/api/v1/courses/#{@course.id}/assignments/#{@assignment.id}/anonymous_provisional_grades/status"
@params = {

View File

@ -2528,144 +2528,119 @@ describe AssignmentsApiController, type: :request do
describe 'final_grader_id' do
before(:once) do
course_with_teacher(active_all: true)
course_with_teacher(active_all: true)
end
context 'when Anonymous Moderated Marking is enabled' do
before(:once) do
course_with_teacher(active_all: true)
@course.root_account.enable_feature!(:anonymous_moderated_marking)
end
it 'allows updating final_grader_id for a participating instructor with "Select Final Grade" permissions' do
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: @teacher.id } },
)
expect(json_parse(response.body)['final_grader_id']).to eq @teacher.id
end
it 'does not allow updating final_grader_id if the user does not have "Select Final Grade" permissions' do
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
@course.root_account.role_overrides.create!(
permission: 'select_final_grade',
role: teacher_role,
enabled: false
)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: @teacher.id } },
)
error = json_parse(response.body)['errors']['final_grader_id'].first
expect(error['message']).to eq 'user does not have permission to select final grade'
end
it 'does not allow updating final_grader_id if the user is not active in the course' do
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
deactivated_teacher = User.create!
deactivated_teacher = @course.enroll_teacher(deactivated_teacher, enrollment_state: 'inactive')
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: deactivated_teacher.id } },
)
error = json_parse(response.body)['errors']['final_grader_id'].first
expect(error['message']).to eq 'course has no active instructors with this ID'
end
it 'does not allow updating final_grader_id if the course has no user with the supplied ID' do
user_not_enrolled_in_course = User.create!
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: user_not_enrolled_in_course.id } },
)
error = json_parse(response.body)['errors']['final_grader_id'].first
expect(error['message']).to eq 'course has no active instructors with this ID'
end
it 'skips final_grader_id validation if the field has not changed' do
assignment = @course.assignments.create!(
final_grader: @teacher,
grader_count: 2,
moderated_grading: true,
name: 'Some Assignment'
)
@course.root_account.role_overrides.create!(
permission: 'select_final_grade',
role: teacher_role,
enabled: false
)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { name: 'a fancy new name' } },
)
expect(response).to be_success
end
it 'allows updating final_grader_id for a participating instructor with "Select Final Grade" permissions' do
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: @teacher.id } },
)
expect(json_parse(response.body)['final_grader_id']).to eq @teacher.id
end
context 'when Anonymous Moderated Marking is disabled' do
it 'ignores updates to final_grader_id' do
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: @teacher.id } },
)
expect(json_parse(response.body)['final_grader_id']).to be_nil
end
it 'does not allow updating final_grader_id if the user does not have "Select Final Grade" permissions' do
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
@course.root_account.role_overrides.create!(
permission: 'select_final_grade',
role: teacher_role,
enabled: false
)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: @teacher.id } },
)
error = json_parse(response.body)['errors']['final_grader_id'].first
expect(error['message']).to eq 'user does not have permission to select final grade'
end
it 'does not allow updating final_grader_id if the user is not active in the course' do
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
deactivated_teacher = User.create!
deactivated_teacher = @course.enroll_teacher(deactivated_teacher, enrollment_state: 'inactive')
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: deactivated_teacher.id } },
)
error = json_parse(response.body)['errors']['final_grader_id'].first
expect(error['message']).to eq 'course has no active instructors with this ID'
end
it 'does not allow updating final_grader_id if the course has no user with the supplied ID' do
user_not_enrolled_in_course = User.create!
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 2)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { final_grader_id: user_not_enrolled_in_course.id } },
)
error = json_parse(response.body)['errors']['final_grader_id'].first
expect(error['message']).to eq 'course has no active instructors with this ID'
end
it 'skips final_grader_id validation if the field has not changed' do
assignment = @course.assignments.create!(
final_grader: @teacher,
grader_count: 2,
moderated_grading: true,
name: 'Some Assignment'
)
@course.root_account.role_overrides.create!(
permission: 'select_final_grade',
role: teacher_role,
enabled: false
)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
{
controller: 'assignments_api',
action: 'update',
format: 'json',
course_id: @course.id,
id: assignment.to_param
},
{ assignment: { name: 'a fancy new name' } },
)
expect(response).to be_success
end
end
it 'allows updating grader_count' do
course_with_teacher(active_all: true)
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true)
assignment = @course.assignments.create!(name: 'Some Assignment', moderated_grading: true, grader_count: 1)
api_call(
:put,
"/api/v1/courses/#{@course.id}/assignments/#{assignment.id}",
@ -4546,7 +4521,6 @@ describe AssignmentsApiController, type: :request do
context "when the anonymous marking feature flag is set" do
before(:once) do
@course.account.enable_feature!(:anonymous_moderated_marking)
@course.enable_feature!(:anonymous_marking)
end

View File

@ -26,13 +26,13 @@ describe 'Moderated Grades API', type: :request do
sec2 = @course.course_sections.create!(:name => "section 2")
@assignment = @course.assignments.create! name: "asdf"
@assignment.update_attribute :moderated_grading, true
@assignment.update_attribute :grader_count, 1
@student1, @student2, @student3 = n_students_in_course(3, course: @course)
@course.enroll_student(@student1, :section => sec1, :allow_multiple_enrollments => true)
@course.enroll_student(@student2, :section => sec1, :allow_multiple_enrollments => true)
@course.enroll_student(@student3, :section => sec1, :allow_multiple_enrollments => true)
@course.enroll_student(@student3, :section => sec2, :allow_multiple_enrollments => true)
@user = @teacher
@assignment.moderated_grading_selections.create! student: @student1
end
before :each do
@ -46,7 +46,7 @@ describe 'Moderated Grades API', type: :request do
{controller: 'moderation_set', action: 'index',
format: 'json', course_id: @course.id, assignment_id: @assignment.id}
expect(response).to be_success
expect(json.size).to eq 1
expect(json.size).to eq 3
expect(json.first["id"]).to eq @student1.id
end

View File

@ -26,7 +26,9 @@ describe 'Provisional Grades API', type: :request do
course_with_student :active_all => true
ta_in_course :active_all => true
@assignment = @course.assignments.build
@assignment.grader_count = 1
@assignment.moderated_grading = true
@assignment.final_grader_id = @teacher.id
@assignment.save!
subs = @assignment.grade_student @student, :grader => @ta, :score => 0, :provisional => true
@pg = subs.first.provisional_grade(@ta)
@ -37,52 +39,45 @@ describe 'Provisional Grades API', type: :request do
end
it "should fail if the student isn't in the moderation set" do
@assignment.moderated_grading_selections.destroy_all
json = api_call_as_user(@teacher, :put, @path, @params, {}, {}, { :expected_status => 400 })
expect(json['message']).to eq 'student not in moderation set'
end
context "with moderation set" do
before(:once) do
@selection = @assignment.moderated_grading_selections.build
@selection.student_id = @student.id
@selection.save!
end
it "should require :moderate_grades" do
api_call_as_user(@ta, :put, @path, @params, {}, {}, { :expected_status => 401 })
end
it "should select a provisional grade" do
json = api_call_as_user(@teacher, :put, @path, @params)
expect(json).to eq({
'assignment_id' => @assignment.id,
'student_id' => @student.id,
'selected_provisional_grade_id' => @pg.id
})
expect(@selection.reload.provisional_grade).to eq(@pg)
end
it_behaves_like 'authorization when Anonymous Moderated Marking is enabled', :put
it "should use anonymous_id instead of student_id if user cannot view student names" do
allow_any_instance_of(Assignment).to receive(:can_view_student_names?).and_return false
json = api_call_as_user(@teacher, :put, @path, @params)
expect(json).to eq({
'assignment_id' => @assignment.id,
'anonymous_id' => @pg.submission.anonymous_id,
'selected_provisional_grade_id' => @pg.id
})
expect(@selection.reload.provisional_grade).to eq(@pg)
end
it "should select a provisional grade" do
json = api_call_as_user(@teacher, :put, @path, @params)
expect(json).to eq({
'assignment_id' => @assignment.id,
'student_id' => @student.id,
'selected_provisional_grade_id' => @pg.id
})
expect(@assignment.moderated_grading_selections.where(student_id: @student.id).first.provisional_grade).to eq(@pg)
end
it "should use anonymous_id instead of student_id if user cannot view student names" do
allow_any_instance_of(Assignment).to receive(:can_view_student_names?).and_return false
json = api_call_as_user(@teacher, :put, @path, @params)
expect(json).to eq({
'assignment_id' => @assignment.id,
'anonymous_id' => @pg.submission.anonymous_id,
'selected_provisional_grade_id' => @pg.id
})
expect(@assignment.moderated_grading_selections.where(student_id: @student.id).first.provisional_grade).to eq(@pg)
end
it_behaves_like 'authorization for provisional final grade selection', :put
end
describe "copy_to_final_mark" do
before(:once) do
course_with_student :active_all => true
ta_in_course :active_all => true
@assignment = @course.assignments.create! submission_types: 'online_text_entry', moderated_grading: true
@assignment.moderated_grading_selections.create! student: @student
@assignment = @course.assignments.create!(
submission_types: 'online_text_entry',
moderated_grading: true,
grader_count: 1,
final_grader_id: @teacher.id
)
@submission = @assignment.submit_homework(@student, :submission_type => 'online_text_entry', :body => 'hallo')
@pg = @submission.find_or_create_provisional_grade!(@ta, score: 80)
@submission.add_comment(:commenter => @ta, :comment => 'huttah!', :provisional => true)
@ -121,7 +116,7 @@ describe 'Provisional Grades API', type: :request do
expect(json['crocodoc_urls']).to eq([])
end
it_behaves_like 'authorization when Anonymous Moderated Marking is enabled', :post
it_behaves_like 'authorization for provisional final grade selection', :post
end
describe "publish" do
@ -135,6 +130,7 @@ describe 'Provisional Grades API', type: :request do
end
it "requires a moderated assignment" do
@assignment.update_attribute :final_grader_id, @teacher.id
json = api_call_as_user(@teacher, :post, @path, @params, {}, {}, { :expected_status => 400 })
expect(json['message']).to eq 'Assignment does not use moderated grading'
end
@ -142,16 +138,14 @@ describe 'Provisional Grades API', type: :request do
context "with moderated assignment" do
before(:once) do
@assignment.update_attribute :moderated_grading, true
@assignment.update_attribute :grader_count, 2
@assignment.update_attribute :final_grader_id, @teacher.id
end
it "responds with a 200 for a valid request" do
api_call_as_user(@teacher, :post, @path, @params, {}, {}, expected_status: 200)
end
it "requires moderate_grades permissions" do
api_call_as_user(@ta, :post, @path, @params, {}, {}, { :expected_status => 401 })
end
it "requires manage_grades permissions" do
@course.root_account.role_overrides.create!(
permission: :manage_grades,
@ -209,12 +203,6 @@ describe 'Provisional Grades API', type: :request do
end
it "publishes provisional grades" do
@student.communication_channels.create(:path => 'student@example.edu', :path_type => 'email').confirm
n = Notification.create!(:name => 'Submission Graded', :category => 'TestImmediately')
NotificationPolicy.create!(:notification => n,
:communication_channel => @student.communication_channel,
:frequency => 'immediately')
expect(@submission.workflow_state).to eq 'submitted'
expect(@submission.score).to be_nil
expect(@student.messages).to be_empty
@ -227,15 +215,12 @@ describe 'Provisional Grades API', type: :request do
@assignment.reload
expect(@assignment.grades_published_at).to be_within(1.minute.to_i).of(Time.now.utc)
@student.reload
expect(@student.messages.map(&:notification_name)).to be_include 'Submission Graded'
end
it "publishes the selected provisional grade when the student is in the moderation set" do
@submission.provisional_grade(@ta).update_attribute(:graded_at, 1.minute.ago)
sel = @assignment.moderated_grading_selections.create!(:student => @student)
sel = @assignment.moderated_grading_selections.find_by(student: @student)
@other_ta = user_factory :active_user => true
@course.enroll_ta @other_ta, :enrollment_state => 'active'
@ -255,9 +240,7 @@ describe 'Provisional Grades API', type: :request do
context "with one provisional grade" do
it "publishes the only provisional grade if none have been explicitly selected" do
course_with_user("TaEnrollment", course: @course, active_all: true)
second_ta = @user
@submission = @assignment.submit_homework(@student, body: "hello")
@assignment.moderated_grading_selections.create!(student: @student)
@assignment.grade_student(@student, grader: @ta, score: 72, provisional: true)
api_call_as_user(@teacher, :post, @path, @params)
@ -274,7 +257,6 @@ describe 'Provisional Grades API', type: :request do
it "publishes even when some submissions have no grades" do
@submission = @assignment.submit_homework(@student, body: "hello")
@assignment.moderated_grading_selections.create!(student: @student)
@user = @teacher
raw_api_call(:post, @path, @params)
@ -286,7 +268,6 @@ describe 'Provisional Grades API', type: :request do
it "does not publish if none have been explicitly selected" do
@submission = @assignment.submit_homework(@student, body: "hello")
@assignment.moderated_grading_selections.create!(student: @student)
@assignment.grade_student(@student, grader: @ta, score: 72, provisional: true)
@assignment.grade_student(@student, grader: @second_ta, score: 88, provisional: true)
@ -303,8 +284,7 @@ describe 'Provisional Grades API', type: :request do
student_2 = student_in_course(active_all: true, course: @course).user
submission_1 = @assignment.submit_homework(student_1, body: "hello")
submission_2 = @assignment.submit_homework(student_2, body: "hello")
selection_1 = @assignment.moderated_grading_selections.create!(student: student_1)
@assignment.moderated_grading_selections.create!(student: student_2)
selection_1 = @assignment.moderated_grading_selections.find_by(student: student_1)
@assignment.grade_student(student_1, grader: @ta, score: 12, provisional: true)
@assignment.grade_student(student_1, grader: @second_ta, score: 34, provisional: true)
@assignment.grade_student(student_2, grader: @ta, score: 56, provisional: true)
@ -322,7 +302,7 @@ describe 'Provisional Grades API', type: :request do
end
end
it_behaves_like 'authorization when Anonymous Moderated Marking is enabled', :post
it_behaves_like 'authorization for provisional final grade selection', :post
end
end
end

View File

@ -1729,6 +1729,7 @@ describe 'Submissions API', type: :request do
points_possible: 10
)
@assignment.update_attribute(:moderated_grading, true)
@assignment.update_attribute(:grader_count, 2)
submission = @assignment.submit_homework(@student, body: 'nice work')
@provisional_grade = submission.provisional_grades.build do |grade|
grade.scorer = @teacher
@ -2805,7 +2806,10 @@ describe 'Submissions API', type: :request do
end
it "creates a provisional grade and comment" do
@assignment.update_attribute(:moderated_grading, true)
@assignment.moderated_grading = true
@assignment.grader_count = 2
@assignment.final_grader = @teacher
@assignment.save!
submission = @assignment.submit_homework(@student, :body => 'what')
json = api_call(
@ -2844,7 +2848,10 @@ describe 'Submissions API', type: :request do
end
it "creates a provisional grade and comment when no submission exists" do
@assignment.update_attribute(:moderated_grading, true)
@assignment.moderated_grading = true
@assignment.grader_count = 2
@assignment.final_grader = @teacher
@assignment.save!
json = api_call(
:put,
@ -3864,14 +3871,13 @@ describe 'Submissions API', type: :request do
course_with_teacher_logged_in active_all: true
student_in_course active_all: true
@user = @teacher
assignment = @course.assignments.create!(moderated_grading: true)
assignment = @course.assignments.create!(moderated_grading: true, grader_count: 1)
submission = assignment.submit_homework(@student, submission_type: 'online_upload',
attachments: [crocodocable_attachment_model(context: @student)])
provisional_grade = submission.find_or_create_provisional_grade!(@teacher, score: 1)
assignment.moderated_grading_selections.create! do |s|
s.student = @student
s.provisional_grade = provisional_grade
end
assignment.moderated_grading_selections.
where(student_id: @student.id).first.
update_attribute(:provisional_grade, provisional_grade)
assignment.update(grades_published_at: 1.hour.ago)
submission.reload
submission.attachments.first.create_crocodoc_document(uuid: '1234',
@ -4206,6 +4212,7 @@ describe 'Submissions API', type: :request do
@student2 = student_in_course(:active_all => true).user
@assignment = @course.assignments.build
@assignment.moderated_grading = true
@assignment.grader_count = 1
@assignment.save!
@assignment.submit_homework @student1, :body => 'EHLO'
@path = "/api/v1/courses/#{@course.id}/assignments/#{@assignment.id}/gradeable_students"
@ -4263,35 +4270,31 @@ describe 'Submissions API', type: :request do
api_call_as_user(@ta, :get, @path, @params, {}, {}, { :expected_status => 401 })
end
context "when Anonymous Moderated Marking is enabled" do
before(:once) { @course.root_account.enable_feature!(:anonymous_moderated_marking) }
it "is unauthorized when the user is not the assigned final grader" do
api_call_as_user(@teacher, :get, @path, @params, {}, {}, expected_status: 401)
end
it "is unauthorized when the user is not the assigned final grader" do
api_call_as_user(@teacher, :get, @path, @params, {}, {}, expected_status: 401)
end
it "is unauthorized when the user is an account admin without 'Select Final Grade for Moderation' permission" do
@course.account.role_overrides.create!(role: admin_role, enabled: false, permission: :select_final_grade)
api_call_as_user(account_admin_user, :get, @path, @params, {}, {}, expected_status: 401)
end
it "is unauthorized when the user is an account admin without 'Select Final Grade for Moderation' permission" do
@course.account.role_overrides.create!(role: admin_role, enabled: false, permission: :select_final_grade)
api_call_as_user(account_admin_user, :get, @path, @params, {}, {}, expected_status: 401)
end
it "is authorized when the user is the final grader" do
@assignment.update!(final_grader: @teacher, grader_count: 2)
api_call_as_user(@teacher, :get, @path, @params, {}, {}, expected_status: 200)
end
it "is authorized when the user is the final grader" do
@assignment.update!(final_grader: @teacher, grader_count: 2)
api_call_as_user(@teacher, :get, @path, @params, {}, {}, expected_status: 200)
end
it "is authorized when the user is an account admin with 'Select Final Grade for Moderation' permission" do
api_call_as_user(account_admin_user, :get, @path, @params, {}, {}, expected_status: 200)
end
it "is authorized when the user is an account admin with 'Select Final Grade for Moderation' permission" do
api_call_as_user(account_admin_user, :get, @path, @params, {}, {}, expected_status: 200)
end
it "includes provisional grades with selections" do
@assignment.update!(final_grader: @teacher)
sub = @assignment.grade_student(@student1, :score => 90, :grader => @ta, :provisional => true).first
pg = sub.provisional_grades.first
sel = @assignment.moderated_grading_selections.build
sel.student_id = @student1.id
sel.selected_provisional_grade_id = pg.id
sel.save!
@assignment.moderated_grading_selections.
where(student_id: @student1.id).first.
update_attribute(:provisional_grade, pg)
json = api_call_as_user(@teacher, :get, @path, @params)
expect(json).to match_array(
[{"id"=>@student1.id,
@ -4321,12 +4324,12 @@ describe 'Submissions API', type: :request do
end
it "anonymizes speedgrader_url if anonymously grading" do
@assignment.update!(final_grader: @teacher)
sub = @assignment.grade_student(@student1, :score => 90, :grader => @ta, :provisional => true).first
pg = sub.provisional_grades.first
sel = @assignment.moderated_grading_selections.build
sel.student_id = @student1.id
sel.selected_provisional_grade_id = pg.id
sel.save!
@assignment.moderated_grading_selections.
where(student_id: @student1.id).first.
update_attribute(:provisional_grade, pg)
allow_any_instance_of(Assignment).to receive(:can_view_student_names?).and_return false
json = api_call_as_user(@teacher, :get, @path, @params)
anonymous_id = @assignment.submission_for_student(@student1).anonymous_id
@ -4339,12 +4342,12 @@ describe 'Submissions API', type: :request do
end
it "anonymizes scorer id of provisional grade if grading double blind" do
@assignment.update!(final_grader: @teacher)
sub = @assignment.grade_student(@student1, :score => 90, :grader => @ta, :provisional => true).first
pg = sub.provisional_grades.first
sel = @assignment.moderated_grading_selections.build
sel.student_id = @student1.id
sel.selected_provisional_grade_id = pg.id
sel.save!
@assignment.moderated_grading_selections.
where(student_id: @student1.id).first.
update_attribute(:provisional_grade, pg)
allow_any_instance_of(Assignment).to receive(:can_view_student_names?).and_return false
allow_any_instance_of(Assignment).to receive(:can_view_other_grader_identities?).and_return false
json = api_call_as_user(@teacher, :get, @path, @params)
@ -4363,6 +4366,7 @@ describe 'Submissions API', type: :request do
@student2 = student_in_course(:active_all => true).user
@assignment1 = @course.assignments.build
@assignment1.moderated_grading = true
@assignment1.grader_count = 1
@assignment1.save!
@assignment2 = @course.assignments.build
@assignment2.save!

View File

@ -62,7 +62,7 @@ QUnit.module('GradebookHeaderMenu#hideMenuActionsWithUnmetDependencies', {
submissions_downloads: 1
}
this.gradebook = {
options: {anonymous_moderated_marking_enabled: false, gradebook_is_editable: true}
options: {gradebook_is_editable: true}
}
this.menuElement = document.createElement('ul')
this.createMenu(this.menuElement)
@ -180,7 +180,7 @@ QUnit.module('GradebookHeaderMenu#disableUnavailableMenuActions', {
this.createMenu(this.menuElement)
this.menu = $(this.menuElement)
this.gradebook = {
options: {anonymous_moderated_marking_enabled: false, gradebook_is_editable: true}
options: {gradebook_is_editable: true}
}
},
teardown() {
@ -242,28 +242,18 @@ test('does not disable "Set Default Grade" when isAdmin', function() {
})
test('disables "Unmute Assignment" when the assignment is moderated and grades have not been published', function () {
this.gradebook.options.anonymous_moderated_marking_enabled = true
this.assignment = {moderated_grading: true, grades_published: false, inClosedGradingPeriod: false, muted: true}
this.disableUnavailableMenuActions(this.menu)
strictEqual(this.menu.find('[data-action="toggleMuting"]')[0].getAttribute('aria-disabled'), 'true')
})
test('does not disable "Unmute Assignment" when Anonymous Moderated Marking is disabled', function () {
this.gradebook.options.anonymous_moderated_marking_enabled = false
this.assignment = {moderated_grading: true, grades_published: false, inClosedGradingPeriod: false, muted: true}
this.disableUnavailableMenuActions(this.menu)
strictEqual(this.menu.find('[data-action="toggleMuting"]')[0].getAttribute('aria-disabled'), null)
})
test('does not disable "Unmute Assignment" when grades are published', function () {
this.gradebook.options.anonymous_moderated_marking_enabled = false
this.assignment = {moderated_grading: true, grades_published: true, inClosedGradingPeriod: false, muted: true}
this.disableUnavailableMenuActions(this.menu)
strictEqual(this.menu.find('[data-action="toggleMuting"]')[0].getAttribute('aria-disabled'), null)
})
test('does not disable "Mute Assignment"', function () {
this.gradebook.options.anonymous_moderated_marking_enabled = true
test('does not disable "Mute Assignment" when the assignment can be muted', function () {
this.assignment = {moderated_grading: true, grades_published: false, inClosedGradingPeriod: false, muted: false}
this.disableUnavailableMenuActions(this.menu)
strictEqual(this.menu.find('[data-action="toggleMuting"]')[0].getAttribute('aria-disabled'), null)

View File

@ -943,43 +943,27 @@ QUnit.module('Gradebook#gotAllAssignmentGroups', suiteHooks => {
$('#assignment_group_weights_dialog').remove()
})
QUnit.module('when Anonymous Moderated Marking is enabled', hooks => {
hooks.beforeEach(() => {
gradebook.options.anonymous_moderated_marking_enabled = true
})
test('sets moderation_in_progress to true for a moderated assignment whose grades are not published', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(moderatedUnpublishedAssignment.moderation_in_progress, true) })
test('sets moderation_in_progress to true for a moderated assignment whose grades are not published', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(moderatedUnpublishedAssignment.moderation_in_progress, true) })
test('sets moderation_in_progress to false for a moderated assignment whose grades are published', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(moderatedPublishedAssignment.moderation_in_progress, false)
})
test('sets moderation_in_progress to false for an unmoderated assignment', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(unmoderatedAssignment.moderation_in_progress, false)
})
test('sets hide_grades_when_muted to true for an anonymous assignment', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(anonymousUnmoderatedAssignment.hide_grades_when_muted, true)
})
test('sets hide_grades_when_muted to false for a non-anonymous assignment', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(unmoderatedAssignment.hide_grades_when_muted, false)
})
test('sets moderation_in_progress to false for a moderated assignment whose grades are published', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(moderatedPublishedAssignment.moderation_in_progress, false)
})
test('does not set moderation_in_progress when anonymous moderated marking is off', () => {
test('sets moderation_in_progress to false for an unmoderated assignment', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(moderatedUnpublishedAssignment.moderation_in_progress, undefined)
strictEqual(unmoderatedAssignment.moderation_in_progress, false)
})
test('does not set hide_grades_when_muted when anonymous moderated marking is off', () => {
test('sets hide_grades_when_muted to true for an anonymous assignment', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(moderatedUnpublishedAssignment.hide_grades_when_muted, undefined)
strictEqual(anonymousUnmoderatedAssignment.hide_grades_when_muted, true)
})
test('sets hide_grades_when_muted to false for a non-anonymous assignment', () => {
gradebook.gotAllAssignmentGroups(assignmentGroups)
strictEqual(unmoderatedAssignment.hide_grades_when_muted, false)
})
})

View File

@ -59,9 +59,7 @@ test('speed_grader_enabled sets speedgrader url', function() {
equal(dialog.dialog.find('.more-details-link').length, 1)
})
test('speedGraderUrl excludes student id when Anonymous Moderated Marking is ' +
'enabled and the assignment is anonymously graded', function() {
this.options.anonymous_moderated_marking_enabled = true
test('speedGraderUrl excludes student id when assignment is anonymously graded', function() {
this.assignment.anonymous_grading = true
this.options.context_url = 'http://some-fake-url'
const dialog = new SubmissionDetailsDialog(this.assignment, this.user, this.options)
@ -69,28 +67,7 @@ test('speedGraderUrl excludes student id when Anonymous Moderated Marking is ' +
notOk(dialog.submission.speedGraderUrl.match(/student_id/))
})
test('speedGraderUrl includes student id when Anonymous Moderated Marking is ' +
'enabled and the assignment is not anonymously graded', function() {
this.options.anonymous_moderated_marking_enabled = true
this.options.context_url = 'http://some-fake-url'
const dialog = new SubmissionDetailsDialog(this.assignment, this.user, this.options)
ok(dialog.submission.speedGraderUrl.match(/student_id/))
})
test('speedGraderUrl includes student id when Anonymous Moderated Marking is ' +
'disabled and the assignment is anonymously graded', function() {
this.options.anonymous_moderated_marking_enabled = false
this.assignment.anonymous_grading = true
this.options.context_url = 'http://some-fake-url'
const dialog = new SubmissionDetailsDialog(this.assignment, this.user, this.options)
ok(dialog.submission.speedGraderUrl.match(/student_id/))
})
test('speedGraderUrl includes student id when Anonymous Moderated Marking is ' +
'disabled and the assignment is not anonymously graded', function() {
this.options.anonymous_moderated_marking_enabled = false
test('speedGraderUrl includes student id when assignment is not anonymously graded', function() {
this.options.context_url = 'http://some-fake-url'
const dialog = new SubmissionDetailsDialog(this.assignment, this.user, this.options)

View File

@ -25,7 +25,6 @@ import Header from 'jsx/assignments/ModerationHeader'
QUnit.module('ModerationHeader', {
setup() {
this.props = {
anonymousModeratedMarkingEnabled: false,
muted: false,
onPublishClick() {},
onReviewClick() {},
@ -153,7 +152,6 @@ QUnit.module('ModerationHeader#unmuteAssignmentButton', (hooks) => {
hooks.beforeEach(() => {
props = {
anonymousModeratedMarkingEnabled: true,
muted: true,
onPublishClick() {},
onReviewClick() {},
@ -179,18 +177,11 @@ QUnit.module('ModerationHeader#unmuteAssignmentButton', (hooks) => {
wrapper.unmount()
})
test('renders the unmute button if Anonymous Moderated Marking is enabled', () => {
test('renders the unmute button', () => {
renderHeader()
strictEqual(wrapper.find(unmuteButtonSelector).exists(), true)
})
test('does not render the unmute button if Anonymous Moderated Marking is not enabled', () => {
props.anonymousModeratedMarkingEnabled = false
renderHeader()
strictEqual(wrapper.find(unmuteButtonSelector).exists(), false)
})
test('enables the unmute button if the assignment is published and muted', () => {
props.published = true
props.muted = true

View File

@ -1199,7 +1199,6 @@ QUnit.module('Assignment#renderModeratedGradingFormFieldGroup', (hooks) => {
hooks.beforeEach(() => {
fakeENV.setup({
ANONYMOUS_MODERATED_MARKING_ENABLED: false,
AVAILABLE_MODERATORS: availableModerators,
HAS_GRADED_SUBMISSIONS: false,
LOCALE: 'en',

View File

@ -18,7 +18,6 @@
import fakeENV from 'helpers/fakeENV'
import SpeedgraderHelpers, {
isAnonymousModeratedMarkingEnabled,
setupIsAnonymous,
setupAnonymizableId
} from 'speed_grader_helpers'
@ -36,10 +35,6 @@ QUnit.module('SpeedGrader', {
}
})
test('isAnonymousModeratedMarkingEnabled is available on main object', () => {
strictEqual(SpeedgraderHelpers.isAnonymousModeratedMarkingEnabled, isAnonymousModeratedMarkingEnabled)
})
test('setupIsAnonymous is available on main object', () => {
strictEqual(SpeedgraderHelpers.setupIsAnonymous, setupIsAnonymous)
})
@ -441,56 +436,18 @@ test('Posts to the resubmit URL', () => {
$.ajaxJSON = previousAjaxJson
})
QUnit.module('SpeedgraderHelpers.isAnonymousModeratedMarking', suiteHooks => {
suiteHooks.afterEach(() => {
fakeENV.teardown()
})
test('returns false when not set', () => {
delete ENV.anonymous_moderated_marking_enabled
strictEqual(isAnonymousModeratedMarkingEnabled(), false)
})
test('returns false when disabled', () => {
fakeENV.setup({anonymous_moderated_marking_enabled: false})
strictEqual(isAnonymousModeratedMarkingEnabled(), false)
})
test('returns true when enabled', () => {
fakeENV.setup({anonymous_moderated_marking_enabled: true})
strictEqual(isAnonymousModeratedMarkingEnabled(), true)
})
})
QUnit.module('SpeedgraderHelpers.setupIsAnonymous', suiteHooks => {
suiteHooks.afterEach(() => {
fakeENV.teardown()
})
test('returns true when assignment is anonymously graded and Anonymous Moderated Marking is enabled', () => {
fakeENV.setup({anonymous_moderated_marking_enabled: true})
test('returns true when assignment is anonymously graded', () => {
strictEqual(setupIsAnonymous({anonymous_grading: true}), true)
})
test('returns false when assignment is not anonymously graded and Anonymous Moderated Marking is enabled', () => {
fakeENV.setup({anonymous_moderated_marking_enabled: true})
test('returns false when assignment is not anonymously graded', () => {
strictEqual(setupIsAnonymous({anonymous_grading: false}), false)
})
test('returns false when assignment is anonymously graded and Anonymous Moderated Marking is disabled', () => {
fakeENV.setup({anonymous_moderated_marking_enabled: false})
strictEqual(setupIsAnonymous({anonymous_grading: true}), false)
})
test('returns false when assignment is not anonymously graded and Anonymous Moderated Marking is unset', () => {
delete ENV.anonymous_moderated_marking_enabled
strictEqual(setupIsAnonymous({anonymous_grading: false}), false)
})
test('returns false when assignment is anonymously graded and Anonymous Moderated Marking is unset', () => {
delete ENV.anonymous_moderated_marking_enabled
strictEqual(setupIsAnonymous({anonymous_grading: true}), false)
})
})
QUnit.module('SpeedgraderHelpers.setupAnonymizableId', suiteHooks => {

View File

@ -149,16 +149,7 @@ test('rejects a letter for points_possible', function() {
equal(errors.points_possible[0].message, 'Points possible must be a number')
})
test('does not validate presence of a final grader if anonymous moderated marking is disabled', function() {
const view = this.editView()
sinon.spy(view, 'validateFinalGrader')
view.validateBeforeSave({}, [])
strictEqual(view.validateFinalGrader.callCount, 0)
view.validateFinalGrader.restore()
})
test('validates presence of a final grader if anonymous moderated marking is enabled', function() {
ENV.ANONYMOUS_MODERATED_MARKING_ENABLED = true
test('validates presence of a final grader', function() {
const view = this.editView()
sinon.spy(view, 'validateFinalGrader')
view.validateBeforeSave({}, [])
@ -166,16 +157,7 @@ test('validates presence of a final grader if anonymous moderated marking is ena
view.validateFinalGrader.restore()
})
test('does not validate grader count if anonymous moderated marking is disabled', function() {
const view = this.editView()
sinon.spy(view, 'validateGraderCount')
view.validateBeforeSave({}, [])
strictEqual(view.validateGraderCount.callCount, 0)
view.validateGraderCount.restore()
})
test('validates grader count if anonymous moderated marking is enabled', function() {
ENV.ANONYMOUS_MODERATED_MARKING_ENABLED = true
test('validates grader count', function() {
const view = this.editView()
sinon.spy(view, 'validateGraderCount')
view.validateBeforeSave({}, [])
@ -355,22 +337,6 @@ test('renders escaped angle brackets properly', function() {
equal(view.$description.val().match(desc), desc)
})
test('allows changing moderation setting if no graded submissions exist', function() {
ENV.HAS_GRADED_SUBMISSIONS = false
const view = this.editView({has_submitted_submissions: true, moderated_grading: true})
ok(view.$('[type=checkbox][name=moderated_grading]').prop('checked'))
notOk(view.$('[type=checkbox][name=moderated_grading]').prop('disabled'))
equal(view.$('[type=hidden][name=moderated_grading]').attr('value'), '0')
})
test('locks down moderation setting after students submit', function() {
ENV.HAS_GRADED_SUBMISSIONS = true
const view = this.editView({has_submitted_submissions: true, moderated_grading: true})
ok(view.$('[type=checkbox][name=moderated_grading]').prop('checked'))
ok(view.$('[type=checkbox][name=moderated_grading]').prop('disabled'))
equal(view.$('[type=hidden][name=moderated_grading]').attr('value'), '1')
})
test('routes to discussion details normally', function() {
const view = this.editView({html_url: 'http://foo'})
equal(view.locationAfterSave({}), 'http://foo')
@ -1014,18 +980,11 @@ QUnit.module('EditView: Anonymous Moderated Marking', (hooks) => {
fixtures.innerHTML = ''
})
test('adds the ModeratedGradingFormFieldGroup mount point when anonymous moderated marking is on', () => {
ENV.ANONYMOUS_MODERATED_MARKING_ENABLED = true
test('adds the ModeratedGradingFormFieldGroup mount point', () => {
const view = editView()
view.toJSON()
strictEqual(view.$el.find('[data-component="ModeratedGradingFormFieldGroup"]').length, 1)
})
test('does not add the ModeratedGradingFormFieldGroup mount point when anonymous moderated marking is off', () => {
const view = editView()
view.toJSON()
strictEqual(view.$el.find('[data-component="ModeratedGradingFormFieldGroup"]').length, 0)
})
})
QUnit.module('EditView#validateFinalGrader', (hooks) => {

View File

@ -25,7 +25,6 @@ RSpec.describe AnonymousSubmissionsController do
before do
course_with_student_and_submitted_homework
@context = @course
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@assignment.update!(anonymous_grading: true)
@submission.update!(score: 10)
@assignment.unmute!

View File

@ -218,7 +218,7 @@ describe AssignmentsController do
end
describe "per-assignment permissions" do
let(:js_permissions) { assigns[:js_env][:PERMISSIONS] }
let(:assignment_permissions) { assigns[:js_env][:PERMISSIONS][:by_assignment_id] }
before(:each) do
@course.enable_feature!(:moderated_grading)
@ -230,39 +230,23 @@ describe AssignmentsController do
)
user_session(@teacher)
ta_in_course(active_all: true)
@noneditable_assignment = @course.assignments.create!(
moderated_grading: true,
grader_count: 2,
final_grader: @ta
)
end
context "when Anonymous Moderated Marking is on" do
let(:assignment_permissions) { assigns[:js_env][:PERMISSIONS][:by_assignment_id] }
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
ta_in_course(active_all: true)
@noneditable_assignment = @course.assignments.create!(
moderated_grading: true,
grader_count: 2,
final_grader: @ta
)
end
it "sets the 'update' attribute for an editable assignment to true" do
get 'index', params: {course_id: @course.id}
expect(assignment_permissions[@editable_assignment.id][:update]).to eq(true)
end
it "sets the 'update' attribute for a non-editable assignment to false" do
get 'index', params: {course_id: @course.id}
expect(assignment_permissions[@noneditable_assignment.id][:update]).to eq(false)
end
it "sets the 'update' attribute for an editable assignment to true" do
get 'index', params: {course_id: @course.id}
expect(assignment_permissions[@editable_assignment.id][:update]).to eq(true)
end
context "when Anonymous Moderated Marking is off" do
it "does not set permissions in js_env for individual assignments" do
get 'index', params: {course_id: @course.id}
expect(js_permissions).not_to include(:by_assignment_id)
end
it "sets the 'update' attribute for a non-editable assignment to false" do
get 'index', params: {course_id: @course.id}
expect(assignment_permissions[@noneditable_assignment.id][:update]).to eq(false)
end
end
end
@ -270,202 +254,115 @@ describe AssignmentsController do
describe "GET 'show_moderate'" do
before(:each) do
user_session(@teacher)
end
let(:assignment) do
@course.assignments.create(
title: 'some assignment',
workflow_state: 'published',
moderated_grading: true
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@other_teacher = @user
@assignment = @course.assignments.create!(
moderated_grading: true,
final_grader: @other_teacher,
grader_count: 2,
workflow_state: 'published'
)
end
describe 'js_env for URLS' do
let(:urls) { assigns[:js_env][:URLS] }
it 'sets student_submissions_url' do
get 'show_moderate', params: {course_id: @course.id, assignment_id: assignment.id}
expect(urls[:student_submissions_url]).to eq "http://test.host/api/v1/courses/#{@course.id}/assignments/#{assignment.id}/submissions?include[]=user_summary&include[]=provisional_grades"
end
it 'sets provisional_grades_base_url' do
get 'show_moderate', params: {course_id: @course.id, assignment_id: assignment.id}
expect(urls[:provisional_grades_base_url]).to eq "http://test.host/api/v1/courses/#{@course.id}/assignments/#{assignment.id}/provisional_grades"
end
it 'sets unmute_assignment_url' do
get 'show_moderate', params: {course_id: @course.id, assignment_id: assignment.id}
expect(urls[:unmute_assignment_url]).to eq "http://test.host/courses/#{@course.id}/assignments/#{assignment.id}/mute?status=false"
end
it "renders the page when the current user is the selected moderator" do
user_session(@other_teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
end
it "sets the js_env for ASSIGNMENT_TITLE" do
get 'show_moderate', params: {course_id: @course.id, assignment_id: assignment.id}
expect(assigns[:js_env][:ASSIGNMENT_TITLE]).to eq "some assignment"
it "renders unauthorized when the current user is not the selected moderator" do
user_session(@teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_unauthorized
end
describe 'permissions' do
before(:once) do
@user = User.create!
@custom_role = @course.root_account.roles.create!(name: 'CustomRole', base_role_type: 'TaEnrollment')
@course.root_account.role_overrides.create!(permission: :moderate_grades, role: @custom_role, enabled: true)
@course.root_account.role_overrides.create!(permission: :view_all_grades, role: @custom_role, enabled: false)
@course.root_account.role_overrides.create!(permission: :manage_grades, role: @custom_role, enabled: false)
@course.enroll_user(@user, 'TaEnrollment', role: @custom_role, active_all: true)
@assignment = @course.assignments.create!(workflow_state: 'published', moderated_grading: true)
end
before(:each) { user_session(@user) }
let(:permissions) { assigns[:js_env][:PERMISSIONS] }
let(:allow_editing) do
override = @course.root_account.role_overrides.find_by(permission: 'manage_grades')
override.update!(enabled: true)
end
let(:allow_viewing) do
override = @course.root_account.role_overrides.find_by(permission: 'view_all_grades')
override.update!(enabled: true)
end
it 'grants the user view permissions if they have "View all grades" permissions in the course' do
allow_viewing
get :show_moderate, params: {course_id: @course, assignment_id: @assignment}
expect(permissions[:view_grades]).to eq true
end
it 'grants the user view permissions if they have "Edit grades" permissions in the course' do
allow_editing
get :show_moderate, params: {course_id: @course, assignment_id: @assignment}
expect(permissions[:view_grades]).to eq true
end
it 'denies the user view permissions if they lack both "View all grades" and "Edit grades" \
permissions in the course' do
get :show_moderate, params: {course_id: @course, assignment_id: @assignment}
expect(permissions[:view_grades]).to eq false
end
it 'grants the user edit permissions if they have "Edit grades" permissions in the course' do
allow_editing
get :show_moderate, params: {course_id: @course, assignment_id: @assignment}
expect(permissions[:edit_grades]).to eq true
end
it 'denies the user edit permissions if they lack "Edit grades" permissions in the course' do
get :show_moderate, params: {course_id: @course, assignment_id: @assignment}
expect(permissions[:edit_grades]).to eq false
end
it "renders unauthorized when no moderator is selected and the user is not an admin" do
@assignment.update!(final_grader: nil)
user_session(@teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(401)
end
context "when Anonymous Moderated Grading is enabled" do
before :once do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
it "renders unauthorized when no moderator is selected and the user is an admin without " \
"'Select Final Grade for Moderation' permission" do
@course.account.role_overrides.create!(role: admin_role, enabled: false, permission: :select_final_grade)
@assignment.update!(final_grader: nil)
user_session(account_admin_user)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(401)
end
it "renders the page when the current user is an admin and not the selected moderator" do
account_admin_user(account: @course.root_account)
user_session(@admin)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
end
it "renders the page when no moderator is selected and the user is an admin with " \
"'Select Final Grade for Moderation' permission" do
@assignment.update!(final_grader: nil)
user_session(account_admin_user)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
end
describe "js_env" do
let_once(:grader_1) do
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@other_teacher = @user
@assignment = @course.assignments.create!(
@user
end
let_once(:grader_2) do
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@user
end
let(:env) { assigns[:js_env] }
before :once do
@assignment.moderation_graders.create!(anonymous_id: "abcde", user: grader_1)
@assignment.moderation_graders.create!(anonymous_id: "fghij", user: grader_2)
end
before :each do
@assignment.update_attributes(
moderated_grading: true,
final_grader: @other_teacher,
grader_count: 2,
workflow_state: 'published'
grader_count: 2
)
end
it "renders the page when the current user is the selected moderator" do
user_session(@other_teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
end
it "renders unauthorized when the current user is not the selected moderator" do
user_session(@teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_unauthorized
it "includes ASSIGNMENT.course_id" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:course_id]).to be(@course.id)
end
it "renders unauthorized when no moderator is selected and the user is not an admin" do
@assignment.update!(final_grader: nil)
user_session(@teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(401)
it "includes ASSIGNMENT.id" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:id]).to be(@assignment.id)
end
it "renders unauthorized when no moderator is selected and the user is an admin without " \
"'Select Final Grade for Moderation' permission" do
@course.account.role_overrides.create!(role: admin_role, enabled: false, permission: :select_final_grade)
@assignment.update!(final_grader: nil)
user_session(account_admin_user)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(401)
it "includes ASSIGNMENT.grades_published" do
@assignment.update!(grades_published_at: 1.day.ago)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:grades_published]).to be(true)
end
it "renders the page when the current user is an admin and not the selected moderator" do
account_admin_user(account: @course.root_account)
user_session(@admin)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
it "includes ASSIGNMENT.muted" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:muted]).to be(true)
end
it "renders the page when no moderator is selected and the user is an admin with " \
"'Select Final Grade for Moderation' permission" do
@assignment.update!(final_grader: nil)
user_session(account_admin_user)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
it "includes ASSIGNMENT.title" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:title]).to eql(@assignment.title)
end
describe "js_env" do
let_once(:grader_1) do
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@user
end
let_once(:grader_2) do
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@user
end
let(:env) { assigns[:js_env] }
before :once do
@assignment.moderation_graders.create!(anonymous_id: "abcde", user: grader_1)
@assignment.moderation_graders.create!(anonymous_id: "fghij", user: grader_2)
end
before :each do
user_session(@other_teacher)
end
it "includes ASSIGNMENT.course_id" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:course_id]).to be(@course.id)
end
it "includes ASSIGNMENT.id" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:id]).to be(@assignment.id)
end
it "includes ASSIGNMENT.grades_published" do
@assignment.update!(grades_published_at: 1.day.ago)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:grades_published]).to be(true)
end
it "includes ASSIGNMENT.muted" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:muted]).to be(true)
end
it "includes ASSIGNMENT.title" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:title]).to eql(@assignment.title)
end
it "includes moderation graders in GRADERS" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
moderation_grader_ids = @assignment.moderation_graders.map(&:id)
expect(env[:GRADERS].map {|grader| grader[:id]}).to match_array(moderation_grader_ids)
end
it "includes moderation graders in GRADERS" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
moderation_grader_ids = @assignment.moderation_graders.map(&:id)
expect(env[:GRADERS].map {|grader| grader[:id]}).to match_array(moderation_grader_ids)
end
end
end
@ -719,18 +616,17 @@ describe AssignmentsController do
user_session(@teacher)
end
context "with anonymous moderated marking enabled and moderated grading on" do
context "with moderated grading on" do
before :each do
@course.account.enable_feature!(:anonymous_moderated_marking)
@assignment.update!(moderated_grading: true, grader_count: 1)
end
it "should fail if anonymous_moderated_marking is enabled, grades are not published, and status is false" do
it "should fail if grades are not published, and status is false" do
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: false }, format: 'json'
assert_unauthorized
end
it "should mute if anonymous_moderated_marking is enabled, grades are not published, and status is true" do
it "should mute if grades are not published, and status is true" do
@assignment.update!(muted: false)
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: true }, format: 'json'
@assignment.reload
@ -893,7 +789,7 @@ describe AssignmentsController do
let(:request_params) { [:edit, params: {course_id: course, id: @assignment}] }
end
shared_examples 'course feature flag made available by Anonymous Moderated Marking account flag' do
shared_examples 'course feature flags for Anonymous Moderated Marking' do
before(:each) do
user_session(@teacher)
end
@ -904,30 +800,11 @@ describe AssignmentsController do
expect(assigns[:js_env][js_env_attribute]).to be false
end
it 'is false when the feature flag is enabled' do
it 'is true when the feature flag is enabled' do
@course.enable_feature!(feature_flag)
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][js_env_attribute]).to be false
end
context 'when Anonymous Moderated Marking is enabled' do
before(:once) do
@course.account.enable_feature!(:anonymous_moderated_marking)
end
it 'is false when the feature flag is not enabled' do
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][js_env_attribute]).to be false
end
it 'is true when the feature flag is enabled' do
@course.enable_feature!(feature_flag)
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][js_env_attribute]).to be true
end
expect(assigns[:js_env][js_env_attribute]).to be true
end
end
@ -983,26 +860,8 @@ describe AssignmentsController do
expect(assigns[:js_env][:SIS_NAME]).to eq('Foo Bar')
end
describe 'js_env ANONYMOUS_MODERATED_MARKING_ENABLED' do
before(:each) do
user_session(@teacher)
end
it 'is true when the root account has Anonymous Moderated Marking enabled' do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
get :edit, params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_MODERATED_MARKING_ENABLED]).to be true
end
it 'is false when the root account does not have Anonymous Moderated Marking enabled' do
get :edit, params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_MODERATED_MARKING_ENABLED]).to be false
end
end
it 'js_env AVAILABLE_MODERATORS includes the name and id for each available moderator' do
user_session(@teacher)
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@assignment.update!(grader_count: 2, moderated_grading: true)
get :edit, params: { course_id: @course.id, id: @assignment.id }
expected_moderators = @course.instructors.map { |user| { name: user.name, id: user.id } }
@ -1111,14 +970,14 @@ describe AssignmentsController do
end
describe 'js_env ANONYMOUS_GRADING_ENABLED' do
it_behaves_like 'course feature flag made available by Anonymous Moderated Marking account flag' do
it_behaves_like 'course feature flags for Anonymous Moderated Marking' do
let(:js_env_attribute) { :ANONYMOUS_GRADING_ENABLED }
let(:feature_flag) { :anonymous_marking }
end
end
describe 'js_env MODERATED_GRADING_ENABLED' do
it_behaves_like 'course feature flag made available by Anonymous Moderated Marking account flag' do
it_behaves_like 'course feature flags for Anonymous Moderated Marking' do
let(:js_env_attribute) { :MODERATED_GRADING_ENABLED }
let(:feature_flag) { :moderated_grading }
end

View File

@ -203,9 +203,7 @@ describe CanvadocSessionsController do
end
let(:hmac) { Canvas::Security.hmac_sha1(blob.to_json) }
it "disables submission annotations for an anonymously-graded assignment " \
"when Anonymous Moderated Marking is enabled" do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
it "disables submission annotations for an anonymously-graded assignment" do
@assignment.update!(anonymous_grading: true)
# The controller fetches different instances of the model objects we're
# working with here, so unfortunately we can't mock them specifically.
@ -215,9 +213,8 @@ describe CanvadocSessionsController do
get :show, params: {blob: blob.to_json, hmac: hmac}
end
it "enables submission annotations for an anonymously-graded assignment " \
"when Anonymous Moderated Marking is disabled" do
@assignment.update!(anonymous_grading: true)
it "enables submission annotations for a non-anonymously-graded assignment" do
@assignment.update!(anonymous_grading: false)
# The controller fetches different instances of the model objects we're
# working with here, so unfortunately we can't mock them specifically.
expect_any_instance_of(Canvadoc).to receive(:session_url).

View File

@ -488,38 +488,25 @@ describe CoursesController do
grader_count: 2,
final_grader: @teacher
)
ta_in_course(active_all: true)
@uneditable_assignment = @course.assignments.create!(
moderated_grading: true,
grader_count: 2,
final_grader: @ta
)
end
context "when Anonymous Moderated Marking is on" do
let(:assignment_permissions) { assigns[:js_env][:PERMISSIONS][:by_assignment_id] }
let(:assignment_permissions) { assigns[:js_env][:PERMISSIONS][:by_assignment_id] }
before(:each) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
ta_in_course(active_all: true)
@uneditable_assignment = @course.assignments.create!(
moderated_grading: true,
grader_count: 2,
final_grader: @ta
)
end
it "sets the 'update' attribute for an editable assignment to true" do
get 'show', params: {id: @course.id}
expect(assignment_permissions[@editable_assignment.id][:update]).to eq(true)
end
it "sets the 'update' attribute for an uneditable assignment to false" do
get 'show', params: {id: @course.id}
expect(assignment_permissions[@uneditable_assignment.id][:update]).to eq(false)
end
it "sets the 'update' attribute for an editable assignment to true" do
get 'show', params: {id: @course.id}
expect(assignment_permissions[@editable_assignment.id][:update]).to eq(true)
end
context "when Anonymous Moderated Marking is off" do
it "does not set permissions in js_env for individual assignments" do
get 'show', params: {id: @course.id}
expect(js_permissions).not_to include(:by_assignment_id)
end
it "sets the 'update' attribute for an uneditable assignment to false" do
get 'show', params: {id: @course.id}
expect(assignment_permissions[@uneditable_assignment.id][:update]).to eq(false)
end
end
end
@ -2378,11 +2365,11 @@ describe CoursesController do
user_session(@teacher)
post 'student_view', params: {course_id: @course.id}
test_student = @course.student_view_student
assignment = @course.assignments.create!(:workflow_state => 'published', :moderated_grading => true)
assignment = @course.assignments.create!(workflow_state: 'published', moderated_grading: true, grader_count: 2)
assignment.grade_student test_student, { :grade => 1, :grader => @teacher, :provisional => true }
file = assignment.attachments.create! uploaded_data: default_uploaded_data
assignment.submissions.first.add_comment(commenter: @teacher, message: 'blah', provisional: true, attachments: [file])
assignment.moderated_grading_selections.create!(:student => test_student, :provisional_grade => ModeratedGrading::ProvisionalGrade.last)
assignment.moderated_grading_selections.where(student: test_student).first.update_attribute(:provisional_grade, ModeratedGrading::ProvisionalGrade.last)
expect(test_student.submissions.size).not_to be_zero
delete 'reset_test_student', params: {course_id: @course.id}

View File

@ -741,19 +741,6 @@ describe GradebooksController do
end
end
it "includes anonymous_moderated_marking_enabled for Old Gradebook" do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
get :show, params: { course_id: @course.id }
expect(gradebook_options.fetch(:anonymous_moderated_marking_enabled)).to eq(true)
end
it "includes anonymous_moderated_marking_enabled for New Gradebook" do
@course.enable_feature!(:new_gradebook)
@course.root_account.enable_feature!(:anonymous_moderated_marking)
get :show, params: { course_id: @course.id }
expect(gradebook_options.fetch(:anonymous_moderated_marking_enabled)).to eq(true)
end
it "includes colors if New Gradebook is enabled" do
@course.enable_feature!(:new_gradebook)
get :show, params: {course_id: @course.id}
@ -1285,10 +1272,6 @@ describe GradebooksController do
end
describe 'anonymous assignment' do
before :once do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
end
it 'works with the absense of user_id and the presence of anonymous_id' do
user_session(@teacher)
@assignment.update!(anonymous_grading: true)
@ -1413,7 +1396,7 @@ describe GradebooksController do
context "moderated grading" do
before :once do
@assignment = @course.assignments.create!(:title => "some assignment", :moderated_grading => true)
@assignment = @course.assignments.create!(title: "some assignment", moderated_grading: true, grader_count: 1)
@student = @course.enroll_student(User.create!(:name => "some user"), :enrollment_state => :active).user
end
@ -1483,16 +1466,16 @@ describe GradebooksController do
expect(pg.graded_anonymously).to eq false
end
it "doesn't create a provisional grade when the student has one already (and isn't in the moderation set)" do
submission = @assignment.submit_homework(@student, :body => "hello")
it "doesn't create a provisional grade when the student has one already" do
@assignment.submit_homework(@student, :body => "hello")
other_teacher = teacher_in_course(:course => @course, :active_all => true).user
submission.find_or_create_provisional_grade!(other_teacher)
@assignment.grade_student(@student, grade: 2, grader: other_teacher, provisional: true)
post 'update_submission', params: {:course_id => @course.id,
:submission => { :score => 100, :comment => "provisional!", :assignment_id => @assignment.id,
:user_id => @student.id, :provisional => true }}, :format => :json
expect(response).to_not be_success
expect(response.body).to include("Student already has the maximum number of provisional grades")
expect(response.body).to include("The maximum number of graders has been reached for this assignment")
end
it "should create a provisional grade even if the student has one but is in the moderation set" do
@ -1500,8 +1483,6 @@ describe GradebooksController do
other_teacher = teacher_in_course(:course => @course, :active_all => true).user
submission.find_or_create_provisional_grade!(other_teacher)
@assignment.moderated_grading_selections.create!(:student => @student)
post 'update_submission', params: {:course_id => @course.id,
:submission => { :score => 100, :comment => "provisional!", :assignment_id => @assignment.id,
:user_id => @student.id, :provisional => true }}, :format => :json
@ -1547,11 +1528,10 @@ describe GradebooksController do
end
end
describe 'provisional grade error handling for Anonymous Moderated Marking' do
describe 'provisional grade error handling' do
before(:once) do
course_with_student(active_all: true)
teacher_in_course(active_all: true)
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@assignment = @course.assignments.create!(
title: 'yet another assignment',
@ -1653,20 +1633,14 @@ describe GradebooksController do
expect(assigns[:disable_unmute_assignment]).to eq false
end
it 'sets disable_unmute_assignment to false if anonymous moderated marking is disabled' do
get 'speed_grader', params: {course_id: @course, assignment_id: @assignment.id}
expect(assigns[:disable_unmute_assignment]).to eq false
end
it 'sets disable_unmute_assignment to false if assignment grades have been published' do
@assignment.update!(grades_published_at: Time.zone.now)
get 'speed_grader', params: {course_id: @course, assignment_id: @assignment.id}
expect(assigns[:disable_unmute_assignment]).to eq false
end
it 'sets disable_unmute_assignment to true if assignment muted, anonymous moderated marking enabled, and grades not published' do
it 'sets disable_unmute_assignment to true if assignment muted and grades not published' do
@assignment.update!(muted: true, grades_published_at: nil, moderated_grading: true, grader_count: 1)
@assignment.root_account.enable_feature!(:anonymous_moderated_marking)
get 'speed_grader', params: {course_id: @course, assignment_id: @assignment.id}
expect(assigns[:disable_unmute_assignment]).to eq true
end

View File

@ -543,47 +543,41 @@ describe SubmissionsController do
expect(body['published_score']).to be nil
end
context "for an assignment that has anonymous grading and muted with anonymous_moderated_marking enabled" do
before :each do
@assignment.root_account.enable_feature!(:anonymous_moderated_marking)
end
it "renders the page for submitting student" do
user_session(@student)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_status(200)
end
it "renders the page for submitting student" do
user_session(@student)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_status(200)
end
it "renders unauthorized for non-submitting student" do
new_student = User.create!
@context.enroll_student(new_student, enrollment_state: 'active')
user_session(new_student)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_unauthorized
end
it "renders unauthorized for non-submitting student" do
new_student = User.create!
@context.enroll_student(new_student, enrollment_state: 'active')
user_session(new_student)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_unauthorized
end
it "renders unauthorized for teacher" do
user_session(@teacher)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_unauthorized
end
it "renders unauthorized for teacher" do
user_session(@teacher)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_unauthorized
end
it "renders unauthorized for admin" do
user_session(account_admin_user)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_unauthorized
end
it "renders unauthorized for admin" do
user_session(account_admin_user)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_unauthorized
end
it "renders the page for site admin" do
user_session(site_admin_user)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_status(200)
end
it "renders the page for site admin" do
user_session(site_admin_user)
@assignment.update!(anonymous_grading: true, muted: true)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, id: @student.id}
assert_status(200)
end
context "with user id not present in course" do

View File

@ -56,44 +56,6 @@ describe GradebooksHelper do
end
end
describe '#anonymous_grading_required?' do
it 'returns false by default' do
assignment = assignment_model
expect(helper.anonymous_grading_required?(assignment)).to eq false
end
it 'returns true if course setting is on' do
assignment = assignment_model
assignment.context.enable_feature!(:anonymous_grading)
expect(helper.anonymous_grading_required?(assignment)).to eq true
end
it 'returns true if sub-account setting is on' do
root_account = Account.default
sub_account = root_account.sub_accounts.create!
sub_account.enable_feature!(:anonymous_grading)
sub_account_course = course_model(account: sub_account)
assignment = assignment_model(course: sub_account_course)
expect(helper.anonymous_grading_required?(assignment)).to eq true
end
it 'returns true if root account setting is on' do
root_account = Account.default
root_account.enable_feature!(:anonymous_grading)
sub_account = root_account.sub_accounts.create!
sub_account_course = course_model(account: sub_account)
assignment = assignment_model(course: sub_account_course)
expect(helper.anonymous_grading_required?(assignment)).to eq true
end
it 'returns true if site admin setting is on' do
site_admin_account = Account.site_admin
site_admin_account.enable_feature!(:anonymous_grading)
assignment = assignment_model
expect(helper.anonymous_grading_required?(assignment)).to eq true
end
end
describe '#force_anonymous_grading?' do
it 'returns false by default' do
expect(helper.force_anonymous_grading?(assignment_model)).to eq false
@ -104,26 +66,15 @@ describe GradebooksHelper do
expect(helper.force_anonymous_grading?(assignment)).to eq true
end
it 'returns true if anonymous grading flag set' do
Account.default.enable_feature!(:anonymous_grading)
expect(helper.force_anonymous_grading?(assignment_model)).to eq true
it 'returns true for an anonymously-graded assignment' do
assignment = assignment_model
assignment.anonymous_grading = true
expect(helper.force_anonymous_grading?(assignment)).to eq true
end
context 'when Anonymous Moderated Marking is enabled' do
before(:once) do
Account.default.enable_feature!(:anonymous_moderated_marking)
end
it 'returns true for an anonymously-graded assignment' do
assignment = assignment_model
assignment.anonymous_grading = true
expect(helper.force_anonymous_grading?(assignment)).to eq true
end
it 'returns false for a non-anonymously-graded assignment' do
assignment = assignment_model
expect(helper.force_anonymous_grading?(assignment)).to eq false
end
it 'returns false for a non-anonymously-graded assignment' do
assignment = assignment_model
expect(helper.force_anonymous_grading?(assignment)).to eq false
end
end
@ -138,8 +89,9 @@ describe GradebooksHelper do
end
it 'returns anonymous grading' do
Account.default.enable_feature!(:anonymous_grading)
expect(helper.force_anonymous_grading_reason(assignment_model)).to match(/anonymous grading/)
assignment = assignment_model
assignment.anonymous_grading = true
expect(helper.force_anonymous_grading_reason(assignment)).to match(/anonymous grading/)
end
end

View File

@ -309,7 +309,7 @@ describe "ratio of submissions graded" do
let(:moderate_button) { Nokogiri::HTML(response.body).at_css('#moderated_grading_button') }
it 'shows the moderation link for moderated assignments' do
@assignment.update!(moderated_grading: true)
@assignment.update!(moderated_grading: true, grader_count: 1, final_grader: @teacher)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(moderate_button).not_to be_nil

View File

@ -50,25 +50,25 @@ define([
// time this is being written a significant amount of work is needed
// to be able to require javascript files that live in the spec directory
QUnit.module('SubmissionStateMap with anonymous moderated marking enabled');
QUnit.module('SubmissionStateMap');
test ('submission has grade visible if not anonymous', function() {
const assignment = { id: '1', muted: true };
const map = createAndSetupMap(assignment, { anonymousModeratedMarkingEnabled: true });
const map = createAndSetupMap(assignment);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.hideGrade, false);
});
test ('submission has grade visible if not muted', function() {
const assignment = { id: '1', anonymous_grading: true };
const map = createAndSetupMap(assignment, { anonymousModeratedMarkingEnabled: true });
const map = createAndSetupMap(assignment);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.hideGrade, false);
});
test ('submission has grade hidden if anonymous and muted', function() {
const assignment = { id: '1', anonymous_grading: true, muted: true };
const map = createAndSetupMap(assignment, { anonymousModeratedMarkingEnabled: true });
const map = createAndSetupMap(assignment);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.hideGrade, true);
});

View File

@ -50,25 +50,25 @@ define([
// time this is being written a significant amount of work is needed
// to be able to require javascript files that live in the spec directory
QUnit.module('SubmissionStateMap with anonymous moderated marking enabled');
QUnit.module('SubmissionStateMap');
test ('submission is unlocked if not anonymous', function() {
const assignment = { id: '1', muted: true };
const map = createAndSetupMap(assignment, { anonymousModeratedMarkingEnabled: true });
const map = createAndSetupMap(assignment);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.locked, false);
});
test ('submission is unlocked if not muted', function() {
const assignment = { id: '1', anonymous_grading: true };
const map = createAndSetupMap(assignment, { anonymousModeratedMarkingEnabled: true });
const map = createAndSetupMap(assignment);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.locked, false);
});
test ('submission is locked if anonymous and muted', function() {
const assignment = { id: '1', anonymous_grading: true, muted: true };
const map = createAndSetupMap(assignment, { anonymousModeratedMarkingEnabled: true });
const map = createAndSetupMap(assignment);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.locked, true);
});

View File

@ -6198,18 +6198,6 @@ test('sets the submission state map .isAdmin when the current user roles do not
strictEqual(gradebook.submissionStateMap.isAdmin, false);
});
test('sets submission state map .anonymousModeratedMarkingEnabled when anonymous moderated marking flag is set', function () {
const gradebook = createGradebook({ anonymous_moderated_marking_enabled: true });
gradebook.initSubmissionStateMap();
strictEqual(gradebook.submissionStateMap.anonymousModeratedMarkingEnabled, true);
});
test('sets submission state map .anonymousModeratedMarkingEnabled to false when anonymous moderated marking flag is reset', function () {
const gradebook = createGradebook({ anonymous_moderated_marking_enabled: false });
gradebook.initSubmissionStateMap();
strictEqual(gradebook.submissionStateMap.anonymousModeratedMarkingEnabled, false);
});
QUnit.module('Gradebook#initPostGradesLtis');
test('sets postGradesLtis as an array', function () {
@ -6973,19 +6961,6 @@ QUnit.module('Gradebook#getSubmissionTrayProps', function(suiteHooks) {
moxios.uninstall();
});
test('anonymousModeratedMarkingEnabled is true when options.anonymous_moderated_marking_enabled is true', function () {
gradebook.options.anonymous_moderated_marking_enabled = true
gradebook.setSubmissionTrayState(true, '1101', '2301');
const props = gradebook.getSubmissionTrayProps(gradebook.student('1101'));
strictEqual(props.anonymousModeratedMarkingEnabled, true);
});
test('anonymousModeratedMarkingEnabled is false when options.anonymous_moderated_marking_enabled is false', function () {
gradebook.setSubmissionTrayState(true, '1101', '2301');
const props = gradebook.getSubmissionTrayProps(gradebook.student('1101'));
strictEqual(props.anonymousModeratedMarkingEnabled, false);
});
test('gradingDisabled is true when the submission state is locked', function () {
sinon.stub(gradebook.submissionStateMap, 'getSubmissionState').returns({ locked: true });
gradebook.setSubmissionTrayState(true, '1101', '2301');

View File

@ -39,8 +39,7 @@ function createMap (opts = {}) {
const defaults = {
hasGradingPeriods: false,
selectedGradingPeriodID: '0',
isAdmin: false,
anonymousModeratedMarkingEnabled: false
isAdmin: false
};
const params = { ...defaults, ...opts };
@ -122,123 +121,121 @@ QUnit.module('#setSubmissionCellState', function() {
strictEqual(submission.hideGrade, false);
});
QUnit.module('anonymous moderated marking enabled', function() {
test('the submission state is locked when the student is not assigned', function() {
const assignment = {
id: '1',
published: true,
only_visible_to_overrides: true,
assignment_visibility: ['2']
}
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true })
test('the submission state is locked when the student is not assigned', function() {
const assignment = {
id: '1',
published: true,
only_visible_to_overrides: true,
assignment_visibility: ['2']
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.locked, true)
})
test('the submission state is not locked if not moderated grading', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, false);
});
test('the submission state has hideGrade not set if not moderated grading', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
test('the submission state is not locked if moderated grading and grades published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: true
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, false);
});
test('the submission state has hideGrade not set if moderated grading and grades published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: true
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
test('the submission state is locked if moderated grading and grades not published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, true);
});
test('the submission state has hideGrade not set if moderated grading and grades not published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
QUnit.module('when the assignment is anonymous', function(hooks) {
let assignment
hooks.beforeEach(() => {
assignment = { id: '1', published: true, anonymous_grading: true }
})
test('the submission state is locked when the assignment is muted', function() {
assignment.muted = true
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.locked, true)
})
test('the submission state is not locked if not moderated grading', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: false
};
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true });
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, false);
});
test('the submission state has hideGrade not set if not moderated grading', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: false
};
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true });
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
test('the submission state is not locked if moderated grading and grades published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: true
};
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true });
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, false);
});
test('the submission state has hideGrade not set if moderated grading and grades published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: true
};
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true });
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
test('the submission state is locked if moderated grading and grades not published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true });
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, true);
});
test('the submission state has hideGrade not set if moderated grading and grades not published', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: true,
grades_published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true });
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
QUnit.module('when the assignment is anonymous', function(hooks) {
let assignment
hooks.beforeEach(() => {
assignment = { id: '1', published: true, anonymous_grading: true }
})
test('the submission state is locked when the assignment is muted', function() {
assignment.muted = true
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true })
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.locked, true)
})
test('the submission state is hidden when the assignment is muted', function() {
assignment.muted = true
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true })
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.hideGrade, true)
})
test('the submission state is unlocked when the assignment is unmuted', function() {
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true })
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.locked, false)
})
test('the submission state is not hidden when the assignment is unmuted', function() {
const map = createAndSetupMap(assignment, studentWithSubmission, { anonymousModeratedMarkingEnabled: true })
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.hideGrade, false)
})
test('the submission state is hidden when the assignment is muted', function() {
assignment.muted = true
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.hideGrade, true)
})
});
test('the submission state is unlocked when the assignment is unmuted', function() {
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.locked, false)
})
test('the submission state is not hidden when the assignment is unmuted', function() {
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
strictEqual(submission.hideGrade, false)
})
})
QUnit.module('no submission', function() {
test('the submission object is missing if the assignment is late', function () {

View File

@ -173,11 +173,10 @@ QUnit.module('AssignmentColumnHeaderRenderer', function (suiteHooks) {
equal(component.props.downloadSubmissionsAction, gradebook.getDownloadSubmissionsAction.returnValues[0]);
});
test('the anonymousGrading prop is `false` when the assignment is anonymous', function () {
test('the anonymousGrading prop is `true` when the assignment is anonymous', function () {
assignment.anonymous_grading = true
render()
// anonymousGrading can only be true if Anonymous Moderated Marking is enabled
strictEqual(component.props.assignment.anonymousGrading, false)
strictEqual(component.props.assignment.anonymousGrading, true)
})
test('the anonymousGrading prop is `false` when the assignment is not anonymous', function () {
@ -505,23 +504,6 @@ QUnit.module('AssignmentColumnHeaderRenderer', function (suiteHooks) {
render();
equal(component.props.sortBySetting.settingKey, 'grade');
});
QUnit.module('when Anonymous Moderated Marking is enabled', function (hooks) {
hooks.beforeEach(() => {
gradebook.options.anonymous_moderated_marking_enabled = true
})
test('the anonymousGrading prop is `true` when the assignment is anonymous', function () {
assignment.anonymous_grading = true
render()
strictEqual(component.props.assignment.anonymousGrading, true)
})
test('the anonymousGrading prop is `false` when the assignment is not anonymous', function () {
render()
strictEqual(component.props.assignment.anonymousGrading, false)
})
})
});
QUnit.module('#destroy', function () {

View File

@ -20,7 +20,6 @@ import Gradebook from 'compiled/gradezilla/Gradebook';
export function createGradebook (options = {}) {
const gradebook = new Gradebook({
anonymous_moderated_marking_enabled: false,
colors: {},
context_allows_gradebook_uploads: true,
context_id: '1',

View File

@ -42,7 +42,6 @@ QUnit.module('SubmissionTray', function (hooks) {
});
const defaultProps = {
anonymousModeratedMarkingEnabled: false,
contentRef (ref) {
content = ref;
},
@ -202,10 +201,8 @@ QUnit.module('SubmissionTray', function (hooks) {
strictEqual(speedGraderLink, speedGraderUrl);
});
test('invokes "onAnonymousSpeedGraderClick" when the SpeedGrader link is clicked ' +
'if the assignment is anonymous and Anonymous Moderated Marking is enabled', function () {
test('invokes "onAnonymousSpeedGraderClick" when the SpeedGrader link is clicked if the assignment is anonymous', function () {
const props = {
anonymousModeratedMarkingEnabled: true,
assignment: {
name: 'Book Report',
gradingType: 'points',
@ -221,18 +218,10 @@ QUnit.module('SubmissionTray', function (hooks) {
strictEqual(props.onAnonymousSpeedGraderClick.callCount, 1)
})
test('omits student_id from SpeedGrader link if enabled and assignment is ' +
'anonymously graded and anonymous moderated marking is enabled', function() {
mountComponent({anonymousModeratedMarkingEnabled: true, assignment: {anonymousGrading: true}});
const speedGraderLink = document.querySelector('.SubmissionTray__Container a[href*="speed_grader"]').getAttribute('href');
notOk(speedGraderLink.match(/student_id/))
});
test('includes student_id in the SpeedGrader link if enabled and assignment is ' +
'anonymously graded and anonymous moderated marking is disabled', function() {
test('omits student_id from SpeedGrader link if enabled and assignment is anonymously graded', function() {
mountComponent({assignment: {anonymousGrading: true}});
const speedGraderLink = document.querySelector('.SubmissionTray__Container a[href*="speed_grader"]').getAttribute('href');
ok(speedGraderLink.match(/student_id/))
notOk(speedGraderLink.match(/student_id/))
});
test('does not show SpeedGrader link if disabled', function () {

View File

@ -24,11 +24,9 @@ QUnit.module('AssignmentMuterDialogManager', suiteHooks => {
let assignment
let submissionsLoaded
let anonymousModeratedMarkingEnabled
suiteHooks.beforeEach(() => {
anonymousModeratedMarkingEnabled = false
assignment = {moderated_grading: false, grades_published: true, muted: true}
assignment = {anonymous_grading: false, grades_published: true, muted: true}
submissionsLoaded = false
})
@ -36,8 +34,7 @@ QUnit.module('AssignmentMuterDialogManager', suiteHooks => {
return new AssignmentMuterDialogManager(
assignment,
url,
submissionsLoaded,
anonymousModeratedMarkingEnabled
submissionsLoaded
)
}
@ -95,23 +92,13 @@ QUnit.module('AssignmentMuterDialogManager', suiteHooks => {
})
test('returns false when the assignment is moderated and grades have not been published', () => {
anonymousModeratedMarkingEnabled = true
assignment.grades_published = false
assignment.moderated_grading = true
submissionsLoaded = true
strictEqual(createManager().isDialogEnabled(), false)
})
test('returns true for moderated assignments when Anonymous Moderated Marking is disabled', () => {
anonymousModeratedMarkingEnabled = false
assignment.grades_published = false
assignment.moderated_grading = true
submissionsLoaded = true
strictEqual(createManager().isDialogEnabled(), true)
})
test('returns true for moderated assignments when grades have been published', () => {
anonymousModeratedMarkingEnabled = true
assignment.grades_published = true
assignment.moderated_grading = true
submissionsLoaded = true
@ -119,7 +106,6 @@ QUnit.module('AssignmentMuterDialogManager', suiteHooks => {
})
test('returns true for moderated assignments when not muted', () => {
anonymousModeratedMarkingEnabled = true
assignment.grades_published = false
assignment.moderated_grading = true
assignment.muted = false
@ -128,7 +114,6 @@ QUnit.module('AssignmentMuterDialogManager', suiteHooks => {
})
test('returns true for assignments when not moderated', () => {
anonymousModeratedMarkingEnabled = true
assignment.grades_published = true
assignment.moderated_grading = false
submissionsLoaded = true

File diff suppressed because it is too large Load Diff

View File

@ -35,11 +35,16 @@ describe Api::V1::Submission do
let(:user) { User.create! }
let(:course) { Course.create! }
let(:assignment) { course.assignments.create! }
let(:teacher) {
teacher = User.create!
course.enroll_teacher(teacher)
teacher
}
let(:session) { {} }
let(:context) { nil }
let(:params) { { includes: [field]} }
let(:submission) { assignment.submissions.create!(user: user) }
let(:provisional_grade) { submission.provisional_grades.create!(scorer: User.create!) }
let(:provisional_grade) { submission.provisional_grades.create!(scorer: teacher) }
describe 'speedgrader_url' do
it "links to the speed grader for a student's submission" do

View File

@ -52,41 +52,14 @@ describe DataFixup::BackfillAnonymousGradingData do
@course.enable_feature!(:anonymous_grading)
end
context "when the base Anonymous Moderated Marking flag is off" do
before(:once) do
@root_account.disable_feature!(:anonymous_moderated_marking)
end
it "does not cause Anonymous Marking for the course to register as enabled" do
# Note that technically this *does* flip on the Anonymous Marking
# feature flag for the course, but because it depends on the base
# AMM flag, any check for whether it's enabled while that flag is
# off will return false. This is confusing but is the "correct"
# behavior for these purposes.
do_backfill
expect(@course).not_to be_feature_enabled(:anonymous_marking)
end
it "sets assignments to be anonymously graded" do
do_backfill
expect(assignment_anonymously_graded).to be true
end
it "enables Anonymous Marking for the course" do
do_backfill
expect(@course).to be_feature_enabled(:anonymous_marking)
end
context "when the base Anonymous Moderated Marking flag is on" do
before(:once) do
@root_account.enable_feature!(:anonymous_moderated_marking)
end
it "enables Anonymous Marking for the course" do
do_backfill
expect(@course).to be_feature_enabled(:anonymous_marking)
end
it "sets assignments to be anonymously graded" do
do_backfill
expect(assignment_anonymously_graded).to be true
end
it "sets assignments to be anonymously graded" do
do_backfill
expect(assignment_anonymously_graded).to be true
end
end
end

View File

@ -1,69 +0,0 @@
#
# Copyright (C) 2018 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require_relative '../../spec_helper.rb'
describe 'anonymous moderated marking' do
let(:root_account) { account_model }
let(:course) { course_factory(account: root_account, active_all: true) }
let(:anonymous_grading_feature) { Feature.definitions['anonymous_marking'] }
describe 'anonymous grading flag' do
context 'when the base AMM flag is not enabled' do
it 'is not allowed on the account level' do
expect(root_account).not_to be_feature_allowed(:anonymous_marking)
end
it 'is not visible on the account level' do
expect(anonymous_grading_feature.visible_on.call(root_account)).to be_falsey
end
it 'is not allowed on the course level' do
expect(course).not_to be_feature_allowed(:anonymous_marking)
end
it 'is not visible on the course level' do
expect(anonymous_grading_feature.visible_on.call(course)).to be_falsey
end
end
context 'when the base AMM flag is enabled' do
before(:each) do
root_account.enable_feature!(:anonymous_moderated_marking)
end
it 'is visible on the account level' do
expect(anonymous_grading_feature.visible_on.call(root_account)).to be_truthy
end
it 'is visible on the course level' do
expect(anonymous_grading_feature.visible_on.call(course)).to be_truthy
end
it 'is allowed on the course level if allowed on the account level' do
root_account.allow_feature!(:anonymous_marking)
expect(course).to be_feature_allowed(:anonymous_marking)
end
it 'is enabled on the course level if enabled on the account level' do
root_account.enable_feature!(:anonymous_marking)
expect(course).to be_feature_enabled(:anonymous_marking)
end
end
end
end

View File

@ -33,23 +33,16 @@ describe Moderation do
@student = User.create!
end
it "does not create selections if anonymous moderated marking is not enabled" do
it "does not create selections if moderated grading is false" do
expect{ test_moderation.create_moderation_selections_for_assignment(@assignment.id, [@student.id], []) }.
not_to change{ @assignment.moderated_grading_selections.count }
end
it "does not create selections if anonymous moderated marking is enabled and moderated grading is false" do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
expect{ test_moderation.create_moderation_selections_for_assignment(@assignment.id, [@student.id], []) }.
not_to change{ @assignment.moderated_grading_selections.count }
end
context "with anonymous moderated marking enabled and moderated grading on" do
context "with moderated grading on" do
before :once do
@student2 = User.create!
@student3 = User.create!
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@assignment.update!(moderated_grading: true, grader_count: 1)
end

View File

@ -151,8 +151,11 @@ describe Assignment::SpeedGrader do
it "excludes provisional comments" do
setup_assignment_with_homework
@assignment.moderated_grading = true
@assignment.grader_count = 2
@assignment.save!
@submission = @assignment.submissions.first
@comment = @submission.add_comment(:comment => 'comment', :provisional => true)
@comment = @submission.add_comment(comment: 'comment', author: @teacher, provisional: true)
json = Assignment::SpeedGrader.new(@assignment, @user).json
expect(json[:submissions].first[:submission_comments]).to be_empty
end
@ -616,8 +619,6 @@ describe Assignment::SpeedGrader do
let(:submission_json) { json['submissions'][0] }
before :once do
course.account.enable_feature!(:anonymous_moderated_marking)
course.enroll_student(student, section: section).accept!
assignment.update_submission(student, comment: 'comment by student', commenter: student)
@ -919,11 +920,6 @@ describe Assignment::SpeedGrader do
expect(ras.count).to eq 1
expect(ras[0]['assessor_id']).to eq @ta.id.to_s
end
it "determines whether the student needs a provisional grade" do
expect(@json['context']['students'][0]['needs_provisional_grade']).to be_falsey
expect(@json['context']['students'][1]['needs_provisional_grade']).to be_truthy # other student
end
end
describe "for moderator" do
@ -1202,8 +1198,6 @@ describe Assignment::SpeedGrader do
let(:grader_json) { Assignment::SpeedGrader.new(assignment, ta, avatars: true, grading_role: :grader).json }
before :once do
course.account.enable_feature!(:anonymous_moderated_marking)
course.enroll_student(student_1, section: section_1).accept!
course.enroll_student(student_2, section: section_2).accept!
@ -1503,8 +1497,6 @@ describe Assignment::SpeedGrader do
let(:submission_json) { json['submissions'][0] }
before :once do
course.account.enable_feature!(:anonymous_moderated_marking)
course.enroll_student(student, section: section).accept!
assignment.update_submission(student, comment: 'comment by student', commenter: student)

View File

@ -183,7 +183,7 @@ describe Assignment do
assignment = @course.assignments.new(assignment_valid_attributes)
expect(DueDateCacher).to receive(:recompute).with(assignment, update_grades: true)
assignment.update!(moderated_grading: !assignment.moderated_grading)
assignment.update!(moderated_grading: !assignment.moderated_grading, grader_count: 2)
end
it 'invokes DueDateCacher if called in a before_save context' do
@ -244,40 +244,23 @@ describe Assignment do
)
end
context 'when Anonymous Moderated Marking is enabled' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
end
it 'returns false if the user is not the final grader and not an admin' do
assistant = User.create!
@course.enroll_ta(assistant, enrollment_state: 'active')
expect(@assignment.permits_moderation?(assistant)).to be false
end
it 'returns true if the user is the final grader' do
expect(@assignment.permits_moderation?(@teacher)).to be true
end
it 'returns true if the user is an admin with "select final grader for moderation" privileges' do
expect(@assignment.permits_moderation?(account_admin_user)).to be true
end
it 'returns false if the user is an admin without "select final grader for moderation" privileges' do
@course.account.role_overrides.create!(role: admin_role, enabled: false, permission: :select_final_grade)
expect(@assignment.permits_moderation?(account_admin_user)).to be false
end
it 'returns false if the user is not the final grader and not an admin' do
assistant = User.create!
@course.enroll_ta(assistant, enrollment_state: 'active')
expect(@assignment.permits_moderation?(assistant)).to be false
end
context 'when Anonymous Moderated Marking is disabled' do
it 'returns true if the user has moderate grades privileges' do
expect(@assignment.permits_moderation?(@teacher)).to be true
end
it 'returns true if the user is the final grader' do
expect(@assignment.permits_moderation?(@teacher)).to be true
end
it 'returns false if the user does not have moderate grades privileges' do
@course.root_account.role_overrides.create!(permission: 'moderate_grades', enabled: false, role: teacher_role)
expect(@assignment.permits_moderation?(@teacher)).to be false
end
it 'returns true if the user is an admin with "select final grader for moderation" privileges' do
expect(@assignment.permits_moderation?(account_admin_user)).to be true
end
it 'returns false if the user is an admin without "select final grader for moderation" privileges' do
@course.account.role_overrides.create!(role: admin_role, enabled: false, permission: :select_final_grade)
expect(@assignment.permits_moderation?(account_admin_user)).to be false
end
end
@ -314,9 +297,8 @@ describe Assignment do
end
end
context 'when Anonymous Moderated Marking is enabled' do
context 'when the assignment is anonymously graded' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
assignment.update!(anonymous_grading: true)
end
@ -521,10 +503,6 @@ describe Assignment do
end
end
end
context 'when Anonymous Moderated Marking is disabled' do
it_behaves_like "grader anonymity does not apply"
end
end
describe '#can_view_other_grader_comments?' do
@ -560,75 +538,57 @@ describe Assignment do
end
end
context 'when Anonymous Moderated Marking is enabled' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
context 'when the assignment is not moderated' do
before :once do
assignment.update!(moderated_grading: false)
end
context 'when the assignment is not moderated' do
before :once do
assignment.update!(moderated_grading: false)
end
it_behaves_like "grader comment hiding does not apply"
end
it_behaves_like "grader comment hiding does not apply"
context 'when grader comments are visible to other graders' do
before :once do
assignment.update!(
grader_comments_visible_to_graders: true,
grader_names_visible_to_final_grader: true
)
end
context 'when the assignment is not anonymously graded' do
before :once do
assignment.update!(anonymous_grading: false)
end
it_behaves_like "grader comment hiding does not apply"
it_behaves_like "grader comment hiding does not apply"
it 'returns true when the user is not the final grader and not an admin' do
expect(assignment.can_view_other_grader_comments?(ta)).to be true
end
context 'when grader comments are visible to other graders' do
before :once do
assignment.update!(
grader_comments_visible_to_graders: true,
grader_names_visible_to_final_grader: true
)
end
it_behaves_like "grader comment hiding does not apply"
it 'returns true when the user is not the final grader and not an admin' do
expect(assignment.can_view_other_grader_comments?(ta)).to be true
end
it 'returns true when the user is the final grader' do
expect(assignment.can_view_other_grader_comments?(@teacher)).to be true
end
it 'returns true when the user is an admin' do
expect(assignment.can_view_other_grader_comments?(admin)).to be true
end
it 'returns true when the user is the final grader' do
expect(assignment.can_view_other_grader_comments?(@teacher)).to be true
end
context 'when grader comments are hidden to other graders' do
before :once do
assignment.update!(
grader_comments_visible_to_graders: false,
grader_names_visible_to_final_grader: true
)
end
it 'returns false when the user is not the final grader and not an admin' do
expect(assignment.can_view_other_grader_comments?(ta)).to be false
end
it 'returns true when the user is the final grader' do
# The final grader must always be able to see grader comments.
expect(assignment.can_view_other_grader_comments?(@teacher)).to be true
end
it 'returns true when the user is an admin' do
expect(assignment.can_view_other_grader_comments?(admin)).to be true
end
it 'returns true when the user is an admin' do
expect(assignment.can_view_other_grader_comments?(admin)).to be true
end
end
context 'when Anonymous Moderated Marking is disabled' do
it_behaves_like "grader comment hiding does not apply"
context 'when grader comments are hidden to other graders' do
before :once do
assignment.update!(
grader_comments_visible_to_graders: false,
grader_names_visible_to_final_grader: true
)
end
it 'returns false when the user is not the final grader and not an admin' do
expect(assignment.can_view_other_grader_comments?(ta)).to be false
end
it 'returns true when the user is the final grader' do
# The final grader must always be able to see grader comments.
expect(assignment.can_view_other_grader_comments?(@teacher)).to be true
end
it 'returns true when the user is an admin' do
expect(assignment.can_view_other_grader_comments?(admin)).to be true
end
end
end
@ -665,32 +625,22 @@ describe Assignment do
end
end
context 'when Anonymous Moderated Marking is enabled' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
context 'when the assignment is not anonymously graded' do
before :once do
assignment.update!(anonymous_grading: false)
end
context 'when the assignment is not anonymously graded' do
before :once do
assignment.update!(anonymous_grading: false)
end
it_behaves_like "student anonymity does not apply"
end
context 'when the assignment is anonymously graded' do
it 'returns false when the user is not an admin' do
expect(assignment.can_view_student_names?(@teacher)).to be false
end
it 'returns false when the user is an admin' do
expect(assignment.can_view_student_names?(admin)).to be false
end
end
it_behaves_like "student anonymity does not apply"
end
context 'when Anonymous Moderated Marking is disabled' do
it_behaves_like "student anonymity does not apply"
context 'when the assignment is anonymously graded' do
it 'returns false when the user is not an admin' do
expect(assignment.can_view_student_names?(@teacher)).to be false
end
it 'returns false when the user is an admin' do
expect(assignment.can_view_student_names?(admin)).to be false
end
end
end
@ -1388,9 +1338,8 @@ describe Assignment do
end
end
context 'for a moderated assignment with Anonymous Moderated Marking enabled' do
context 'for a moderated assignment' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
student_in_course
teacher_in_course
@first_teacher = @teacher
@ -1623,10 +1572,8 @@ describe Assignment do
expect(comment).not_to be_hidden
end
context 'for moderated assignments with Anonymous Moderated Marking enabled' do
context 'for moderated assignments' do
before(:once) do
@assignment.root_account.enable_feature!(:anonymous_moderated_marking)
teacher_in_course
@first_teacher = @teacher
@ -2288,40 +2235,34 @@ describe Assignment do
expect(@assignment.muted?).to eql false
end
context 'when Anonymous Moderated Marking is enabled' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
end
it 'does not mute non-anonymous, non-moderated assignments when created' do
assignment = @course.assignments.create!
expect(assignment).not_to be_muted
end
it 'does not mute non-anonymous, non-moderated assignments when created' do
assignment = @course.assignments.create!
expect(assignment).not_to be_muted
end
it 'mutes anonymous assignments when created' do
assignment = @course.assignments.create!(anonymous_grading: true)
expect(assignment).to be_muted
end
it 'mutes anonymous assignments when created' do
assignment = @course.assignments.create!(anonymous_grading: true)
expect(assignment).to be_muted
end
it 'mutes moderated assignments when created' do
assignment = @course.assignments.create!(moderated_grading: true, grader_count: 1)
expect(assignment).to be_muted
end
it 'mutes moderated assignments when created' do
assignment = @course.assignments.create!(moderated_grading: true, grader_count: 1)
expect(assignment).to be_muted
end
it 'mutes assignments when they are update from non-anonymous to anonymous' do
assignment = @course.assignments.create!
expect { assignment.update!(anonymous_grading: true) }.to change {
assignment.muted?
}.from(false).to(true)
end
it 'mutes assignments when they are update from non-anonymous to anonymous' do
assignment = @course.assignments.create!
expect { assignment.update!(anonymous_grading: true) }.to change {
assignment.muted?
}.from(false).to(true)
end
it 'does not mute assignments when they are updated from anonymous to non-anonymous' do
assignment = @course.assignments.create!(anonymous_grading: true)
assignment.update!(muted: false)
expect { assignment.update!(anonymous_grading: false) }.not_to change {
assignment.muted?
}.from(false)
end
it 'does not mute assignments when they are updated from anonymous to non-anonymous' do
assignment = @course.assignments.create!(anonymous_grading: true)
assignment.update!(muted: false)
expect { assignment.update!(anonymous_grading: false) }.not_to change {
assignment.muted?
}.from(false)
end
end
@ -2335,9 +2276,8 @@ describe Assignment do
expect(@assignment.unmute!).to be_falsey
end
context "when Anonymous Moderated Marking is enabled and assignment is anonymously graded" do
context "when assignment is anonymously graded" do
before :once do
@course.root_account.enable_feature! :anonymous_moderated_marking
@assignment.update_attributes(moderated_grading: true, anonymous_grading: true, grader_count: 1)
@assignment.mute!
end
@ -2374,9 +2314,8 @@ describe Assignment do
end
end
context "when Anonymous Moderated Marking is enabled and assignment is anonymously graded and not moderated" do
context "when assignment is anonymously graded and not moderated" do
before :once do
@course.account.enable_feature! :anonymous_moderated_marking
@assignment.update_attributes(moderated_grading: false, anonymous_grading: true)
@assignment.mute!
end
@ -2391,9 +2330,8 @@ describe Assignment do
end
end
context "when Anonymous Moderated Marking is enabled and assignment is not anonymously graded" do
context "when assignment is not anonymously graded" do
before :once do
@course.account.enable_feature! :anonymous_moderated_marking
@assignment.update_attributes(moderated_grading: true, anonymous_grading: false, grader_count: 1)
@assignment.mute!
end
@ -2407,23 +2345,6 @@ describe Assignment do
expect(@assignment.unmute!).to eq(true)
end
end
context "when Anonymous Moderated Marking is disabled and assignment is anonymously graded" do
before :once do
@course.account.disable_feature! :anonymous_moderated_marking
@assignment.update_attributes(moderated_grading: true, anonymous_grading: true, grader_count: 1)
@assignment.mute!
end
it "unmutes the assignment" do
@assignment.unmute!
expect(@assignment).not_to be_muted
end
it "returns true" do
expect(@assignment.unmute!).to eq(true)
end
end
end
describe "infer_times" do
@ -3169,37 +3090,34 @@ describe Assignment do
end
describe "to update" do
context "when Anonymous Moderated Marking is enabled" do
before(:each) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@course.enable_feature!(:moderated_grading)
before(:each) do
@course.enable_feature!(:moderated_grading)
@moderator = teacher_in_course(course: @course, active_all: true).user
@non_moderator = teacher_in_course(course: @course, active_all: true).user
@moderator = teacher_in_course(course: @course, active_all: true).user
@non_moderator = teacher_in_course(course: @course, active_all: true).user
@moderated_assignment = @course.assignments.create!(
moderated_grading: true,
grader_count: 3,
final_grader: @moderator
)
end
@moderated_assignment = @course.assignments.create!(
moderated_grading: true,
grader_count: 3,
final_grader: @moderator
)
end
it "allows the designated moderator to update a moderated assignment" do
expect(@moderated_assignment.grants_right?(@moderator, :update)).to eq(true)
end
it "allows the designated moderator to update a moderated assignment" do
expect(@moderated_assignment.grants_right?(@moderator, :update)).to eq(true)
end
it "does not allow non-moderators to update a moderated assignment" do
expect(@moderated_assignment.grants_right?(@non_moderator, :update)).to eq(false)
end
it "does not allow non-moderators to update a moderated assignment" do
expect(@moderated_assignment.grants_right?(@non_moderator, :update)).to eq(false)
end
it "allows an admin to update a moderated assignment" do
expect(@moderated_assignment.grants_right?(@admin, :update)).to eq(true)
end
it "allows an admin to update a moderated assignment" do
expect(@moderated_assignment.grants_right?(@admin, :update)).to eq(true)
end
it "allows a teacher to update a moderated assignment with no moderator selected" do
@moderated_assignment.update!(final_grader: nil)
expect(@moderated_assignment.grants_right?(@non_moderator, :update)).to eq(true)
end
it "allows a teacher to update a moderated assignment with no moderator selected" do
@moderated_assignment.update!(final_grader: nil)
expect(@moderated_assignment.grants_right?(@non_moderator, :update)).to eq(true)
end
end
end
@ -5812,6 +5730,7 @@ describe Assignment do
assignment_model(course: @course)
@assignment.grade_student @student, score: 0, grader: @teacher
@assignment.moderated_grading = true
@assignment.grader_count = 1
expect(@assignment.save).to eq false
expect(@assignment.errors[:moderated_grading]).to be_present
end
@ -5820,6 +5739,7 @@ describe Assignment do
assignment_model(course: @course)
@assignment.peer_reviews = true
@assignment.moderated_grading = true
@assignment.grader_count = 1
expect(@assignment.save).to eq false
expect(@assignment.errors[:moderated_grading]).to be_present
end
@ -5828,12 +5748,13 @@ describe Assignment do
assignment_model(course: @course)
@assignment.group_category = @course.group_categories.create!(name: "groups")
@assignment.moderated_grading = true
@assignment.grader_count = 1
expect(@assignment.save).to eq false
expect(@assignment.errors[:moderated_grading]).to be_present
end
it "does not allow turning off if graded submissions exist" do
assignment_model(course: @course, moderated_grading: true)
assignment_model(course: @course, moderated_grading: true, grader_count: 2, final_grader: @teacher)
expect(@assignment).to be_moderated_grading
@assignment.grade_student @student, score: 0, grader: @teacher
@assignment.moderated_grading = false
@ -5842,7 +5763,7 @@ describe Assignment do
end
it "does not allow turning off if provisional grades exist" do
assignment_model(course: @course, moderated_grading: true)
assignment_model(course: @course, moderated_grading: true, grader_count: 2)
expect(@assignment).to be_moderated_grading
submission = @assignment.submit_homework @student, body: "blah"
submission.find_or_create_provisional_grade!(@teacher, score: 0)
@ -5854,6 +5775,7 @@ describe Assignment do
it "does not allow turning on for an ungraded assignment" do
assignment_model(course: @course, submission_types: 'not_graded')
@assignment.moderated_grading = true
@assignment.grader_count = 1
expect(@assignment.save).to eq false
expect(@assignment.errors[:moderated_grading]).to be_present
end
@ -5861,6 +5783,7 @@ describe Assignment do
it "does not allow creating a new ungraded assignment with moderated grading" do
a = @course.assignments.build
a.moderated_grading = true
a.grader_count = 1
a.submission_types = 'not_graded'
expect(a).not_to be_valid
end
@ -5953,17 +5876,18 @@ describe Assignment do
describe '.remove_user_as_final_grader_immediately' do
it 'removes the user as final grader in all assignments in the given course' do
2.times { @course.assignments.create!(moderated_grading: true, final_grader: @teacher) }
another_teacher = User.create!
2.times { @course.assignments.create!(moderated_grading: true, grader_count: 2, final_grader: @teacher) }
og_teacher = @teacher
another_teacher = teacher_in_course(course: @course, active_all: true).user
@course.enroll_teacher(another_teacher, active_all: true)
@course.assignments.create!(moderated_grading: true, final_grader: another_teacher)
expect { Assignment.remove_user_as_final_grader_immediately(@teacher.id, @course.id) }.to change {
@course.assignments.create!(moderated_grading: true, grader_count: 2, final_grader: another_teacher)
expect { Assignment.remove_user_as_final_grader_immediately(og_teacher.id, @course.id) }.to change {
@course.assignments.order(:created_at).pluck(:final_grader_id)
}.from([@teacher.id, @teacher.id, another_teacher.id]).to([nil, nil, another_teacher.id])
}.from([og_teacher.id, og_teacher.id, another_teacher.id]).to([nil, nil, another_teacher.id])
end
it 'includes soft-deleted assignments when removing the user as final grader' do
assignment = @course.assignments.create!(moderated_grading: true, final_grader: @teacher)
assignment = @course.assignments.create!(moderated_grading: true, grader_count: 2, final_grader: @teacher)
assignment.destroy
expect { Assignment.remove_user_as_final_grader_immediately(@teacher.id, @course.id) }.to change {
assignment.reload.final_grader_id
@ -6044,7 +5968,6 @@ describe Assignment do
describe '#available_moderators' do
before(:once) do
@course = Course.create!
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@first_teacher = User.create!
@second_teacher = User.create!
[@first_teacher, @second_teacher].each { |user| @course.enroll_teacher(user, enrollment_state: 'active') }
@ -6149,36 +6072,24 @@ describe Assignment do
@assignment.moderation_graders.create!(user: second_teacher, anonymous_id: '12345')
end
it 'returns false if anonymous moderated marking is off' do
@assignment.moderation_graders.create!(user: @ta, anonymous_id: '54321')
it 'returns false if all provisional grader slots are not filled' do
expect(@assignment.moderated_grader_limit_reached?).to eq false
end
context 'when anonymous moderated marking is enabled' do
before :once do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
end
it 'returns true if all provisional grader slots are filled' do
@assignment.moderation_graders.create!(user: @ta, anonymous_id: '54321')
expect(@assignment.moderated_grader_limit_reached?).to eq true
end
it 'returns false if all provisional grader slots are not filled' do
expect(@assignment.moderated_grader_limit_reached?).to eq false
end
it 'ignores grades issued by the final grader when determining if slots are filled' do
@assignment.moderation_graders.create!(user: @teacher, anonymous_id: '00000')
expect(@assignment.moderated_grader_limit_reached?).to eq false
end
it 'returns true if all provisional grader slots are filled' do
@assignment.moderation_graders.create!(user: @ta, anonymous_id: '54321')
expect(@assignment.moderated_grader_limit_reached?).to eq true
end
it 'ignores grades issued by the final grader when determining if slots are filled' do
@assignment.moderation_graders.create!(user: @teacher, anonymous_id: '00000')
expect(@assignment.moderated_grader_limit_reached?).to eq false
end
it 'returns false if moderated grading is off' do
@assignment.moderation_graders.create!(user: @ta, anonymous_id: '54321')
@assignment.moderated_grading = false
expect(@assignment.moderated_grader_limit_reached?).to eq false
end
it 'returns false if moderated grading is off' do
@assignment.moderation_graders.create!(user: @ta, anonymous_id: '54321')
@assignment.moderated_grading = false
expect(@assignment.moderated_grader_limit_reached?).to eq false
end
end
@ -6197,7 +6108,6 @@ describe Assignment do
moderated_grading: true
)
@assignment.moderation_graders.create!(user: @second_teacher, anonymous_id: '12345')
@course.root_account.enable_feature!(:anonymous_moderated_marking)
end
shared_examples 'grader permissions are checked' do
@ -6287,7 +6197,6 @@ describe Assignment do
describe 'Anonymous Moderated Marking setting validation' do
before(:once) do
@course.account.enable_feature!(:anonymous_moderated_marking)
assignment_model(course: @course)
end

View File

@ -127,8 +127,13 @@ module Assignments
context "moderated grading count" do
before do
@assignment = @course.assignments.create(:title => "some assignment",
:submission_types => ['online_text_entry'], :moderated_grading => true, :points_possible => 3)
@assignment = @course.assignments.create(
title: "some assignment",
submission_types: ['online_text_entry'],
moderated_grading: true,
grader_count: 2,
points_possible: 3
)
@students = []
3.times do
student = student_in_course(:course => @course, :active_all => true).user
@ -136,8 +141,8 @@ module Assignments
@students << student
end
@ta1 = ta_in_course(:course => course_factory, :active_all => true).user
@ta2 = ta_in_course(:course => course_factory, :active_all => true).user
@ta1 = ta_in_course(:course => @course, :active_all => true).user
@ta2 = ta_in_course(:course => @course, :active_all => true).user
end
it "should only include students with no marks when unmoderated" do
@ -151,12 +156,10 @@ module Assignments
expect(querier.count).to eq 2
@students[1].submissions.first.find_or_create_provisional_grade!(@ta1)
expect(querier.count).to eq 1
expect(querier.count).to eq 2
end
it "should only include students without two marks when moderated" do
@students.each{|s| @assignment.moderated_grading_selections.create!(:student => s)}
querier = NeedsGradingCountQuery.new(@assignment, @teacher)
expect(querier.count).to eq 3

View File

@ -243,14 +243,6 @@ describe ContentMigration do
expect(new_assignment.group_category.name).to eq "Project Groups"
end
it "should copy moderated_grading setting" do
assignment_model(:course => @copy_from, :points_possible => 40,
:submission_types => 'file_upload', :grading_type => 'points', :moderated_grading => true)
run_course_copy
new_assignment = @copy_to.assignments.where(migration_id: mig_id(@assignment)).first
expect(new_assignment).to be_moderated_grading
end
it "should not copy peer_reviews_assigned" do
assignment_model(:course => @copy_from, :points_possible => 40, :submission_types => 'file_upload', :grading_type => 'points')
@assignment.peer_reviews_assigned = true

View File

@ -154,18 +154,12 @@ describe Course do
describe '#moderators' do
before(:once) do
@course = Course.create!
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@teacher = User.create!
@course.enroll_teacher(@teacher)
@ta = User.create!
@course.enroll_ta(@ta)
end
it 'returns an empty list if the root account has Anonymous Moderated Marking disabled' do
@course.root_account.disable_feature!(:anonymous_moderated_marking)
expect(@course.moderators).to be_empty
end
it 'includes active teachers' do
expect(@course.moderators).to include @teacher
end

View File

@ -201,7 +201,6 @@ describe Enrollment do
context 'when the user is a final grader' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@teacher = User.create!
@another_teacher = User.create!
@course.enroll_teacher(@teacher, enrollment_state: 'active', allow_multiple_enrollments: true)
@ -210,7 +209,7 @@ describe Enrollment do
@course.assignments.create!(moderated_grading: true, final_grader: @another_teacher, grader_count: 2)
end
it 'removes the user as final grader from all course assignments if Anonymous Moderated Marking is enabled' do
it 'removes the user as final grader from all course assignments' do
expect { @course.enrollments.find_by!(user: @teacher).destroy }.to change {
@course.assignments.order(:created_at).pluck(:final_grader_id)
}.from([nil, @teacher.id, @teacher.id, @another_teacher.id]).to([nil, nil, nil, @another_teacher.id])

View File

@ -359,7 +359,6 @@ describe Lti::LtiOutboundAdapter do
url: tool.url
)
)
allow_any_instance_of(Account).to receive(:feature_enabled?).with(:anonymous_moderated_marking).and_return(false)
end
it 'builds the expected encrypted JWT with the correct course data' do

View File

@ -238,9 +238,8 @@ describe ModeratedGrading::ProvisionalGrade do
expect(sub.graded_anonymously).to eq true
end
context 'for a moderated assignment with Anonymous Moderated Marking enabled' do
context 'for a moderated assignment' do
before(:each) do
course.root_account.enable_feature!(:anonymous_moderated_marking)
assignment.update!(moderated_grading: true, grader_count: 2)
end

View File

@ -537,16 +537,6 @@ describe RoleOverride do
it 'is available to account admins, account memberships, teachers, and TAs' do
expect(permission[:available_to]).to match_array %w(AccountAdmin AccountMembership TeacherEnrollment TaEnrollment)
end
it 'is allowed when Anonymous Moderated Marking is enabled for the account' do
@account.root_account.enable_feature!(:anonymous_moderated_marking)
expect(permission[:account_allows].call(@account)).to be true
end
it 'is not allowed when Anonymous Moderated Marking is disabled for the account' do
@account.root_account.disable_feature!(:anonymous_moderated_marking)
expect(permission[:account_allows].call(@account)).to be false
end
end
describe 'view_audit_trail' do
@ -559,16 +549,6 @@ describe RoleOverride do
it 'is available to teachers, TAs, admins and account memberships' do
expect(permission[:available_to]).to match_array %w(TeacherEnrollment AccountAdmin AccountMembership)
end
it 'is allowed when Anonymous Moderated Marking is enabled for the account' do
@account.root_account.enable_feature!(:anonymous_moderated_marking)
expect(permission[:account_allows].call(@account)).to be true
end
it 'is not allowed when Anonymous Moderated Marking is disabled for the account' do
@account.root_account.disable_feature!(:anonymous_moderated_marking)
expect(permission[:account_allows].call(@account)).to be false
end
end
end

View File

@ -188,41 +188,23 @@ describe Submission do
submission_spec_model(assignment: @assignment)
end
context 'with Anonymous Moderated Marking enabled' do
before(:once) do
@assignment.root_account.enable_feature!(:anonymous_moderated_marking)
@submission.assignment.reload
end
it 'may not be graded if grades are not published' do
expect(@submission.grants_right?(@teacher, :grade)).to eq false
end
it 'sets an error message indicating moderation is in progress if grades are not published' do
@submission.grants_right?(@teacher, :grade)
expect(@submission.grading_error_message).to eq 'This assignment is currently being moderated'
end
it 'may be graded if grades are not published but grade_posting_in_progress is true' do
@submission.grade_posting_in_progress = true
expect(@submission.grants_right?(@teacher, :grade)).to eq true
end
it 'may be graded when grades for the assignment are published' do
@submission.assignment.update!(grades_published_at: Time.zone.now)
expect(@submission.grants_right?(@teacher, :grade)).to eq true
end
it 'may not be graded if grades are not published' do
expect(@submission.grants_right?(@teacher, :grade)).to eq false
end
context 'with Anonymous Moderated Marking disabled' do
it 'may be graded when grades for the assignment are not published' do
expect(@submission.grants_right?(@teacher, :grade)).to eq true
end
it 'sets an error message indicating moderation is in progress if grades are not published' do
@submission.grants_right?(@teacher, :grade)
expect(@submission.grading_error_message).to eq 'This assignment is currently being moderated'
end
it 'may be graded when grades for the assignment are published' do
@submission.assignment.update!(grades_published_at: Time.zone.now)
expect(@submission.grants_right?(@teacher, :grade)).to eq true
end
it 'may be graded if grades are not published but grade_posting_in_progress is true' do
@submission.grade_posting_in_progress = true
expect(@submission.grants_right?(@teacher, :grade)).to eq true
end
it 'may be graded when grades for the assignment are published' do
@submission.assignment.update!(grades_published_at: Time.zone.now)
expect(@submission.grants_right?(@teacher, :grade)).to eq true
end
end
end
@ -3630,9 +3612,10 @@ describe Submission do
describe 'find_or_create_provisional_grade!' do
before(:once) do
submission_spec_model
@assignment.grader_count = 1
@assignment.moderated_grading = true
@assignment.save!
submission_spec_model
@teacher2 = User.create(name: "some teacher 2")
@context.enroll_teacher(@teacher2)
@ -3701,7 +3684,7 @@ describe Submission do
end
it "raises an exception if grade is not final and student does not need a provisional grade" do
@submission.find_or_create_provisional_grade!(@teacher)
@assignment.grade_student(@student, grade: 2, grader: @teacher, provisional: true)
expect{ @submission.find_or_create_provisional_grade!(@teacher2, final: false) }
.to raise_error(Assignment::GradeError, "Student already has the maximum number of provisional grades")
@ -3727,6 +3710,7 @@ describe Submission do
context "moderated" do
before(:once) do
@assignment.grader_count = 1
@assignment.moderated_grading = true
@assignment.save!
@submission.reload
@ -3742,7 +3726,6 @@ describe Submission do
context "student in moderation set" do
it "returns the student alone" do
@assignment.moderated_grading_selections.create!(student: @student)
expect(@submission.moderated_grading_whitelist).to eq([@student.moderated_grading_ids])
end
end
@ -3763,7 +3746,7 @@ describe Submission do
context "student in moderation set" do
before(:once) do
@sel = @assignment.moderated_grading_selections.create!(student: @student)
@sel = @assignment.moderated_grading_selections.find_by(student: @student)
end
it "returns nil if no provisional grade was published" do
@ -4072,16 +4055,10 @@ describe Submission do
describe "#can_view_details" do
before :each do
@assignment.root_account.enable_feature!(:anonymous_moderated_marking)
@assignment.update!(anonymous_grading: true, muted: true)
@submission = @assignment.submit_homework(@student, submission_type: 'online_text_entry', body: 'a body')
end
it "returns true if anonymous_moderated_marking is not enabled" do
@assignment.root_account.disable_feature!(:anonymous_moderated_marking)
expect(@submission.can_view_details?(@student)).to be true
end
it "returns true for submitting student if assignment anonymous grading and muted" do
expect(@submission.can_view_details?(@student)).to be true
end
@ -4700,6 +4677,9 @@ describe Submission do
else
assignment.submissions.find_by!(user: user)
end
unless assignment.grades_published? || @submission.grade_posting_in_progress || assignment.permits_moderation?(user)
opts.delete(:grade)
end
@submission.update!(opts)
@submission
end

View File

@ -752,6 +752,7 @@ describe UserLearningObjectScopes do
end
end
@course2.assignments.first.update_attribute(:moderated_grading, true)
@course2.assignments.first.update_attribute(:grader_count, 2)
end
it "should not count assignments with no provisional grades" do

View File

@ -167,7 +167,6 @@ describe GradeSummaryAssignmentPresenter do
describe "#show_submission_details_link?" do
before :each do
@assignment.root_account.enable_feature!(:anonymous_moderated_marking)
@submission_stub = double()
allow(@submission_stub).to receive(:originality_reports_for_display)
end

View File

@ -62,22 +62,6 @@ describe 'Access Different Gradebooks Environments', type: :request do
end
end
describe 'anonymous_moderated_marking_enabled' do
it 'is false when the root account does not have anonymous_moderated_marking enabled' do
get speed_grader_course_gradebook_path(course_id: @course.id), params: { assignment_id: @assignment.id }
js_env = js_env_from_response(response)
expect(js_env.fetch('anonymous_moderated_marking_enabled')).to be false
end
it 'is true when the root account has anonymous_moderated_marking enabled' do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
get speed_grader_course_gradebook_path(course_id: @course.id), params: { assignment_id: @assignment.id }
js_env = js_env_from_response(response)
expect(js_env.fetch('anonymous_moderated_marking_enabled')).to be true
end
end
describe 'show_help_menu_item' do
it 'is false when the root account does not have a support URL configured' do
get speed_grader_course_gradebook_path(course_id: @course.id), params: { assignment_id: @assignment.id }
@ -109,7 +93,6 @@ describe 'Access Different Gradebooks Environments', type: :request do
context 'for a moderated assignment with no grades published' do
before(:once) do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
@assignment.update!(
final_grader: @teacher,
grader_count: 2,
@ -133,6 +116,7 @@ describe 'Access Different Gradebooks Environments', type: :request do
it 'is set to :grader for a moderated assignment whose grades have been published' do
@assignment.update!(
moderated_grading: true,
grader_count: 2,
grades_published_at: Time.zone.now
)
expect(js_env.fetch('grading_role')).to eq 'grader'
@ -187,27 +171,4 @@ describe 'Access Different Gradebooks Environments', type: :request do
end
end
end
describe 'GET #show' do
describe 'js_env' do
describe 'anonymous_moderated_marking_enabled' do
before(:each) do
user_session(@teacher)
end
it 'is false when the root account does not have anonymous_moderated_marking enabled' do
get course_gradebook_path(course_id: @course.id)
js_env = js_env_from_response(response)
expect(js_env.dig('GRADEBOOK_OPTIONS', 'anonymous_moderated_marking_enabled')).to be false
end
it 'is true when the root account has anonymous_moderated_marking enabled' do
@course.root_account.enable_feature!(:anonymous_moderated_marking)
get course_gradebook_path(course_id: @course.id)
js_env = js_env_from_response(response)
expect(js_env.dig('GRADEBOOK_OPTIONS', 'anonymous_moderated_marking_enabled')).to be true
end
end
end
end
end

View File

@ -22,8 +22,6 @@ describe 'Anonymous Moderated Marking' do
include_context 'in-process server selenium tests'
before(:each) do
Account.default.enable_feature!(:anonymous_moderated_marking)
# create a course with a teacher
course_with_teacher(course_name: 'Course1')
end

View File

@ -187,7 +187,7 @@ describe "assignment groups" do
replace_content(f("#ag_#{ag.id}_assignment_name"), "Disappear")
fj('.create_assignment:visible').click
wait_for_ajaximations
refresh_page
expect(fj("#assignment_group_#{ag.id} .assignment:eq(1) .ig-title").text).to match "Disappear"
f("#assignment_group_#{ag.id} .al-trigger").click
@ -264,6 +264,7 @@ describe "assignment groups" do
replace_content(f("#ag_#{ag.id}_assignment_points"), assignment_points)
fj('.create_assignment:visible').click
wait_for_ajaximations
refresh_page
# Checks for correct values in back end.
a = ag.reload.assignments.last

View File

@ -22,10 +22,12 @@ describe "moderated grading assignments" do
include_context "in-process server selenium tests"
before do
Account.default.enable_feature!(:moderated_grading)
@course = course_model
@course.offer!
@assignment = @course.assignments.create!(submission_types: 'online_text_entry', title: 'Test Assignment')
@assignment.update_attribute :moderated_grading, true
@assignment.update_attribute :grader_count, 2
@assignment.update_attribute :workflow_state, 'published'
@student = User.create!
@course.enroll_student(@student)
@ -33,35 +35,9 @@ describe "moderated grading assignments" do
@course.enroll_ta(@user)
end
it "publishes grades from the moderate screen" do
sub = @assignment.submit_homework(@student, :submission_type => 'online_text_entry', :body => 'hallo')
sub.find_or_create_provisional_grade!(@user, score: 80)
course_with_teacher_logged_in course: @course
get "/courses/#{@course.id}/assignments/#{@assignment.id}/moderate"
f('.ModeratedGrading__Header-PublishBtn').click
driver.switch_to.alert.accept
assert_flash_notice_message("Success! Grades were published to the grade book")
end
context "student tray" do
before(:each) do
@account = Account.default
@account.enable_feature!(:student_context_cards)
end
it "moderated assignment should display student name in tray", priority: "1", test_id: 3022071 do
course_with_teacher_logged_in course: @course
get "/courses/#{@course.id}/assignments/#{@assignment.id}/moderate"
f("a[data-student_id='#{@student.id}']").click
expect(f(".StudentContextTray-Header__Name h2 a")).to include_text("User")
end
end
context "with assignment moderation setting" do
before(:each) do
# turn on the moderation flag
Account.default.enable_feature!(:anonymous_moderated_marking)
Account.default.enable_feature!(:anonymous_marking)
Account.default.enable_feature!(:moderated_grading)
@moderated_assignment = @course.assignments.create!(
@ -105,7 +81,6 @@ describe "moderated grading assignments" do
context "with moderator selected" do
before(:each) do
# turn on the moderation flag
Account.default.enable_feature!(:anonymous_moderated_marking)
Account.default.enable_feature!(:anonymous_marking)
# create 2 teachers

View File

@ -31,6 +31,7 @@ describe "quizzes assignments" do
ag = @course.assignment_groups.create!(:name => "Quiz group")
get "/courses/#{@course.id}/assignments"
build_assignment_with_type("Quiz", :assignment_group_id => ag.id, :name => "New Quiz", :submit => true)
refresh_page
expect_new_page_load { f("#assignment_group_#{ag.id}_assignments .ig-title").click }
expect(driver.current_url).to match %r{/courses/\d+/quizzes/\d+}
end

View File

@ -72,6 +72,8 @@ describe "assignments" do
before do
@assignment = @course.assignments.create({name: "Test Moderated Assignment"})
@assignment.update_attribute(:moderated_grading, true)
@assignment.update_attribute(:grader_count, 1)
@assignment.update_attribute(:final_grader, @teacher)
@assignment.unpublish
end
@ -814,15 +816,14 @@ describe "assignments" do
@course.start_at = nil
@course.save!
@assignment = @course.assignments.create({name: "Test Moderated Assignment"})
@assignment.update_attribute(:moderated_grading, true)
@assignment.update_attributes(
moderated_grading: true,
grader_count: 1,
final_grader: @teacher
)
@assignment.publish
end
it "should show the moderated grading page for moderated grading assignments", priority: "1", test_id: 609651 do
get "/courses/#{@course.id}/assignments/#{@assignment.id}/moderate"
expect(f('#assignment_moderation')).to be_displayed
end
it "should deny access for a regular student to the moderation page", priority: "1", test_id: 609652 do
course_with_student_logged_in({course: @course})
get "/courses/#{@course.id}/assignments/#{@assignment.id}/moderate"

View File

@ -128,7 +128,12 @@ describe "dashboard" do
before do
@teacher = @user
@student = student_in_course(:course => @course, :active_all => true).user
@assignment = @course.assignments.create!(:title => "some assignment", :submission_types => ['online_text_entry'], :moderated_grading => true)
@assignment = @course.assignments.create!(
title: "some assignment",
submission_types: ['online_text_entry'],
moderated_grading: true,
grader_count: 2
)
@assignment.submit_homework(@student, :body => "submission")
end

View File

@ -23,7 +23,6 @@ describe 'Original Gradebook' do
include GradebookCommon
before(:each) do
Account.default.enable_feature!(:anonymous_moderated_marking)
Account.default.enable_feature!(:anonymous_grading)
# create a course with a teacher
@ -61,7 +60,7 @@ describe 'Original Gradebook' do
student_enrollment2.update!(workflow_state: 'active')
end
context 'with Anonymous Moderated Marking ON in submission detail' do
context 'submission detail' do
before(:each) do
user_session(@teacher1)
Gradebook::MultipleGradingPeriods.visit_gradebook(@anonymous_course)
@ -77,7 +76,7 @@ describe 'Original Gradebook' do
end
end
context 'with Anonymous Moderated Marking ON has grade cells', priority: '1', test_id: 3496299 do
context 'has grade cells', priority: '1', test_id: 3496299 do
before(:each) do
user_session(@teacher1)
Gradebook::MultipleGradingPeriods.visit_gradebook(@anonymous_course)
@ -90,11 +89,5 @@ describe 'Original Gradebook' do
class_attribute_fetched = grade_cell_grayed.attribute("class")
expect(class_attribute_fetched).to include "grayed-out cannot_edit"
end
it 'not greyed out with grades visible when assignment is unmuted' do
refresh_page
Gradebook::MultipleGradingPeriods.toggle_assignment_mute_option(@anonymous_assignment.id)
expect(Gradebook::MultipleGradingPeriods.cell_graded?("11", 0, 0)).to be true
end
end
end

View File

@ -249,7 +249,6 @@ describe "editing grades" do
context "for a moderated assignment" do
before(:each) do
# turn on the moderation flag
Account.default.enable_feature!(:anonymous_moderated_marking)
Account.default.enable_feature!(:anonymous_marking)
# create 1 teacher

View File

@ -23,8 +23,6 @@ describe 'Anonymous Moderated Marking' do
include_context 'in-process server selenium tests'
before(:each) do
Account.default.enable_feature!(:anonymous_moderated_marking)
# create a course with a teacher
course_with_teacher(course_name: 'Course1', active_all: true)
end

View File

@ -133,8 +133,7 @@ describe "Gradezilla - Assignment Column" do
context "with anonymous assignment" do
before(:each) do
# enable anonymous flags at account level
Account.default.enable_feature!(:anonymous_moderated_marking)
# enable anonymous flag at account level
Account.default.enable_feature!(:anonymous_marking)
# re-use the course and student setup from the describe block up-above

View File

@ -273,7 +273,6 @@ describe "Gradezilla editing grades" do
context "for a moderated assignment" do
before(:each) do
# turn on the moderation flag
Account.default.enable_feature!(:anonymous_moderated_marking)
Account.default.enable_feature!(:anonymous_marking)
now = Time.zone.now

View File

@ -25,7 +25,6 @@ describe 'Moderated Marking' do
include_context 'in-process server selenium tests'
before(:each) do
Account.default.enable_feature!(:anonymous_moderated_marking)
Account.default.enable_feature!(:moderated_grading)
# create a course with two teachers

View File

@ -45,7 +45,15 @@ class Speedgrader
end
def settings_link
f('#settings_link')
f('#speedgrader-settings button')
end
def options_link
fxpath('//span[text() = "Options"]')
end
def keyboard_shortcuts_link
fxpath('//ul[@role = "menu"]//span[text() = "Keyboard Shortcuts"]')
end
def hide_students_chkbox
@ -194,8 +202,16 @@ class Speedgrader
settings_link.click
end
def click_options_link
options_link.click
end
def click_keyboard_shortcuts_link
keyboard_shortcuts_link.click
end
def select_hide_student_names
hide_students_chkbox
hide_students_chkbox.click
end
def click_next_student_btn

Some files were not shown because too many files have changed in this diff Show More