ensure graded assignments aren't gradable after removal from overrides
closes GRADE-124 test plan: * Create a differentiated assignment * Submit the assignment from two students * Assign grades to all but one student * Unassign the assignment from a graded student and the ungraded student * Go back to gradebook * Verify that the cell for the graded student is grayed out and not editable * Verify that the cell for the ungraded student is grayed out and not editable Change-Id: I93c9a2f4dec0888d56ba39682bc2184196f25bba Reviewed-on: https://gerrit.instructure.com/122731 Reviewed-by: Spencer Olson <solson@instructure.com> Reviewed-by: Matt Taylor <mtaylor@instructure.com> QA-Review: KC Naegle <knaegle@instructure.com> Tested-by: Jenkins QA-Review: Anju Reddy <areddy@instructure.com> Product-Review: Matt Goodwin <mattg@instructure.com>
This commit is contained in:
parent
12f57bbdfb
commit
e966615880
|
@ -928,7 +928,7 @@ define [
|
||||||
@submissionsForStudent(student),
|
@submissionsForStudent(student),
|
||||||
@assignmentGroups,
|
@assignmentGroups,
|
||||||
@options.group_weighting_scheme,
|
@options.group_weighting_scheme,
|
||||||
@gradingPeriodSet if hasGradingPeriods,
|
(@gradingPeriodSet if hasGradingPeriods),
|
||||||
EffectiveDueDates.scopeToUser(@effectiveDueDates, student.id) if hasGradingPeriods
|
EffectiveDueDates.scopeToUser(@effectiveDueDates, student.id) if hasGradingPeriods
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -642,13 +642,12 @@ class SubmissionsApiController < ApplicationController
|
||||||
@assignment = @context.assignments.active.find(params[:assignment_id])
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
||||||
@user = get_user_considering_section(params[:user_id])
|
@user = get_user_considering_section(params[:user_id])
|
||||||
|
|
||||||
authorized = false
|
@submission = @assignment.all_submissions.find_or_create_by!(user: @user)
|
||||||
@submission = @assignment.submissions.find_or_create_by!(user: @user)
|
|
||||||
|
|
||||||
if params[:submission] || params[:rubric_assessment]
|
authorized = if params[:submission] || params[:rubric_assessment]
|
||||||
authorized = authorized_action(@submission, @current_user, :grade)
|
authorized_action(@submission, @current_user, :grade)
|
||||||
else
|
else
|
||||||
authorized = authorized_action(@submission, @current_user, :comment)
|
authorized_action(@submission, @current_user, :comment)
|
||||||
end
|
end
|
||||||
|
|
||||||
if authorized
|
if authorized
|
||||||
|
|
|
@ -124,7 +124,7 @@ class AssignmentOverride < ActiveRecord::Base
|
||||||
if due_at_overridden_changed? || set_id_changed? ||
|
if due_at_overridden_changed? || set_id_changed? ||
|
||||||
(set_type_changed? && set_type != 'ADHOC') ||
|
(set_type_changed? && set_type != 'ADHOC') ||
|
||||||
(due_at_overridden && due_at_changed?) ||
|
(due_at_overridden && due_at_changed?) ||
|
||||||
(due_at_overridden && workflow_state_changed?)
|
workflow_state_changed?
|
||||||
DueDateCacher.recompute(assignment)
|
DueDateCacher.recompute(assignment)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -46,6 +46,10 @@ class Submission < ActiveRecord::Base
|
||||||
assignment_in_closed_grading_period: {
|
assignment_in_closed_grading_period: {
|
||||||
status: false,
|
status: false,
|
||||||
message: I18n.t('This assignment is in a closed grading period for this student')
|
message: I18n.t('This assignment is in a closed grading period for this student')
|
||||||
|
}.freeze,
|
||||||
|
not_applicable: {
|
||||||
|
status: false,
|
||||||
|
message: I18n.t('This assignment is not applicable to this student')
|
||||||
}.freeze
|
}.freeze
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
@ -1368,11 +1372,10 @@ class Submission < ActiveRecord::Base
|
||||||
private :can_autograde?
|
private :can_autograde?
|
||||||
|
|
||||||
def can_autograde_symbolic_status
|
def can_autograde_symbolic_status
|
||||||
|
return :not_applicable if deleted?
|
||||||
return :unpublished unless assignment.published?
|
return :unpublished unless assignment.published?
|
||||||
return :not_autograded if grader_id >= 0
|
return :not_autograded if grader_id >= 0
|
||||||
|
|
||||||
student_id = user_id || self.user.try(:id)
|
|
||||||
|
|
||||||
if grading_period&.closed?
|
if grading_period&.closed?
|
||||||
:assignment_in_closed_grading_period
|
:assignment_in_closed_grading_period
|
||||||
else
|
else
|
||||||
|
@ -1395,12 +1398,11 @@ class Submission < ActiveRecord::Base
|
||||||
def can_grade_symbolic_status(user = nil)
|
def can_grade_symbolic_status(user = nil)
|
||||||
user ||= grader
|
user ||= grader
|
||||||
|
|
||||||
|
return :not_applicable if deleted?
|
||||||
return :unpublished unless assignment.published?
|
return :unpublished unless assignment.published?
|
||||||
return :cant_manage_grades unless context.grants_right?(user, nil, :manage_grades)
|
return :cant_manage_grades unless context.grants_right?(user, nil, :manage_grades)
|
||||||
return :account_admin if context.account_membership_allows(user)
|
return :account_admin if context.account_membership_allows(user)
|
||||||
|
|
||||||
student_id = self.user_id || self.user.try(:id)
|
|
||||||
|
|
||||||
if grading_period&.closed?
|
if grading_period&.closed?
|
||||||
:assignment_in_closed_grading_period
|
:assignment_in_closed_grading_period
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 - 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
class IgnoreDeletedSubmissionsForAssignmentVisibility < ActiveRecord::Migration[5.0]
|
||||||
|
tag :postdeploy
|
||||||
|
|
||||||
|
def up
|
||||||
|
self.connection.execute "DROP VIEW #{connection.quote_table_name('assignment_student_visibilities')}"
|
||||||
|
self.connection.execute "DROP VIEW #{connection.quote_table_name('quiz_student_visibilities')}"
|
||||||
|
|
||||||
|
# Update the view so submission scores aren't as important as the submission's workflow_state
|
||||||
|
self.connection.execute %(CREATE VIEW #{connection.quote_table_name('assignment_student_visibilities')} AS
|
||||||
|
SELECT DISTINCT a.id as assignment_id,
|
||||||
|
e.user_id as user_id,
|
||||||
|
c.id as course_id
|
||||||
|
|
||||||
|
FROM #{Assignment.quoted_table_name} a
|
||||||
|
|
||||||
|
JOIN #{Course.quoted_table_name} c
|
||||||
|
ON a.context_id = c.id
|
||||||
|
AND a.context_type = 'Course'
|
||||||
|
|
||||||
|
JOIN #{Enrollment.quoted_table_name} e
|
||||||
|
ON e.course_id = c.id
|
||||||
|
AND e.type IN ('StudentEnrollment', 'StudentViewEnrollment')
|
||||||
|
AND e.workflow_state != 'deleted'
|
||||||
|
|
||||||
|
JOIN #{CourseSection.quoted_table_name} cs
|
||||||
|
ON cs.course_id = c.id
|
||||||
|
AND e.course_section_id = cs.id
|
||||||
|
|
||||||
|
LEFT JOIN #{GroupMembership.quoted_table_name} gm
|
||||||
|
ON gm.user_id = e.user_id
|
||||||
|
AND gm.workflow_state = 'accepted'
|
||||||
|
|
||||||
|
LEFT JOIN #{Group.quoted_table_name} g
|
||||||
|
ON g.context_type = 'Course'
|
||||||
|
AND g.context_id = c.id
|
||||||
|
AND g.workflow_state = 'available'
|
||||||
|
AND gm.group_id = g.id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverrideStudent.quoted_table_name} aos
|
||||||
|
ON aos.assignment_id = a.id
|
||||||
|
AND aos.user_id = e.user_id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverride.quoted_table_name} ao
|
||||||
|
ON ao.assignment_id = a.id
|
||||||
|
AND ao.workflow_state = 'active'
|
||||||
|
AND (
|
||||||
|
(ao.set_type = 'CourseSection' AND ao.set_id = cs.id)
|
||||||
|
OR (ao.set_type = 'ADHOC' AND ao.set_id IS NULL AND ao.id = aos.assignment_override_id)
|
||||||
|
OR (ao.set_type = 'Group' AND ao.set_id = g.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
LEFT JOIN #{Submission.quoted_table_name} s
|
||||||
|
ON s.user_id = e.user_id
|
||||||
|
AND s.assignment_id = a.id
|
||||||
|
AND s.workflow_state != 'deleted'
|
||||||
|
|
||||||
|
WHERE a.workflow_state NOT IN ('deleted','unpublished')
|
||||||
|
AND(
|
||||||
|
( a.only_visible_to_overrides = 'true' AND (ao.id IS NOT NULL OR s.id IS NOT NULL))
|
||||||
|
OR (COALESCE(a.only_visible_to_overrides, 'false') = 'false')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.connection.execute %(CREATE VIEW #{connection.quote_table_name('quiz_student_visibilities')} AS
|
||||||
|
SELECT DISTINCT q.id as quiz_id,
|
||||||
|
e.user_id as user_id,
|
||||||
|
c.id as course_id
|
||||||
|
|
||||||
|
FROM #{Quizzes::Quiz.quoted_table_name} q
|
||||||
|
|
||||||
|
JOIN #{Course.quoted_table_name} c
|
||||||
|
ON q.context_id = c.id
|
||||||
|
AND q.context_type = 'Course'
|
||||||
|
|
||||||
|
JOIN #{Enrollment.quoted_table_name} e
|
||||||
|
ON e.course_id = c.id
|
||||||
|
AND e.type IN ('StudentEnrollment', 'StudentViewEnrollment')
|
||||||
|
AND e.workflow_state != 'deleted'
|
||||||
|
|
||||||
|
JOIN #{CourseSection.quoted_table_name} cs
|
||||||
|
ON cs.course_id = c.id
|
||||||
|
AND e.course_section_id = cs.id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverrideStudent.quoted_table_name} aos
|
||||||
|
ON aos.quiz_id = q.id
|
||||||
|
AND aos.user_id = e.user_id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverride.quoted_table_name} ao
|
||||||
|
ON ao.quiz_id = q.id
|
||||||
|
AND ao.workflow_state = 'active'
|
||||||
|
AND (
|
||||||
|
(ao.set_type = 'CourseSection' AND ao.set_id = cs.id)
|
||||||
|
OR (ao.set_type = 'ADHOC' AND ao.set_id IS NULL AND ao.id = aos.assignment_override_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
LEFT JOIN #{Assignment.quoted_table_name} a
|
||||||
|
ON a.context_id = q.context_id
|
||||||
|
AND a.submission_types LIKE 'online_quiz'
|
||||||
|
AND a.id = q.assignment_id
|
||||||
|
|
||||||
|
LEFT JOIN #{Submission.quoted_table_name} s
|
||||||
|
ON s.user_id = e.user_id
|
||||||
|
AND s.assignment_id = a.id
|
||||||
|
AND s.workflow_state != 'deleted'
|
||||||
|
|
||||||
|
WHERE q.workflow_state NOT IN ('deleted','unpublished')
|
||||||
|
AND(
|
||||||
|
( q.only_visible_to_overrides = 'true' AND (ao.id IS NOT NULL OR s.id IS NOT NULL))
|
||||||
|
OR (COALESCE(q.only_visible_to_overrides, 'false') = 'false')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
self.connection.execute "DROP VIEW #{connection.quote_table_name('assignment_student_visibilities')}"
|
||||||
|
self.connection.execute "DROP VIEW #{connection.quote_table_name('quiz_student_visibilities')}"
|
||||||
|
|
||||||
|
# Recreate the old view where submission scores are significant
|
||||||
|
self.connection.execute %(CREATE VIEW #{connection.quote_table_name('assignment_student_visibilities')} AS
|
||||||
|
SELECT DISTINCT a.id as assignment_id,
|
||||||
|
e.user_id as user_id,
|
||||||
|
c.id as course_id
|
||||||
|
|
||||||
|
FROM #{Assignment.quoted_table_name} a
|
||||||
|
|
||||||
|
JOIN #{Course.quoted_table_name} c
|
||||||
|
ON a.context_id = c.id
|
||||||
|
AND a.context_type = 'Course'
|
||||||
|
|
||||||
|
JOIN #{Enrollment.quoted_table_name} e
|
||||||
|
ON e.course_id = c.id
|
||||||
|
AND e.type IN ('StudentEnrollment', 'StudentViewEnrollment')
|
||||||
|
AND e.workflow_state != 'deleted'
|
||||||
|
|
||||||
|
JOIN #{CourseSection.quoted_table_name} cs
|
||||||
|
ON cs.course_id = c.id
|
||||||
|
AND e.course_section_id = cs.id
|
||||||
|
|
||||||
|
LEFT JOIN #{GroupMembership.quoted_table_name} gm
|
||||||
|
ON gm.user_id = e.user_id
|
||||||
|
AND gm.workflow_state = 'accepted'
|
||||||
|
|
||||||
|
LEFT JOIN #{Group.quoted_table_name} g
|
||||||
|
ON g.context_type = 'Course'
|
||||||
|
AND g.context_id = c.id
|
||||||
|
AND g.workflow_state = 'available'
|
||||||
|
AND gm.group_id = g.id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverrideStudent.quoted_table_name} aos
|
||||||
|
ON aos.assignment_id = a.id
|
||||||
|
AND aos.user_id = e.user_id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverride.quoted_table_name} ao
|
||||||
|
ON ao.assignment_id = a.id
|
||||||
|
AND ao.workflow_state = 'active'
|
||||||
|
AND (
|
||||||
|
(ao.set_type = 'CourseSection' AND ao.set_id = cs.id)
|
||||||
|
OR (ao.set_type = 'ADHOC' AND ao.set_id IS NULL AND ao.id = aos.assignment_override_id)
|
||||||
|
OR (ao.set_type = 'Group' AND ao.set_id = g.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
LEFT JOIN #{Submission.quoted_table_name} s
|
||||||
|
ON s.user_id = e.user_id
|
||||||
|
AND s.assignment_id = a.id
|
||||||
|
AND s.score IS NOT NULL
|
||||||
|
|
||||||
|
WHERE a.workflow_state NOT IN ('deleted','unpublished')
|
||||||
|
AND(
|
||||||
|
( a.only_visible_to_overrides = 'true' AND (ao.id IS NOT NULL OR s.id IS NOT NULL))
|
||||||
|
OR (COALESCE(a.only_visible_to_overrides, 'false') = 'false')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.connection.execute %(CREATE VIEW #{connection.quote_table_name('quiz_student_visibilities')} AS
|
||||||
|
SELECT DISTINCT q.id as quiz_id,
|
||||||
|
e.user_id as user_id,
|
||||||
|
c.id as course_id
|
||||||
|
|
||||||
|
FROM #{Quizzes::Quiz.quoted_table_name} q
|
||||||
|
|
||||||
|
JOIN #{Course.quoted_table_name} c
|
||||||
|
ON q.context_id = c.id
|
||||||
|
AND q.context_type = 'Course'
|
||||||
|
|
||||||
|
JOIN #{Enrollment.quoted_table_name} e
|
||||||
|
ON e.course_id = c.id
|
||||||
|
AND e.type IN ('StudentEnrollment', 'StudentViewEnrollment')
|
||||||
|
AND e.workflow_state != 'deleted'
|
||||||
|
|
||||||
|
JOIN #{CourseSection.quoted_table_name} cs
|
||||||
|
ON cs.course_id = c.id
|
||||||
|
AND e.course_section_id = cs.id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverrideStudent.quoted_table_name} aos
|
||||||
|
ON aos.quiz_id = q.id
|
||||||
|
AND aos.user_id = e.user_id
|
||||||
|
|
||||||
|
LEFT JOIN #{AssignmentOverride.quoted_table_name} ao
|
||||||
|
ON ao.quiz_id = q.id
|
||||||
|
AND ao.workflow_state = 'active'
|
||||||
|
AND (
|
||||||
|
(ao.set_type = 'CourseSection' AND ao.set_id = cs.id)
|
||||||
|
OR (ao.set_type = 'ADHOC' AND ao.set_id IS NULL AND ao.id = aos.assignment_override_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
LEFT JOIN #{Assignment.quoted_table_name} a
|
||||||
|
ON a.context_id = q.context_id
|
||||||
|
AND a.submission_types LIKE 'online_quiz'
|
||||||
|
AND a.id = q.assignment_id
|
||||||
|
|
||||||
|
LEFT JOIN #{Submission.quoted_table_name} s
|
||||||
|
ON s.user_id = e.user_id
|
||||||
|
AND s.assignment_id = a.id
|
||||||
|
AND s.score IS NOT NULL
|
||||||
|
|
||||||
|
WHERE q.workflow_state NOT IN ('deleted','unpublished')
|
||||||
|
AND(
|
||||||
|
( q.only_visible_to_overrides = 'true' AND (ao.id IS NOT NULL OR s.id IS NOT NULL))
|
||||||
|
OR (COALESCE(q.only_visible_to_overrides, 'false') = 'false')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -286,29 +286,6 @@ class EffectiveDueDates
|
||||||
#{filter_students_sql('e')}
|
#{filter_students_sql('e')}
|
||||||
),
|
),
|
||||||
|
|
||||||
-- fetch all students who have graded submissions
|
|
||||||
-- because if the student received a grade, they
|
|
||||||
-- shouldn't lose visibility to the assignment
|
|
||||||
override_submissions_students AS (
|
|
||||||
SELECT
|
|
||||||
s.user_id AS student_id,
|
|
||||||
s.assignment_id,
|
|
||||||
NULL::integer AS override_id,
|
|
||||||
NULL::timestamp AS due_at,
|
|
||||||
'Submission'::varchar AS override_type,
|
|
||||||
FALSE AS due_at_overridden,
|
|
||||||
3 AS priority
|
|
||||||
FROM
|
|
||||||
models a
|
|
||||||
INNER JOIN #{Submission.quoted_table_name} s ON s.assignment_id = a.id
|
|
||||||
INNER JOIN #{Enrollment.quoted_table_name} e ON e.course_id = a.context_id AND e.user_id = s.user_id
|
|
||||||
WHERE
|
|
||||||
(s.grade IS NOT NULL OR s.excused) AND
|
|
||||||
e.workflow_state NOT IN ('rejected', 'deleted') AND
|
|
||||||
e.type IN ('StudentEnrollment', 'StudentViewEnrollment')
|
|
||||||
#{filter_students_sql('s')}
|
|
||||||
),
|
|
||||||
|
|
||||||
-- join all these students together into a single table
|
-- join all these students together into a single table
|
||||||
override_all_students AS (
|
override_all_students AS (
|
||||||
SELECT * FROM override_adhoc_students
|
SELECT * FROM override_adhoc_students
|
||||||
|
@ -318,8 +295,6 @@ class EffectiveDueDates
|
||||||
SELECT * FROM override_sections_students
|
SELECT * FROM override_sections_students
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT * FROM override_everyonelse_students
|
SELECT * FROM override_everyonelse_students
|
||||||
UNION ALL
|
|
||||||
SELECT * FROM override_submissions_students
|
|
||||||
),
|
),
|
||||||
|
|
||||||
-- and pick the latest override date as the effective due date
|
-- and pick the latest override date as the effective due date
|
||||||
|
|
|
@ -1690,18 +1690,6 @@ describe 'Submissions API', type: :request do
|
||||||
|
|
||||||
expect(json.size).to eq 0
|
expect(json.size).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the graded submisson even if the student is not in the overriden section" do
|
|
||||||
@assignment.grade_student(@student, grade: 5, grader: @teacher)
|
|
||||||
Score.where(enrollment_id: @student.enrollments).delete_all
|
|
||||||
@student.enrollments.each(&:destroy_permanently!)
|
|
||||||
student_in_section(@section2, user: @student)
|
|
||||||
|
|
||||||
json = call_to_for_students(as_student: false)
|
|
||||||
|
|
||||||
expect(json.size).to eq 1
|
|
||||||
json.each { |submission| expect(submission['user_id']).to eq @student.id }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2208,6 +2196,33 @@ describe 'Submissions API', type: :request do
|
||||||
expect(json['score']).to eq 12.9
|
expect(json['score']).to eq 12.9
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "doesn't allow grading a deleted submission" do
|
||||||
|
submission = @assignment.submissions.find_by(user: @student)
|
||||||
|
submission.destroy
|
||||||
|
|
||||||
|
api_call(
|
||||||
|
:put,
|
||||||
|
"/api/v1/courses/#{@course.id}/assignments/#{@assignment.id}/submissions/#{@student.id}.json",
|
||||||
|
{
|
||||||
|
controller: 'submissions_api',
|
||||||
|
action: 'update',
|
||||||
|
format: 'json',
|
||||||
|
course_id: @course.id.to_s,
|
||||||
|
assignment_id: @assignment.id.to_s,
|
||||||
|
user_id: @student.id.to_s
|
||||||
|
}, {
|
||||||
|
submission: {
|
||||||
|
posted_grade: 'B'
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
expected_status: :unauthorized
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(submission.score).to be_nil
|
||||||
|
expect(submission.grade).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
it "can excuse assignments" do
|
it "can excuse assignments" do
|
||||||
json = api_call(
|
json = api_call(
|
||||||
:put,
|
:put,
|
||||||
|
|
|
@ -656,23 +656,12 @@ describe Course do
|
||||||
expect(edd.to_hash).to eq({})
|
expect(edd.to_hash).to eq({})
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes not-assigned students with existing graded submissions' do
|
it 'ignores not-assigned students with existing graded submissions' do
|
||||||
@assignment1.grade_student(@student1, grade: 5, grader: @teacher)
|
@assignment1.grade_student(@student1, grade: 5, grader: @teacher)
|
||||||
|
|
||||||
edd = EffectiveDueDates.for_course(@test_course, @assignment1)
|
edd = EffectiveDueDates.for_course(@test_course, @assignment1)
|
||||||
result = edd.to_hash
|
result = edd.to_hash
|
||||||
expected = {
|
expect(result).to be_empty
|
||||||
@assignment1.id => {
|
|
||||||
@student1.id => {
|
|
||||||
due_at: nil,
|
|
||||||
grading_period_id: nil,
|
|
||||||
in_closed_grading_period: false,
|
|
||||||
override_id: nil,
|
|
||||||
override_source: 'Submission'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect(result).to eq expected
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'uses assigned date instead of submission date even if submission was late' do
|
it 'uses assigned date instead of submission date even if submission was late' do
|
||||||
|
@ -1440,39 +1429,6 @@ describe Course do
|
||||||
}
|
}
|
||||||
expect(result).to eq expected
|
expect(result).to eq expected
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is false if the due date is only due to a graded submission even if the last grading period is closed' do
|
|
||||||
Factories::GradingPeriodHelper.new.create_for_group(@gp_group, {
|
|
||||||
start_date: 50.days.ago(@now),
|
|
||||||
end_date: 35.days.ago(@now),
|
|
||||||
close_date: 30.days.from_now(@now)
|
|
||||||
})
|
|
||||||
Factories::GradingPeriodHelper.new.create_for_group(@gp_group, {
|
|
||||||
start_date: 20.days.ago(@now),
|
|
||||||
end_date: 15.days.ago(@now),
|
|
||||||
close_date: 10.days.ago(@now)
|
|
||||||
})
|
|
||||||
@assignment1.grade_student(@student1, grade: 5, grader: @teacher)
|
|
||||||
@assignment1.submissions.find_by!(user: @student1).update!(
|
|
||||||
submitted_at: 1.week.from_now(@now),
|
|
||||||
submission_type: 'online_text_entry'
|
|
||||||
)
|
|
||||||
|
|
||||||
edd = EffectiveDueDates.for_course(@test_course, @assignment1)
|
|
||||||
result = edd.to_hash
|
|
||||||
expected = {
|
|
||||||
@assignment1.id => {
|
|
||||||
@student1.id => {
|
|
||||||
due_at: nil,
|
|
||||||
grading_period_id: nil,
|
|
||||||
in_closed_grading_period: false,
|
|
||||||
override_id: nil,
|
|
||||||
override_source: 'Submission'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect(result).to eq expected
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1174,27 +1174,32 @@ describe GradeCalculator do
|
||||||
set_up_course_for_differentiated_assignments
|
set_up_course_for_differentiated_assignments
|
||||||
end
|
end
|
||||||
it "should calculate scores based on visible assignments only" do
|
it "should calculate scores based on visible assignments only" do
|
||||||
# 5 + 15 + 10 + 20 + 10
|
# Non-overridden assignments are not visible to this student at all even though she's been graded on them
|
||||||
expect(final_grade_info(@user, @course)[:total]).to eq 60
|
# because the assignment is only visible to overrides. Therefore only the (first three) overridden assignments
|
||||||
expect(final_grade_info(@user, @course)[:possible]).to eq 100
|
# ever count towards her final grade in all these specs
|
||||||
|
# 5 + 15 + 10
|
||||||
|
expect(final_grade_info(@user, @course)[:total]).to eq 30
|
||||||
|
expect(final_grade_info(@user, @course)[:possible]).to eq 60
|
||||||
end
|
end
|
||||||
it "should drop the lowest visible when that rule is in place" do
|
it "should drop the lowest visible when that rule is in place" do
|
||||||
@group.update_attribute(:rules, 'drop_lowest:1')
|
@group.update_attribute(:rules, 'drop_lowest:1') # rubocop:disable Rails/SkipsModelValidations
|
||||||
# 5 + 15 + 10 + 20 + 10 - 5
|
# 5 + 15 + 10 - 5
|
||||||
expect(final_grade_info(@user, @course)[:total]).to eq 55
|
expect(final_grade_info(@user, @course)[:total]).to eq 25
|
||||||
expect(final_grade_info(@user, @course)[:possible]).to eq 80
|
expect(final_grade_info(@user, @course)[:possible]).to eq 40
|
||||||
end
|
end
|
||||||
it "should drop the highest visible when that rule is in place" do
|
it "should drop the highest visible when that rule is in place" do
|
||||||
@group.update_attribute(:rules, 'drop_highest:1')
|
@group.update_attribute(:rules, 'drop_highest:1') # rubocop:disable Rails/SkipsModelValidations
|
||||||
# 5 + 15 + 10 + 20 + 10 - 20
|
# 5 + 15 + 10 - 15
|
||||||
expect(final_grade_info(@user, @course)[:total]).to eq 40
|
expect(final_grade_info(@user, @course)[:total]).to eq 15
|
||||||
expect(final_grade_info(@user, @course)[:possible]).to eq 80
|
expect(final_grade_info(@user, @course)[:possible]).to eq 40
|
||||||
end
|
end
|
||||||
it "should not count an invisible assignment with never drop on" do
|
it "should not count an invisible assignment with never drop on" do
|
||||||
|
# rubocop:disable Rails/SkipsModelValidations
|
||||||
@group.update_attribute(:rules, "drop_lowest:2\nnever_drop:#{@overridden_lowest.id}")
|
@group.update_attribute(:rules, "drop_lowest:2\nnever_drop:#{@overridden_lowest.id}")
|
||||||
# 5 + 15 + 10 + 20 + 10 - 10 - 10
|
# rubocop:enable Rails/SkipsModelValidations
|
||||||
expect(final_grade_info(@user, @course)[:total]).to eq 40
|
# 5 + 15 + 10 - 10
|
||||||
expect(final_grade_info(@user, @course)[:possible]).to eq 60
|
expect(final_grade_info(@user, @course)[:total]).to eq 20
|
||||||
|
expect(final_grade_info(@user, @course)[:possible]).to eq 40
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -462,9 +462,8 @@ describe GradebookUserIds do
|
||||||
it "places students that are not assigned at the end, but before fake students" do
|
it "places students that are not assigned at the end, but before fake students" do
|
||||||
@assignment.update!(only_visible_to_overrides: true)
|
@assignment.update!(only_visible_to_overrides: true)
|
||||||
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
||||||
student5 = student_in_course(course: @course, active_all: true).user
|
|
||||||
expect(gradebook_user_ids.user_ids).to eq(
|
expect(gradebook_user_ids.user_ids).to eq(
|
||||||
[@student2.id, @student1.id, @student4.id, @student3.id, student5.id, @fake_student.id]
|
[@student2.id, @student1.id, @student3.id, @student4.id, @fake_student.id]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -495,9 +494,8 @@ describe GradebookUserIds do
|
||||||
it "places students that are not assigned at the end, but before fake students" do
|
it "places students that are not assigned at the end, but before fake students" do
|
||||||
@assignment.update!(only_visible_to_overrides: true)
|
@assignment.update!(only_visible_to_overrides: true)
|
||||||
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
||||||
student5 = student_in_course(course: @course, active_all: true).user
|
|
||||||
expect(gradebook_user_ids.user_ids).to eq(
|
expect(gradebook_user_ids.user_ids).to eq(
|
||||||
[@student2.id, @student1.id, @student3.id, @student4.id, student5.id, @fake_student.id]
|
[@student2.id, @student1.id, @student3.id, @student4.id, @fake_student.id]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -541,9 +539,8 @@ describe GradebookUserIds do
|
||||||
it "places students that are not assigned at the end, but before fake students" do
|
it "places students that are not assigned at the end, but before fake students" do
|
||||||
@assignment.update!(only_visible_to_overrides: true)
|
@assignment.update!(only_visible_to_overrides: true)
|
||||||
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
||||||
student5 = student_in_course(course: @course, active_all: true).user
|
|
||||||
expect(gradebook_user_ids.user_ids).to eq(
|
expect(gradebook_user_ids.user_ids).to eq(
|
||||||
[@student3.id, @student4.id, @student1.id, @student2.id, student5.id, @fake_student.id]
|
[@student3.id, @student1.id, @student2.id, @student4.id, @fake_student.id]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -576,9 +573,8 @@ describe GradebookUserIds do
|
||||||
it "places students that are not assigned at the end, but before fake students" do
|
it "places students that are not assigned at the end, but before fake students" do
|
||||||
@assignment.update!(only_visible_to_overrides: true)
|
@assignment.update!(only_visible_to_overrides: true)
|
||||||
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
create_adhoc_override_for_assignment(@assignment, [@student1, @student3, @student2], due_at: nil)
|
||||||
student5 = student_in_course(course: @course, active_all: true).user
|
|
||||||
expect(gradebook_user_ids.user_ids).to eq(
|
expect(gradebook_user_ids.user_ids).to eq(
|
||||||
[@student4.id, @student3.id, @student1.id, @student2.id, student5.id, @fake_student.id]
|
[@student3.id, @student1.id, @student2.id, @student4.id, @fake_student.id]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -727,24 +727,24 @@ describe AssignmentOverride do
|
||||||
@override.save
|
@override.save
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not trigger when non-applicable override is created" do
|
it "triggers when override without a due_date is created" do
|
||||||
expect(DueDateCacher).to receive(:recompute).never
|
expect(DueDateCacher).to receive(:recompute)
|
||||||
@assignment.assignment_overrides.create
|
@assignment.assignment_overrides.create
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not trigger when non-applicable override deleted" do
|
it "triggers when override without a due_date deleted" do
|
||||||
@override.clear_due_at_override
|
@override.clear_due_at_override
|
||||||
@override.save
|
@override.save
|
||||||
|
|
||||||
expect(DueDateCacher).to receive(:recompute).never
|
expect(DueDateCacher).to receive(:recompute)
|
||||||
@override.destroy
|
@override.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not trigger when non-applicable override undeleted" do
|
it "triggers when override without a due_date undeleted" do
|
||||||
@override.clear_due_at_override
|
@override.clear_due_at_override
|
||||||
@override.destroy
|
@override.destroy
|
||||||
|
|
||||||
expect(DueDateCacher).to receive(:recompute).never
|
expect(DueDateCacher).to receive(:recompute)
|
||||||
@override.workflow_state = 'active'
|
@override.workflow_state = 'active'
|
||||||
@override.save
|
@override.save
|
||||||
end
|
end
|
||||||
|
|
|
@ -83,7 +83,11 @@ describe AssignmentOverrideStudent do
|
||||||
|
|
||||||
it 'on destroy, recalculates cached due dates on the assignment' do
|
it 'on destroy, recalculates cached due dates on the assignment' do
|
||||||
override_student = @assignment_override.assignment_override_students.create!(user: @student)
|
override_student = @assignment_override.assignment_override_students.create!(user: @student)
|
||||||
expect(DueDateCacher).to receive(:recompute).with(@assignment)
|
|
||||||
|
# Expect DueDateCacher to be called once from AssignmentOverrideStudent after it's destroyed and another time
|
||||||
|
# after it realizes that its corresponding AssignmentOverride can also be destroyed because it now has an empty
|
||||||
|
# set of students. Hence the specific nature of this expectation.
|
||||||
|
expect(DueDateCacher).to receive(:recompute).with(@assignment).twice
|
||||||
override_student.destroy
|
override_student.destroy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1840,30 +1840,28 @@ describe Assignment do
|
||||||
context "differentiated_assignments" do
|
context "differentiated_assignments" do
|
||||||
before :once do
|
before :once do
|
||||||
setup_differentiated_assignments
|
setup_differentiated_assignments
|
||||||
@submissions = []
|
@assignment.submit_homework(@student1, submission_type: 'online_url', url: 'http://www.google.com')
|
||||||
[@student1, @student2].each do |u|
|
@submissions = @assignment.submissions
|
||||||
@submissions << @assignment.submit_homework(u, :submission_type => "online_url", :url => "http://www.google.com")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
context "feature on" do
|
context "feature on" do
|
||||||
it "should assign peer reviews only to students with visibility" do
|
it "should assign peer reviews only to students with visibility" do
|
||||||
@assignment.peer_review_count = 1
|
@assignment.peer_review_count = 1
|
||||||
res = @assignment.assign_peer_reviews
|
res = @assignment.assign_peer_reviews
|
||||||
expect(res.length).to eql(0)
|
expect(res.length).to be 0
|
||||||
@submissions.each do |s|
|
@submissions.reload.each do |s|
|
||||||
expect(res.map{|a| a.asset}).not_to be_include(s)
|
expect(res.map(&:asset)).not_to include(s)
|
||||||
expect(res.map{|a| a.assessor_asset}).not_to be_include(s)
|
expect(res.map(&:assessor_asset)).not_to include(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
# once graded the student will have visibility
|
# let's add this student to the section the assignment is assigned to
|
||||||
# and will therefore show up in the peer reviews
|
student_in_section(@section1, user: @student2)
|
||||||
@assignment.grade_student(@student2, :grader => @teacher, :grade => '100')
|
@assignment.submit_homework(@student2, submission_type: 'online_url', url: 'http://www.google.com')
|
||||||
|
|
||||||
res = @assignment.assign_peer_reviews
|
res = @assignment.assign_peer_reviews
|
||||||
expect(res.length).to eql(@submissions.length)
|
expect(res.length).to be 2
|
||||||
@submissions.each do |s|
|
@submissions.reload.each do |s|
|
||||||
expect(res.map{|a| a.asset}).to be_include(s)
|
expect(res.map(&:asset)).to include(s)
|
||||||
expect(res.map{|a| a.assessor_asset}).to be_include(s)
|
expect(res.map(&:assessor_asset)).to include(s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -226,11 +226,11 @@ describe "differentiated_assignments" do
|
||||||
teacher_in_course(course: @course)
|
teacher_in_course(course: @course)
|
||||||
enroll_user_in_group(@group_foo, {user: @student})
|
enroll_user_in_group(@group_foo, {user: @student})
|
||||||
end
|
end
|
||||||
it "should keep the assignment visible if there is a grade" do
|
it "should not keep the assignment visible even if there is a grade" do
|
||||||
@assignment.grade_student(@student, grade: 10, grader: @teacher)
|
@assignment.grade_student(@student, grade: 10, grader: @teacher)
|
||||||
@student.group_memberships.each(&:destroy!)
|
@student.group_memberships.each(&:destroy!)
|
||||||
enroll_user_in_group(@group_bar, {user: @student})
|
enroll_user_in_group(@group_bar, {user: @student})
|
||||||
ensure_user_sees_assignment
|
ensure_user_does_not_see_assignment
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not keep the assignment visible if there is no grade" do
|
it "should not keep the assignment visible if there is no grade" do
|
||||||
|
@ -240,11 +240,11 @@ describe "differentiated_assignments" do
|
||||||
ensure_user_does_not_see_assignment
|
ensure_user_does_not_see_assignment
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should keep the assignment visible if the grade is zero" do
|
it "should not keep the assignment visible even if the grade is zero" do
|
||||||
@assignment.grade_student(@student, grade: 0, grader: @teacher)
|
@assignment.grade_student(@student, grade: 0, grader: @teacher)
|
||||||
@student.group_memberships.each(&:destroy!)
|
@student.group_memberships.each(&:destroy!)
|
||||||
enroll_user_in_group(@group_bar, {user: @student})
|
enroll_user_in_group(@group_bar, {user: @student})
|
||||||
ensure_user_sees_assignment
|
ensure_user_does_not_see_assignment
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -297,12 +297,12 @@ describe "differentiated_assignments" do
|
||||||
enroller_user_in_section(@section_foo)
|
enroller_user_in_section(@section_foo)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should keep the assignment visible if there is a grade" do
|
it "should not keep the assignment visible even if there is a grade" do
|
||||||
@assignment.grade_student(@user, grade: 10, grader: @teacher)
|
@assignment.grade_student(@user, grade: 10, grader: @teacher)
|
||||||
Score.where(enrollment_id: @user.enrollments).delete_all
|
Score.where(enrollment_id: @user.enrollments).delete_all
|
||||||
@user.enrollments.each(&:destroy_permanently!)
|
@user.enrollments.each(&:destroy_permanently!)
|
||||||
enroller_user_in_section(@section_bar, {user: @user})
|
enroller_user_in_section(@section_bar, {user: @user})
|
||||||
ensure_user_sees_assignment
|
ensure_user_does_not_see_assignment
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not keep the assignment visible if there is no grade" do
|
it "should not keep the assignment visible if there is no grade" do
|
||||||
|
@ -313,12 +313,12 @@ describe "differentiated_assignments" do
|
||||||
ensure_user_does_not_see_assignment
|
ensure_user_does_not_see_assignment
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should keep the assignment visible if the grade is zero" do
|
it "should not keep the assignment visible even if the grade is zero" do
|
||||||
@assignment.grade_student(@user, grade: 0, grader: @teacher)
|
@assignment.grade_student(@user, grade: 0, grader: @teacher)
|
||||||
Score.where(enrollment_id: @user.enrollments).delete_all
|
Score.where(enrollment_id: @user.enrollments).delete_all
|
||||||
@user.enrollments.each(&:destroy_permanently!)
|
@user.enrollments.each(&:destroy_permanently!)
|
||||||
enroller_user_in_section(@section_bar, {user: @user})
|
enroller_user_in_section(@section_bar, {user: @user})
|
||||||
ensure_user_sees_assignment
|
ensure_user_does_not_see_assignment
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -345,7 +345,7 @@ describe "differentiated_assignments" do
|
||||||
end
|
end
|
||||||
it "should update when the override is deleted" do
|
it "should update when the override is deleted" do
|
||||||
ensure_user_sees_assignment
|
ensure_user_sees_assignment
|
||||||
@assignment.assignment_overrides.each(&:destroy_permanently!)
|
@assignment.assignment_overrides.each(&:destroy!)
|
||||||
ensure_user_does_not_see_assignment
|
ensure_user_does_not_see_assignment
|
||||||
end
|
end
|
||||||
it "should not return duplicate visibilities with multiple visible sections" do
|
it "should not return duplicate visibilities with multiple visible sections" do
|
||||||
|
|
|
@ -187,12 +187,12 @@ describe "differentiated_assignments" do
|
||||||
@student = @user
|
@student = @user
|
||||||
teacher_in_course(course: @course)
|
teacher_in_course(course: @course)
|
||||||
end
|
end
|
||||||
it "should keep the quiz visible if there is a grade" do
|
it "should not keep the quiz visible even if there is a grade" do
|
||||||
@quiz.assignment.grade_student(@student, grade: 10, grader: @teacher)
|
@quiz.assignment.grade_student(@student, grade: 10, grader: @teacher)
|
||||||
Score.where(enrollment_id: @student.enrollments).delete_all
|
Score.where(enrollment_id: @student.enrollments).delete_all
|
||||||
@student.enrollments.each(&:destroy_permanently!)
|
@student.enrollments.each(&:destroy_permanently!)
|
||||||
enroller_user_in_section(@section_bar, {user: @student})
|
enroller_user_in_section(@section_bar, {user: @student})
|
||||||
ensure_user_sees_quiz
|
ensure_user_does_not_see_quiz
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not keep the quiz visible if there is no score, even if it has a grade" do
|
it "should not keep the quiz visible if there is no score, even if it has a grade" do
|
||||||
|
@ -205,12 +205,12 @@ describe "differentiated_assignments" do
|
||||||
ensure_user_does_not_see_quiz
|
ensure_user_does_not_see_quiz
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should keep the quiz visible if the grade is zero" do
|
it "should not keep the quiz visible even if the grade is zero" do
|
||||||
@quiz.assignment.grade_student(@student, grade: 0, grader: @teacher)
|
@quiz.assignment.grade_student(@student, grade: 0, grader: @teacher)
|
||||||
Score.where(enrollment_id: @student.enrollments).delete_all
|
Score.where(enrollment_id: @student.enrollments).delete_all
|
||||||
@student.enrollments.each(&:destroy_permanently!)
|
@student.enrollments.each(&:destroy_permanently!)
|
||||||
enroller_user_in_section(@section_bar, {user: @student})
|
enroller_user_in_section(@section_bar, {user: @student})
|
||||||
ensure_user_sees_quiz
|
ensure_user_does_not_see_quiz
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ describe "differentiated_assignments" do
|
||||||
end
|
end
|
||||||
it "should update when the override is deleted" do
|
it "should update when the override is deleted" do
|
||||||
ensure_user_sees_quiz
|
ensure_user_sees_quiz
|
||||||
@quiz.assignment_overrides.to_a.each(&:destroy_permanently!)
|
@quiz.assignment_overrides.to_a.each(&:destroy!)
|
||||||
ensure_user_does_not_see_quiz
|
ensure_user_does_not_see_quiz
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -74,6 +74,29 @@ describe Submission do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "grade" do
|
describe "grade" do
|
||||||
|
context "the submission is deleted" do
|
||||||
|
before(:once) do
|
||||||
|
@assignment.due_at = in_open_grading_period
|
||||||
|
@assignment.save!
|
||||||
|
submission_spec_model
|
||||||
|
@submission.update(workflow_state: 'deleted')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not have grade permissions if the user is a root account admin" do
|
||||||
|
expect(@submission.grants_right?(@admin, :grade)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not have grade permissions if the user is non-root account admin with manage_grades permissions" do
|
||||||
|
expect(@submission.grants_right?(@teacher, :grade)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't have grade permissions if the user is non-root account admin without manage_grades permissions" do
|
||||||
|
@student = user_factory(active_all: true)
|
||||||
|
@context.enroll_student(@student)
|
||||||
|
expect(@submission.grants_right?(@student, :grade)).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "the submission is due in an open grading period" do
|
context "the submission is due in an open grading period" do
|
||||||
before(:once) do
|
before(:once) do
|
||||||
@assignment.due_at = in_open_grading_period
|
@assignment.due_at = in_open_grading_period
|
||||||
|
@ -89,7 +112,7 @@ describe Submission do
|
||||||
expect(@submission.grants_right?(@teacher, :grade)).to eq(true)
|
expect(@submission.grants_right?(@teacher, :grade)).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "has not have grade permissions if the user is non-root account admin without manage_grades permissions" do
|
it "doesn't have grade permissions if the user is non-root account admin without manage_grades permissions" do
|
||||||
@student = user_factory(active_all: true)
|
@student = user_factory(active_all: true)
|
||||||
@context.enroll_student(@student)
|
@context.enroll_student(@student)
|
||||||
expect(@submission.grants_right?(@student, :grade)).to eq(false)
|
expect(@submission.grants_right?(@student, :grade)).to eq(false)
|
||||||
|
@ -111,7 +134,7 @@ describe Submission do
|
||||||
expect(@submission.grants_right?(@teacher, :grade)).to eq(true)
|
expect(@submission.grants_right?(@teacher, :grade)).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "has not have grade permissions if the user is non-root account admin without manage_grades permissions" do
|
it "doesn't have grade permissions if the user is non-root account admin without manage_grades permissions" do
|
||||||
@student = user_factory(active_all: true)
|
@student = user_factory(active_all: true)
|
||||||
@context.enroll_student(@student)
|
@context.enroll_student(@student)
|
||||||
expect(@submission.grants_right?(@student, :grade)).to eq(false)
|
expect(@submission.grants_right?(@student, :grade)).to eq(false)
|
||||||
|
|
|
@ -82,7 +82,6 @@ describe "interaction with differentiated quizzes" do
|
||||||
submit_quiz(@da_quiz)
|
submit_quiz(@da_quiz)
|
||||||
# destroy the override and automatically generated grade providing visibility to the current student
|
# destroy the override and automatically generated grade providing visibility to the current student
|
||||||
AssignmentOverride.find(@da_quiz.assignment_overrides.first!.id).destroy
|
AssignmentOverride.find(@da_quiz.assignment_overrides.first!.id).destroy
|
||||||
@da_quiz.assignment.grade_student(@user, grade: nil, grader: @teacher)
|
|
||||||
create_section_override_for_assignment(@da_quiz, course_section: @section1)
|
create_section_override_for_assignment(@da_quiz, course_section: @section1)
|
||||||
# assure we get the no longer counted banner on the quiz page
|
# assure we get the no longer counted banner on the quiz page
|
||||||
get "/courses/#{@course.id}/quizzes/#{@da_quiz.id}"
|
get "/courses/#{@course.id}/quizzes/#{@da_quiz.id}"
|
||||||
|
@ -97,7 +96,6 @@ describe "interaction with differentiated quizzes" do
|
||||||
create_section_override_for_assignment(@da_quiz)
|
create_section_override_for_assignment(@da_quiz)
|
||||||
submit_quiz(@da_quiz)
|
submit_quiz(@da_quiz)
|
||||||
AssignmentOverride.find(@da_quiz.assignment_overrides.first!.id).destroy
|
AssignmentOverride.find(@da_quiz.assignment_overrides.first!.id).destroy
|
||||||
@da_quiz.assignment.grade_student(@user, grade: nil, grader: @teacher)
|
|
||||||
create_section_override_for_assignment(@da_quiz, course_section: @section1)
|
create_section_override_for_assignment(@da_quiz, course_section: @section1)
|
||||||
get "/courses/#{@course.id}/quizzes/#{@da_quiz.id}"
|
get "/courses/#{@course.id}/quizzes/#{@da_quiz.id}"
|
||||||
expect(f("#content")).not_to contain_css(".take_quiz_link")
|
expect(f("#content")).not_to contain_css(".take_quiz_link")
|
||||||
|
@ -183,7 +181,6 @@ describe "interaction with differentiated quizzes" do
|
||||||
submit_quiz(@da_quiz)
|
submit_quiz(@da_quiz)
|
||||||
# destroy the override and automatically generated grade providing visibility to the current student
|
# destroy the override and automatically generated grade providing visibility to the current student
|
||||||
AssignmentOverride.find(@da_quiz.assignment_overrides.first!.id).destroy
|
AssignmentOverride.find(@da_quiz.assignment_overrides.first!.id).destroy
|
||||||
@da_quiz.assignment.grade_student(@user, grade: nil, grader: @teacher)
|
|
||||||
create_section_override_for_assignment(@da_quiz, course_section: @section1)
|
create_section_override_for_assignment(@da_quiz, course_section: @section1)
|
||||||
# assure we get the no longer counted banner on the quiz page
|
# assure we get the no longer counted banner on the quiz page
|
||||||
get "/courses/#{@course.id}/quizzes/#{@da_quiz.id}"
|
get "/courses/#{@course.id}/quizzes/#{@da_quiz.id}"
|
||||||
|
|
|
@ -52,12 +52,11 @@ describe "gradebook" do
|
||||||
expect(cell.find_element(:css, '.gradebook-cell')).not_to have_class('grayed-out')
|
expect(cell.find_element(:css, '.gradebook-cell')).not_to have_class('grayed-out')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should gray out cells after removing a score which removes visibility" do
|
it "should gray out cells after removing an override which removes visibility" do
|
||||||
selector = '#gradebook_grid .container_1 .slick-row:nth-child(1) .l5'
|
selector = '#gradebook_grid .container_1 .slick-row:nth-child(1) .l5'
|
||||||
@da_assignment.grade_student(@student_1, grade: 42, grader: @teacher)
|
@da_assignment.grade_student(@student_1, grade: 42, grader: @teacher)
|
||||||
@override.destroy
|
@override.destroy
|
||||||
get "/courses/#{@course.id}/gradebook"
|
get "/courses/#{@course.id}/gradebook"
|
||||||
edit_grade(selector, '')
|
|
||||||
cell = f(selector)
|
cell = f(selector)
|
||||||
expect(cell.find_element(:css, '.gradebook-cell')).to have_class('grayed-out')
|
expect(cell.find_element(:css, '.gradebook-cell')).to have_class('grayed-out')
|
||||||
end
|
end
|
||||||
|
|
|
@ -53,12 +53,11 @@ describe "Gradezilla" do
|
||||||
expect(cell.find_element(:css, '.gradebook-cell')).not_to have_class('grayed-out')
|
expect(cell.find_element(:css, '.gradebook-cell')).not_to have_class('grayed-out')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should gray out cells after removing a score which removes visibility" do
|
it "should gray out cells after removing an override which removes visibility" do
|
||||||
selector = '#gradebook_grid .container_1 .slick-row:nth-child(1) .l4'
|
selector = '#gradebook_grid .container_1 .slick-row:nth-child(1) .l4'
|
||||||
@da_assignment.grade_student(@student_1, grade: 42, grader: @teacher)
|
@da_assignment.grade_student(@student_1, grade: 42, grader: @teacher)
|
||||||
@override.destroy
|
@override.destroy
|
||||||
Gradezilla.visit(@course)
|
Gradezilla.visit(@course)
|
||||||
edit_grade(selector, '')
|
|
||||||
cell = f(selector)
|
cell = f(selector)
|
||||||
expect(cell.find_element(:css, '.gradebook-cell')).to have_class('grayed-out')
|
expect(cell.find_element(:css, '.gradebook-cell')).to have_class('grayed-out')
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue