canvas-lms/spec/integration/assignments_spec.rb

496 lines
18 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
#
# Copyright (C) 2012 - 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')
require 'nokogiri'
describe "assignments" do
def multiple_section_submissions
course_with_student(:active_all => true); @student1 = @student
@s2enrollment = student_in_course(:active_all => true); @student2 = @user
@section = @course.course_sections.create!
@s2enrollment.course_section = @section; @s2enrollment.save!
@assignment = @course.assignments.create!(:title => "Test 1", :submission_types => "online_upload")
@submission1 = @assignment.submit_homework(@student1, :submission_type => "online_text_entry", :body => "hi")
@submission2 = @assignment.submit_homework(@student2, :submission_type => "online_text_entry", :body => "there")
end
def create_assignment_section_override(section, due_at)
override = assignment_override_model(:assignment => @assignment)
override.set = section
override.override_due_at(due_at)
override.save!
end
it "should correctly list ungraded and total submissions for teacher" do
multiple_section_submissions
course_with_teacher_logged_in(:course => @course, :active_all => true)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
expect(Nokogiri::HTML5(response.body).at_css('.graded_count').text).to match(/0 out of 2/)
end
it "should correctly list ungraded and total submissions for ta" do
multiple_section_submissions
@taenrollment = course_with_ta(:course => @course, :active_all => true)
@taenrollment.limit_privileges_to_course_section = true
@taenrollment.save!
user_session(@ta)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
expect(Nokogiri::HTML5(response.body).at_css('.graded_count').text).to match(/0 out of 1/)
end
student view; closes #6995 allows course admins to view the course from a student perspective. this is accessible from a button on the course/settings page. They should be able to interact with the course as a student would, including submitting homework and quizzes. Right now there is one student view student per course, so if the course has multiple administrators, they will all share the same student view student. There are a few things that won't work in student view the way the would for a normal student, most notably access to conversations is disabled. Additionally, any publicly visible action that the teacher takes while in student view will still be publicly visible -- for example if the teacher posts a discussion topic/reply as the student view student, it will be visible to the whole class. test-plan: - (the following should be tried both as a full teacher and as a section-limited course admin) - set up a few assignments, quizzes, discussions, and module progressions in a course. - enter student view from the coures settings page. - work through the things you set up above. - leave student view from the upper right corner of the page. - as a teacher you should be able to grade the fake student so that they can continue to progress. - the student should not show up in the course users list - the student should not show up at the account level at all: * total user list * statistics Change-Id: I886a4663777f3ef2bdae594349ff6da6981e14ed Reviewed-on: https://gerrit.instructure.com/9484 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Cody Cutrer <cody@instructure.com>
2012-03-14 04:08:19 +08:00
it "should show student view student submission as needing grading" do
course_with_teacher_logged_in(:active_all => true)
@fake_student = @course.student_view_student
assignment_model(:course => @course, :submission_types => 'online_text_entry', :title => 'Assignment 1')
@assignment.submit_homework(@fake_student, :submission_type => 'online_text_entry', :body => "my submission")
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
expect(Nokogiri::HTML5(response.body).at_css('.graded_count').text).to match(/0 out of 1/)
student view; closes #6995 allows course admins to view the course from a student perspective. this is accessible from a button on the course/settings page. They should be able to interact with the course as a student would, including submitting homework and quizzes. Right now there is one student view student per course, so if the course has multiple administrators, they will all share the same student view student. There are a few things that won't work in student view the way the would for a normal student, most notably access to conversations is disabled. Additionally, any publicly visible action that the teacher takes while in student view will still be publicly visible -- for example if the teacher posts a discussion topic/reply as the student view student, it will be visible to the whole class. test-plan: - (the following should be tried both as a full teacher and as a section-limited course admin) - set up a few assignments, quizzes, discussions, and module progressions in a course. - enter student view from the coures settings page. - work through the things you set up above. - leave student view from the upper right corner of the page. - as a teacher you should be able to grade the fake student so that they can continue to progress. - the student should not show up in the course users list - the student should not show up at the account level at all: * total user list * statistics Change-Id: I886a4663777f3ef2bdae594349ff6da6981e14ed Reviewed-on: https://gerrit.instructure.com/9484 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Cody Cutrer <cody@instructure.com>
2012-03-14 04:08:19 +08:00
end
describe "due date overrides" do
include TextHelper
before do
course_with_teacher_logged_in(:active_all => true)
assignment_model(:course => @course, :due_at => 3.days.from_now)
@assignment.update_attribute :due_at, 2.days.from_now
@cs1 = @course.default_section
@cs2 = @course.course_sections.create!
end
it "should show 'Everyone' when there are no overrides" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
doc = Nokogiri::HTML5(response.body)
expect(doc.css(".assignment_dates").text).to include "Everyone"
expect(doc.css(".assignment_dates").text).not_to include "Everyone else"
end
it "should show 'Everyone else' when some sections have due date overrides" do
due_at1 = 3.days.from_now
create_assignment_section_override(@cs1, due_at1)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
doc = Nokogiri::HTML5(response.body)
expect(doc.css(".assignment_dates").text).to include "Everyone else"
end
it "should not show 'Everyone else' when all sections have due date overrides" do
due_at1, due_at2 = 3.days.from_now, 4.days.from_now
create_assignment_section_override(@cs1, due_at1)
create_assignment_section_override(@cs2, due_at2)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
doc = Nokogiri::HTML5(response.body)
expect(doc.css(".assignment_dates").text).not_to include "Everyone"
end
end
end
describe "download submissions link" do
before do
course_with_teacher_logged_in(:active_all => true)
assignment_model(:course => @course, :submission_types => 'online_url', :title => 'Assignment 1')
@student = User.create!(:name => 'student1')
@student.register!
@student.workflow_state = 'active'
@student2 = User.create!(:name => 'student2')
@student2.register
@student2.workflow_state = 'active'
@student2.save
@course.enroll_user(@student, 'StudentEnrollment')
@course.enroll_user(@student2, 'StudentEnrollment')
@course.save!
@student.save!
@student2.save!
end
it "should not show download submissions button with no submissions" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#download_submission_button')).to be_nil
end
it "should not show download submissions button with no submissions from active students" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update(submission_type: 'online_url')
@student.enrollments.each(&:conclude)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#download_submission_button')).to be_nil
end
it "should show download submissions button with submission not graded" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update(submission_type: 'online_url')
expect(@submission.state).to eql(:submitted)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#download_submission_button')).not_to be_nil
end
it "should show download submissions button with a submission graded" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update!(submission_type: 'online_url')
@submission.grade_it
@submission.score = 5
@submission.save!
expect(@submission.state).to eql(:graded)
@submission2 = @assignment.submissions.find_by!(user: @student2)
@submission2.update!(submission_type: 'online_url')
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#download_submission_button')).not_to be_nil
end
it "should show download submissions button with all submissions graded" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update!(submission_type: 'online_url')
@submission.grade_it
@submission.score = 5
@submission.save!
expect(@submission.state).to eql(:graded)
@submission2 = @assignment.submissions.find_by!(user: @student2)
@submission2.update!(submission_type: 'online_url')
@submission2.grade_it
@submission2.score = 5
@submission2.save!
expect(@submission2.state).to eql(:graded)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#download_submission_button')).not_to be_nil
end
it "should not show download submissions button to students" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update!(submission_type: 'online_url')
expect(@submission.state).to eql(:submitted)
user_session(@student)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#download_submission_button')).to be_nil
end
end
describe "ratio of submissions graded" do
before do
course_with_teacher_logged_in(:active_all => true)
assignment_model(:course => @course, :submission_types => 'online_url', :title => 'Assignment 1')
@student = User.create!(:name => 'student1')
@student.register!
@student.workflow_state = 'active'
@student2 = User.create!(:name => 'student2')
@student2.register
@student2.workflow_state = 'active'
@student2.save
@course.enroll_user(@student, 'StudentEnrollment')
@course.enroll_user(@student2, 'StudentEnrollment')
@course.save!
@student.save!
@student2.save!
end
it "should not show ratio of submissions graded with no submissions" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#ratio_of_submissions_graded')).to be_nil
end
it "should show ratio of submissions graded with submission not graded" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update!(submission_type: 'online_url')
expect(@submission.state).to eql(:submitted)
@submission2 = @assignment.submissions.find_by!(user: @student2)
@submission2.update!(submission_type: 'online_url')
expect(@submission2.state).to eql(:submitted)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#ratio_of_submissions_graded').text.strip).to eq "0 out of 2 Submissions Graded"
end
it "should show ratio of submissions graded with a submission graded" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update!(submission_type: 'online_url')
@submission.grade_it
@submission.score = 5
@submission.save!
expect(@submission.state).to eql(:graded)
@submission2 = @assignment.submissions.find_by!(user: @student2)
@submission2.update!(submission_type: 'online_url')
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#ratio_of_submissions_graded').text.strip).to eq "1 out of 2 Submissions Graded"
end
it "should show ratio of submissions graded with all submissions graded" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update!(submission_type: 'online_url')
@submission.grade_it
@submission.score = 5
@submission.save!
expect(@submission.state).to eql(:graded)
@submission2 = @assignment.submissions.find_by!(user: @student2)
@submission2.update!(submission_type: 'online_url')
@submission2.grade_it
@submission2.score = 5
@submission2.save!
expect(@submission2.state).to eql(:graded)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#ratio_of_submissions_graded').text.strip).to eq "2 out of 2 Submissions Graded"
end
it "should not show ratio of submissions graded to students" do
@submission = @assignment.submissions.find_by!(user: @student)
@submission.update!(submission_type: 'online_url')
expect(@submission.state).to eql(:submitted)
user_session(@student)
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(response).to be_successful
doc = Nokogiri::HTML5(response.body)
expect(doc.at_css('#ratio_of_submissions_graded')).to be_nil
end
Fix two AMM-related moderation/anonymity bugs 1. If Anonymous Moderated Marking is enabled, check the assignment's anonymous grading setting to determine whether to anonymize names in SpeedGrader, instead of always anonymizing assignments. If not enabled, revert to checking the (old) "Anonymous Grading" course flag. 2. On the assignment edit page, make sure not to show the "Moderate" if the assignment doesn't have moderated grading enabled (in addition to the other conditions). closes GRADE-1133 Test plan: Testing SpeedGrader anonymity: (Note that the "hide student names" setting in SpeedGrader's options menu, if enabled, will force anonymity regardless of the assignment's settings. If student names are showing up anonymous regardless of what you do, make sure that setting is off.) - Enable AMM for the root account - Create an assignment with anonymous grading enabled and one without - In SpeedGrader, the anonymous assignment should anonymize user names while the non-anonymous one should not - Disable AMM and make sure SpeedGrader anonymity is now determined based on the course's Anonymous Grading setting (the *old* anonymous grading setting) as it was before Testing the Moderate link for an assignment: ("Never" and "always" in this plan mean that it should behave that way regardless of the status of the AMM flag.) - Create an assignment with moderated grading disabled: - On the edit page, the "Moderate" button should never appear - Create a moderated assignment and set the current user as final grader - On the edit page, the "Moderate" button should always appear - Create a moderated assignment and set a different user as final grader - On the edit page, the "Moderate" button should appear if AMM is OFF but be hidden if it is ON. Change-Id: I4159dbe271cb76791aa93bb6ad07acdc333cdf53 Reviewed-on: https://gerrit.instructure.com/149863 Tested-by: Jenkins Reviewed-by: Spencer Olson <solson@instructure.com> Reviewed-by: Jeremy Neander <jneander@instructure.com> QA-Review: Anju Reddy <areddy@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-05-11 00:53:34 +08:00
describe 'assignment moderation' do
let(:moderate_button) { Nokogiri::HTML5(response.body).at_css('#moderated_grading_button') }
Fix two AMM-related moderation/anonymity bugs 1. If Anonymous Moderated Marking is enabled, check the assignment's anonymous grading setting to determine whether to anonymize names in SpeedGrader, instead of always anonymizing assignments. If not enabled, revert to checking the (old) "Anonymous Grading" course flag. 2. On the assignment edit page, make sure not to show the "Moderate" if the assignment doesn't have moderated grading enabled (in addition to the other conditions). closes GRADE-1133 Test plan: Testing SpeedGrader anonymity: (Note that the "hide student names" setting in SpeedGrader's options menu, if enabled, will force anonymity regardless of the assignment's settings. If student names are showing up anonymous regardless of what you do, make sure that setting is off.) - Enable AMM for the root account - Create an assignment with anonymous grading enabled and one without - In SpeedGrader, the anonymous assignment should anonymize user names while the non-anonymous one should not - Disable AMM and make sure SpeedGrader anonymity is now determined based on the course's Anonymous Grading setting (the *old* anonymous grading setting) as it was before Testing the Moderate link for an assignment: ("Never" and "always" in this plan mean that it should behave that way regardless of the status of the AMM flag.) - Create an assignment with moderated grading disabled: - On the edit page, the "Moderate" button should never appear - Create a moderated assignment and set the current user as final grader - On the edit page, the "Moderate" button should always appear - Create a moderated assignment and set a different user as final grader - On the edit page, the "Moderate" button should appear if AMM is OFF but be hidden if it is ON. Change-Id: I4159dbe271cb76791aa93bb6ad07acdc333cdf53 Reviewed-on: https://gerrit.instructure.com/149863 Tested-by: Jenkins Reviewed-by: Spencer Olson <solson@instructure.com> Reviewed-by: Jeremy Neander <jneander@instructure.com> QA-Review: Anju Reddy <areddy@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-05-11 00:53:34 +08:00
it 'shows the moderation link for moderated assignments' do
@assignment.update!(moderated_grading: true, grader_count: 1, final_grader: @teacher)
Fix two AMM-related moderation/anonymity bugs 1. If Anonymous Moderated Marking is enabled, check the assignment's anonymous grading setting to determine whether to anonymize names in SpeedGrader, instead of always anonymizing assignments. If not enabled, revert to checking the (old) "Anonymous Grading" course flag. 2. On the assignment edit page, make sure not to show the "Moderate" if the assignment doesn't have moderated grading enabled (in addition to the other conditions). closes GRADE-1133 Test plan: Testing SpeedGrader anonymity: (Note that the "hide student names" setting in SpeedGrader's options menu, if enabled, will force anonymity regardless of the assignment's settings. If student names are showing up anonymous regardless of what you do, make sure that setting is off.) - Enable AMM for the root account - Create an assignment with anonymous grading enabled and one without - In SpeedGrader, the anonymous assignment should anonymize user names while the non-anonymous one should not - Disable AMM and make sure SpeedGrader anonymity is now determined based on the course's Anonymous Grading setting (the *old* anonymous grading setting) as it was before Testing the Moderate link for an assignment: ("Never" and "always" in this plan mean that it should behave that way regardless of the status of the AMM flag.) - Create an assignment with moderated grading disabled: - On the edit page, the "Moderate" button should never appear - Create a moderated assignment and set the current user as final grader - On the edit page, the "Moderate" button should always appear - Create a moderated assignment and set a different user as final grader - On the edit page, the "Moderate" button should appear if AMM is OFF but be hidden if it is ON. Change-Id: I4159dbe271cb76791aa93bb6ad07acdc333cdf53 Reviewed-on: https://gerrit.instructure.com/149863 Tested-by: Jenkins Reviewed-by: Spencer Olson <solson@instructure.com> Reviewed-by: Jeremy Neander <jneander@instructure.com> QA-Review: Anju Reddy <areddy@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-05-11 00:53:34 +08:00
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(moderate_button).not_to be_nil
end
it 'does not show the moderation link for non-moderated assignments' do
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(moderate_button).to be_nil
end
end
end
describe "assignments_2 feature flag and parameter" do
context "as a teacher" do
before :once do
course_with_teacher(active_all: true)
@assignment = @course.assignments.create!(title: "some assignment")
end
before :each do
user_session @teacher
end
describe "with feature disabled" do
it "shows the old assignments page even with query parameter" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}?assignments_2=1"
html = Nokogiri::HTML5(response.body)
expect(html.at_css('div#assignment_show')).to be
end
end
describe "with feature enabled" do
before :once do
Account.default.enable_feature! :assignments_2_teacher
end
it "it shows new assignments" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
html = Nokogiri::HTML5(response.body)
expect(html.at_css('div#assignment_show')).not_to be
end
it "shows old assignments when explicitly requested" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}?assignments_2=0"
html = Nokogiri::HTML5(response.body)
expect(html.at_css('div#assignment_show')).to be
end
end
end
describe "as a student" do
before :once do
course_with_student(active_all: true)
@assignment = @course.assignments.create!(title: "some assignment")
end
before :each do
user_session @student
end
describe "with feature disabled" do
it "shows the old assignments page even with query parameter" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}?assignments_2=1"
html = Nokogiri::HTML5(response.body)
expect(html.at_css('div#assignment_show')).to be
end
end
describe "with feature enabled" do
before :once do
Account.default.enable_feature! :assignments_2_student
end
it "shows new assignments by default" do
@assignment.submission_types = 'online_text_entry'
@assignment.save!
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
html = Nokogiri::HTML5(response.body)
expect(html.at_css('div#assignment_show')).not_to be
end
it "shows old assignments if requested" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}?assignments_2=0"
html = Nokogiri::HTML5(response.body)
expect(html.at_css('div#assignment_show')).to be
end
it "sets the necessary RCS ENV" do
@assignment.submission_types = 'online_text_entry'
@assignment.save!
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(controller.js_env).to have_key(:RICH_CONTENT_APP_HOST)
end
end
end
describe "as an observer" do
before(:once) do
course_with_student(active_all: true)
@assignment = @course.assignments.create!(title: "Some Assignment")
@observer = user_factory(active_all: true, active_state: 'active')
@course.enroll_user(
@observer,
'ObserverEnrollment',
section: @course.course_sections.first,
enrollment_state: 'active', allow_multiple_enrollments: true
)
add_linked_observer(@student, @observer)
end
before(:each) do
user_session(@observer)
end
let(:old_assignment_page_indicator) { Nokogiri::HTML5(response.body).at_css('div#assignment_show') }
context "with the feature disabled" do
it "shows the old assignments page even with query parameter" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}?assignments_2=1"
expect(old_assignment_page_indicator).to be_present
end
it "shows the old assignments page without the query parameter" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(old_assignment_page_indicator).to be_present
end
end
context "with the feature enabled" do
before :once do
Account.default.enable_feature! :assignments_2_student
end
# we always send observers to the 'old' assignments page
it "shows the old assignments page even with query parameter" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}?assignments_2=1"
expect(old_assignment_page_indicator).to be_present
end
it "shows the old assignments page without the query parameter" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}"
expect(old_assignment_page_indicator).to be_present
end
end
end
describe "description" do
before :each do
skip "TODO doesn't work right because public_user_content is wonky"
end
let(:description) { <<~HTML }
<a href="#{attachment_model.public_download_url}">link</a>
HTML
it "excludes verifiers if course is not public" do
course_with_student(:active_all => true)
user_session(@student)
expect(UserContent::FilesHandler).to receive(:new).with(hash_including(is_public: false))
assignment = @course.assignments.create(
title: 'some assignment',
description: description
)
get "/courses/#{@course.id}/assignments/#{assignment.id}"
end
it "includes verifiers if course is public" do
expect(UserContent::FilesHandler).to receive(:new).with(hash_including(is_public: true))
course = course_factory(
active_all: true,
is_public: true,
)
assignment = assignment_model(
course: course,
submission_types: "online_url",
description: description
)
get "/courses/#{course.id}/assignments/#{assignment.id}"
end
end
end