canvas-lms/spec/controllers/assignments_controller_spec.rb

1749 lines
71 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__) + '/../sharding_spec_helper')
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
require File.expand_path(File.dirname(__FILE__) + '/../lti2_spec_helper')
describe AssignmentsController do
before :once do
course_with_teacher(active_all: true)
student_in_course(active_all: true)
course_assignment
end
def course_assignment(course = nil)
course ||= @course
@group = course.assignment_groups.create(:name => "some group")
@assignment = course.assignments.create(
:title => "some assignment",
:assignment_group => @group,
:due_at => Time.zone.now + 1.week
)
@assignment
end
describe "GET 'index'" do
it "should throw 404 error without a valid context id" do
#controller.use_rails_error_handling!
get 'index', params: {:course_id => 'notvalid'}
assert_status(404)
end
it "should return unauthorized without a valid session" do
get 'index', params: {:course_id => @course.id}
assert_unauthorized
end
it "should redirect 'disabled', if disabled by the teacher" do
user_session(@student)
@course.update_attribute(:tab_configuration, [{'id'=>3,'hidden'=>true}])
get 'index', params: {:course_id => @course.id}
expect(response).to be_redirect
expect(flash[:notice]).to match(/That page has been disabled/)
end
it "should set WEIGHT_FINAL_GRADES in js_env" do
user_session @teacher
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:WEIGHT_FINAL_GRADES]).to eq(@course.apply_group_weights?)
end
it "js_env HAS_ASSIGNMENTS is true when the course has assignments" do
user_session(@teacher)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:HAS_ASSIGNMENTS]).to eq(true)
end
it "js_env HAS_ASSIGNMENTS is false when the course does not have assignments" do
user_session(@teacher)
@assignment.workflow_state = 'deleted'
@assignment.save!
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:HAS_ASSIGNMENTS]).to eq(false)
end
it "js_env DUE_DATE_REQUIRED_FOR_ACCOUNT is true when AssignmentUtil.due_date_required_for_account? == true" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:due_date_required_for_account?).and_return(true)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:DUE_DATE_REQUIRED_FOR_ACCOUNT]).to eq(true)
end
it "js_env SIS_INTEGRATION_SETTINGS_ENABLED is true when AssignmentUtil.sis_integration_settings_enabled? == true" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:sis_integration_settings_enabled?).and_return(true)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:SIS_INTEGRATION_SETTINGS_ENABLED]).to eq(true)
end
it "js_env SIS_INTEGRATION_SETTINGS_ENABLED is false when AssignmentUtil.sis_integration_settings_enabled? == false" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:sis_integration_settings_enabled?).and_return(false)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:SIS_INTEGRATION_SETTINGS_ENABLED]).to eq(false)
end
it "js_env DUE_DATE_REQUIRED_FOR_ACCOUNT is false when AssignmentUtil.due_date_required_for_account? == false" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:due_date_required_for_account?).and_return(false)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:DUE_DATE_REQUIRED_FOR_ACCOUNT]).to eq(false)
end
it "js_env SIS_NAME is SIS when @context does not respond_to assignments" do
user_session(@teacher)
allow(@course).to receive(:respond_to?).and_return(false)
allow(controller).to receive(:set_js_assignment_data).and_return({:js_env => {}})
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:SIS_NAME]).to eq('SIS')
end
it "js_env SIS_NAME is Foo Bar when AssignmentUtil.post_to_sis_friendly_name is Foo Bar" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:post_to_sis_friendly_name).and_return('Foo Bar')
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:SIS_NAME]).to eq('Foo Bar')
end
it "js_env POST_TO_SIS_DEFAULT is false when sis_default_grade_export is false on the account" do
user_session(@teacher)
a = @course.account
a.settings[:sis_default_grade_export] = {locked: false, value: false}
a.save!
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:POST_TO_SIS_DEFAULT]).to eq(false)
end
it "js_env POST_TO_SIS_DEFAULT is true when sis_default_grade_export is true on the account" do
user_session(@teacher)
a = @course.account
a.settings[:sis_default_grade_export] = {locked: false, value: true}
a.save!
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:POST_TO_SIS_DEFAULT]).to eq(true)
end
it "should set QUIZ_LTI_ENABLED in js_env if quizzes 2 is available" do
user_session @teacher
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.settings[:provision] = {'lti' => 'lti url'}
@course.root_account.save!
@course.root_account.enable_feature! :quizzes_next
@course.enable_feature! :quizzes_next
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:QUIZ_LTI_ENABLED]).to be true
end
it "should not set QUIZ_LTI_ENABLED in js_env if 'newquizzes_on_quiz_page' is enabled" do
user_session @teacher
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.settings[:provision] = {'lti' => 'lti url'}
@course.root_account.save!
@course.root_account.enable_feature! :quizzes_next
@course.root_account.enable_feature! :newquizzes_on_quiz_page
@course.enable_feature! :quizzes_next
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:QUIZ_LTI_ENABLED]).to be false
end
it "should not set QUIZ_LTI_ENABLED in js_env if url is voided" do
user_session @teacher
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://void.url.inseng.net'
)
@course.root_account.settings[:provision] = {'lti' => 'lti url'}
@course.root_account.save!
@course.root_account.enable_feature! :quizzes_next
@course.enable_feature! :quizzes_next
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:QUIZ_LTI_ENABLED]).to be false
end
it "should not set QUIZ_LTI_ENABLED in js_env if quizzes 2 is not available" do
user_session @teacher
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:QUIZ_LTI_ENABLED]).to be false
end
it "should not set QUIZ_LTI_ENABLED in js_env if quizzes_next is not enabled" do
user_session @teacher
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:QUIZ_LTI_ENABLED]).to be false
end
it "should set FLAGS/newquizzes_on_quiz_page in js_env if 'newquizzes_on_quiz_page' is enabled" do
user_session @teacher
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.enable_feature! :newquizzes_on_quiz_page
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:FLAGS][:newquizzes_on_quiz_page]).to be_truthy
end
it "should not set FLAGS/newquizzes_on_quiz_page in js_env if 'newquizzes_on_quiz_page' is disabled" do
user_session @teacher
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.disable_feature! :newquizzes_on_quiz_page
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:FLAGS][:newquizzes_on_quiz_page]).to be_falsey
end
it "js_env MAX_NAME_LENGTH_REQUIRED_FOR_ACCOUNT is true when AssignmentUtil.name_length_required_for_account? == true" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:name_length_required_for_account?).and_return(true)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:MAX_NAME_LENGTH_REQUIRED_FOR_ACCOUNT]).to eq(true)
end
it "js_env MAX_NAME_LENGTH_REQUIRED_FOR_ACCOUNT is false when AssignmentUtil.name_length_required_for_account? == false" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:name_length_required_for_account?).and_return(false)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:MAX_NAME_LENGTH_REQUIRED_FOR_ACCOUNT]).to eq(false)
end
it "js_env MAX_NAME_LENGTH is a 15 when AssignmentUtil.assignment_max_name_length returns 15" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:assignment_max_name_length).and_return(15)
get 'index', params: {:course_id => @course.id}
expect(assigns[:js_env][:MAX_NAME_LENGTH]).to eq(15)
end
context "draft state" do
it "should create a default group if none exist" do
user_session(@student)
get 'index', params: {:course_id => @course.id}
expect(@course.reload.assignment_groups.count).to eq 1
end
it "should separate manage_assignments and manage_grades permissions" do
user_session(@teacher)
@course.account.role_overrides.create! role: teacher_role, permission: 'manage_assignments', enabled: false
get 'index', params: {course_id: @course.id}
expect(assigns[:js_env][:PERMISSIONS][:manage_grades]).to be_truthy
expect(assigns[:js_env][:PERMISSIONS][:manage_assignments]).to be_falsey
expect(assigns[:js_env][:PERMISSIONS][:manage]).to be_falsey
expect(assigns[:js_env][:PERMISSIONS][:manage_course]).to be_truthy
end
end
describe "per-assignment permissions" do
let(:assignment_permissions) { assigns[:js_env][:PERMISSIONS][:by_assignment_id] }
before(:each) do
@course.enable_feature!(:moderated_grading)
@assignment = @course.assignments.create!(
moderated_grading: true,
grader_count: 2,
final_grader: @teacher
)
ta_in_course(active_all: true)
end
it "sets the 'update' attribute to true when user is the final grader" do
user_session(@teacher)
get 'index', params: {course_id: @course.id}
expect(assignment_permissions[@assignment.id][:update]).to eq(true)
end
it "sets the 'update' attribute to true when user has the Select Final Grade permission" do
user_session(@ta)
get 'index', params: {course_id: @course.id}
expect(assignment_permissions[@assignment.id][:update]).to eq(true)
end
it "sets the 'update' attribute to false when user does not have the Select Final Grade permission" do
@course.account.role_overrides.create!(permission: :select_final_grade, enabled: false, role: ta_role)
user_session(@ta)
get 'index', params: {course_id: @course.id}
expect(assignment_permissions[@assignment.id][:update]).to eq(false)
end
end
end
describe "GET 'show_moderate'" do
before(:each) do
user_session(@teacher)
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@other_teacher = @user
@assignment = @course.assignments.create!(
moderated_grading: true,
final_grader: @other_teacher,
grader_count: 2,
workflow_state: 'published'
)
end
it "renders the page when the current user is the selected moderator" do
user_session(@other_teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
end
it "renders unauthorized when the current user is not the selected moderator" do
user_session(@teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_unauthorized
end
it "renders unauthorized when no moderator is selected and the user is not an admin" do
@assignment.update!(final_grader: nil)
user_session(@teacher)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(401)
end
it "renders unauthorized when no moderator is selected and the user is an admin without " \
"'Select Final Grade for Moderation' permission" do
@course.account.role_overrides.create!(role: admin_role, enabled: false, permission: :select_final_grade)
@assignment.update!(final_grader: nil)
user_session(account_admin_user)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(401)
end
it "renders the page when the current user is an admin and not the selected moderator" do
account_admin_user(account: @course.root_account)
user_session(@admin)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
end
it "renders the page when no moderator is selected and the user is an admin with " \
"'Select Final Grade for Moderation' permission" do
@assignment.update!(final_grader: nil)
user_session(account_admin_user)
get 'show_moderate', params: {course_id: @course.id, assignment_id: @assignment.id}
assert_status(200)
end
describe "js_env" do
let_once(:grader_1) do
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@user
end
let_once(:grader_2) do
course_with_user('TeacherEnrollment', {active_all: true, course: @course})
@user
end
let(:env) { assigns[:js_env] }
before :once do
@assignment.grade_student(@student, grader: grader_1, provisional: true, score: 10)
@assignment.grade_student(@student, grader: grader_2, provisional: true, score: 5)
end
before :each do
@assignment.update(
moderated_grading: true,
final_grader: @other_teacher,
grader_count: 2
)
user_session(@other_teacher)
end
it "includes ASSIGNMENT.course_id" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:course_id]).to be(@course.id)
end
it "includes ASSIGNMENT.id" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:id]).to be(@assignment.id)
end
it "includes ASSIGNMENT.grades_published" do
@assignment.update!(grades_published_at: 1.day.ago)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:grades_published]).to be(true)
end
it "includes ASSIGNMENT.muted" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:muted]).to be(true)
end
it "includes ASSIGNMENT.title" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:ASSIGNMENT][:title]).to eql(@assignment.title)
end
it "optionally sets CURRENT_USER.can_view_grader_identities to true" do
@assignment.update(grader_names_visible_to_final_grader: true)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:can_view_grader_identities]).to be(true)
end
it "optionally sets CURRENT_USER.can_view_grader_identities to false" do
@assignment.update(grader_names_visible_to_final_grader: false)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:can_view_grader_identities]).to be(false)
end
it "optionally sets CURRENT_USER.can_view_student_identities to true" do
@assignment.update(anonymous_grading: false)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:can_view_student_identities]).to be(true)
end
it "optionally sets CURRENT_USER.can_view_student_identities to false" do
@assignment.update(anonymous_grading: true)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:can_view_student_identities]).to be(false)
end
describe "CURRENT_USER.grader_id" do
it "is the id of the user when the user can see other grader identities" do
@assignment.moderation_graders.create!(anonymous_id: "other", user: @other_teacher)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:grader_id]).to eql(@other_teacher.id)
end
context "when the user cannot see other grader identities" do
before :each do
@assignment.update(grader_names_visible_to_final_grader: false)
end
it "is the anonymous_id of the associated moderation grader when the user has graded" do
@assignment.moderation_graders.create!(anonymous_id: "other", user: @other_teacher)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:grader_id]).to eql("other")
end
it "is nil when the user has not graded" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:grader_id]).to be_nil
end
end
end
it "includes CURRENT_USER.id" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:CURRENT_USER][:id]).to eql(@other_teacher.id)
end
describe "FINAL_GRADER.grader_id" do
it "is the id of the final grader when the current user can see other grader identities" do
@assignment.moderation_graders.create!(anonymous_id: "other", user: @other_teacher)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:FINAL_GRADER][:grader_id]).to eql(@other_teacher.id)
end
context "when the current user cannot see other grader identities" do
before :each do
@assignment.update(grader_names_visible_to_final_grader: false)
end
it "is the anonymous_id of the final grader's moderation grader when the final grader has graded" do
@assignment.moderation_graders.create!(anonymous_id: "other", user: @other_teacher)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:FINAL_GRADER][:grader_id]).to eql("other")
end
it "is nil when the final grader has not graded" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:FINAL_GRADER][:grader_id]).to be_nil
end
end
end
it "includes FINAL_GRADER.id when the assignment has a final grader" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:FINAL_GRADER][:id]).to eql(@other_teacher.id)
end
it "sets FINAL_GRADER to nil when the assignment does not have a final grader" do
user_session(account_admin_user)
@assignment.update(final_grader: nil)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:FINAL_GRADER]).to be(nil)
end
it "includes moderation graders in GRADERS" do
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
moderation_grader_ids = @assignment.moderation_graders.map(&:id)
expect(env[:GRADERS].map {|grader| grader[:id]}).to match_array(moderation_grader_ids)
end
it "does not include the final grader in GRADERS" do
@assignment.moderation_graders.create!(anonymous_id: "other", user: @other_teacher)
get :show_moderate, params: {course_id: @course.id, assignment_id: @assignment.id}
expect(env[:GRADERS].map {|grader| grader[:id].to_s}).not_to include(@other_teacher.id.to_s)
end
end
end
describe "GET 'show'" do
it "should return 404 on non-existant assignment" do
#controller.use_rails_error_handling!
user_session(@student)
get 'show', params: {:course_id => @course.id, :id => Assignment.maximum(:id) + 100}
assert_status(404)
end
it "doesn't fail on a public course with a nil user" do
course = course_factory(:active_all => true, :is_public => true)
assignment = assignment_model(:course => course, :submission_types => "online_url")
get 'show', params: {:course_id => course.id, :id => assignment.id}
assert_status(200)
end
it "should return unauthorized if not enrolled" do
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
assert_unauthorized
end
it "should assign variables" do
user_session(@student)
a = @course.assignments.create(:title => "some assignment")
get 'show', params: {:course_id => @course.id, :id => a.id}
expect(@course.reload.assignment_groups).not_to be_empty
expect(assigns[:unlocked]).not_to be_nil
end
it "does not show direct share options when disabled" do
user_session(@teacher)
get 'show', params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:can_direct_share]).to eq false
end
it "shows direct share options when enabled" do
Account.default.enable_feature!(:direct_share)
user_session(@teacher)
get 'show', params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:can_direct_share]).to eq true
end
context 'when the assignment is an external tool' do
subject { get 'show', params: {course_id: assignment.course.id, id: assignment.id} }
let(:assignment) { assignment_model }
before { user_session(assignment.course.teachers.first) }
context 'and a default line item was never created' do
let(:launch_url) { 'https://www.my-tool.com/login' }
let(:content_tag) do
ContentTag.create!(
context: assignment,
content_type: 'ContextExternalTool',
url: launch_url
)
end
let(:key) do
DeveloperKey.create!(
scopes: [
TokenScopes::LTI_AGS_LINE_ITEM_SCOPE,
TokenScopes::LTI_AGS_LINE_ITEM_READ_ONLY_SCOPE,
TokenScopes::LTI_AGS_RESULT_READ_ONLY_SCOPE,
TokenScopes::LTI_AGS_SCORE_SCOPE
]
)
end
let(:external_tool) do
tool = external_tool_model(
context: assignment.course,
opts: {
url: launch_url,
developer_key: key
}
)
tool.settings[:use_1_3] = true
tool.save!
tool
end
before do
# For this context, the assignment and tag must
# be created before the tool
assignment.update!(
external_tool_tag: content_tag,
submission_types: 'external_tool'
)
external_tool
end
it { is_expected.to be_success }
it 'creates the default line item' do
expect {
subject
}.to change {
Lti::LineItem.where(assignment: assignment).count
}.from(0).to(1)
end
end
end
context 'when the assignment uses the plagiarism platform' do
include_context 'lti2_spec_helper'
let(:assignment) { @course.assignments.create(:title => "some assignment") }
before do
allow_any_instance_of(AssignmentConfigurationToolLookup).to receive(:create_subscription).and_return true
user_session(@student)
AssignmentConfigurationToolLookup.create!(
assignment: assignment,
tool: message_handler,
tool_type: 'Lti::MessageHandler',
tool_id: message_handler.id
)
end
it "should assign 'similarity_pledge'" do
pledge = 'I made this'
@course.account.update(turnitin_pledge: pledge)
get 'show', params: {:course_id => @course.id, :id => assignment.id}
expect(assigns[:similarity_pledge]).to eq pledge
end
end
it 'uses the vericite pledge if vericite is enabled' do
user_session(@student)
a = @course.assignments.create(:title => "some assignment")
pledge = 'vericite pledge'
allow_any_instance_of(Assignment).to receive(:vericite_enabled?).and_return(true)
allow_any_instance_of(Course).to receive(:vericite_pledge).and_return(pledge)
get 'show', params: {:course_id => @course.id, :id => a.id}
expect(assigns[:similarity_pledge]).to eq pledge
end
it 'uses the closest pledge when vericite is enabled but no pledge is set' do
user_session(@student)
a = @course.assignments.create(:title => "some assignment", vericite_enabled: true)
allow(@course).to receive(:vericite_pledge).and_return("")
get 'show', params: {:course_id => @course.id, :id => a.id}
expect(assigns[:similarity_pledge]).to eq "This assignment submission is my own, original work"
end
it 'uses the turnitin pledge if turnitin is enabled' do
user_session(@student)
a = @course.assignments.create(:title => "some assignment")
pledge = 'tii pledge'
allow_any_instance_of(Assignment).to receive(:turnitin_enabled?).and_return(true)
@course.account.update(turnitin_pledge: pledge)
get 'show', params: {:course_id => @course.id, :id => a.id}
expect(assigns[:similarity_pledge]).to eq pledge
end
it "should assign submission variable if current user and submitted" do
user_session(@student)
@assignment.submit_homework(@student, :submission_type => 'online_url', :url => 'http://www.google.com')
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(response).to be_successful
expect(assigns[:current_user_submission]).not_to be_nil
expect(assigns[:assigned_assessments]).to eq []
end
it "should assign (active) peer review requests" do
@assignment.peer_reviews = true
@assignment.save!
@student1 = @student
@student2 = student_in_course(:active_all => true).user
@student3 = student_in_course(:enrollment_state => 'inactive').user
sub1 = @assignment.submit_homework(@student1, :submission_type => 'online_url', :url => 'http://www.example.com/1')
sub2 = @assignment.submit_homework(@student2, :submission_type => 'online_url', :url => 'http://www.example.com/2')
sub3 = @assignment.submit_homework(@student3, :submission_type => 'online_url', :url => 'http://www.example.com/3')
sub2.assign_assessor(sub1)
sub3.assign_assessor(sub1)
user_session(@student1)
get 'show', :params => { :course_id => @course.id, :id => @assignment.id }
expect(assigns[:current_user_submission]).to eq sub1
expect(assigns[:assigned_assessments].map(&:submission)).to eq [sub2]
end
it "should redirect to wiki page if assignment is linked to wiki page" do
@course.enable_feature!(:conditional_release)
user_session(@student)
@assignment.reload.submission_types = 'wiki_page'
@assignment.save!
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(response).to be_redirect
end
it "should not redirect to wiki page" do
@course.disable_feature!(:conditional_release)
user_session(@student)
@assignment.submission_types = 'wiki_page'
@assignment.save!
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(response).not_to be_redirect
end
it "should redirect to discussion if assignment is linked to discussion" do
user_session(@student)
@assignment.submission_types = 'discussion_topic'
@assignment.save!
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(response).to be_redirect
end
it "should not redirect to discussion for observer if assignment is linked to discussion but read_forum is false" do
course_with_observer(:active_all => true, :course => @course)
user_session(@observer)
@assignment.submission_types = 'discussion_topic'
@assignment.save!
RoleOverride.create!(:context => @course.account, :permission => 'read_forum',
:role => observer_role, :enabled => false)
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(response).not_to be_redirect
expect(response).to be_successful
end
it "should not show locked external tool assignments" do
user_session(@student)
@assignment.lock_at = 1.week.ago
@assignment.due_at = 10.days.ago
@assignment.unlock_at = 2.weeks.ago
@assignment.submission_types = 'external_tool'
@assignment.save
# This is usually a ContentExternalTool, but it only needs to
# be true here because we aren't redirecting to it.
allow_any_instance_of(Assignment).to receive(:external_tool_tag).and_return(true)
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:locked]).to be_truthy
# make sure that the show.html.erb template is rendered, because
# in normal cases we redirect to the assignment's external_tool_tag.
expect(response).to render_template('assignments/show')
end
it "should require login for external tools in a public course" do
@course.update_attribute(:is_public, true)
@course.context_external_tools.create!(
:shared_secret => 'test_secret',
:consumer_key => 'test_key',
:name => 'test tool',
:domain => 'example.com'
)
@assignment.submission_types = 'external_tool'
@assignment.build_external_tool_tag(:url => "http://example.com/test")
@assignment.save!
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
assert_require_login
end
it 'should set user_has_google_drive' do
user_session(@student)
a = @course.assignments.create(:title => "some assignment")
plugin = Canvas::Plugin.find(:google_drive)
plugin_setting = PluginSetting.find_by_name(plugin.id) || PluginSetting.new(:name => plugin.id, :settings => plugin.default_settings)
plugin_setting.posted_settings = {}
plugin_setting.save!
google_drive_mock = double('google_drive')
allow(google_drive_mock).to receive(:authorized?).and_return(true)
allow(controller).to receive(:google_drive_connection).and_return(google_drive_mock)
get 'show', params: {:course_id => @course.id, :id => a.id}
expect(response).to be_successful
expect(assigns(:user_has_google_drive)).to be true
end
context "page views enabled" do
before do
Setting.set('enable_page_views', 'db')
@old_thread_context = Thread.current[:context]
Thread.current[:context] = { request_id: SecureRandom.uuid }
allow(BasicLTI::Sourcedid).to receive(:encryption_secret) {'encryption-secret-5T14NjaTbcYjc4'}
allow(BasicLTI::Sourcedid).to receive(:signing_secret) {'signing-secret-vp04BNqApwdwUYPUI'}
end
after do
Thread.current[:context] = @old_thread_context
end
it "should log an AUA as an assignment view for an external tool assignment" do
user_session(@student)
@course.context_external_tools.create!(
:shared_secret => 'test_secret',
:consumer_key => 'test_key',
:name => 'test tool',
:domain => 'example.com'
)
@assignment.submission_types = 'external_tool'
@assignment.build_external_tool_tag(:url => "http://example.com/test")
@assignment.save!
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(response).to be_successful
aua = AssetUserAccess.where(user_id: @student, context_type: 'Course', context_id: @course).first
expect(aua.asset_category).to eq 'assignments'
expect(aua.asset_code).to eq @assignment.asset_string
end
end
describe "js_env" do
before :each do
user_session @teacher
end
describe "filter_speed_grader_by_student_group" do
it "is included in the SETTINGS hash" do
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env][:SETTINGS]).to have_key :filter_speed_grader_by_student_group
end
describe "setting value" do
context "when the course has the 'Filter SpeedGrader by Student Group' setting enabled" do
before(:once) do
@course.root_account.enable_feature!(:filter_speed_grader_by_student_group)
@course.update!(filter_speed_grader_by_student_group: true)
category = @course.group_categories.create!(name: "category")
category.create_groups(2)
end
let(:category) { @course.group_categories.first }
let(:group_filter_setting) { assigns[:js_env][:SETTINGS][:filter_speed_grader_by_student_group] }
it "is set to true for non-group assignments" do
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(group_filter_setting).to be true
end
it "is set to true for group assignments that grade students individually" do
@assignment.update!(group_category: category, grade_group_students_individually: true)
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(group_filter_setting).to be true
end
it "is set to false for non-group assignments that do not grade students individually" do
@assignment.update!(group_category: category)
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(group_filter_setting).to be false
end
it "is included when assignment is an external tool type" do
@assignment.update!(submission_types: "external_tool", external_tool_tag: ContentTag.new)
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env][:SETTINGS]).to have_key(:filter_speed_grader_by_student_group)
end
end
end
context "when filter_speed_grader_by_student_group? is true" do
before :once do
@course.root_account.enable_feature!(:filter_speed_grader_by_student_group)
@course.update!(filter_speed_grader_by_student_group: true)
category = @course.group_categories.create!(name: "category")
category.create_groups(2)
end
it "includes all group categories for the course if the assignment does not belong to a specific category" do
get :show, params: {course_id: @course.id, id: @assignment.id}
group_category_ids = assigns[:js_env][:group_categories].map { |category| category["id"] }
expect(group_category_ids).to eq @course.group_categories.map(&:id)
end
it "includes only the relevant group category if the assignment is a group assignment" do
assignment_category = @course.group_categories.create!(name: "special category")
@assignment.update!(group_category: assignment_category, grade_group_students_individually: true)
get :show, params: {course_id: @course.id, id: @assignment.id}
group_category_ids = assigns[:js_env][:group_categories].map { |category| category["id"] }
expect(group_category_ids).to contain_exactly(assignment_category.id)
end
it "includes the gradebook settings student group id if the group is valid for this assignment" do
first_group_id = @course.groups.first.id.to_s
@teacher.preferences[:gradebook_settings] = {
@course.global_id => {
'filter_rows_by' => {
'student_group_id' => first_group_id
}
}
}
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env][:selected_student_group_id]).to eq first_group_id
end
it "does not set selected_student_group_id if the selected group is not eligible for this assignment" do
@teacher.preferences[:gradebook_settings] = {
@course.global_id => {
'filter_rows_by' => {
'student_group_id' => @course.groups.first.id.to_s
}
}
}
assignment_category = @course.group_categories.create!(name: "special category")
@assignment.update!(group_category: assignment_category)
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).not_to include(:selected_student_group_id)
end
it "does not set selected_student_group_id if no group is selected" do
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).not_to include(:selected_student_group_id)
end
it "does not set selected_student_group_id if the selected group has been deleted" do
@teacher.preferences[:gradebook_settings] = {
@course.id => {
'filter_rows_by' => {
'student_group_id' => @course.groups.second.id.to_s
}
}
}
@course.groups.second.destroy!
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).not_to include(:selected_student_group_id)
end
it "includes group_categories when assignment is an external tool type" do
@assignment.update!(submission_types: "external_tool", external_tool_tag: ContentTag.new)
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).to have_key(:group_categories)
end
it "includes selected_student_group_id when assignment is an external tool type" do
@assignment.update!(submission_types: "external_tool", external_tool_tag: ContentTag.new)
first_group_id = @course.groups.first.id.to_s
@teacher.preferences[:gradebook_settings] = {
@course.global_id => {
'filter_rows_by' => {
'student_group_id' => first_group_id
}
}
}
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).to have_key(:selected_student_group_id)
end
end
context "when filter_speed_grader_by_student_group? is false" do
it "does not include the course group categories" do
@course.group_categories.create!(name: "category")
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).not_to have_key :group_categories
end
it "does not include the gradebook settings student group id" do
@teacher.preferences[:gradebook_settings] = {
@course.id => {
'filter_rows_by' => {
'student_group_id' => '23'
}
}
}
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).not_to have_key :selected_student_group_id
end
end
end
describe "speed_grader_url" do
it "is included when user can view SpeedGrader and assignment is published" do
user_session @teacher
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).to have_key :speed_grader_url
end
it "is not included when user cannot view SpeedGrader" do
user_session @student
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).not_to have_key :speed_grader_url
end
it "is not included when assignment is not published" do
@assignment.unpublish
user_session @teacher
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).not_to have_key :speed_grader_url
end
it "includes speed_grader_url when assignment is an external tool type" do
@assignment.update!(submission_types: "external_tool", external_tool_tag: ContentTag.new)
get :show, params: {course_id: @course.id, id: @assignment.id}
expect(assigns[:js_env]).to have_key(:speed_grader_url)
end
end
end
end
describe "GET 'syllabus'" do
it "should require authorization" do
#controller.use_rails_error_handling!
get 'syllabus', params: {:course_id => @course.id}
assert_unauthorized
end
it "should redirect 'disabled', if disabled by the teacher" do
user_session(@student)
@course.update_attribute(:tab_configuration, [{'id'=>1,'hidden'=>true}])
get 'syllabus', params: {:course_id => @course.id}
expect(response).to be_redirect
expect(flash[:notice]).to match(/That page has been disabled/)
end
it "should assign variables" do
@course.update_attribute(:syllabus_body, "<p>Here is your syllabus.</p>")
user_session(@student)
get 'syllabus', params: {:course_id => @course.id}
expect(assigns[:syllabus_body]).not_to be_nil
end
end
describe "PUT 'toggle_mute'" do
it "should require authorization" do
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: true }, format: 'json'
assert_unauthorized
end
context "while logged in" do
before :each do
user_session(@teacher)
end
context "with moderated grading on" do
before :each do
@assignment.update!(moderated_grading: true, grader_count: 1)
end
it "should fail if grades are not published, and status is false" do
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: false }, format: 'json'
assert_unauthorized
end
it "should mute if grades are not published, and status is true" do
@assignment.update!(muted: false)
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: true }, format: 'json'
@assignment.reload
expect(@assignment).to be_muted
end
end
it "should mute if status is true" do
@assignment.update!(muted: false)
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: true }, format: 'json'
@assignment.reload
expect(@assignment).to be_muted
end
it "should unmute if status is false" do
@assignment.update_attribute(:muted, true)
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: false }, format: 'json'
@assignment.reload
expect(@assignment).not_to be_muted
end
describe 'anonymize_students' do
it "is included in the response" do
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: !@assignment.muted }, format: 'json'
assignment_json = json_parse(response.body)['assignment']
expect(assignment_json).to have_key('anonymize_students')
end
it "is true if the assignment is anonymous and muted" do
@assignment.update!(anonymous_grading: true)
@assignment.unmute!
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: !@assignment.muted }, format: 'json'
assignment_json = json_parse(response.body)['assignment']
expect(assignment_json.fetch('anonymize_students')).to be true
end
it "is false if the assignment is anonymous and unmuted" do
@assignment.update!(anonymous_grading: true)
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: !@assignment.muted }, format: 'json'
assignment_json = json_parse(response.body)['assignment']
expect(assignment_json.fetch('anonymize_students')).to be false
end
it "is false if the assignment is not anonymous" do
put 'toggle_mute', params: { course_id: @course.id, assignment_id: @assignment.id, status: !@assignment.muted }, format: 'json'
assignment_json = json_parse(response.body)['assignment']
expect(assignment_json.fetch('anonymize_students')).to be false
end
end
end
end
describe "GET 'new'" do
it "should require authorization" do
#controller.use_rails_error_handling!
get 'new', params: {:course_id => @course.id}
assert_unauthorized
end
it "should default to unpublished for draft state" do
@course.require_assignment_group
get 'new', params: {:course_id => @course.id}
expect(assigns[:assignment].workflow_state).to eq 'unpublished'
end
it "js_env DUE_DATE_REQUIRED_FOR_ACCOUNT is true when AssignmentUtil.due_date_required_for_account? == true" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:due_date_required_for_account?).and_return(true)
get 'new', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:DUE_DATE_REQUIRED_FOR_ACCOUNT]).to eq(true)
end
it "js_env DUE_DATE_REQUIRED_FOR_ACCOUNT is false when AssignmentUtil.due_date_required_for_account? == false" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:due_date_required_for_account?).and_return(false)
get 'new', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:DUE_DATE_REQUIRED_FOR_ACCOUNT]).to eq(false)
end
it "js_env SIS_NAME is Foo Bar when AssignmentUtil.post_to_sis_friendly_name is Foo Bar" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:post_to_sis_friendly_name).and_return('Foo Bar')
get 'new', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:SIS_NAME]).to eq('Foo Bar')
end
context "with ?quiz_lti query param" do
it "uses quizzes 2 if available" do
tool = @course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
user_session(@teacher)
get 'new', params: {:course_id => @course.id, :quiz_lti => true}
expect(assigns[:assignment].quiz_lti?).to be true
expect(assigns[:assignment].external_tool_tag.content).to eq tool
expect(assigns[:assignment].external_tool_tag.url).to eq tool.url
end
it "falls back to normal behaviour if quizzes 2 is not set up" do
user_session(@teacher)
get 'new', params: {:course_id => @course.id, :quiz => true}
expect(assigns[:assignment].quiz_lti?).to be false
end
end
it 'set active_tab to assignments' do
get 'new', params: { :course_id => @course.id, :quiz_lti => true }
expect(assigns[:active_tab]).to eq('assignments')
end
context "when newquizzes_on_quiz_page FF is set" do
before do
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.settings[:provision] = {'lti' => 'lti url'}
@course.root_account.save!
@course.root_account.enable_feature! :quizzes_next
@course.root_account.enable_feature! :newquizzes_on_quiz_page
end
it 'sets active tab to quizzes for new quizzes' do
user_session(@teacher)
get 'new', params: { course_id: @course.id, quiz_lti: true }
expect(assigns[:active_tab]).to eq('quizzes')
end
it 'sets crumb to Quizzes for new quizzes' do
user_session(@teacher)
get 'new', params: { course_id: @course.id, quiz_lti: true }
expect(assigns[:_crumbs]).to include(['Quizzes', "/courses/#{@course.id}/quizzes", {}])
end
it 'sets active tab to quizzes for editing quizzes' do
user_session(@teacher)
post 'edit', params: { course_id: @course.id, id: @assignment.id, quiz_lti: true }
expect(assigns[:active_tab]).to eq('quizzes')
end
it 'sets crumb to Quizzes for editing quizzes' do
user_session(@teacher)
post 'new', params: { course_id: @course.id, id: @assignment.id, quiz_lti: true }
expect(assigns[:_crumbs]).to include(['Quizzes', "/courses/#{@course.id}/quizzes", {}])
end
end
end
describe "POST 'create'" do
it "sets the lti_context_id if provided" do
user_session(@student)
lti_context_id = SecureRandom.uuid
jwt = Canvas::Security.create_jwt(lti_context_id: lti_context_id)
post 'create', params: {course_id: @course.id, assignment: {title: "some assignment",secure_params: jwt}}
expect(assigns[:assignment].lti_context_id).to eq lti_context_id
end
it "should require authorization" do
#controller.use_rails_error_handling!
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment"}}
assert_unauthorized
end
it "should create assignment" do
user_session(@student)
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment"}}
expect(assigns[:assignment]).not_to be_nil
expect(assigns[:assignment].title).to eql("some assignment")
expect(assigns[:assignment].context_id).to eql(@course.id)
end
it "should create assignment when no groups exist yet" do
user_session(@student)
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment", :assignment_group_id => ''}}
expect(assigns[:assignment]).not_to be_nil
expect(assigns[:assignment].title).to eql("some assignment")
expect(assigns[:assignment].context_id).to eql(@course.id)
end
it "should set updating_user on created assignment" do
user_session(@teacher)
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment", :submission_types => "discussion_topic"}}
a = assigns[:assignment]
expect(a).not_to be_nil
expect(a.discussion_topic).not_to be_nil
expect(a.discussion_topic.user_id).to eql(@teacher.id)
end
it "should default to unpublished if draft state is enabled" do
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment"}}
expect(assigns[:assignment]).to be_unpublished
end
it "should assign to a group" do
user_session(@student)
group2 = @course.assignment_groups.create!(name: 'group2')
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment", :assignment_group_id => group2.to_param}}
expect(assigns[:assignment]).not_to be_nil
expect(assigns[:assignment].title).to eql("some assignment")
expect(assigns[:assignment].context_id).to eql(@course.id)
expect(assigns[:assignment].assignment_group).to eq group2
end
it "should not assign to a group from a different course" do
user_session(@student)
course2 = Account.default.courses.create!
group2 = course2.assignment_groups.create!(name: 'group2')
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment", :assignment_group_id => group2.to_param}}
expect(response).to be_not_found
end
it 'should use the default post-to-SIS setting' do
a = @course.account
a.settings[:sis_default_grade_export] = {locked: false, value: true}
a.save!
post 'create', params: {:course_id => @course.id, :assignment => {:title => "some assignment"}}
expect(assigns[:assignment]).to be_post_to_sis
end
end
describe "GET 'edit'" do
include_context "grading periods within controller" do
let(:course) { @course }
let(:teacher) { @teacher }
let(:request_params) { [:edit, params: {course_id: course, id: @assignment}] }
end
shared_examples 'course feature flags for Anonymous Moderated Marking' do
before(:each) do
user_session(@teacher)
end
it 'is false when the feature flag is not enabled' do
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][js_env_attribute]).to be false
end
it 'is true when the feature flag is enabled' do
@course.enable_feature!(feature_flag)
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][js_env_attribute]).to be true
end
end
it "js_env CANCEL_TO points to quizzes when quiz_lti? is true" do
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.enable_feature! :quizzes_next
@course.root_account.enable_feature! :newquizzes_on_quiz_page
@course.enable_feature! :quizzes_next
user_session(@teacher)
get 'new', params: { :course_id => @course.id, :quiz_lti => true }
expect(assigns[:js_env][:CANCEL_TO]).to include('quizzes')
end
it "js_env CANCEL_TO points to assignments when quiz_lti? is not included" do
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.enable_feature! :quizzes_next
@course.root_account.enable_feature! :newquizzes_on_quiz_page
@course.enable_feature! :quizzes_next
user_session(@teacher)
get 'new', params: { :course_id => @course.id, id: @assignment.id }
expect(assigns[:js_env][:CANCEL_TO]).to include('assignments')
end
it "js_env CANCEL_TO points to assignments when newquizzes_on_quiz_page feature flag is off" do
@course.context_external_tools.create!(
:name => 'Quizzes.Next',
:consumer_key => 'test_key',
:shared_secret => 'test_secret',
:tool_id => 'Quizzes 2',
:url => 'http://example.com/launch'
)
@course.root_account.enable_feature! :quizzes_next
@course.enable_feature! :quizzes_next
user_session(@teacher)
get 'new', params: { :course_id => @course.id, :quiz_lti => true }
expect(assigns[:js_env][:CANCEL_TO]).to include('assignments')
end
it "should require authorization" do
# controller.use_rails_error_handling!
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
assert_unauthorized
end
it "should find assignment" do
user_session(@student)
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:assignment]).to eql(@assignment)
end
it "should set 'ROOT_OUTCOME_GROUP' in js_env" do
user_session @teacher
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:ROOT_OUTCOME_GROUP]).not_to be_nil
end
it "bootstraps the correct assignment info to js_env" do
user_session(@teacher)
tool = @course.context_external_tools.create!(name: "a", url: "http://www.google.com", consumer_key: '12345', shared_secret: 'secret')
@assignment.tool_settings_tool = tool
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:ASSIGNMENT]['id']).to eq @assignment.id
expect(assigns[:js_env][:ASSIGNMENT_OVERRIDES]).to eq []
expect(assigns[:js_env][:COURSE_ID]).to eq @course.id
expect(assigns[:js_env][:SELECTED_CONFIG_TOOL_ID]).to eq tool.id
expect(assigns[:js_env][:SELECTED_CONFIG_TOOL_TYPE]).to eq tool.class.to_s
end
it "bootstrap the assignment originality report visibility settings to js_env" do
user_session(@teacher)
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:REPORT_VISIBILITY_SETTING]).to eq('immediate')
end
it "js_env DUE_DATE_REQUIRED_FOR_ACCOUNT is true when AssignmentUtil.due_date_required_for_account? == true" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:due_date_required_for_account?).and_return(true)
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:DUE_DATE_REQUIRED_FOR_ACCOUNT]).to eq(true)
end
it "js_env DUE_DATE_REQUIRED_FOR_ACCOUNT is false when AssignmentUtil.due_date_required_for_account? == false" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:due_date_required_for_account?).and_return(false)
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:DUE_DATE_REQUIRED_FOR_ACCOUNT]).to eq(false)
end
it "js_env SIS_NAME is Foo Bar when AssignmentUtil.post_to_sis_friendly_name is Foo Bar" do
user_session(@teacher)
allow(AssignmentUtil).to receive(:post_to_sis_friendly_name).and_return('Foo Bar')
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:SIS_NAME]).to eq('Foo Bar')
end
it 'js_env AVAILABLE_MODERATORS includes the name and id for each available moderator' do
user_session(@teacher)
@assignment.update!(grader_count: 2, moderated_grading: true)
get :edit, params: { course_id: @course.id, id: @assignment.id }
expected_moderators = @course.instructors.map { |user| { name: user.name, id: user.id } }
expect(assigns[:js_env][:AVAILABLE_MODERATORS]).to match_array expected_moderators
end
it 'js_env MODERATED_GRADING_MAX_GRADER_COUNT is the max grader count for the assignment' do
user_session(@teacher)
get :edit, params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:MODERATED_GRADING_MAX_GRADER_COUNT]).to eq @assignment.moderated_grading_max_grader_count
end
it 'js_env SUBMISSION_TYPE_SELECTION_TOOLS is correctly set for submission type tools' do
@course.root_account.enable_feature! :submission_type_tool_placement
tool_settings = {
base_title: 'my title',
external_url: 'https://tool.launch.url',
selection_width: 750,
selection_height: 480,
icon_url: nil,
}
@tool = factory_with_protected_attributes(@course.context_external_tools,
:url => "http://www.justanexamplenotarealwebsite.com/tool1",
:shared_secret => 'test123',
:consumer_key => 'test123',
:name => tool_settings[:base_title],
:settings => {
:submission_type_selection => tool_settings
}
)
user_session(@teacher)
get :edit, params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:SUBMISSION_TYPE_SELECTION_TOOLS][0]).to include(
base_title: tool_settings[:base_title],
title: tool_settings[:base_title],
selection_width: tool_settings[:selection_width],
selection_height: tool_settings[:selection_height]
)
end
context 'when the root account does not have a default tool url set' do
let(:course) { @course }
let(:root_account) { course.root_account }
before do
user_session(@teacher)
get :edit, params: { course_id: course.id, id: @assignment.id }
end
it 'does not set "DEFAULT_ASSIGNMENT_TOOL_URL"' do
expect(assigns.dig(:js_env, :DEFAULT_ASSIGNMENT_TOOL_URL)).to be_nil
end
it 'does not set "DEFAULT_ASSIGNMENT_TOOL_NAME"' do
expect(assigns.dig(:js_env, :DEFAULT_ASSIGNMENT_TOOL_NAME)).to be_nil
end
end
context 'when the root account has a default tool url and name set' do
let(:course) { @course }
let(:root_account) { course.root_account }
let(:default_url) { 'https://www.my-tool.com/blti' }
let(:default_name) { 'Default Name' }
let(:button_text) { 'Click Me' }
let(:info_message) { 'Some information for you.' }
before do
root_account.settings[:default_assignment_tool_url] = default_url
root_account.settings[:default_assignment_tool_name] = default_name
root_account.settings[:default_assignment_tool_button_text] = button_text
root_account.settings[:default_assignment_tool_info_message] = info_message
root_account.save!
user_session(@teacher)
get :edit, params: { course_id: course.id, id: @assignment.id }
end
it 'sets "DEFAULT_ASSIGNMENT_TOOL_URL"' do
expect(assigns.dig(:js_env, :DEFAULT_ASSIGNMENT_TOOL_URL)).to eq default_url
end
it 'sets "DEFAULT_ASSIGNMENT_TOOL_NAME"' do
expect(assigns.dig(:js_env, :DEFAULT_ASSIGNMENT_TOOL_NAME)).to eq default_name
end
it 'sets "DEFAULT_ASSIGNMENT_TOOL_BUTTON_TEXT"' do
expect(assigns.dig(:js_env, :DEFAULT_ASSIGNMENT_TOOL_BUTTON_TEXT)).to eq button_text
end
it 'sets "DEFAULT_ASSIGNMENT_TOOL_INFO_MESSAGE"' do
expect(assigns.dig(:js_env, :DEFAULT_ASSIGNMENT_TOOL_INFO_MESSAGE)).to eq info_message
end
end
describe 'js_env ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED' do
before(:each) do
user_session(@teacher)
end
it 'is true when the course has anonymous_instructor_annotations on' do
@course.enable_feature!(:anonymous_instructor_annotations)
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED]).to be true
end
it 'is true when the account has anonymous_instructor_annotations on' do
@course.account.enable_feature!(:anonymous_instructor_annotations)
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED]).to be true
end
it 'is false when the course has anonymous_instructor_annotations off' do
@course.disable_feature!(:anonymous_instructor_annotations)
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED]).to be false
end
it 'is false when the account has anonymous_instructor_annotations off' do
@course.account.disable_feature!(:anonymous_instructor_annotations)
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED]).to be false
end
end
context 'plagiarism detection platform' do
include_context 'lti2_spec_helper'
let(:service_offered) do
[
{
"endpoint" => "http://originality.docker/eula",
"action" => ["GET"],
"@id" => "http://originality.docker/lti/v2/services#vnd.Canvas.Eula",
"@type" => "RestService"
}
]
end
before do
allow_any_instance_of(AssignmentConfigurationToolLookup).to receive(:create_subscription).and_return true
allow(Lti::ToolProxy).to receive(:find_active_proxies_for_context).with(@course) { Lti::ToolProxy.where(id: tool_proxy.id) }
tool_proxy.resources << resource_handler
tool_proxy.update!(context: @course)
AssignmentConfigurationToolLookup.create!(
assignment: @assignment,
tool: message_handler,
tool_type: 'Lti::MessageHandler',
tool_id: message_handler.id
)
end
it "bootstraps the correct message_handler id for LTI 2 tools to js_env" do
user_session(@teacher)
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:SELECTED_CONFIG_TOOL_ID]).to eq message_handler.id
end
it "bootstraps the correct EULA link for the associated LTI 2 tool" do
tool_proxy.raw_data['tool_profile']['service_offered'] = service_offered
tool_proxy.save!
user_session(@student)
get 'show', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:EULA_URL]).to eq service_offered[0]['endpoint']
end
end
context "redirects" do
before do
user_session(@teacher)
end
it "to quiz" do
assignment_quiz [], course: @course
get 'edit', params: {:course_id => @course.id, :id => @quiz.assignment.id}
expect(response).to redirect_to controller.edit_course_quiz_path(@course, @quiz)
end
it "to discussion topic" do
group_assignment_discussion course: @course
get 'edit', params: {:course_id => @course.id, :id => @root_topic.assignment.id}
expect(response).to redirect_to controller.edit_course_discussion_topic_path(@course, @root_topic)
end
it "to wiki page" do
@course.enable_feature!(:conditional_release)
wiki_page_assignment_model course: @course
get 'edit', params: {:course_id => @course.id, :id => @page.assignment.id}
expect(response).to redirect_to controller.edit_course_wiki_page_path(@course, @page)
end
it "includes return_to" do
assignment_quiz [], course: @course
get 'edit', params: {:course_id => @course.id, :id => @quiz.assignment.id, :return_to => 'flibberty'}
expect(response.redirect_url).to match(/\?return_to=flibberty/)
end
end
context "conditional release" do
before do
allow(ConditionalRelease::Service).to receive(:env_for).and_return({ dummy: 'cr-assignment' })
end
it "should define env when enabled" do
allow(ConditionalRelease::Service).to receive(:enabled_in_context?).and_return(true)
user_session(@teacher)
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:dummy]).to eq 'cr-assignment'
end
it "should not define env when not enabled" do
allow(ConditionalRelease::Service).to receive(:enabled_in_context?).and_return(false)
user_session(@teacher)
get 'edit', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:js_env][:dummy]).to be nil
end
end
describe 'js_env ANONYMOUS_GRADING_ENABLED' do
it_behaves_like 'course feature flags for Anonymous Moderated Marking' do
let(:js_env_attribute) { :ANONYMOUS_GRADING_ENABLED }
let(:feature_flag) { :anonymous_marking }
end
end
describe 'js_env MODERATED_GRADING_ENABLED' do
it_behaves_like 'course feature flags for Anonymous Moderated Marking' do
let(:js_env_attribute) { :MODERATED_GRADING_ENABLED }
let(:feature_flag) { :moderated_grading }
end
end
end
describe "DELETE 'destroy'" do
it "should require authorization" do
delete 'destroy', params: {:course_id => @course.id, :id => @assignment.id}
assert_unauthorized
end
it "should delete assignments if authorized" do
user_session(@teacher)
delete 'destroy', params: {:course_id => @course.id, :id => @assignment.id}
expect(assigns[:assignment]).not_to be_nil
expect(assigns[:assignment]).not_to be_frozen
expect(assigns[:assignment]).to be_deleted
end
end
describe "POST 'publish'" do
it "should require authorization" do
post 'publish_quizzes', params: { course_id: @course.id, quizzes: [@assignment.id] }
assert_unauthorized
end
it "should publish unpublished assignments" do
user_session(@teacher)
@assignment = @course.assignments.build(title: 'New quiz!', workflow_state: 'unpublished')
@assignment.save!
expect(@assignment).not_to be_published
post 'publish_quizzes', params: { course_id: @course.id, quizzes: [@assignment.id] }
expect(@assignment.reload).to be_published
end
end
describe "POST 'unpublish'" do
it "should require authorization" do
post 'unpublish_quizzes', params: { course_id: @course.id, quizzes: [@assignment.id] }
assert_unauthorized
end
it "should unpublish published quizzes" do
user_session(@teacher)
@assignment = @course.assignments.create(title: 'New quiz!', workflow_state: 'published')
expect(@assignment).to be_published
post 'unpublish_quizzes', params: { course_id: @course.id, quizzes: [@assignment.id] }
expect(@assignment.reload).not_to be_published
end
end
describe "GET list_google_docs" do
it "passes errors through to Canvas::Errors" do
user_session(@teacher)
connection = double()
allow(connection).to receive(:list_with_extension_filter).and_raise(ArgumentError)
allow(controller).to receive(:google_drive_connection).and_return(connection)
allow_any_instance_of(Assignment).to receive(:allow_google_docs_submission?).and_return(true)
expect(Canvas::Errors).to receive(:capture_exception)
params = {course_id: @course.id, id: @assignment.id}
get 'list_google_docs', params: params, format: 'json'
expect(response.code).to eq("200")
end
end
end