870 lines
33 KiB
Ruby
870 lines
33 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#
|
|
# 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__) + '/common')
|
|
|
|
describe "people" do
|
|
include_context "in-process server selenium tests"
|
|
|
|
def add_user(option_text, username, user_list_selector)
|
|
click_option('#enrollment_type', option_text)
|
|
f('textarea.user_list').send_keys(username)
|
|
f('.verify_syntax_button').click
|
|
wait_for_ajax_requests
|
|
expect(f('#user_list_parsed')).to include_text(username)
|
|
f('.add_users_button').click
|
|
wait_for_ajaximations
|
|
expect(f(user_list_selector)).to include_text(username)
|
|
end
|
|
|
|
def open_student_group_dialog
|
|
f('#add-group-set').click
|
|
dialog = fj('.ui-dialog:visible')
|
|
expect(dialog).to be_displayed
|
|
dialog
|
|
end
|
|
|
|
def create_student_group(group_text = "new student group")
|
|
expect_new_page_load do
|
|
f("#people-options .Button").click
|
|
fln('View User Groups').click
|
|
end
|
|
open_student_group_dialog
|
|
replace_content(f('#new_category_name'), group_text)
|
|
submit_form('.group-category-create')
|
|
wait_for_ajaximations
|
|
expect(f('.collectionViewItems')).to include_text(group_text)
|
|
end
|
|
|
|
def enroll_student(student)
|
|
e1 = @course.enroll_student(student)
|
|
e1.workflow_state = 'active'
|
|
e1.save!
|
|
@course.reload
|
|
end
|
|
|
|
def enroll_ta(ta)
|
|
e1 = @course.enroll_ta(ta)
|
|
e1.workflow_state = 'active'
|
|
e1.save!
|
|
@course.reload
|
|
end
|
|
|
|
def create_user(student_name)
|
|
user = User.create!(:name => student_name)
|
|
user.register!
|
|
user.pseudonyms.create!(:unique_id => student_name, :password => 'qwertyuiop', :password_confirmation => 'qwertyuiop')
|
|
@course.reload
|
|
user
|
|
end
|
|
|
|
def enroll_more_students
|
|
student_1 = create_user("jake@test.com")
|
|
student_2 = create_user("test@test.com")
|
|
student_3 = create_user("new@test.com")
|
|
student_4 = create_user("this@test.com")
|
|
enroll_student(student_1)
|
|
enroll_student(student_2)
|
|
enroll_student(student_3)
|
|
enroll_student(student_4)
|
|
end
|
|
|
|
def open_dropdown_menu(selector = ".rosterUser")
|
|
row = f(selector)
|
|
driver.action.move_to(row).perform
|
|
f("#{selector} .admin-links a.al-trigger").click
|
|
expect(f("#{selector} .admin-links ul.al-options")).to be_displayed
|
|
end
|
|
|
|
def expect_dropdown_item(option, selector = ".rosterUser")
|
|
expect(f("#{selector} .admin-links ul.al-options li a[data-event=#{option}]")).to be_truthy
|
|
end
|
|
|
|
def expect_no_dropdown_item(option, selector = ".rosterUser")
|
|
expect(f("#{selector} .admin-links ul.al-options")).not_to contain_css("li a[data-event=#{option}]")
|
|
end
|
|
|
|
# Returns visibility boolean, assumes existence
|
|
def dropdown_item_visible?(option, selector = ".rosterUser")
|
|
f("#{selector} .admin-links ul.al-options li a[data-event=#{option}]").displayed?
|
|
end
|
|
|
|
def close_dropdown_menu
|
|
driver.action.send_keys(:escape).perform
|
|
end
|
|
|
|
context "people as a teacher" do
|
|
|
|
before :once do
|
|
course_with_teacher active_user: true, active_course: true, active_enrollment: true, name: 'Mrs. Commanderson'
|
|
# add first student
|
|
@student_1 = create_user('student@test.com')
|
|
|
|
enroll_student(@student_1)
|
|
|
|
# adding users for tests to work correctly
|
|
@student_2 = create_user('student2@test.com')
|
|
@test_ta = create_user('ta@test.com')
|
|
|
|
enroll_ta(@test_ta)
|
|
end
|
|
|
|
before :each do
|
|
user_session @teacher
|
|
end
|
|
|
|
it "should have tabs" do
|
|
get "/courses/#{@course.id}/users"
|
|
expect(f('.collectionViewItems>li:first-child').text).to match "Everyone"
|
|
end
|
|
|
|
it "should display a dropdown menu when item cog is clicked" do
|
|
get "/courses/#{@course.id}/users"
|
|
open_dropdown_menu
|
|
end
|
|
|
|
it "should display the option to remove a student from a course if manually enrolled" do
|
|
get "/courses/#{@course.id}/users"
|
|
open_dropdown_menu("tr[id=user_#{@student_1.id}]")
|
|
expect(dropdown_item_visible?('removeFromCourse', "tr[id=user_#{@student_1.id}]")).to be true
|
|
end
|
|
|
|
it "should display the option to remove a student from a course has a SIS ID", priority: "1", test_id: 336018 do
|
|
@course.sis_source_id = 'xyz'
|
|
@course.save
|
|
enroll_student(@student_2)
|
|
# need to hit /users page again to show enrollment of 2nd student
|
|
get "/courses/#{@course.id}/users"
|
|
wait_for_ajaximations
|
|
# check 1st student
|
|
open_dropdown_menu("tr[id=user_#{@student_1.id}]")
|
|
expect(dropdown_item_visible?('removeFromCourse', "tr[id=user_#{@student_1.id}]")).to be true
|
|
close_dropdown_menu
|
|
# check 2nd student
|
|
open_dropdown_menu("tr[id=user_#{@student_2.id}]")
|
|
expect(dropdown_item_visible?('removeFromCourse', "tr[id=user_#{@student_2.id}]")).to be true
|
|
end
|
|
|
|
it "should display remove option for student with/without SIS id", priority: "1", test_id: 332576 do
|
|
enroll_student(@student_2)
|
|
@student = user_with_managed_pseudonym
|
|
@course.enroll_student(@student)
|
|
@course.save
|
|
get "/courses/#{@course.id}/users"
|
|
# check 1st student
|
|
open_dropdown_menu("tr[id=user_#{@student_1.id}]")
|
|
expect(dropdown_item_visible?('removeFromCourse', "tr[id=user_#{@student_1.id}]")).to be true
|
|
close_dropdown_menu
|
|
# check 2nd student
|
|
open_dropdown_menu("tr[id=user_#{@student_2.id}]")
|
|
expect(dropdown_item_visible?('removeFromCourse', "tr[id=user_#{@student_2.id}]")).to be true
|
|
end
|
|
|
|
it "should display the option to remove a ta from the course" do
|
|
get "/courses/#{@course.id}/users"
|
|
open_dropdown_menu("tr[id=user_#{@test_ta.id}]")
|
|
expect(dropdown_item_visible?('removeFromCourse', "tr[id=user_#{@test_ta.id}]")).to be true
|
|
end
|
|
|
|
it "should display activity report on clicking Student Interaction button", priority: "1", test_id: 244446 do
|
|
get "/courses/#{@course.id}/users"
|
|
f("#people-options .Button").click
|
|
fln("Student Interactions Report").click
|
|
expect(f("h1").text).to eq "Teacher Activity Report for #{@user.name}"
|
|
end
|
|
|
|
it "should not display Student Interaction button for a student", priority: "1", test_id: 244450 do
|
|
user_session(@student_1)
|
|
get "/courses/#{@course.id}/users"
|
|
expect(f("#content")).not_to contain_link("Student Interactions Report")
|
|
end
|
|
|
|
it "should focus on the + Group Set button after the tabs" do
|
|
get "/courses/#{@course.id}/users"
|
|
driver.execute_script("$('.collectionViewItems > li:last a').focus()")
|
|
active = driver.execute_script("return document.activeElement")
|
|
active.send_keys(:tab)
|
|
check_element_has_focus(f('.group-categories-actions .btn-primary'))
|
|
end
|
|
|
|
it "should validate the main page" do
|
|
get "/courses/#{@course.id}/users"
|
|
users = ff('.roster_user_name')
|
|
expect(users[1].text).to match @student_1.name
|
|
expect(users[0].text).to match @teacher.name
|
|
end
|
|
|
|
it "should navigate to registered services on profile page" do
|
|
get "/courses/#{@course.id}/users"
|
|
f("#people-options .Button").click
|
|
fln('View Registered Services').click
|
|
fln('Link web services to my account').click
|
|
expect(f('#unregistered_services')).to be_displayed
|
|
end
|
|
|
|
it "should make a new set of student groups" do
|
|
get "/courses/#{@course.id}/users"
|
|
create_student_group
|
|
end
|
|
|
|
it "should test self sign up functionality" do
|
|
get "/courses/#{@course.id}/users"
|
|
f("#people-options .Button").click
|
|
expect_new_page_load { fln('View User Groups').click }
|
|
dialog = open_student_group_dialog
|
|
dialog.find_element(:css, '#enable_self_signup').click
|
|
expect(dialog.find_element(:css, '#split_groups')).not_to be_displayed
|
|
expect(dialog).to include_text("groups now")
|
|
end
|
|
|
|
it "should test self sign up / group structure functionality" do
|
|
get "/courses/#{@course.id}/users"
|
|
group_count = "4"
|
|
expect_new_page_load do
|
|
f("#people-options .Button").click
|
|
fln('View User Groups').click
|
|
end
|
|
dialog = open_student_group_dialog
|
|
replace_content(f('#new_category_name'), 'new group')
|
|
dialog.find_element(:css, '#enable_self_signup').click
|
|
replace_content(fj('input[name="create_group_count"]:visible'), group_count)
|
|
submit_form('.group-category-create')
|
|
wait_for_ajaximations
|
|
expect(@course.groups.count).to eq 4
|
|
expect(f('.groups-with-count')).to include_text("Groups (#{group_count})")
|
|
end
|
|
|
|
it "should test group structure functionality" do
|
|
get "/courses/#{@course.id}/users"
|
|
enroll_more_students
|
|
|
|
group_count = "4"
|
|
expect_new_page_load do
|
|
f("#people-options .Button").click
|
|
fln('View User Groups').click
|
|
end
|
|
dialog = open_student_group_dialog
|
|
replace_content(f('#new_category_name'), 'new group')
|
|
dialog.find_element(:css, '#split_groups').click
|
|
replace_content(fj('input[name="create_group_count"]:visible'), group_count)
|
|
expect(@course.groups.count).to eq 0
|
|
submit_form('.group-category-create')
|
|
wait_for_ajaximations
|
|
run_jobs
|
|
wait_for_ajaximations
|
|
expect(@course.groups.count).to eq group_count.to_i
|
|
expect(f('.groups-with-count')).to include_text("Groups (#{group_count})")
|
|
end
|
|
|
|
it "should auto-create groups based on # of students" do
|
|
enroll_more_students
|
|
get "/courses/#{@course.id}/groups#new"
|
|
f("#new_category_name").send_keys("Groups of 2")
|
|
f("input#num_students").click
|
|
count_input = f("input[name='create_group_member_count']")
|
|
count_input.clear
|
|
count_input.send_keys 2
|
|
fj("button:contains('Save')").click
|
|
wait_for_ajax_requests # initiates job request
|
|
run_jobs
|
|
wait_for_ajaximations # finishes calculations and repopulates list
|
|
expect(ff("li.group").size).to eq 3
|
|
end
|
|
|
|
it "should edit a student group" do
|
|
get "/courses/#{@course.id}/users"
|
|
new_group_name = "new group edit name"
|
|
create_student_group
|
|
fj('.group-category-actions:visible a:visible').click
|
|
f('.edit-category').click
|
|
edit_form = f('.group-category-edit')
|
|
edit_form.find_element(:css, 'input[name="name"]').send_keys(new_group_name)
|
|
submit_form(edit_form)
|
|
wait_for_ajaximations
|
|
expect(f(".collectionViewItems")).to include_text(new_group_name)
|
|
end
|
|
|
|
it "should delete a student group" do
|
|
group_category = GroupCategory.create(:name => "new student group", :context => @course)
|
|
|
|
get "/courses/#{@course.id}/groups#tab-#{group_category.id}"
|
|
fj('.group-category-actions:visible a:visible').click
|
|
f('.delete-category').click
|
|
accept_alert
|
|
wait_for_ajaximations
|
|
expect(f('.empty-groupset-instructions')).to be_displayed
|
|
end
|
|
|
|
it "should test prior enrollment functionality" do
|
|
@course.complete
|
|
get "/courses/#{@course.id}/users"
|
|
expect_new_page_load do
|
|
f("#people-options .Button").click
|
|
fln('View Prior Enrollments').click
|
|
end
|
|
expect(f('#users')).to include_text(@student_1.name)
|
|
end
|
|
|
|
it "should deal with observers linked to multiple students" do
|
|
@students = []
|
|
@obs = user_model(:name => "The Observer")
|
|
2.times do |i|
|
|
student_in_course(:name => "Student #{i}")
|
|
@students << @student
|
|
e = @course.observer_enrollments.create!(:user => @obs, :workflow_state => 'active')
|
|
e.associated_user_id = @student.id
|
|
e.save!
|
|
end
|
|
|
|
2.times do |i|
|
|
student_in_course(:name => "Student #{i+2}")
|
|
@students << @student
|
|
end
|
|
|
|
get "/courses/#{@course.id}/users/#{@obs.id}"
|
|
f('.more_user_information_link').click
|
|
wait_for_ajaximations
|
|
enrollments = ff(".enrollment")
|
|
expect(enrollments.length).to eq 2
|
|
|
|
expect(enrollments[0]).to include_text @students[0].name
|
|
expect(enrollments[1]).to include_text @students[1].name
|
|
end
|
|
|
|
it "allows conclude/restore without profiles enabled" do
|
|
get "/courses/#{@course.id}/users/#{@student_1.id}"
|
|
f('.more_user_information_link').click
|
|
wait_for_animations
|
|
f('.conclude_enrollment_link').click
|
|
accept_alert
|
|
wait_for_ajaximations
|
|
f('.unconclude_enrollment_link').click
|
|
wait_for_ajaximations
|
|
expect(f('.conclude_enrollment_link')).to be_displayed
|
|
end
|
|
|
|
it "allows conclude/restore with profiles enabled" do
|
|
account = Account.default
|
|
account.settings[:enable_profiles] = true
|
|
account.save!
|
|
|
|
get "/courses/#{@course.id}/users/#{@student_1.id}"
|
|
f('.conclude_enrollment_link').click
|
|
accept_alert
|
|
wait_for_ajaximations
|
|
f('.unconclude_enrollment_link').click
|
|
wait_for_ajaximations
|
|
expect(f('.conclude_enrollment_link')).to be_displayed
|
|
end
|
|
end
|
|
|
|
context "people as a TA" do
|
|
before :once do
|
|
course_with_ta(:active_all => true)
|
|
end
|
|
|
|
before :each do
|
|
user_session @ta
|
|
end
|
|
|
|
it "should validate that the TA cannot delete / conclude or reset course" do
|
|
get "/courses/#{@course.id}/settings"
|
|
expect(f("#content")).not_to contain_css('.delete_course_link')
|
|
expect(f("#content")).not_to contain_css('.reset_course_content_button')
|
|
get "/courses/#{@course.id}/confirm_action?event=conclude"
|
|
expect(f('#unauthorized_message')).to include_text('Access Denied')
|
|
end
|
|
|
|
# TODO reimplement per CNVS-29609, but make sure we're testing at the right level
|
|
it "should validate that a TA cannot rename a teacher"
|
|
|
|
it "includes login id column if the user has :view_user_logins, even if they don't have :manage_students" do
|
|
RoleOverride.create!(:context => Account.default, :permission => 'manage_students', :role => ta_role, :enabled => false)
|
|
get "/courses/#{@course.id}/users"
|
|
index = ff('table.roster th').map(&:text).find_index('Login ID')
|
|
expect(index).not_to be_nil
|
|
ta_row = ff("table.roster #user_#{@ta.id} td").map(&:text)
|
|
expect(ta_row[index].strip).to eq @ta.pseudonym.unique_id
|
|
end
|
|
|
|
it "does not include login id column if the user does not have :view_user_logins, even if they do have :manage_students" do
|
|
RoleOverride.create!(:context => Account.default, :permission => 'view_user_logins', :role => ta_role, :enabled => false)
|
|
get "/courses/#{@course.id}/users"
|
|
index = ff('table.roster th').map(&:text).find_index('Login ID')
|
|
expect(index).to be_nil
|
|
end
|
|
|
|
context "without view all grades permissions" do
|
|
before(:each) do
|
|
['view_all_grades', 'manage_grades'].each do |permission|
|
|
RoleOverride.create!(permission: permission, enabled: false, context: @course.account, role: ta_role)
|
|
end
|
|
end
|
|
|
|
it "doesn't show the Interactions Report link without view all grades permissions" do
|
|
@student = create_user('student@test.com')
|
|
enroll_student(@student)
|
|
get "/courses/#{@course.id}/users/#{@student.id}"
|
|
expect(f("#content")).not_to contain_link("Interactions Report")
|
|
end
|
|
|
|
it "doesn't show the Student Interactions Report link without view all grades permissions" do
|
|
get "/courses/#{@course.id}/users/#{@ta.id}"
|
|
expect(f("#content")).not_to contain_link("Student Interactions Report")
|
|
end
|
|
|
|
context "with new profile flag enabled" do
|
|
before(:each) do
|
|
@course.account.settings[:enable_profiles] = true
|
|
@course.account.save!
|
|
@student = create_user('student@test.com')
|
|
enroll_student(@student)
|
|
end
|
|
|
|
it "doesn't show the Interactions Report link without permissions" do
|
|
get "/courses/#{@course.id}/users/#{@student.id}"
|
|
expect(f("#content")).not_to contain_link("Interactions Report")
|
|
end
|
|
|
|
it "doesn't show the Student Interactions Report link without permissions" do
|
|
get "/courses/#{@course.id}/users/#{@ta.id}"
|
|
expect(f("#content")).not_to contain_link("Student Interactions Report")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "people as a student" do
|
|
|
|
before :once do
|
|
course_with_student(:active_all => true)
|
|
end
|
|
|
|
before :each do
|
|
user_session @student
|
|
end
|
|
|
|
it "should not link avatars to a user's profile page if profiles are disabled" do
|
|
@course.account.settings[:enable_profiles] = false
|
|
@course.account.enable_service(:avatars)
|
|
@course.account.save!
|
|
get "/courses/#{@course.id}/users/#{@student.id}"
|
|
expect(f('.avatar')['href']).not_to be_present
|
|
end
|
|
|
|
end
|
|
|
|
context "course with multiple sections", priority: "2" do
|
|
before :once do
|
|
course_with_teacher active_course: true, active_user: true
|
|
@section2 = @course.course_sections.create!(name: 'section2')
|
|
end
|
|
|
|
before :each do
|
|
user_session @teacher
|
|
end
|
|
|
|
it "should save add people form data" do
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
f('#addUsers').click
|
|
wait_for_ajaximations
|
|
|
|
expect(f(".addpeople")).to be_displayed
|
|
replace_content(f(".addpeople__peoplesearch textarea"),'student@example.com')
|
|
click_INSTUI_Select_option('#peoplesearch_select_role', ta_role.id.to_s, :value)
|
|
click_INSTUI_Select_option('#peoplesearch_select_section', 'Unnamed Course', :text)
|
|
f('#addpeople_next').click
|
|
wait_for_ajaximations
|
|
|
|
expect(f(".peoplevalidationissues__missing")).to be_displayed
|
|
f('#addpeople_back').click
|
|
wait_for_ajaximations
|
|
|
|
# verify form and options have not changed
|
|
expect(f('.addpeople__peoplesearch')).to be_displayed
|
|
expect(f('.addpeople__peoplesearch textarea').text).to eq 'student@example.com'
|
|
expect(f('#peoplesearch_select_role').attribute('value')).to eq 'TA'
|
|
expect(f('#peoplesearch_select_section').attribute('value')).to eq 'Unnamed Course'
|
|
end
|
|
|
|
it "should add a student to a section", priority: "1", test_id: 296460 do
|
|
student = create_user("student@example.com")
|
|
enroll_student(student)
|
|
get "/courses/#{@course.id}/users"
|
|
f(".StudentEnrollment .icon-more").click
|
|
fln("Edit Sections").click
|
|
f(".token_input.browsable").click
|
|
section_input_element = driver.find_element(:name, "token_capture")
|
|
section_input_element.send_keys("section2")
|
|
f('.last.context').click
|
|
wait_for_ajaximations
|
|
ff('.ui-button-text')[1].click
|
|
wait_for_ajaximations
|
|
expect(ff(".StudentEnrollment")[0]).to include_text("section2")
|
|
end
|
|
|
|
it "should remove a student from a section", priority: "1", test_id: 296461 do
|
|
@student = user_factory
|
|
@course.enroll_student(@student, allow_multiple_enrollments: true)
|
|
@course.enroll_student(@student, section: @section2, allow_multiple_enrollments: true)
|
|
get "/courses/#{@course.id}/users"
|
|
f(".StudentEnrollment .icon-more").click
|
|
fln("Edit Sections").click
|
|
fln("Remove user from section2").click
|
|
ff('.ui-button-text')[1].click
|
|
wait_for_ajaximations
|
|
expect(ff(".StudentEnrollment")[0]).not_to include_text("section2")
|
|
end
|
|
|
|
it "should edit a designer's sections" do
|
|
designer = create_user("student@example.com")
|
|
@course.enroll_designer(designer, :enrollment_state => "active")
|
|
get "/courses/#{@course.id}/users"
|
|
f(".DesignerEnrollment .icon-more").click
|
|
fln("Edit Sections").click
|
|
f(".token_input.browsable").click
|
|
section_input_element = driver.find_element(:name, "token_capture")
|
|
section_input_element.send_keys("section2")
|
|
f('.last.context').click
|
|
wait_for_ajaximations
|
|
ff('.ui-button-text')[1].click
|
|
wait_for_ajaximations
|
|
expect(ff(".DesignerEnrollment")[0]).to include_text("section2")
|
|
end
|
|
|
|
it "removes students linked to an observer" do
|
|
@student1 = user_factory; @course.enroll_student(@student1, enrollment_state: :active)
|
|
@student2 = user_factory; @course.enroll_student(@student2, enrollment_state: :active)
|
|
@observer = user_factory
|
|
@course.enroll_user(@observer, 'ObserverEnrollment', enrollment_state: :active, associated_user_id: @student1.id, allow_multiple_enrollments: true)
|
|
@course.enroll_user(@observer, 'ObserverEnrollment', enrollment_state: :active, associated_user_id: @student2.id, allow_multiple_enrollments: true)
|
|
get "/courses/#{@course.id}/users"
|
|
f(".ObserverEnrollment .icon-more").click
|
|
fln("Link to Students").click
|
|
fln("Remove linked student #{@student1.name}", f("#token_#{@student1.id}")).click
|
|
f('.ui-dialog-buttonset .btn-primary').click
|
|
wait_for_ajax_requests
|
|
expect(@observer.enrollments.not_deleted.map(&:associated_user_id)).not_to include @student1.id
|
|
expect(@observer.enrollments.not_deleted.map(&:associated_user_id)).to include @student2.id
|
|
end
|
|
|
|
it "should gray out sections the user doesn't have permission to remove" do
|
|
@student = user_with_managed_pseudonym
|
|
e = @course.enroll_student(@student, allow_multiple_enrollments: true)
|
|
sis = @course.root_account.sis_batches.create
|
|
e.sis_batch_id = sis.id
|
|
e.save!
|
|
get "/courses/#{@course.id}/users"
|
|
ff(".icon-more")[1].click
|
|
fln("Edit Sections").click
|
|
expect(f('#user_sections li.cannot_remove').text).to include @course.default_section.name
|
|
|
|
# add another section (not via SIS) and ensure it remains editable
|
|
f(".token_input.browsable").click
|
|
section_input_element = driver.find_element(:name, "token_capture")
|
|
section_input_element.send_keys("section2")
|
|
f('.last.context').click
|
|
wait_for_ajaximations
|
|
expect(f("a[title='Remove user from section2']")).not_to be_nil
|
|
f('.ui-dialog-buttonset .btn-primary').click
|
|
wait_for_ajaximations
|
|
|
|
ff(".icon-more")[1].click
|
|
fln("Edit Sections").click
|
|
expect(f('#user_sections li.cannot_remove').text).to include @course.default_section.name
|
|
expect(f("a[title='Remove user from section2']")).not_to be_nil
|
|
end
|
|
end
|
|
|
|
it "should get the max total activity time" do
|
|
course_with_admin_logged_in
|
|
sec1 = @course.course_sections.create!(name: "section1")
|
|
sec2 = @course.course_sections.create!(name: "section2")
|
|
@student = user_factory
|
|
e1 = @course.enroll_student(@student, section: sec1, allow_multiple_enrollments: true)
|
|
@course.enroll_student(@student, section: sec2, allow_multiple_enrollments: true)
|
|
Enrollment.where(:id => e1).update_all(:total_activity_time => 900)
|
|
get "/courses/#{@course.id}/users"
|
|
wait_for_ajaximations
|
|
expect(f("#user_#{@student.id} td:nth-child(8)").text.strip).to eq "15:00"
|
|
end
|
|
|
|
it "should filter by role ids" do
|
|
account_model
|
|
course_with_teacher_logged_in(:account => @account)
|
|
old_role = custom_student_role("Role")
|
|
old_role.deactivate!
|
|
|
|
new_role = @account.roles.new(:name => old_role.name)
|
|
new_role.base_role_type = "StudentEnrollment"
|
|
new_role.save!
|
|
new_role
|
|
|
|
student_in_course(:course => @course, :role => new_role, :name => "number2")
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
click_option("select[name=enrollment_role_id]", new_role.id.to_s, :value)
|
|
wait_for_ajaximations
|
|
expect(ff('tr.rosterUser').count).to eq 1
|
|
end
|
|
|
|
context "editing role" do
|
|
before :once do
|
|
course_factory
|
|
@section = @course.course_sections.create!(name: "section1")
|
|
|
|
@teacher = user_with_pseudonym(:active_all => true)
|
|
@enrollment = @course.enroll_teacher(@teacher, enrollment_state: 'active')
|
|
end
|
|
|
|
before :each do
|
|
admin_logged_in
|
|
end
|
|
|
|
it "should let observers have their roles changed if they don't have associated users" do
|
|
@course.enroll_user(@teacher, "ObserverEnrollment", :allow_multiple_enrollments => true)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_dropdown_menu("#user_#{@teacher.id}")
|
|
expect_dropdown_item('editRoles', "#user_#{@teacher.id}")
|
|
end
|
|
|
|
it "should not let observers with associated users have their roles changed" do
|
|
student = user_factory
|
|
@course.enroll_student(student)
|
|
@course.enroll_user(@teacher, "ObserverEnrollment", :allow_multiple_enrollments => true, :associated_user_id => student.id)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_dropdown_menu("#user_#{@teacher.id}")
|
|
expect_no_dropdown_item('editRoles', "#user_#{@teacher.id}")
|
|
end
|
|
|
|
def open_role_dialog(user)
|
|
f("#user_#{user.id} .admin-links a.al-trigger").click
|
|
f("#user_#{user.id} .admin-links a[data-event='editRoles']").click
|
|
end
|
|
|
|
it "should let users change to an observer role" do
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_role_dialog(@teacher)
|
|
|
|
expect(fj("#edit_roles #role_id option:selected")).to include_text("Teacher")
|
|
expect(f("#edit_roles #role_id option[value='#{student_role.id}']")).to be_present
|
|
expect(f("#edit_roles #role_id option[value='#{observer_role.id}']")).to be_present
|
|
end
|
|
|
|
it "should not let users change to a type they don't have permission to manage" do
|
|
@course.root_account.role_overrides.create!(:role => admin_role, :permission => 'manage_students', :enabled => false)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_role_dialog(@teacher)
|
|
expect(f("#edit_roles #role_id option[value='#{ta_role.id}']")).to be_present
|
|
expect(f("#content")).not_to contain_css("#edit_roles #role_id option[value='#{student_role.id}']")
|
|
end
|
|
|
|
it "should retain the same enrollment state" do
|
|
role_name = 'Custom Teacher'
|
|
role = @course.account.roles.create(:name => role_name)
|
|
role.base_role_type = 'TeacherEnrollment'
|
|
role.save!
|
|
@enrollment.deactivate
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_role_dialog(@teacher)
|
|
click_option("#edit_roles #role_id", role.id.to_s, :value)
|
|
f('.ui-dialog-buttonpane .btn-primary').click
|
|
wait_for_ajaximations
|
|
assert_flash_notice_message "Role successfully updated"
|
|
|
|
expect(f("#user_#{@teacher.id}")).to include_text(role_name)
|
|
@enrollment.reload
|
|
expect(@enrollment).to be_deleted
|
|
|
|
new_enrollment = @teacher.enrollments.not_deleted.first
|
|
expect(new_enrollment.role).to eq role
|
|
expect(new_enrollment.workflow_state).to eq "inactive"
|
|
end
|
|
|
|
it "should work with enrollments in different sections" do
|
|
enrollment2 = @course.enroll_user(@teacher, "TeacherEnrollment", :allow_multiple_enrollments => true, :section => @section)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_role_dialog(@teacher)
|
|
click_option("#edit_roles #role_id", ta_role.id.to_s, :value)
|
|
f('.ui-dialog-buttonpane .btn-primary').click
|
|
wait_for_ajaximations
|
|
assert_flash_notice_message "Role successfully updated"
|
|
|
|
expect(@enrollment.reload).to be_deleted
|
|
expect(enrollment2.reload).to be_deleted
|
|
|
|
new_enrollment1 = @teacher.enrollments.not_deleted.where(:course_section_id => @course.default_section).first
|
|
new_enrollment2 = @teacher.enrollments.not_deleted.where(:course_section_id => @section).first
|
|
expect(new_enrollment1.role).to eq ta_role
|
|
expect(new_enrollment2.role).to eq ta_role
|
|
end
|
|
|
|
it "should work with preexiting enrollments in the destination role" do
|
|
# should not try to overwrite this one
|
|
enrollment2 = @course.enroll_user(@teacher, "TaEnrollment", :allow_multiple_enrollments => true)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_role_dialog(@teacher)
|
|
click_option("#edit_roles #role_id", ta_role.id.to_s, :value)
|
|
f('.ui-dialog-buttonpane .btn-primary').click
|
|
wait_for_ajaximations
|
|
assert_flash_notice_message "Role successfully updated"
|
|
|
|
expect(@enrollment.reload).to be_deleted
|
|
expect(enrollment2.reload).to_not be_deleted
|
|
end
|
|
|
|
it "should work with multiple enrollments in one section" do
|
|
# shouldn't conflict with each other - should only add one enrollment for the new role
|
|
enrollment2 = @course.enroll_user(@teacher, "TaEnrollment", :allow_multiple_enrollments => true)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
open_role_dialog(@teacher)
|
|
expect(f("#edit_roles")).to include_text("This user has multiple roles") # warn them that both roles will be removed
|
|
click_option("#edit_roles #role_id", student_role.id.to_s, :value)
|
|
f('.ui-dialog-buttonpane .btn-primary').click
|
|
wait_for_ajaximations
|
|
assert_flash_notice_message "Role successfully updated"
|
|
|
|
expect(@enrollment.reload).to be_deleted
|
|
expect(enrollment2.reload).to be_deleted
|
|
|
|
new_enrollment = @teacher.enrollments.not_deleted.first
|
|
expect(new_enrollment.role).to eq student_role
|
|
end
|
|
|
|
it "should not show the option to edit roles for a soft-concluded course" do
|
|
@course.conclude_at = 2.days.ago
|
|
@course.restrict_enrollments_to_course_dates = true
|
|
@course.save!
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
open_dropdown_menu("#user_#{@teacher.id}")
|
|
expect_no_dropdown_item('editRoles', "#user_#{@teacher.id}")
|
|
end
|
|
|
|
it "should not show the option to edit roles for a SIS imported enrollment" do
|
|
sis = @course.root_account.sis_batches.create
|
|
student = user_with_pseudonym(:active_all => true)
|
|
enrollment = @course.enroll_teacher(student)
|
|
enrollment.sis_batch_id = sis.id
|
|
enrollment.save!
|
|
|
|
user_session(@teacher)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
open_dropdown_menu("#user_#{student.id}")
|
|
expect_no_dropdown_item('editRoles', "#user_#{student.id}")
|
|
end
|
|
|
|
it "should redirect to groups page " do
|
|
user_session(@teacher)
|
|
|
|
get "/courses/#{@course.id}/users"
|
|
|
|
group_link = ff('#group_categories_tabs .ui-tabs-nav li').last
|
|
expect(group_link).to include_text("Groups")
|
|
|
|
expect_new_page_load { group_link.click }
|
|
expect(driver.current_url).to include("/courses/#{@course.id}/groups")
|
|
end
|
|
|
|
context "student tray" do
|
|
before :once do
|
|
@account = Account.default
|
|
@account.enable_feature!(:student_context_cards)
|
|
@student = create_user('student@test.com')
|
|
@enrollment = @course.enroll_student(@student, enrollment_state: :active)
|
|
end
|
|
|
|
it "course people page should display student name in tray", priority: "1", test_id: 3022066 do
|
|
get("/courses/#{@course.id}/users")
|
|
f("a[data-student_id='#{@student.id}']").click
|
|
expect(f(".StudentContextTray-Header__Name h2 a")).to include_text("student@test.com")
|
|
expect(f('.StudentContextTray-Header')).to contain_css('i.icon-email')
|
|
end
|
|
|
|
it "should not display the message button if the student enrollment is inactive" do
|
|
@enrollment.deactivate
|
|
get("/courses/#{@course.id}/users")
|
|
f("a[data-student_id='#{@student.id}']").click
|
|
expect(f('.StudentContextTray-Header')).not_to contain_css('i.icon-email')
|
|
end
|
|
|
|
context "student context card tool placement" do
|
|
before :once do
|
|
@tool = Account.default.context_external_tools.new(:name => "a", :domain => "google.com", :consumer_key => '12345', :shared_secret => 'secret')
|
|
@tool.student_context_card = {
|
|
:url => "http://www.example.com",
|
|
:text => "See data for this student or whatever",
|
|
:required_permissions => "view_all_grades,manage_grades"}
|
|
@tool.save!
|
|
end
|
|
|
|
it "should show a link to the tool" do
|
|
get("/courses/#{@course.id}/users")
|
|
f("a[data-student_id='#{@student.id}']").click
|
|
|
|
link = ff(".StudentContextTray-QuickLinks__Link a")[1]
|
|
expect(link).to include_text(@tool.label_for(:student_context_card))
|
|
expect(link['href']).to eq course_external_tool_url(@course, @tool) + "?launch_type=student_context_card&student_id=#{@student.id}"
|
|
end
|
|
|
|
it "should not show link if the user doesn't have the permissions specified by the tool" do
|
|
@course.account.role_overrides.create!(:permission => "manage_grades", :role => admin_role, :enabled => false)
|
|
get("/courses/#{@course.id}/users")
|
|
f("a[data-student_id='#{@student.id}']").click
|
|
|
|
link = ff(".StudentContextTray-QuickLinks__Link a")[1]
|
|
expect(link).to be_nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
it "should not show unenroll link to admins without permissions" do
|
|
account_admin_user(:active_all => true)
|
|
user_session(@admin)
|
|
|
|
course_with_student(:active_all => true)
|
|
get "/users/#{@student.id}"
|
|
|
|
expect(f("#courses")).to contain_css(".unenroll_link")
|
|
|
|
Account.default.role_overrides.create!(:permission => "manage_students", :enabled => false, :role => admin_role)
|
|
refresh_page
|
|
|
|
expect(f("#courses")).to_not contain_css(".unenroll_link")
|
|
end
|
|
end
|