Fix moderated assignments with graded rubrics
Closes: GRADE-2414 Test plan: - Given a course with a Teacher, on TA and a student - Given a moderated assignment with one Grader - Given the teacher is the final grader - Given a rubric attached to the assignment with the option "use for grading" enabled - Given the TA has graded the student with the rubric - Given the TA has also given a *different* score in the normal grade box than what the rubric score was - Given on the moderation page the Teacher selects the TA's score. - When clicking the "Release Grades" button - Then submitting grades works and does not error Change-Id: Ia2d06047ec492bd79a17a1fd086861e016ccdf9d Reviewed-on: https://gerrit.instructure.com/208051 Tested-by: Jenkins Reviewed-by: Jeremy Neander <jneander@instructure.com> Reviewed-by: Adrian Packel <apackel@instructure.com> QA-Review: Adrian Packel <apackel@instructure.com> Product-Review: Jonathan Fenton <jfenton@instructure.com>
This commit is contained in:
parent
f285948546
commit
8cf3d457d6
|
@ -1823,6 +1823,7 @@ class Assignment < ActiveRecord::Base
|
|||
submission.workflow_state = "graded"
|
||||
end
|
||||
submission.group = group
|
||||
submission.grade_posting_in_progress = opts.fetch(:grade_posting_in_progress, false)
|
||||
previously_graded ? submission.with_versioning(:explicit => true) { submission.save! } : submission.save!
|
||||
submission.audit_grade_changes = false
|
||||
|
||||
|
|
|
@ -182,30 +182,32 @@ class ModeratedGrading::ProvisionalGrade < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def publish_rubric_assessments!
|
||||
copy_rubric_assessments!(submission)
|
||||
self.rubric_assessments.each do |provisional_assessment|
|
||||
rubric_association = provisional_assessment.rubric_association
|
||||
|
||||
params = {
|
||||
artifact: submission,
|
||||
assessment_type: provisional_assessment.assessment_type
|
||||
}
|
||||
|
||||
unless rubric_association.assessments_unique_per_asset?(provisional_assessment.assessment_type)
|
||||
params = params.merge({assessor_id: provisional_assessment.assessor})
|
||||
end
|
||||
|
||||
def copy_rubric_assessments!(dest_artifact)
|
||||
self.rubric_assessments.each do |prov_assmt|
|
||||
assoc = prov_assmt.rubric_association
|
||||
rubric_assessment = rubric_association.rubric_assessments.find_by(params)
|
||||
rubric_assessment ||= rubric_association.rubric_assessments.build(
|
||||
params.merge(
|
||||
assessor: provisional_assessment.assessor,
|
||||
user: self.student,
|
||||
rubric: rubric_association.rubric,
|
||||
)
|
||||
)
|
||||
|
||||
pub_assmt = nil
|
||||
# see RubricAssociation#assess
|
||||
if dest_artifact.is_a?(Submission)
|
||||
if assoc.assessments_unique_per_asset?(prov_assmt.assessment_type)
|
||||
pub_assmt = assoc.rubric_assessments.where(artifact_id: dest_artifact.id, artifact_type: dest_artifact.class_name,
|
||||
assessment_type: prov_assmt.assessment_type).first
|
||||
else
|
||||
pub_assmt = assoc.rubric_assessments.where(artifact_id: dest_artifact.id, artifact_type: dest_artifact.class_name,
|
||||
assessment_type: prov_assmt.assessment_type, assessor_id: prov_assmt.assessor).first
|
||||
end
|
||||
end
|
||||
pub_assmt ||= assoc.rubric_assessments.build(:assessor => prov_assmt.assessor, :artifact => dest_artifact,
|
||||
:user => self.student, :rubric => assoc.rubric, :assessment_type => prov_assmt.assessment_type)
|
||||
pub_assmt.score = prov_assmt.score
|
||||
pub_assmt.data = prov_assmt.data
|
||||
rubric_assessment.score = provisional_assessment.score
|
||||
rubric_assessment.data = provisional_assessment.data
|
||||
rubric_assessment.submission.grade_posting_in_progress = submission.grade_posting_in_progress
|
||||
|
||||
pub_assmt.save!
|
||||
rubric_assessment.save!
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -157,14 +157,20 @@ class RubricAssessment < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def update_artifact
|
||||
return unless artifact.present? && rubric_association&.use_for_grading? && artifact.score != score
|
||||
return if artifact.blank? || !rubric_association&.use_for_grading? || artifact.score == score
|
||||
|
||||
case artifact_type
|
||||
when "Submission"
|
||||
assignment = rubric_association.association_object
|
||||
return unless assignment.grants_right?(assessor, :grade)
|
||||
|
||||
assignment.grade_student(artifact.student, score: score, grader: assessor, graded_anonymously: @graded_anonymously_set)
|
||||
assignment.grade_student(
|
||||
artifact.student,
|
||||
score: score,
|
||||
grader: assessor,
|
||||
graded_anonymously: @graded_anonymously_set,
|
||||
grade_posting_in_progress: artifact.grade_posting_in_progress
|
||||
)
|
||||
artifact.reload
|
||||
when "ModeratedGrading::ProvisionalGrade"
|
||||
artifact.update!(score: score)
|
||||
|
|
|
@ -74,7 +74,7 @@ module Factories
|
|||
title: 'new outcome',
|
||||
description: '<p>This is <b>awesome</b>.</p>',
|
||||
calculation_method: 'highest')
|
||||
[opts[:outcome_context], @course].compact.uniq.each do |context|
|
||||
[opts[:outcome_context], course].compact.uniq.each do |context|
|
||||
root = context.root_outcome_group
|
||||
root.add_outcome(@outcome)
|
||||
root.save!
|
||||
|
@ -123,8 +123,7 @@ module Factories
|
|||
}
|
||||
}
|
||||
|
||||
@rubric = @course.rubrics.build
|
||||
@rubric = course.rubrics.build
|
||||
@rubric.update_criteria(rubric_params)
|
||||
@rubric.reload
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1594,88 +1594,122 @@ describe Assignment do
|
|||
end
|
||||
|
||||
describe '#grade_student' do
|
||||
before(:once) { setup_assignment_without_submission }
|
||||
|
||||
context 'with a submission that cannot be graded' do
|
||||
before :each do
|
||||
allow_any_instance_of(Submission).to receive(:grader_can_grade?).and_return(false)
|
||||
let_once(:now) { Time.zone.now }
|
||||
let_once(:student) { User.create!.tap {|u| course.enroll_student(u, enrollment_state: 'active') } }
|
||||
let_once(:teacher) { User.create!.tap {|u| course.enroll_teacher(u, enrollment_state: 'active') } }
|
||||
let_once(:assignment) { course.assignments.create! }
|
||||
let_once(:course) do
|
||||
course = Account.default.courses.create!
|
||||
course.offer!
|
||||
course
|
||||
end
|
||||
|
||||
it 'raises a GradeError when Submission#grader_can_grade? returns false' do
|
||||
describe 'grade_posting_in_progress' do
|
||||
let(:submission) { instance_double("Submission") }
|
||||
|
||||
before do
|
||||
allow(assignment).to receive(:find_or_create_submissions).
|
||||
with([student], Submission.preload(:grading_period, :stream_item)).
|
||||
and_yield([submission])
|
||||
end
|
||||
|
||||
it 'sets grade_posting_in_progress to false when absent' do
|
||||
expect(assignment).to receive(:save_grade_to_submission).
|
||||
with([submission], student, nil, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
|
||||
it 'sets grade_posting_in_progress to true when present' do
|
||||
expect(assignment).to receive(:save_grade_to_submission).
|
||||
with([submission], student, nil, grade: 10, grader: teacher, grade_posting_in_progress: true)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher, grade_posting_in_progress: true)
|
||||
end
|
||||
|
||||
it 'sets grade_posting_in_progress to false when present' do
|
||||
expect(assignment).to receive(:save_grade_to_submission).
|
||||
with([submission], student, nil, grade: 10, grader: teacher, grade_posting_in_progress: false)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher, grade_posting_in_progress: false)
|
||||
end
|
||||
end
|
||||
|
||||
it 'raises a GradeError when grader does not have permission' do
|
||||
expect {
|
||||
@assignment.grade_student(@user, grade: 42, grader: @teacher)
|
||||
assignment.grade_student(student, grade: 42, grader: student)
|
||||
}.to raise_error(Assignment::GradeError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a submission that has an existing grade' do
|
||||
it 'applies the late penalty' do
|
||||
Timecop.freeze do
|
||||
@assignment.update(points_possible: 100, due_at: 1.5.days.ago, submission_types: %w[online_text_entry])
|
||||
late_policy_factory(course: @course, deduct: 15.0, every: :day, missing: 80.0)
|
||||
@assignment.submit_homework(@user, submission_type: 'online_text_entry', body: 'foo')
|
||||
@assignment.grade_student(@user, grade: "100", grader: @teacher)
|
||||
@assignment.reload
|
||||
|
||||
expect(@assignment.submission_for_student(@user).grade).to eql('70')
|
||||
@assignment.grade_student(@user, grade: '70', grader: @teacher)
|
||||
expect(@assignment.submission_for_student(@user).grade).to eql('40')
|
||||
end
|
||||
around(:once) do |block|
|
||||
Timecop.freeze(now) do
|
||||
block.call
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a valid student' do
|
||||
before :once do
|
||||
@result = @assignment.grade_student(@user, grade: "10", grader: @teacher)
|
||||
@assignment.reload
|
||||
before(:once) do
|
||||
assignment.update!(points_possible: 100, due_at: 36.hours.ago(now), submission_types: %w[online_text_entry])
|
||||
late_policy_factory(course: course, deduct: 15.0, every: :day, missing: 80.0)
|
||||
assignment.submit_homework(student, submission_type: :online_text_entry, body: :foo)
|
||||
end
|
||||
|
||||
it 'returns an array' do
|
||||
expect(@result).to be_is_a(Array)
|
||||
it 'applies the late penalty to a full credit grade' do
|
||||
submission, * = assignment.grade_student(student, grade: "100", grader: teacher)
|
||||
expect(submission.grade).to eql('70')
|
||||
end
|
||||
|
||||
it 'applies the late penalty to a grade less than full credit' do
|
||||
submission, * = assignment.grade_student(student, grade: '70', grader: teacher)
|
||||
expect(submission.grade).to eql('40')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a submission' do
|
||||
subject_once { submissions }
|
||||
let_once(:submissions) { assignment.grade_student(student, grade: "10", grader: teacher) }
|
||||
|
||||
it { is_expected.to be_an Array }
|
||||
|
||||
it 'now has a submission' do
|
||||
expect(@assignment.submissions.size).to eql(1)
|
||||
assignment.reload
|
||||
expect(assignment.submissions.count).to be 1
|
||||
end
|
||||
|
||||
describe 'the submission after grading' do
|
||||
subject { @assignment.submissions.first }
|
||||
subject_once(:submission) { submissions.first }
|
||||
|
||||
describe '#state' do
|
||||
subject { super().state }
|
||||
it { is_expected.to eql(:graded) }
|
||||
it { expect(submission.state).to be :graded }
|
||||
end
|
||||
it { is_expected.to eq @result[0] }
|
||||
|
||||
describe '#score' do
|
||||
subject { super().score }
|
||||
it { is_expected.to eq 10.0 }
|
||||
it { expect(submission.score).to eq 10.0 }
|
||||
end
|
||||
|
||||
describe '#user_id' do
|
||||
subject { super().user_id }
|
||||
it { is_expected.to eq @user.id }
|
||||
it { expect(submission.user_id).to eq student.id }
|
||||
end
|
||||
|
||||
it 'has a version length of one' do
|
||||
expect(submission.versions.length).to eq 1
|
||||
end
|
||||
specify { expect(subject.versions.length).to eq 1 }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no student' do
|
||||
it 'raises an error' do
|
||||
expect { @assignment.grade_student(nil) }.to raise_error(Assignment::GradeError, 'Student is required')
|
||||
expect { assignment.grade_student(nil) }.to raise_error(Assignment::GradeError, 'Student is required')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a student that does not belong' do
|
||||
it 'raises an error' do
|
||||
expect { @assignment.grade_student(User.new) }.to raise_error(Assignment::GradeError, 'Student must be enrolled in the course as a student to be graded')
|
||||
expect { assignment.grade_student(User.new) }.to raise_error(Assignment::GradeError, 'Student must be enrolled in the course as a student to be graded')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an invalid initial grade' do
|
||||
before :once do
|
||||
@result = @assignment.grade_student(@user, grade: "{", grader: @teacher)
|
||||
@assignment.reload
|
||||
@result = assignment.grade_student(student, grade: "{", grader: teacher)
|
||||
assignment.reload
|
||||
end
|
||||
|
||||
it 'does not change the workflow_state to graded' do
|
||||
|
@ -1686,10 +1720,9 @@ describe Assignment do
|
|||
|
||||
context "moderated assignment" do
|
||||
let_once(:assignment) do
|
||||
@course.assignments.create!(moderated_grading: true, grader_count: 1, final_grader: @teacher)
|
||||
course.assignments.create!(moderated_grading: true, grader_count: 1, final_grader: teacher)
|
||||
end
|
||||
let_once(:student) { course_with_user("StudentEnrollment", course: @course, active_all: true, name: "Stu").user }
|
||||
let_once(:ta) { course_with_user("TaEnrollment", course: @course, active_all: true, name: "Ta").user }
|
||||
let_once(:ta) { course_with_user("TaEnrollment", course: course, active_all: true, name: "Ta").user }
|
||||
let(:pg) { @result.first.provisional_grades.find_by!(scorer: ta) }
|
||||
|
||||
before(:each) do
|
||||
|
@ -1740,8 +1773,8 @@ describe Assignment do
|
|||
|
||||
context 'with an excused assignment' do
|
||||
before :once do
|
||||
@result = @assignment.grade_student(@user, grader: @teacher, excuse: true)
|
||||
@assignment.reload
|
||||
@result = assignment.grade_student(student, grader: teacher, excuse: true)
|
||||
assignment.reload
|
||||
end
|
||||
|
||||
it 'excuses the assignment and marks it as graded' do
|
||||
|
@ -1753,18 +1786,18 @@ describe Assignment do
|
|||
|
||||
context 'with anonymous grading' do
|
||||
it 'explicitly sets anonymous grading if given' do
|
||||
@assignment.grade_student(@user, graded_anonymously: true, grade: "10", grader: @teacher)
|
||||
@assignment.reload
|
||||
expect(@assignment.submissions.first.graded_anonymously).to be_truthy
|
||||
assignment.grade_student(student, graded_anonymously: true, grade: "10", grader: teacher)
|
||||
assignment.reload
|
||||
expect(assignment.submissions.first.graded_anonymously).to be_truthy
|
||||
end
|
||||
|
||||
it 'does not set anonymous grading if not given' do
|
||||
@assignment.grade_student(@user, graded_anonymously: true, grade: "10", grader: @teacher)
|
||||
@assignment.reload
|
||||
@assignment.grade_student(@user, grade: "10", grader: @teacher)
|
||||
@assignment.reload
|
||||
assignment.grade_student(student, graded_anonymously: true, grade: "10", grader: teacher)
|
||||
assignment.reload
|
||||
assignment.grade_student(student, grade: "10", grader: teacher)
|
||||
assignment.reload
|
||||
# should still true because grade didn't actually change
|
||||
expect(@assignment.submissions.first.graded_anonymously).to be_truthy
|
||||
expect(assignment.submissions.first.graded_anonymously).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1887,7 +1920,6 @@ describe Assignment do
|
|||
end
|
||||
|
||||
describe 'AnonymousOrModerationEvent creation on grading a submission' do
|
||||
let_once(:course) { Course.create! }
|
||||
let_once(:assignment) do
|
||||
course.assignments.create!(
|
||||
anonymous_grading: true,
|
||||
|
@ -1896,10 +1928,6 @@ describe Assignment do
|
|||
)
|
||||
end
|
||||
|
||||
let_once(:student) { course.enroll_student(User.create!, active_all: true).user }
|
||||
let_once(:submission) { assignment.submission_for_student(student) }
|
||||
let_once(:teacher) { course.enroll_teacher(User.create!, enrollment_state: 'active').user }
|
||||
|
||||
let(:last_event) do
|
||||
AnonymousOrModerationEvent.where(assignment: assignment, event_type: 'submission_updated').last
|
||||
end
|
||||
|
@ -1929,7 +1957,7 @@ describe Assignment do
|
|||
end
|
||||
|
||||
it 'includes the affected submission on the event' do
|
||||
assignment.grade_student(student, grader: teacher, score: 75)
|
||||
submission, * = assignment.grade_student(student, grader: teacher, score: 75)
|
||||
expect(last_event.submission_id).to eq submission.id
|
||||
end
|
||||
|
||||
|
@ -1990,12 +2018,14 @@ describe Assignment do
|
|||
it "creates a submission_changed event when unexcusing the assignment" do
|
||||
moderated_assignment.grade_student(student, grader: teacher, provisional: true, excuse: true)
|
||||
moderated_assignment.grade_student(student, grader: teacher, provisional: true, score: 40)
|
||||
|
||||
expect(last_event.payload['excused']).to eq [true, false]
|
||||
end
|
||||
|
||||
it "does not capture score changes in the submission_changed event" do
|
||||
moderated_assignment.grade_student(student, grader: teacher, provisional: true, excuse: true)
|
||||
moderated_assignment.grade_student(student, grader: teacher, provisional: true, score: 40)
|
||||
|
||||
expect(last_event.payload).not_to include('score')
|
||||
end
|
||||
end
|
||||
|
@ -2011,22 +2041,14 @@ describe Assignment do
|
|||
end
|
||||
|
||||
describe "submission posting" do
|
||||
let(:course) { Course.create! }
|
||||
|
||||
let(:student) { course.enroll_student(User.create!, enrollment_state: 'active').user }
|
||||
let(:teacher) { course.enroll_teacher(User.create!, enrollment_state: 'active').user }
|
||||
|
||||
let(:assignment) { course.assignments.create!(title: "hi") }
|
||||
let(:submission) { assignment.submission_for_student(student) }
|
||||
|
||||
context "when the submission is unposted" do
|
||||
it "posts the submission if a grade is assigned" do
|
||||
assignment.grade_student(student, grader: teacher, score: 50)
|
||||
submission, * = assignment.grade_student(student, grader: teacher, score: 50)
|
||||
expect(submission).to be_posted
|
||||
end
|
||||
|
||||
it "posts the submission if an excusal is granted" do
|
||||
assignment.grade_student(student, grader: teacher, excused: true)
|
||||
submission, * = assignment.grade_student(student, grader: teacher, excused: true)
|
||||
expect(submission).to be_posted
|
||||
end
|
||||
|
||||
|
@ -2035,13 +2057,13 @@ describe Assignment do
|
|||
PostPolicy.enable_feature!
|
||||
|
||||
assignment.post_policy.update!(post_manually: true)
|
||||
assignment.grade_student(student, grader: teacher, score: 50)
|
||||
submission, * = assignment.grade_student(student, grader: teacher, score: 50)
|
||||
expect(submission).not_to be_posted
|
||||
end
|
||||
|
||||
it "does not post the submission for a muted assignment when post policies are not enabled" do
|
||||
assignment.mute!
|
||||
assignment.grade_student(student, grader: teacher, score: 50)
|
||||
submission, * = assignment.grade_student(student, grader: teacher, score: 50)
|
||||
expect(submission).not_to be_posted
|
||||
end
|
||||
|
||||
|
@ -2052,51 +2074,49 @@ describe Assignment do
|
|||
final_grader: teacher,
|
||||
grader_count: 2
|
||||
)
|
||||
moderated_assignment.grade_student(student, grader: teacher, provisional: true, score: 40)
|
||||
expect(moderated_assignment.submission_for_student(student)).not_to be_posted
|
||||
submission, * = moderated_assignment.grade_student(student, grader: teacher, provisional: true, score: 40)
|
||||
expect(submission).not_to be_posted
|
||||
end
|
||||
end
|
||||
|
||||
it "does not update the posted_at date for a previously-posted submission" do
|
||||
submission = assignment.submissions.find_by!(user: student)
|
||||
submission.update!(posted_at: 1.day.ago)
|
||||
|
||||
expect {
|
||||
assignment.grade_student(student, grader: teacher, score: 50)
|
||||
}.not_to change {
|
||||
assignment.submission_for_student(student).posted_at
|
||||
submission.reload.posted_at
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "grade change audit records" do
|
||||
let(:student) { @course.enroll_student(User.create!, enrollment_state: :active).user }
|
||||
let(:teacher) { @course.enroll_teacher(User.create!, enrollment_state: :active).user }
|
||||
|
||||
context "when post policies are enabled" do
|
||||
before(:once) do
|
||||
PostPolicy.enable_feature!
|
||||
@course.enable_feature!(:new_gradebook)
|
||||
course.enable_feature!(:new_gradebook)
|
||||
end
|
||||
|
||||
context "when assignment posts manually" do
|
||||
before(:each) do
|
||||
@assignment.ensure_post_policy(post_manually: true)
|
||||
assignment.ensure_post_policy(post_manually: true)
|
||||
end
|
||||
|
||||
it "inserts a record" do
|
||||
expect(Auditors::GradeChange::Stream).to receive(:insert).once
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
|
||||
context "when assignment posts automatically" do
|
||||
before(:each) do
|
||||
@assignment.ensure_post_policy(post_manually: false)
|
||||
assignment.ensure_post_policy(post_manually: false)
|
||||
end
|
||||
|
||||
it "inserts a record" do
|
||||
expect(Auditors::GradeChange::Stream).to receive(:insert).once
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2108,57 +2128,57 @@ describe Assignment do
|
|||
|
||||
context "when assignment is muted" do
|
||||
before(:each) do
|
||||
@assignment.mute!
|
||||
assignment.mute!
|
||||
end
|
||||
|
||||
it "inserts a record" do
|
||||
expect(Auditors::GradeChange::Stream).to receive(:insert).once
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
|
||||
context "when assignment is unmuted" do
|
||||
before(:each) do
|
||||
@assignment.unmute!
|
||||
assignment.unmute!
|
||||
end
|
||||
|
||||
it "inserts a record" do
|
||||
expect(Auditors::GradeChange::Stream).to receive(:insert).once
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "grade change live events" do
|
||||
let(:student) { @course.enroll_student(User.create!, enrollment_state: :active).user }
|
||||
let(:teacher) { @course.enroll_teacher(User.create!, enrollment_state: :active).user }
|
||||
let(:student) { course.enroll_student(User.create!, enrollment_state: :active).user }
|
||||
let(:teacher) { course.enroll_teacher(User.create!, enrollment_state: :active).user }
|
||||
|
||||
context "when post policies are enabled" do
|
||||
before(:once) do
|
||||
PostPolicy.enable_feature!
|
||||
@course.enable_feature!(:new_gradebook)
|
||||
course.enable_feature!(:new_gradebook)
|
||||
end
|
||||
|
||||
context "when assignment posts manually" do
|
||||
before(:each) do
|
||||
@assignment.ensure_post_policy(post_manually: true)
|
||||
assignment.ensure_post_policy(post_manually: true)
|
||||
end
|
||||
|
||||
it "emits an event" do
|
||||
expect(Canvas::LiveEvents).to receive(:grade_changed).once
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
|
||||
context "when assignment posts automatically" do
|
||||
before(:each) do
|
||||
@assignment.ensure_post_policy(post_manually: false)
|
||||
assignment.ensure_post_policy(post_manually: false)
|
||||
end
|
||||
|
||||
it "emits two events when grading: one for grading and one for posting" do
|
||||
expect(Canvas::LiveEvents).to receive(:grade_changed).twice
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2170,23 +2190,23 @@ describe Assignment do
|
|||
|
||||
context "when assignment is muted" do
|
||||
before(:each) do
|
||||
@assignment.mute!
|
||||
assignment.mute!
|
||||
end
|
||||
|
||||
it "emits an event" do
|
||||
expect(Canvas::LiveEvents).to receive(:grade_changed).once
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
|
||||
context "when assignment is unmuted" do
|
||||
before(:each) do
|
||||
@assignment.unmute!
|
||||
assignment.unmute!
|
||||
end
|
||||
|
||||
it "emits an event" do
|
||||
expect(Canvas::LiveEvents).to receive(:grade_changed).once
|
||||
@assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
assignment.grade_student(student, grade: 10, grader: teacher)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -270,63 +270,66 @@ describe ModeratedGrading::ProvisionalGrade do
|
|||
|
||||
describe "grade_matches_current_submission" do
|
||||
it "returns true if the grade is newer than the submission" do
|
||||
sub = nil
|
||||
submission = nil
|
||||
Timecop.freeze(10.minutes.ago) do
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
end
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
expect(pg.reload.grade_matches_current_submission).to eq true
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
expect(provisional_grade.reload.grade_matches_current_submission).to eq true
|
||||
end
|
||||
|
||||
it "returns false if the submission is newer than the grade" do
|
||||
sub = nil
|
||||
pg = nil
|
||||
submission = nil
|
||||
provisional_grade = nil
|
||||
Timecop.freeze(10.minutes.ago) do
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
end
|
||||
assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'resubmit')
|
||||
expect(pg.reload.grade_matches_current_submission).to eq false
|
||||
assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'resubmit')
|
||||
expect(provisional_grade.reload.grade_matches_current_submission).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
describe 'unique constraint' do
|
||||
it "disallows multiple provisional grades from the same user" do
|
||||
pg1 = submission.provisional_grades.build(score: 75)
|
||||
pg1.scorer = scorer
|
||||
pg1.save!
|
||||
pg2 = submission.provisional_grades.build(score: 80)
|
||||
pg2.scorer = scorer
|
||||
expect { pg2.save! }.to raise_error(ActiveRecord::RecordNotUnique)
|
||||
first_provisional_grade = submission.provisional_grades.build(score: 75)
|
||||
first_provisional_grade.scorer = scorer
|
||||
first_provisional_grade.save!
|
||||
second_provisional_grade = submission.provisional_grades.build(score: 80)
|
||||
second_provisional_grade.scorer = scorer
|
||||
expect { second_provisional_grade.save! }.to raise_error(ActiveRecord::RecordNotUnique)
|
||||
end
|
||||
|
||||
it "disallows multiple final provisional grades" do
|
||||
pg1 = submission.provisional_grades.build(score: 75, final: false)
|
||||
pg1.scorer = scorer
|
||||
pg1.save!
|
||||
pg2 = submission.provisional_grades.build(score: 75, final: true)
|
||||
pg2.scorer = scorer
|
||||
pg2.save!
|
||||
pg3 = submission.provisional_grades.build(score: 80, final: true)
|
||||
pg3.scorer = User.create!
|
||||
expect { pg3.save! }.to raise_error(ActiveRecord::RecordNotUnique)
|
||||
first_provisional_grade = submission.provisional_grades.build(score: 75, final: false)
|
||||
first_provisional_grade.scorer = scorer
|
||||
first_provisional_grade.save!
|
||||
second_provisional_grade = submission.provisional_grades.build(score: 75, final: true)
|
||||
second_provisional_grade.scorer = scorer
|
||||
second_provisional_grade.save!
|
||||
third_provisional_grade = submission.provisional_grades.build(score: 80, final: true)
|
||||
third_provisional_grade.scorer = User.create!
|
||||
expect { third_provisional_grade.save! }.to raise_error(ActiveRecord::RecordNotUnique)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#graded_at when a grade changes' do
|
||||
it { expect(provisional_grade.graded_at).to be_nil }
|
||||
|
||||
it 'updates the graded_at timestamp when changing grade' do
|
||||
Timecop.freeze(@now) do
|
||||
provisional_grade.update_attributes(grade: 'B')
|
||||
expect(provisional_grade.graded_at).to eql @now
|
||||
end
|
||||
end
|
||||
|
||||
it 'updates the graded_at timestamp when changing score' do
|
||||
Timecop.freeze(@now) do
|
||||
provisional_grade.update_attributes(score: 80)
|
||||
expect(provisional_grade.graded_at).to eql @now
|
||||
end
|
||||
end
|
||||
|
||||
it 'updated graded_at when force_save is set, regardless of whether the grade actually changed' do
|
||||
Timecop.freeze(@now) do
|
||||
provisional_grade.force_save = true
|
||||
|
@ -338,102 +341,133 @@ describe ModeratedGrading::ProvisionalGrade do
|
|||
|
||||
describe 'infer_grade' do
|
||||
it 'infers a grade if only score is given' do
|
||||
pg = submission.find_or_create_provisional_grade!(scorer, score: 0)
|
||||
expect(pg.grade).not_to be_nil
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 0)
|
||||
expect(provisional_grade.grade).not_to be_nil
|
||||
end
|
||||
|
||||
it 'leaves grade nil if score is nil' do
|
||||
pg = submission.find_or_create_provisional_grade! scorer
|
||||
expect(pg.grade).to be_nil
|
||||
provisional_grade = submission.find_or_create_provisional_grade! scorer
|
||||
expect(provisional_grade.grade).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "publish_rubric_assessments!" do
|
||||
it "publishes rubric assessments to the submission" do
|
||||
@course = course
|
||||
outcome_with_rubric
|
||||
association = @rubric.associate_with(assignment, course, :purpose => 'grading', :use_for_grading => true)
|
||||
outcome_with_rubric(course: course)
|
||||
association = @rubric.associate_with(assignment, course, purpose: 'grading', use_for_grading: true)
|
||||
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
|
||||
prov_assmt = association.assess(:user => student, :assessor => scorer, :artifact => pg,
|
||||
:assessment => { :assessment_type => 'grading',
|
||||
:"criterion_#{@rubric.criteria_object.first.id}" => { :points => 3, :comments => "good 4 u" } })
|
||||
provisional_assessment = association.assess(
|
||||
user: student,
|
||||
assessor: scorer,
|
||||
artifact: provisional_grade,
|
||||
assessment: {
|
||||
assessment_type: 'grading',
|
||||
:"criterion_#{@rubric.criteria_object.first.id}" => {
|
||||
points: 3,
|
||||
comments: "good 4 u"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
expect(provisional_assessment.score).to eq 3
|
||||
|
||||
expect(prov_assmt.score).to eq 3
|
||||
|
||||
pg.publish!
|
||||
|
||||
real_assmt = sub.rubric_assessments.first
|
||||
expect(real_assmt.score).to eq 3
|
||||
expect(real_assmt.assessor).to eq scorer
|
||||
expect(real_assmt.rubric_association).to eq association
|
||||
expect(real_assmt.data).to eq prov_assmt.data
|
||||
provisional_grade.publish!
|
||||
real_assessment = submission.rubric_assessments.first
|
||||
expect(real_assessment.score).to eq 3
|
||||
expect(real_assessment.assessor).to eq scorer
|
||||
expect(real_assessment.rubric_association).to eq association
|
||||
expect(real_assessment.data).to eq provisional_assessment.data
|
||||
end
|
||||
|
||||
it "posts learning outcome results" do
|
||||
@course = course
|
||||
outcome_with_rubric
|
||||
association = @rubric.associate_with(assignment, course, :purpose => 'grading', :use_for_grading => true)
|
||||
outcome_with_rubric(course: course)
|
||||
association = @rubric.associate_with(assignment, course, purpose: 'grading', use_for_grading: true)
|
||||
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
|
||||
expect do
|
||||
association.assess(:user => student, :assessor => scorer, :artifact => pg,
|
||||
:assessment => { :assessment_type => 'grading',
|
||||
:"criterion_#{@rubric.criteria_object.first.id}" => { :points => 3, :comments => "good 4 u" } })
|
||||
association.assess(
|
||||
user: student,
|
||||
assessor: scorer,
|
||||
artifact: provisional_grade,
|
||||
assessment: {
|
||||
assessment_type: 'grading',
|
||||
:"criterion_#{@rubric.criteria_object.first.id}" => {
|
||||
points: 3,
|
||||
comments: "good 4 u"
|
||||
}
|
||||
}
|
||||
)
|
||||
end.to change { LearningOutcomeResult.count }.by(0)
|
||||
|
||||
expect { provisional_grade.publish!}.to change { LearningOutcomeResult.count }.by(1)
|
||||
end
|
||||
|
||||
expect do
|
||||
pg.publish!
|
||||
end.to change { LearningOutcomeResult.count }.by(1)
|
||||
it "sets grade_posting_in_progress on the rubric_assessment's submission" do
|
||||
outcome_with_rubric(course: course)
|
||||
association = @rubric.associate_with(assignment, course, purpose: 'grading', use_for_grading: true)
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
provisional_grade.submission.grade_posting_in_progress = true
|
||||
|
||||
association.assess(
|
||||
user: student,
|
||||
assessor: scorer,
|
||||
artifact: provisional_grade,
|
||||
assessment: {
|
||||
assessment_type: :grading,
|
||||
:"criterion_#{@rubric.criteria_object.first.id}" => {
|
||||
points: 3,
|
||||
comments: "good 4 u"
|
||||
}
|
||||
}
|
||||
)
|
||||
provisional_grade.publish!
|
||||
expect(submission.reload.score).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
describe "publish!" do
|
||||
it "sets the submission as 'graded'" do
|
||||
assignment.update!(moderated_grading: true, grader_count: 2)
|
||||
sub = submission_model(assignment: assignment, user: student)
|
||||
provisional_grade = sub.find_or_create_provisional_grade!(scorer, score: 80, graded_anonymously: true)
|
||||
|
||||
submission = submission_model(assignment: assignment, user: student)
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 80, graded_anonymously: true)
|
||||
provisional_grade.publish!
|
||||
sub.reload
|
||||
submission.reload
|
||||
|
||||
expect(sub.workflow_state).to eq 'graded'
|
||||
expect(submission.workflow_state).to eq 'graded'
|
||||
end
|
||||
|
||||
it "updates the submission with provisional grade attributes" do
|
||||
@course = course
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 80, graded_anonymously: true)
|
||||
sub.reload
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 80, graded_anonymously: true)
|
||||
submission.reload
|
||||
|
||||
expect(pg).to receive(:publish_rubric_assessments!).once
|
||||
pg.publish!
|
||||
sub.reload
|
||||
expect(provisional_grade).to receive(:publish_rubric_assessments!).once
|
||||
provisional_grade.publish!
|
||||
submission.reload
|
||||
|
||||
expect(sub.grade_matches_current_submission).to eq true
|
||||
expect(sub.graded_at).not_to be_nil
|
||||
expect(sub.grader_id).to eq scorer.id
|
||||
expect(sub.score).to eq 80
|
||||
expect(sub.grade).not_to be_nil
|
||||
expect(sub.graded_anonymously).to eq true
|
||||
expect(submission.grade_matches_current_submission).to eq true
|
||||
expect(submission.graded_at).not_to be_nil
|
||||
expect(submission.grader_id).to eq scorer.id
|
||||
expect(submission.score).to eq 80
|
||||
expect(submission.grade).not_to be_nil
|
||||
expect(submission.graded_anonymously).to eq true
|
||||
end
|
||||
|
||||
it "duplicates submission comments from the provisional grade to the submission" do
|
||||
@course = course
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
provisional_comment = sub.add_comment(commenter: scorer, comment: 'blah', provisional: true)
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
provisional_comment = submission.add_comment(commenter: scorer, comment: 'blah', provisional: true)
|
||||
|
||||
pg.publish!
|
||||
sub.reload
|
||||
provisional_grade.publish!
|
||||
submission.reload
|
||||
|
||||
real_comment = sub.submission_comments.first
|
||||
real_comment = submission.submission_comments.first
|
||||
expect(real_comment.provisional_grade_id).to be_nil
|
||||
expect(real_comment.author).to eq scorer
|
||||
expect(real_comment.comment).to eq provisional_comment.comment
|
||||
|
@ -441,44 +475,42 @@ describe ModeratedGrading::ProvisionalGrade do
|
|||
end
|
||||
|
||||
it "shares attachments between duplicated submission comments" do
|
||||
@course = course
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
file = assignment.attachments.create! uploaded_data: default_uploaded_data
|
||||
provisional_comment = sub.add_comment(commenter: scorer, comment: 'blah', provisional: true, attachments: [file])
|
||||
provisional_comment = submission.add_comment(commenter: scorer, comment: 'blah', provisional: true, attachments: [file])
|
||||
|
||||
pg.publish!
|
||||
sub.reload
|
||||
provisional_grade.publish!
|
||||
submission.reload
|
||||
|
||||
real_comment = sub.submission_comments.first
|
||||
real_comment = submission.submission_comments.first
|
||||
expect(real_comment.attachments).to eq provisional_comment.attachments
|
||||
end
|
||||
|
||||
it "does not duplicate submission comments not associated with the provisional grade" do
|
||||
@course = course
|
||||
sub = assignment.submit_homework(student, :submission_type => 'online_text_entry', :body => 'hallo')
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
sub.add_comment(commenter: scorer, comment: 'provisional', provisional: true)
|
||||
sub.add_comment(commenter: scorer, comment: 'normal', provisional: false)
|
||||
submission = assignment.submit_homework(student, submission_type: 'online_text_entry', body: 'hallo')
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
submission.add_comment(commenter: scorer, comment: 'provisional', provisional: true)
|
||||
submission.add_comment(commenter: scorer, comment: 'normal', provisional: false)
|
||||
|
||||
pg.publish!
|
||||
sub.reload
|
||||
provisional_grade.publish!
|
||||
submission.reload
|
||||
|
||||
expect(sub.submission_comments.map(&:comment)).to match_array(['provisional', 'normal'])
|
||||
expect(submission.submission_comments.map(&:comment)).to match_array(['provisional', 'normal'])
|
||||
end
|
||||
|
||||
it "triggers GradeCalculator#recompute_final_score by default" do
|
||||
sub = assignment.submit_homework(student, submission_type: "online_text_entry", body: "hello")
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
submission = assignment.submit_homework(student, submission_type: "online_text_entry", body: "hello")
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
expect(GradeCalculator).to receive(:recompute_final_score).once
|
||||
pg.publish!
|
||||
provisional_grade.publish!
|
||||
end
|
||||
|
||||
it "does not triggers GradeCalculator#recompute_final_score if passed skip_grade_calc true" do
|
||||
sub = assignment.submit_homework(student, submission_type: "online_text_entry", body: "hello")
|
||||
pg = sub.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
submission = assignment.submit_homework(student, submission_type: "online_text_entry", body: "hello")
|
||||
provisional_grade = submission.find_or_create_provisional_grade!(scorer, score: 1)
|
||||
expect(GradeCalculator).not_to receive(:recompute_final_score)
|
||||
pg.publish!(skip_grade_calc: true)
|
||||
provisional_grade.publish!(skip_grade_calc: true)
|
||||
end
|
||||
|
||||
it 'does not create a duplicate submission comment created event when a provisional grade is published' do
|
||||
|
|
|
@ -495,6 +495,53 @@ describe RubricAssessment do
|
|||
end
|
||||
|
||||
describe '#update_artifact' do
|
||||
describe 'grade_posting_in_progress' do
|
||||
subject_once(:ra) do
|
||||
RubricAssessment.new(
|
||||
score: 2.0,
|
||||
assessment_type: :grading,
|
||||
rubric: rubric,
|
||||
artifact: submission,
|
||||
assessor: @teacher
|
||||
)
|
||||
end
|
||||
|
||||
let_once(:rubric) { rubric_model }
|
||||
let_once(:submission) { @assignment.submissions.find_by!(user: @student) }
|
||||
|
||||
before do
|
||||
submission.score = 1
|
||||
ra.build_rubric_association(
|
||||
use_for_grading: true,
|
||||
association_object: @assignment
|
||||
)
|
||||
end
|
||||
|
||||
it 'is nil by default' do
|
||||
expect(@assignment).to receive(:grade_student).with(
|
||||
ra.submission.student,
|
||||
score: ra.score,
|
||||
grader: ra.assessor,
|
||||
graded_anonymously: nil,
|
||||
grade_posting_in_progress: nil
|
||||
)
|
||||
ra.save!
|
||||
end
|
||||
|
||||
it 'passes grade_posting_in_progress from submission' do
|
||||
submission.grade_posting_in_progress = true
|
||||
|
||||
expect(@assignment).to receive(:grade_student).with(
|
||||
ra.submission.student,
|
||||
score: ra.score,
|
||||
grader: ra.assessor,
|
||||
graded_anonymously: nil,
|
||||
grade_posting_in_progress: submission.grade_posting_in_progress
|
||||
)
|
||||
ra.save!
|
||||
end
|
||||
end
|
||||
|
||||
it 'should set group on submission' do
|
||||
group_category = @course.group_categories.create!(name: "Test Group Set")
|
||||
group = @course.groups.create!(name: "Group A", group_category: group_category)
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#
|
||||
# Copyright (C) 2019 - 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 '../../common'
|
||||
require_relative '../pages/moderate_page'
|
||||
require_relative '../pages/speedgrader_page'
|
||||
|
||||
describe 'Moderated Marking' do
|
||||
include_context 'in-process server selenium tests'
|
||||
|
||||
let_once(:account) do
|
||||
account = Account.default
|
||||
account.enable_feature!(:moderated_grading)
|
||||
account
|
||||
end
|
||||
|
||||
let_once(:course) do
|
||||
course = account.courses.create!
|
||||
course.offer!
|
||||
course
|
||||
end
|
||||
|
||||
let_once(:teacher) { teacher_in_course(course: course, active_enrollment: true).user }
|
||||
let_once(:ta) { ta_in_course(course: course, active_enrollment: true).user }
|
||||
let_once(:student) { student_in_course(course: course, active_enrollment: true).user }
|
||||
|
||||
let_once(:assignment) do
|
||||
course.assignments.create!(
|
||||
final_grader: teacher,
|
||||
grader_count: 2,
|
||||
moderated_grading: true,
|
||||
points_possible: 10,
|
||||
submission_types: :online_text_entry,
|
||||
title:'Moderated Assignment',
|
||||
)
|
||||
end
|
||||
|
||||
context 'moderation page' do
|
||||
it 'allows viewing provisional grades and releasing final grade' do
|
||||
rubric = outcome_with_rubric
|
||||
association = rubric.associate_with(assignment, course, purpose: 'grading')
|
||||
association.update!(use_for_grading: true)
|
||||
assignment.submit_homework(student, submission_type: :online_text_entry, body: :asdf)
|
||||
|
||||
user_session(ta)
|
||||
Speedgrader.visit(course.id, assignment.id)
|
||||
|
||||
scroll_into_view('.toggle_full_rubric')
|
||||
f('.toggle_full_rubric').click
|
||||
f('td.criterion_points input').send_keys('3')
|
||||
Speedgrader.expand_right_pane
|
||||
fj("span:contains('Amazing'):visible").click
|
||||
wait_for_ajaximations
|
||||
scroll_into_view('.save_rubric_button')
|
||||
f('#rubric_full .save_rubric_button').click
|
||||
wait_for_ajaximations
|
||||
|
||||
Speedgrader.grade_input.send_keys 10
|
||||
Speedgrader.grade_input.send_keys :tab
|
||||
wait_for_ajaximations
|
||||
|
||||
user_session(teacher)
|
||||
ModeratePage.visit(course.id, assignment.id)
|
||||
ModeratePage.select_provisional_grade_for_student_by_position(student, 1)
|
||||
ModeratePage.click_release_grades_button
|
||||
driver.switch_to.alert.accept
|
||||
expect_instui_flash_message "Grades were successfully released to the gradebook"
|
||||
wait_for_ajax_requests
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue