309 lines
12 KiB
Ruby
309 lines
12 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#
|
|
# Copyright (C) 2015 - present Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
require_relative "../common"
|
|
require_relative "../helpers/files_common"
|
|
require_relative "../helpers/announcements_common"
|
|
require_relative "../helpers/color_common"
|
|
|
|
describe "dashcards" do
|
|
include_context "in-process server selenium tests"
|
|
include Factories
|
|
include AnnouncementsCommon
|
|
include ColorCommon
|
|
include FilesCommon
|
|
|
|
context "as a student" do
|
|
before do
|
|
@course = course_factory(active_all: true)
|
|
course_with_student_logged_in(active_all: true)
|
|
end
|
|
|
|
it "shows the trigger button for dashboard options menu in new UI", priority: "1" do
|
|
get "/"
|
|
# verify features of new UI
|
|
expect(f("#application.ic-app")).to be_present
|
|
expect(f(".ic-app-header__main-navigation")).to be_present
|
|
# verify the trigger button for the menu is present
|
|
expect(f("#DashboardOptionsMenu_Container button")).to be_present
|
|
end
|
|
|
|
it "toggles dashboard based on the selected menu view", priority: "1" do
|
|
get "/"
|
|
# verify dashboard card view and trigger button for menu
|
|
expect(f(".ic-DashboardCard__link")).to be_displayed
|
|
expect(f("#DashboardOptionsMenu_Container button")).to be_present
|
|
# open dashboard options menu and select recent activity view
|
|
f("#DashboardOptionsMenu_Container button").click
|
|
fj('span[role="menuitemradio"]:contains("Recent Activity")').click
|
|
# verify recent activity view
|
|
expect(f("#dashboard-activity")).to include_text("Recent Activity")
|
|
end
|
|
|
|
it "redirects to announcements index", priority: "1" do
|
|
# Icon will not display unless there is an announcement.
|
|
create_announcement
|
|
get "/"
|
|
|
|
f("a.announcements").click
|
|
expect(driver.current_url).to include("/courses/#{@course.id}/announcements")
|
|
end
|
|
|
|
it "redirects to assignments index", priority: "1" do
|
|
# Icon will not display unless there is an assignment.
|
|
@course.assignments.create!(title: "assignment 1", name: "assignment 1")
|
|
get "/"
|
|
|
|
f("a.assignments").click
|
|
expect(driver.current_url).to include("/courses/#{@course.id}/assignments")
|
|
end
|
|
|
|
it "redirects to discussions index", priority: "1" do
|
|
# Icon will not display unless there is a discussion.
|
|
@course.discussion_topics.create!(title: "discussion 1", message: "This is a message.")
|
|
get "/"
|
|
|
|
f("a.discussions").click
|
|
expect(driver.current_url).to include("/courses/#{@course.id}/discussion_topics")
|
|
end
|
|
|
|
it "redirects to files index", priority: "1" do
|
|
# Icon will not display unless there is a file.
|
|
add_file(fixture_file_upload("example.pdf", "application/pdf"), @course, "example.pdf")
|
|
get "/"
|
|
|
|
f("a.files").click
|
|
expect(driver.current_url).to include("/courses/#{@course.id}/files")
|
|
end
|
|
|
|
it "displays color picker", priority: "1" do
|
|
get "/"
|
|
f(".ic-DashboardCard__header-button").click
|
|
expect(f(".ColorPicker__Container")).to be_displayed
|
|
end
|
|
|
|
it "displays dashcard icons for course contents", priority: "1" do
|
|
# create discussion, announcement, discussion and files as these 4 icons need to be displayed
|
|
@course.discussion_topics.create!(title: "discussion 1", message: "This is a message.")
|
|
@course.assignments.create!(title: "assignment 1", name: "assignment 1")
|
|
create_announcement
|
|
add_file(fixture_file_upload("example.pdf", "application/pdf"), @course, "example.pdf")
|
|
get "/"
|
|
|
|
expect(f("a.announcements")).to be_present
|
|
expect(f("a.assignments")).to be_present
|
|
expect(f("a.discussions")).to be_present
|
|
expect(f("a.files")).to be_present
|
|
end
|
|
|
|
it "shows announcement created notifications in dashcard", priority: "1" do
|
|
create_announcement("New Announcement")
|
|
get "/"
|
|
expect(f("a.announcements .unread_count").text).to include("1")
|
|
end
|
|
|
|
it "does not show hidden tab icons on dashcard", priority: "1" do
|
|
# setup
|
|
@course.tab_configuration = [{ "id" => Course::TAB_DISCUSSIONS, "hidden" => true }]
|
|
@course.save!
|
|
get "/"
|
|
# need not check for announcements, assignments and files as we have not created any
|
|
expect(f("#content")).not_to contain_css(".ic-DashboardCard__action-container .discussions")
|
|
end
|
|
|
|
it "does not show unread notification in dashcard after reading announcements", priority: "1" do
|
|
# Create and have the announcement read by the user.
|
|
topic = create_announcement("New Announcement")
|
|
topic.change_read_state("read", @user)
|
|
|
|
# The unread notifications should go away since the user has read the announcement
|
|
get "/"
|
|
expect(f("#content")).not_to contain_css("a.announcements .unread_count")
|
|
end
|
|
|
|
it "shows discussions created notifications in dashcard", priority: "1" do
|
|
@course.discussion_topics.create!(title: "discussion 1", message: "This is a message.")
|
|
get "/"
|
|
expect(f("a.discussions .unread_count").text).to include("1")
|
|
end
|
|
|
|
it "does not show unread notification in dashcard after reading discussions", priority: "1" do
|
|
# Create and have the discussion read by the user.
|
|
topic = @course.discussion_topics.create!(title: "discussion 1", message: "This is a message.")
|
|
topic.change_read_state("read", @user)
|
|
|
|
# The unread notifications should go away since the user has read the announcement
|
|
get "/"
|
|
expect(f("#content")).not_to contain_css("a.discussions .unread_count")
|
|
end
|
|
|
|
# These tests are currently marked as 'ignore'
|
|
# it 'should show assignments created notifications in dashcard', priority: "1"
|
|
#
|
|
# it 'should show files created notifications in dashcard', priority: "1"
|
|
|
|
context "course name and code display" do
|
|
before do
|
|
@course1 = course_model
|
|
@course1.offer!
|
|
@course1.save!
|
|
enrollment = student_in_course(course: @course1, user: @student)
|
|
enrollment.accept!
|
|
end
|
|
|
|
it "displays special characters in a course title", priority: "1" do
|
|
@course1.name = '(/*-+_@&$#%)"Course 1"æøåñó?äçíì[{c}]<strong>stuff</strong> )'
|
|
@course1.save!
|
|
get "/"
|
|
expect(f(".ic-DashboardCard__header-title").text).to eq(@course1.name)
|
|
end
|
|
|
|
it "displays special characters in course code", priority: "1" do
|
|
# code is not displayed if the course name is too long
|
|
@course1.name = "test"
|
|
@course1.course_code = '(/*-+_@&$#%)"Course 1"[{c}]<strong>stuff</strong> )'
|
|
@course1.save!
|
|
get "/"
|
|
# as course codes are always displayed in upper case
|
|
expect(f(".ic-DashboardCard__header-subtitle").text).to eq(@course1.course_code)
|
|
end
|
|
end
|
|
|
|
context "dashcard custom color calendar" do
|
|
before do
|
|
# create another course to ensure the color matches to the right course
|
|
@course1 = course_factory(
|
|
course_name: "Second Course",
|
|
active_course: true
|
|
)
|
|
enrollment = student_in_course(course: @course1, user: @student)
|
|
enrollment.accept!
|
|
end
|
|
|
|
it "initially matches color to the dashcard", priority: "1" do
|
|
get "/calendar"
|
|
calendar_color = f(".context-list-toggle-box.group_course_#{@course1.id}").style("background-color")
|
|
get "/"
|
|
hero = f("div[aria-label='#{@course1.name}'] .ic-DashboardCard__header_hero").style("background-color")
|
|
expect(hero).to eq(calendar_color)
|
|
end
|
|
|
|
it "customizes color by selecting from color palette on the calendar page", priority: "1" do
|
|
select_color_palette_from_calendar_page
|
|
|
|
# pick a random color from the default 15 colors
|
|
new_color = ff(".ColorPicker__ColorContainer button.ColorPicker__ColorBlock")[rand(0...15)]
|
|
# anything to make chrome happy
|
|
driver.action.move_to(new_color).click.perform
|
|
new_color_code = f("#ColorPickerCustomInput-course_#{@course1.id}").attribute(:value)
|
|
f("#ColorPicker__Apply").click
|
|
wait_for_ajaximations
|
|
|
|
new_displayed_color = f("[role='checkbox'].group_course_#{@course1.id}").style("color")
|
|
|
|
expect("#" + rgba_to_hex(new_displayed_color)).to eq(new_color_code)
|
|
expect(f("#group_course_#{@course1.id}_checkbox_label")).to include_text(@course1.name)
|
|
end
|
|
end
|
|
|
|
context "dashcard color picker" do
|
|
before do
|
|
get "/"
|
|
f(".ic-DashboardCard__header-button").click
|
|
wait_for_ajaximations
|
|
end
|
|
|
|
it "customizes dashcard color by selecting from color palette", priority: "1" do
|
|
# Gets the default background color
|
|
old_color = @user.reload.custom_colors.fetch("course_#{@course.id}")
|
|
|
|
# Picks a new color
|
|
f(".ColorPicker__Container .ColorPicker__ColorBlock:nth-of-type(7)").click
|
|
wait_for_ajaximations
|
|
new_color = f(".ColorPicker__CustomInputContainer .ColorPicker__ColorPreview").attribute(:title)
|
|
|
|
# make sure that we choose a new color for background
|
|
if old_color == new_color
|
|
f(".ColorPicker__Container .ColorPicker__ColorBlock:nth-of-type(8)").click
|
|
wait_for_ajaximations
|
|
new_color = f(".ColorPicker__CustomInputContainer .ColorPicker__ColorPreview").attribute(:title)
|
|
end
|
|
|
|
# Apply new color and verify it sticks
|
|
f(".ColorPicker__Container #ColorPicker__Apply").click
|
|
rgb = convert_hex_to_rgb_color(new_color)
|
|
expect(old_color).not_to eq new_color
|
|
expect(f(".ic-DashboardCard__header_hero")).to have_attribute("style", rgb)
|
|
|
|
keep_trying_until do
|
|
expect(@user.reload.custom_colors.fetch("course_#{@course.id}")).to eq new_color
|
|
end
|
|
end
|
|
|
|
it "customizes dashcard color", priority: "1" do
|
|
hex = random_hex_color
|
|
expect(f(".ColorPicker__Container")).to be_displayed
|
|
replace_content(f("#ColorPickerCustomInput-#{@course.asset_string}"), hex)
|
|
f(".ColorPicker__Container #ColorPicker__Apply").click
|
|
hero = f(".ic-DashboardCard__header_hero")
|
|
if hero.attribute(:style).include?("rgb")
|
|
rgb = convert_hex_to_rgb_color(hex)
|
|
expect(hero).to have_attribute("style", rgb)
|
|
else
|
|
expect(hero).to have_attribute("style", hex)
|
|
end
|
|
end
|
|
|
|
it "sets course nickname" do
|
|
replace_content(f("#NicknameInput"), "course nickname!")
|
|
f(".ColorPicker__Container #ColorPicker__Apply").click
|
|
wait_for_ajaximations
|
|
expect(f(".ic-DashboardCard__header-title").text).to include "course nickname!"
|
|
expect(@student.reload.course_nickname(@course)).to eq "course nickname!"
|
|
end
|
|
|
|
it "sets course nickname when enter is pressed" do
|
|
replace_content(f("#NicknameInput"), "course nickname too!")
|
|
f("#NicknameInput").send_keys(:enter)
|
|
wait_for_ajaximations
|
|
expect(f(".ic-DashboardCard__header-title").text).to include "course nickname too!"
|
|
expect(@student.reload.course_nickname(@course)).to eq "course nickname too!"
|
|
end
|
|
|
|
it "sets dashcard color and course nickname at once" do
|
|
replace_content(f("#NicknameInput"), "course nickname frd!")
|
|
replace_content(f("#ColorPickerCustomInput-#{@course.asset_string}"), "#000000")
|
|
f(".ColorPicker__Container #ColorPicker__Apply").click
|
|
wait_for_ajaximations
|
|
expect(@student.reload.course_nickname(@course)).to eq "course nickname frd!"
|
|
expect(@student.custom_colors[@course.asset_string]).to eq "#000000"
|
|
end
|
|
end
|
|
end
|
|
|
|
def select_color_palette_from_calendar_page
|
|
get "/calendar"
|
|
raise "Not the right course" unless f("#calendars-context-list li:nth-of-type(2)").text.include? @course1.name
|
|
|
|
f("#calendars-context-list li:nth-of-type(2) .ContextList__MoreBtn").click
|
|
wait_for_ajaximations
|
|
expect(f(".ColorPicker__Container")).to be_displayed
|
|
end
|
|
end
|