mirror of
https://github.com/discourse/discourse.git
synced 2024-12-21 13:03:43 +08:00
c8e03f251f
Docking is a leftover from older header code, it looks like it is no longer used in the app. This helper was registering a scroll event listener to check if the header should be docked or not. Initially, a "docked" class was added to the body element. This class persisted through the lifecycle of the app and the scroll event was doing no useful work. Some older themes may still use it in CSS, that will cause a regression, from a quick look at existing code, the surface area should be small (2-3 themes). It's worth removing the event listener for performance reasons. We could possibly add the class "docked" statically to the body element, but it's redundant. It's best to clean up the relevant CSS in themes, where applicable.
307 lines
11 KiB
Ruby
307 lines
11 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
RSpec.describe "Glimmer Header", type: :system do
|
||
let(:header) { PageObjects::Pages::Header.new }
|
||
let(:search) { PageObjects::Pages::Search.new }
|
||
fab!(:current_user) { Fabricate(:user) }
|
||
fab!(:topic)
|
||
|
||
it "renders basics" do
|
||
visit "/"
|
||
expect(page).to have_css("header.d-header")
|
||
expect(page).to have_css("#site-logo")
|
||
end
|
||
|
||
it "displays sign up / login buttons" do
|
||
visit "/"
|
||
expect(page).to have_css("button.sign-up-button")
|
||
expect(page).to have_css("button.login-button")
|
||
|
||
find("button.sign-up-button").click
|
||
expect(page).to have_css(".d-modal.create-account")
|
||
|
||
header.click_outside
|
||
|
||
find("button.login-button").click
|
||
expect(page).to have_css(".d-modal.login-modal")
|
||
end
|
||
|
||
it "shows login button when login required" do
|
||
SiteSetting.login_required = true
|
||
|
||
visit "/"
|
||
expect(page).to have_css("button.login-button")
|
||
expect(page).to have_css("button.sign-up-button")
|
||
expect(page).not_to have_css("#search-button")
|
||
expect(page).not_to have_css("button.btn-sidebar-toggle")
|
||
end
|
||
|
||
it "renders unread notifications count when user's notifications count is updated" do
|
||
Fabricate(
|
||
:notification,
|
||
user: current_user,
|
||
high_priority: true,
|
||
read: false,
|
||
created_at: 8.minutes.ago,
|
||
)
|
||
|
||
sign_in(current_user)
|
||
visit "/"
|
||
expect(page).to have_selector(
|
||
".header-dropdown-toggle.current-user .unread-notifications",
|
||
text: "1",
|
||
)
|
||
end
|
||
|
||
it "doesn't show pending reviewables count for non-legacy navigation menu" do
|
||
SiteSetting.navigation_menu = "sidebar"
|
||
current_user.update!(admin: true)
|
||
Fabricate(:reviewable)
|
||
|
||
sign_in(current_user)
|
||
visit "/"
|
||
expect(page).not_to have_selector(".hamburger-dropdown .badge-notification")
|
||
end
|
||
|
||
it "closes revamped menu when clicking outside" do
|
||
sign_in(current_user)
|
||
visit "/"
|
||
find(".header-dropdown-toggle.current-user").click
|
||
expect(page).to have_selector(".user-menu.revamped")
|
||
find("header.d-header").click
|
||
expect(page).not_to have_selector(".user-menu.revamped")
|
||
end
|
||
|
||
it "closes menu-panel when keyboard focus leaves it" do
|
||
sign_in(current_user)
|
||
visit "/"
|
||
find(".header-dropdown-toggle.current-user").click
|
||
find("##{header.active_element_id}").send_keys(%i[shift tab])
|
||
expect(page).not_to have_selector(".user-menu.revamped")
|
||
end
|
||
|
||
it "automatically focuses the first link in the hamburger panel" do
|
||
SiteSetting.navigation_menu = "header dropdown"
|
||
|
||
visit "/"
|
||
|
||
find("#toggle-hamburger-menu").click
|
||
expect(page).to have_selector(".panel-body")
|
||
first_link = find(".panel-body a", match: :first)
|
||
first_link_href = first_link[:href]
|
||
focused_element_href = evaluate_script("document.activeElement.href")
|
||
|
||
expect(focused_element_href).to eq(first_link_href)
|
||
end
|
||
|
||
it "sets header's height css property" do
|
||
sign_in(current_user)
|
||
visit "/"
|
||
header.resize_element(".d-header", 90)
|
||
wait_for(timeout: 100) do
|
||
header.get_computed_style_value(".d-header", "--header-offset") == "90px"
|
||
end
|
||
expect(header.get_computed_style_value(".d-header", "--header-offset")).to eq("90px")
|
||
|
||
header.resize_element(".d-header", 60)
|
||
wait_for(timeout: 100) do
|
||
header.get_computed_style_value(".d-header", "--header-offset") == "60px"
|
||
end
|
||
expect(header.get_computed_style_value(".d-header", "--header-offset")).to eq("60px")
|
||
end
|
||
|
||
it "moves focus between tabs using arrow keys" do
|
||
sign_in(current_user)
|
||
visit "/"
|
||
find(".header-dropdown-toggle.current-user").click
|
||
expect(header.active_element_id).to eq("user-menu-button-all-notifications")
|
||
|
||
find("##{header.active_element_id}").send_keys(:arrow_down)
|
||
expect(header.active_element_id).to eq("user-menu-button-replies")
|
||
|
||
4.times { find("##{header.active_element_id}").send_keys(:arrow_down) }
|
||
expect(header.active_element_id).to eq("user-menu-button-profile")
|
||
|
||
find("##{header.active_element_id}").send_keys(:arrow_down)
|
||
expect(header.active_element_id).to eq("user-menu-button-all-notifications")
|
||
|
||
find("##{header.active_element_id}").send_keys(:arrow_up)
|
||
expect(header.active_element_id).to eq("user-menu-button-profile")
|
||
end
|
||
|
||
it "prioritizes new personal messages bubble over unseen reviewables and regular notifications bubbles" do
|
||
Fabricate(:private_message_notification, user: current_user)
|
||
Fabricate(
|
||
:notification,
|
||
user: current_user,
|
||
high_priority: true,
|
||
read: false,
|
||
created_at: 8.minutes.ago,
|
||
)
|
||
|
||
sign_in(current_user)
|
||
visit "/"
|
||
expect(page).not_to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.unread-notifications",
|
||
)
|
||
expect(page).not_to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.with-icon.new-reviewables",
|
||
)
|
||
|
||
expect(page).to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.with-icon.new-pms",
|
||
)
|
||
expect(page).to have_css(".d-icon-envelope")
|
||
expect(
|
||
find(".header-dropdown-toggle.current-user .badge-notification.with-icon.new-pms")[:title],
|
||
).to eq(I18n.t("js.notifications.tooltip.new_message_notification", count: 1))
|
||
end
|
||
|
||
it "prioritizes unseen reviewables bubble over regular notifications" do
|
||
current_user.update!(admin: true)
|
||
Fabricate(:reviewable)
|
||
|
||
sign_in(current_user)
|
||
visit "/"
|
||
expect(page).not_to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.unread-notifications",
|
||
)
|
||
expect(page).to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.with-icon.new-reviewables",
|
||
)
|
||
expect(page).not_to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.with-icon.new-pms",
|
||
)
|
||
end
|
||
|
||
it "shows regular notifications bubble if there are neither new personal messages nor unseen reviewables" do
|
||
Fabricate.times(
|
||
3,
|
||
:notification,
|
||
user: current_user,
|
||
high_priority: true,
|
||
read: false,
|
||
created_at: 8.minutes.ago,
|
||
)
|
||
|
||
sign_in(current_user)
|
||
visit "/"
|
||
expect(page).to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.unread-notifications",
|
||
text: "3",
|
||
)
|
||
expect(
|
||
find(".header-dropdown-toggle.current-user .badge-notification.unread-notifications")[:title],
|
||
).to eq(I18n.t("js.notifications.tooltip.regular", count: 3))
|
||
expect(page).not_to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.with-icon.new-reviewables",
|
||
)
|
||
expect(page).not_to have_selector(
|
||
".header-dropdown-toggle.current-user .badge-notification.with-icon.new-pms",
|
||
)
|
||
end
|
||
|
||
context "when resetting password" do
|
||
fab!(:current_user) { Fabricate(:user) }
|
||
|
||
it "does not show search, login, or signup buttons" do
|
||
email_token =
|
||
current_user.email_tokens.create!(
|
||
email: current_user.email,
|
||
scope: EmailToken.scopes[:password_reset],
|
||
)
|
||
|
||
visit "/u/password-reset/#{email_token.token}"
|
||
expect(page).not_to have_css("button.login-button")
|
||
expect(page).not_to have_css("button.sign-up-button")
|
||
expect(page).not_to have_css(".search-dropdown #search-button")
|
||
end
|
||
end
|
||
|
||
context "when logged in and login required" do
|
||
fab!(:current_user) { Fabricate(:user) }
|
||
|
||
it "displays current user when logged in and login required" do
|
||
SiteSetting.login_required = true
|
||
sign_in(current_user)
|
||
|
||
visit "/"
|
||
expect(page).not_to have_css("button.login-button")
|
||
expect(page).not_to have_css("button.sign-up-button")
|
||
expect(page).to have_css("#search-button")
|
||
expect(page).to have_css("button.btn-sidebar-toggle")
|
||
expect(page).to have_css("#current-user")
|
||
end
|
||
end
|
||
|
||
context "when cmd + f keyboard shortcut pressed - when within a topic with 20+ posts" do
|
||
before { sign_in(current_user) }
|
||
fab!(:posts) { Fabricate.times(21, :post, topic: topic) }
|
||
|
||
it "opens search on first press, and closes on the second" do
|
||
visit "/t/#{topic.slug}/#{topic.id}"
|
||
header.search_in_topic_keyboard_shortcut
|
||
expect(search).to have_search_menu_visible
|
||
header.search_in_topic_keyboard_shortcut
|
||
expect(search).to have_no_search_menu_visible
|
||
end
|
||
end
|
||
|
||
describe "mobile topic-info" do
|
||
fab!(:topic)
|
||
fab!(:posts) { Fabricate.times(21, :post, topic: topic) }
|
||
|
||
it "only shows when scrolled down", mobile: true do
|
||
visit "/t/#{topic.slug}/#{topic.id}"
|
||
|
||
expect(page).to have_css("#topic-title") # Main topic title
|
||
expect(page).to have_css("header.d-header .auth-buttons .login-button") # header buttons visible when no topic-info in header
|
||
|
||
page.execute_script("document.querySelector('#post_4').scrollIntoView()")
|
||
|
||
expect(page).not_to have_css("header.d-header .auth-buttons .login-button") # No header buttons
|
||
expect(page).to have_css("header.d-header .title-wrapper .topic-link") # Title is shown in header
|
||
|
||
page.execute_script("window.scrollTo(0, 0)")
|
||
expect(page).to have_css("#topic-title") # Main topic title
|
||
expect(page).to have_css("header.d-header .auth-buttons .login-button") # header buttons visible when no topic-info in header
|
||
end
|
||
|
||
it "shows when navigating direct to a later post", mobile: true do
|
||
visit "/t/#{topic.slug}/#{topic.id}/4"
|
||
|
||
expect(page).not_to have_css("header.d-header .auth-buttons .login-button") # No header buttons
|
||
expect(page).to have_css("header.d-header .title-wrapper .topic-link") # Title is shown in header
|
||
end
|
||
|
||
it "shows when jumping from OP to much later post", mobile: true do
|
||
visit "/t/#{topic.slug}/#{topic.id}"
|
||
|
||
expect(page).to have_css("#topic-title") # Main topic title
|
||
expect(page).to have_css("header.d-header .auth-buttons .login-button") # header buttons visible when no topic-info in header
|
||
|
||
page.execute_script("Discourse.visit('/t/#{topic.slug}/#{topic.id}/21');")
|
||
|
||
expect(page).to have_css("#post_21")
|
||
|
||
expect(page).not_to have_css("header.d-header .auth-buttons .login-button") # No header buttons
|
||
expect(page).to have_css("header.d-header .title-wrapper .topic-link") # Title is shown in header
|
||
end
|
||
|
||
it "shows and hides do-not-disturb icon" do
|
||
sign_in current_user
|
||
visit "/"
|
||
|
||
header = find(".d-header")
|
||
expect(header).not_to have_css(".do-not-disturb-background")
|
||
|
||
current_user.publish_do_not_disturb(ends_at: 1.hour.from_now)
|
||
expect(header).to have_css(".d-header .do-not-disturb-background")
|
||
|
||
current_user.publish_do_not_disturb(ends_at: 1.second.from_now)
|
||
|
||
expect(header).not_to have_css(".d-header .do-not-disturb-background")
|
||
end
|
||
end
|
||
end
|