340 lines
13 KiB
Ruby
340 lines
13 KiB
Ruby
#
|
|
# Copyright (C) 2011 - 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 File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
|
|
|
|
describe SubmissionList do
|
|
it "should initialize with a course" do
|
|
course_model
|
|
expect{@sl = SubmissionList.new(@course)}.not_to raise_error
|
|
expect(@sl).to be_is_a(SubmissionList)
|
|
expect(@sl.course).to eql(@course)
|
|
|
|
expect{@sl = SubmissionList.new(-1)}.to raise_error(ArgumentError, "Must provide a course.")
|
|
end
|
|
|
|
it "should provide a dictionary in 'list'" do
|
|
course_model
|
|
expect(SubmissionList.new(@course).list).to be_is_a(Hashery::Dictionary)
|
|
end
|
|
|
|
it "should create keys in the data when versions of submissions existed" do
|
|
interesting_submission_list
|
|
expect(@sl.list.keys).to eql([Date.parse(Time.now.utc.to_s)])
|
|
end
|
|
|
|
it "should take the time zone into account when dividing grading history into days" do
|
|
course_with_teacher(:active_all => true)
|
|
course_with_student(:course => @course, :active_all => true)
|
|
|
|
@assignment1 = @course.assignments.create!(:title => 'one', :points_possible => 10)
|
|
@assignment2 = @course.assignments.create!(:title => 'two', :points_possible => 10)
|
|
@assignment3 = @course.assignments.create!(:title => 'three', :points_possible => 10)
|
|
|
|
Time.zone = 'Alaska'
|
|
allow(Time).to receive(:now).and_return(Time.utc(2011, 12, 31, 23, 0)) # 12/31 14:00 local time
|
|
@assignment1.grade_student(@student, {:grade => 10, :grader => @teacher})
|
|
allow(Time).to receive(:now).and_return(Time.utc(2012, 1, 1, 1, 0)) # 12/31 16:00 local time
|
|
@assignment2.grade_student(@student, {:grade => 10, :grader => @teacher})
|
|
allow(Time).to receive(:now).and_return(Time.utc(2012, 1, 1, 10, 0)) # 1/01 01:00 local time
|
|
@assignment3.grade_student(@student, {:grade => 10, :grader => @teacher})
|
|
allow(Time).to receive(:now).and_call_original
|
|
|
|
@days = SubmissionList.new(@course).days
|
|
expect(@days.size).to eq 2
|
|
expect(@days[0].date).to eq Date.new(2012, 1, 1)
|
|
expect(@days[0].graders[0].assignments.size).to eq 1
|
|
expect(@days[1].date).to eq Date.new(2011, 12, 31)
|
|
expect(@days[1].graders[0].assignments.size).to eq 2
|
|
end
|
|
|
|
it "handles excused assignments" do
|
|
course_with_teacher(:active_all => true)
|
|
course_with_student(:course => @course, :active_all => true)
|
|
|
|
@some_assignment = @course.assignments.create!(:title => 'one', :points_possible => 10)
|
|
subs = @some_assignment.grade_student(@student, {grade: 8, grader: @teacher})
|
|
subs.each { |s| s.created_at = 3.days.ago; s.updated_at = 3.days.ago; s.save }
|
|
@some_assignment.grade_student(@student, {excuse: true, grader: @teacher})
|
|
@days = SubmissionList.days(@course)
|
|
submissions = @days[0].graders[0].assignments[0].submissions
|
|
submissions.each do |sub|
|
|
expect(sub.current_grade).to eq("EX")
|
|
expect(sub.new_grade).to eq("EX")
|
|
end
|
|
end
|
|
|
|
context "named loops" do
|
|
|
|
before do
|
|
interesting_submission_data
|
|
end
|
|
|
|
it "should be able to loop on days" do
|
|
available_keys = [:graders, :date]
|
|
SubmissionList.days(@course).each do |day|
|
|
expect(day).to be_is_a(OpenStruct)
|
|
expect(day.send(:table).keys.size).to eql(available_keys.size)
|
|
available_keys.each {|k| expect(day.send(:table)).to be_include(k)}
|
|
expect(day.graders).to be_is_a(Array)
|
|
expect(day.date).to be_is_a(Date)
|
|
end
|
|
end
|
|
|
|
it "should be able to loop on graders" do
|
|
available_keys = [:grader_id, :assignments, :name]
|
|
SubmissionList.days(@course).each do |day|
|
|
day.graders.each do |grader|
|
|
expect(grader).to be_is_a(OpenStruct)
|
|
expect(grader.send(:table).keys.size).to eql(available_keys.size)
|
|
available_keys.each {|k| expect(grader.send(:table).keys).to be_include(k)}
|
|
expect(grader.grader_id).to be_is_a(Numeric)
|
|
expect(grader.assignments).to be_is_a(Array)
|
|
expect(grader.name).to be_is_a(String)
|
|
expect(grader.assignments[0].submissions[0].grader).to eql(grader.name)
|
|
expect(grader.assignments[0].submissions[0].grader_id).to eql(grader.grader_id)
|
|
end
|
|
end
|
|
end
|
|
|
|
it "should only keep one diff per grader per day" do
|
|
SubmissionList.days(@course).each do |day|
|
|
day.graders.each do |grader|
|
|
grader.assignments.each do |assignment|
|
|
expect(assignment.submissions.length).to eql assignment.submissions.map(&:student_name).uniq.length
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
it "should be able to loop on assignments" do
|
|
available_keys = [:submission_count, :name, :submissions, :assignment_id]
|
|
SubmissionList.days(@course).each do |day|
|
|
day.graders.each do |grader|
|
|
grader.assignments.each do |assignment|
|
|
expect(assignment).to be_is_a(OpenStruct)
|
|
expect(assignment.send(:table).keys.size).to eql(available_keys.size)
|
|
available_keys.each {|k| expect(assignment.send(:table).keys).to be_include(k)}
|
|
expect(assignment.submission_count).to eql(assignment.submissions.size)
|
|
expect(assignment.name).to be_is_a(String)
|
|
expect(assignment.name).to eql(assignment.submissions[0].assignment_name)
|
|
expect(assignment.submissions).to be_is_a(Array)
|
|
expect(assignment.assignment_id).to eql(assignment.submissions[0].assignment_id)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "submissions" do
|
|
it "should be able to loop on submissions" do
|
|
available_keys = [
|
|
:assignment_id, :assignment_name, :attachment_id, :attachment_ids,
|
|
:body, :course_id, :created_at, :current_grade, :current_graded_at,
|
|
:current_grader, :grade_matches_current_submission, :graded_at,
|
|
:graded_on, :grader, :grader_id, :group_id, :id, :new_grade,
|
|
:new_graded_at, :new_grader, :previous_grade, :previous_graded_at,
|
|
:previous_grader, :processed, :published_grade,
|
|
:published_score, :safe_grader_id, :score, :student_entered_score,
|
|
:student_user_id, :submission_id, :student_name, :submission_type,
|
|
:updated_at, :url, :user_id, :workflow_state
|
|
]
|
|
|
|
SubmissionList.days(@course).each do |day|
|
|
day.graders.each do |grader|
|
|
grader.assignments.each do |assignment|
|
|
assignment.submissions.each do |submission|
|
|
expect(submission).to be_is_a(OpenStruct)
|
|
expect(submission.send(:table).keys.size).to eql(available_keys.size)
|
|
available_keys.each {|k| expect(submission.send(:table).keys).to be_include(k)}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
it "sorts submissions alphabetically by student name" do
|
|
day = SubmissionList.days(@course)[0]
|
|
submissions = day.graders[0].assignments[0].submissions
|
|
expect(submissions[0].student_name).to eql('student')
|
|
expect(submissions[1].student_name).to eql('studeñt')
|
|
expect(submissions[2].student_name).to eql('studeЖt')
|
|
end
|
|
end
|
|
end
|
|
|
|
context "regrading" do
|
|
it 'should include regrade events in the final data' do
|
|
# Figure out how to manually regrade a test piece of data
|
|
interesting_submission_data
|
|
@assignment = @course.assignments.create!(title: 'some_assignment')
|
|
@quiz = Quizzes::Quiz.create!({:context => @course, title: "quiz time", points_possible: 10, assignment_id: @assignment.id, quiz_type: "assignment"})
|
|
@quiz.workflow_state = 'published'
|
|
@quiz.quiz_data = [multiple_choice_question_data]
|
|
@quiz.save!
|
|
@qs = @quiz.generate_submission(@student)
|
|
|
|
@points = 15.0
|
|
|
|
@question = double(:id => 1, :question_data => {:id => 1,
|
|
:regrade_option => 'full_credit',
|
|
:points_possible => @points},
|
|
:quiz_group => nil )
|
|
|
|
@question_regrade = double(:quiz_question => @question,
|
|
:regrade_option => "full_credit" )
|
|
|
|
@answer = { :question_id => 1, :points => @points, :text => ""}
|
|
|
|
@wrapper = Quizzes::QuizRegrader::Answer.new(@answer, @question_regrade)
|
|
Quizzes::SubmissionGrader.new(@qs).grade_submission
|
|
@qs.score_before_regrade = 5.0
|
|
@qs.score = 4.0
|
|
@qs.attempt = 1
|
|
@qs.with_versioning(true, &:save!)
|
|
@qs.save!
|
|
|
|
expect(@qs.score_before_regrade).to eq 5.0
|
|
expect(@qs.score).to eq 4.0
|
|
|
|
|
|
@sl = SubmissionList.days(@course)
|
|
regrades = []
|
|
@sl.each do |day|
|
|
day.graders.each do |grader|
|
|
grader.assignments.each do |assignment|
|
|
assignment.submissions.each do |submission|
|
|
regrades.push submission.score_before_regrade if submission
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
expect(regrades.include?(5.0)).to be_truthy
|
|
end
|
|
end
|
|
|
|
context "remembers the most recent grade change" do
|
|
let(:grader) { User.create name: 'some_grader' }
|
|
let(:student) { User.create name: "some student", workflow_state: "registered" }
|
|
let(:course) { Course.create name: "some course", workflow_state: "available" }
|
|
let(:list) { SubmissionList.new course }
|
|
|
|
let(:assignment) do
|
|
course.assignments.create title: "some assignment",
|
|
points_possible: 10,
|
|
workflow_state: "published"
|
|
end
|
|
|
|
let(:submission) do
|
|
list.days.first.
|
|
graders.first.
|
|
assignments.first.
|
|
submissions.first
|
|
end
|
|
|
|
let!(:enroll_teacher_and_student) do
|
|
course.enroll_teacher(grader).accept
|
|
course.enroll_student student
|
|
end
|
|
|
|
context "when the grade is not blank" do
|
|
let!(:grade_assignment) do
|
|
assignment.grade_student student, {grade: 5, grader: grader}
|
|
assignment.grade_student student, {grade: 3, grader: grader}
|
|
end
|
|
|
|
it "remembers the 'Before' grade " do
|
|
expect(submission.previous_grade).to eq "5"
|
|
end
|
|
it "remembers the 'After' grade" do
|
|
expect(submission.new_grade).to eq "3"
|
|
end
|
|
it "remembers the 'Current' grade" do
|
|
expect(submission.current_grade).to eq "3"
|
|
end
|
|
end
|
|
|
|
context "when the grade is blank" do
|
|
let!(:grade_assignment) do
|
|
assignment.grade_student student, {grade: 6, grader: grader}
|
|
assignment.grade_student student, {grade: 7, grader: grader}
|
|
assignment.grade_student student, {grade: "", grader: grader}
|
|
end
|
|
|
|
it "remembers the 'Before' grade" do
|
|
expect(submission.previous_grade).to eq "7"
|
|
end
|
|
it "remembers the 'After' grade" do
|
|
expect(submission.new_grade).to be_blank
|
|
end
|
|
it "remembers the 'Current' grade" do
|
|
expect(submission.current_grade).to be_blank
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
def interesting_submission_list(opts={})
|
|
interesting_submission_data(opts)
|
|
@course.reload
|
|
@sl = SubmissionList.new(@course)
|
|
end
|
|
|
|
def interesting_submission_data(opts={})
|
|
opts[:grader] ||= {}
|
|
opts[:user] ||= {}
|
|
opts[:course] ||= {}
|
|
opts[:assignment] ||= {}
|
|
opts[:submission] ||= {}
|
|
|
|
@grader = user_model({:name => 'some_grader'}.merge(opts[:grader]))
|
|
@grader2 = user_model({:name => 'another_grader'}.merge(opts[:grader]))
|
|
@student = factory_with_protected_attributes(User, {:name => "studeñt", :workflow_state => "registered"}.merge(opts[:user]))
|
|
@course = factory_with_protected_attributes(Course, {:name => "some course", :workflow_state => "available"}.merge(opts[:course]))
|
|
[@grader, @grader2].each do |grader|
|
|
e = @course.enroll_teacher(grader)
|
|
e.accept
|
|
end
|
|
@course.enroll_student(@student)
|
|
@assignment = @course.assignments.new({
|
|
:title => "some assignment",
|
|
:points_possible => 10
|
|
}.merge(opts[:assignment]))
|
|
@assignment.workflow_state = "published"
|
|
@assignment.save!
|
|
@assignment.grade_student(@student, {:grade => 1.5, :grader => @grader}.merge(opts[:submission]))
|
|
@assignment.grade_student(@student, {:grade => 3, :grader => @grader}.merge(opts[:submission]))
|
|
@assignment.grade_student(@student, {:grade => 5, :grader => @grader2}.merge(opts[:submission]))
|
|
@student = user_model(:name => 'studeЖt')
|
|
@course.enroll_student(@student)
|
|
@assignment.reload
|
|
@assignment.grade_student(@student, {:grade => 8, :grader => @grader}.merge(opts[:submission]))
|
|
@student = user_model(:name => 'student')
|
|
@course.enroll_student(@student)
|
|
@assignment.reload
|
|
@assignment.grade_student(@student, {:grade => 10, :grader => @grader}.merge(opts[:submission]))
|
|
@assignment = @course.assignments.create({
|
|
:title => "another assignment",
|
|
:points_possible => 10
|
|
})
|
|
@assignment.workflow_state = "published"
|
|
@assignment.save!
|
|
@assignment.grade_student(@student, {:grade => 10, :grader => @grader}.merge(opts[:submission]))
|
|
end
|