canvas-lms/spec/controllers/anonymous_submissions_contr...

368 lines
14 KiB
Ruby

#
# Copyright (C) 2018 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require_relative '../spec_helper'
RSpec.describe AnonymousSubmissionsController do
it_behaves_like 'a submission update action', :anonymous_submissions
describe "GET show" do
before do
course_with_student_and_submitted_homework
@course.account.enable_service(:avatars)
@context = @course
@assignment.update!(anonymous_grading: true)
@submission.update!(score: 10)
@assignment.unmute!
end
let(:body) { JSON.parse(response.body)['submission'] }
it "renders show template" do
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id }
expect(response).to render_template('submissions/show')
end
it "renders json with scores for teachers" do
request.accept = Mime[:json].to_s
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id}, format: :json
expect(body['anonymous_id']).to eq @submission.anonymous_id
expect(body['score']).to eq 10
expect(body['grade']).to eq '10'
expect(body['published_grade']).to eq '10'
expect(body['published_score']).to eq 10
end
it "renders json with scores for students" do
user_session(@student)
request.accept = Mime[:json].to_s
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id}, format: :json
expect(body['anonymous_id']).to eq @submission.anonymous_id
expect(body['score']).to eq 10
expect(body['grade']).to eq '10'
expect(body['published_grade']).to eq '10'
expect(body['published_score']).to eq 10
end
it "mark read if reading one's own submission" do
user_session(@student)
request.accept = Mime[:json].to_s
@submission.mark_unread(@student)
@submission.save!
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id}, format: :json
expect(response).to be_successful
submission = Submission.find(@submission.id)
expect(submission.read?(@student)).to be_truthy
end
it "don't mark read if reading someone else's submission" do
user_session(@teacher)
request.accept = Mime[:json].to_s
@submission.mark_unread(@student)
@submission.mark_unread(@teacher)
@submission.save!
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id}, format: :json
expect(response).to be_successful
submission = Submission.find(@submission.id)
expect(submission.read?(@student)).to be_falsey
expect(submission.read?(@teacher)).to be_falsey
end
it "renders json with a not-found error for teachers when the assignment is anonymous and muted" do
@student.update!(name: 'some student')
user_session(@teacher)
@assignment.update!(muted: true)
request.accept = Mime[:json].to_s
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id}, format: :json
# render_user_not_found attempts to render the passed-in ID param and ignores anonymous_id
expect(JSON.parse(response.body)['errors']).to eq "The specified user () is not a student in this course"
end
it "renders json without scores for students on muted assignments" do
user_session(@student)
@assignment.update!(muted: true)
request.accept = Mime[:json].to_s
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id}, format: :json
expect(body['anonymous_id']).to eq @submission.anonymous_id
expect(body['score']).to be nil
expect(body['grade']).to be nil
expect(body['published_grade']).to be nil
expect(body['published_score']).to be nil
end
it "should show rubric assessments to peer reviewers" do
course_with_student(active_all: true)
@course.account.enable_service(:avatars)
@assessor = @student
outcome_with_rubric
@association = @rubric.associate_with @assignment, @context, :purpose => 'grading'
@assignment.peer_reviews = true
@assignment.save!
@assignment.assign_peer_review(@assessor, @submission.user)
@assessment = @association.assess(:assessor => @assessor, :user => @submission.user, :artifact => @submission, :assessment => { :assessment_type => 'grading'})
user_session(@assessor)
get :show, params: {course_id: @context.id, assignment_id: @assignment.id, anonymous_id: @submission.anonymous_id}
expect(response).to be_successful
expect(assigns[:visible_rubric_assessments]).to eq [@assessment]
end
it "redirects to the course page if the viewer may not view details for the submission" do
course = Course.create!
assignment = course.assignments.create!(title: 'hi')
student1 = course.enroll_student(User.create!, active_all: true).user
student2 = course.enroll_student(User.create!, active_all: true).user
student1_submission = assignment.submission_for_student(student1)
user_session(student2)
get :show, params: {course_id: course.id, assignment_id: assignment.id, anonymous_id: student1_submission.anonymous_id}
expect(response).to redirect_to(course_assignment_url(course, assignment))
end
end
context 'originality report' do
let(:account) { Account.default }
let(:course) do
course = account.courses.create!
course.account.enable_service(:avatars)
course.enroll_teacher(teacher, enrollment_state: 'active')
course.enroll_student(student, enrollment_state: 'active')
course
end
let(:teacher) { User.create! }
let(:student) { User.create! }
let(:assignment) { course.assignments.create!(title: 'test assignment') }
let(:attachment) { student.attachments.create!(filename: "submission.doc", uploaded_data: default_uploaded_data) }
let(:submission) { assignment.submit_homework(student, attachments: [attachment]) }
let!(:originality_report) do
OriginalityReport.create!(
attachment: attachment,
submission: submission,
originality_score: 0.5,
originality_report_url: 'http://www.instructure.com'
)
end
before { user_session(teacher) }
describe 'GET originality_report' do
it 'redirects to the originality report URL if it exists' do
get 'originality_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: attachment.asset_string
}
expect(response).to redirect_to originality_report.originality_report_url
end
it 'shows a notice if no URL is present for the OriginalityReport' do
originality_report.update!(originality_report_url: nil)
get 'originality_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: attachment.asset_string
}
expect(flash[:error]).to be_present
end
it 'redirects to SpeedGrader if no URL is present for the OriginalityReport' do
originality_report.update!(originality_report_url: nil)
get 'originality_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: attachment.asset_string
}
redirect_url = speed_grader_course_gradebook_url(
assignment.course,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id
)
expect(response).to redirect_to(redirect_url)
end
it 'returns an error if the assignment does not exist' do
get 'originality_report', params: {
course_id: assignment.context_id,
assignment_id: -1,
anonymous_id: '{ user_id }',
asset_string: attachment.asset_string
}
expect(response).to have_http_status(:not_found)
end
it 'returns an error if anonymous_id is not valid' do
get 'originality_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: '{ user_id }',
asset_string: attachment.asset_string
}
expect(response).to have_http_status(:bad_request)
end
it "returns unauthorized for users who can't read submission" do
unauthorized_user = User.create
user_session(unauthorized_user)
get 'originality_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: attachment.asset_string
}
expect(response).to have_http_status(:unauthorized)
end
end
describe 'POST resubmit_to_turnitin' do
it 'returns an error if assignment_id is not an integer' do
post 'resubmit_to_turnitin', params: {
course_id: assignment.context_id,
assignment_id: 'assignment-id',
anonymous_id: submission.anonymous_id
}
expect(response).to have_http_status(:bad_request)
end
it "returns an error if the assignment does not exist" do
post 'resubmit_to_turnitin', params: {
course_id: assignment.context_id,
assignment_id: -1,
anonymous_id: submission.anonymous_id,
}
expect(response).to have_http_status(:not_found)
end
it "returns an error if the anonymous_id does not exist" do
post 'resubmit_to_turnitin', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: '!?!?!',
}
expect(response).to have_http_status(:bad_request)
end
it "emits a 'plagiarism_resubmit' live event if originality report exists" do
expect(Canvas::LiveEvents).to receive(:plagiarism_resubmit)
post 'resubmit_to_turnitin', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id
}
end
it "emits a 'plagiarism_resubmit' live event if originality report does not exist" do
originality_report.destroy!
expect(Canvas::LiveEvents).to receive(:plagiarism_resubmit)
post 'resubmit_to_turnitin', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id
}
end
end
end
describe 'GET turnitin_report' do
let(:course) { Course.create! }
let(:student) { course.enroll_student(User.create!).user }
let(:teacher) { course.enroll_teacher(User.create!).user }
let(:assignment) do
course.assignments.create!(
anonymous_grading: true,
submission_types: 'online_text_entry',
title: 'hi'
)
end
let(:submission) { assignment.submit_homework(student, body: 'zzzzzzzzzz') }
let(:asset_string) { submission.id.to_s }
before { user_session(teacher) }
it 'returns bad_request if anonymous_id is not valid' do
get 'turnitin_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: '{ anonymous_id }',
asset_string: asset_string
}
expect(response).to have_http_status(:bad_request)
end
context "when the submission's turnitin data contains a report URL" do
before(:each) do
submission.update!(turnitin_data: {asset_string => {report_url: 'MY_GREAT_REPORT'}})
end
it "redirects to the course tool retrieval URL" do
get 'turnitin_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: asset_string
}
expect(response).to redirect_to(/#{retrieve_course_external_tools_url(course.id)}/)
end
it "includes the report URL in the redirect" do
get 'turnitin_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: asset_string
}
expect(response).to redirect_to(/MY_GREAT_REPORT/)
end
end
it "redirects the user to SpeedGrader if no turnitin URL exists" do
get 'turnitin_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: asset_string
}
speed_grader_url = speed_grader_course_gradebook_url(
course,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id
)
expect(response).to redirect_to(speed_grader_url)
end
it "displays a flash error if no turnitin URL exists" do
get 'turnitin_report', params: {
course_id: assignment.context_id,
assignment_id: assignment.id,
anonymous_id: submission.anonymous_id,
asset_string: asset_string
}
expect(flash[:error]).to be_present
end
end
end