mirror of
https://github.com/discourse/discourse.git
synced 2026-08-14 13:58:53 +08:00
When the chat drawer is closed and reopened on a starred channel, the back button took the user to the default channels list instead of the starred-channels list they had originally come from. Root cause: `chatHistory.visit(route)` always appended to history. When the drawer reopens to `lastKnownChatURL` (the channel itself), the same route is appended a second time, shifting `previousRoute` off the original `chat.starred-channels` entry. The back-button fallback in `drawer-routes/channel.gjs` then routed to `chat.channels`. Fix: dedupe consecutive identical route visits in `chatHistory.visit` by comparing name and params (via `deepEqual`). Reopening to the same URL no longer clobbers the user's real navigation context. Adds a unit test for the dedup behavior, a system spec covering the close/reopen scenario, and a view-agnostic `open_channel_row` helper on the drawer page object (the existing `open_channel` is scoped to the channels-list view only and doesn't work from the starred view). https://meta.discourse.org/t/403431
207 lines
7 KiB
Ruby
Vendored
207 lines
7 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe "Drawer - starred channels" do
|
|
fab!(:current_user, :user)
|
|
fab!(:channel_1) { Fabricate(:category_channel, name: "Channel A") }
|
|
fab!(:channel_2) { Fabricate(:category_channel, name: "Channel B") }
|
|
|
|
let(:chat_page) { PageObjects::Pages::Chat.new }
|
|
let(:drawer_page) { PageObjects::Pages::ChatDrawer.new }
|
|
|
|
before do
|
|
chat_system_bootstrap
|
|
channel_1.add(current_user)
|
|
channel_2.add(current_user)
|
|
sign_in(current_user)
|
|
chat_page.prefers_drawer
|
|
end
|
|
|
|
context "when user has starred channels" do
|
|
before { channel_1.membership_for(current_user).update!(starred: true) }
|
|
|
|
it "defaults to starred channels, shows footer tab, and can open channel" do
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
|
|
expect(drawer_page).to have_open_starred_channels
|
|
expect(page).to have_css("#c-footer-starred.--active")
|
|
|
|
find(".chat-channel-row[data-chat-channel-id='#{channel_1.id}']").click
|
|
expect(drawer_page).to have_open_channel(channel_1)
|
|
end
|
|
end
|
|
|
|
context "when user has no starred channels" do
|
|
it "does not show starred tab in footer" do
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
|
|
expect(page).to have_no_css("#c-footer-starred")
|
|
end
|
|
end
|
|
|
|
context "when user has starred both channels and DMs" do
|
|
fab!(:user_1) { Fabricate(:user, username: "alice") }
|
|
fab!(:user_2) { Fabricate(:user, username: "bob") }
|
|
fab!(:dm_channel_1) { Fabricate(:direct_message_channel, users: [current_user, user_1]) }
|
|
fab!(:dm_channel_2) { Fabricate(:direct_message_channel, users: [current_user, user_2]) }
|
|
|
|
before do
|
|
channel_1.membership_for(current_user).update!(starred: true)
|
|
channel_2.membership_for(current_user).update!(starred: true)
|
|
dm_channel_1.membership_for(current_user).update!(starred: true)
|
|
dm_channel_2.membership_for(current_user).update!(starred: true)
|
|
end
|
|
|
|
it "sorts by activity: unread public, unread DMs, read public, read DMs" do
|
|
Fabricate(:chat_message, chat_channel: channel_2, user: user_1)
|
|
Fabricate(:chat_message, chat_channel: dm_channel_1, user: user_1)
|
|
channel_2.membership_for(current_user).update!(last_viewed_at: 1.minute.ago)
|
|
dm_channel_1.membership_for(current_user).update!(last_viewed_at: 1.minute.ago)
|
|
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
drawer_page.click_starred_channels
|
|
|
|
channels = page.all(".chat-channel-row")
|
|
expect(channels.map { |c| c["data-chat-channel-id"] }).to eq(
|
|
[channel_2.id, dm_channel_1.id, channel_1.id, dm_channel_2.id].map(&:to_s),
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when a channel is starred" do
|
|
fab!(:user_1) { Fabricate(:user, username: "alice") }
|
|
|
|
before { channel_1.membership_for(current_user).update!(starred: true) }
|
|
|
|
it "shows the starred channel in both the starred tab AND the channels tab" do
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
drawer_page.click_starred_channels
|
|
|
|
expect(page).to have_css(
|
|
".starred-channels .chat-channel-row[data-chat-channel-id='#{channel_1.id}']",
|
|
)
|
|
|
|
drawer_page.click_channels
|
|
|
|
expect(page).to have_css(
|
|
".public-channels .chat-channel-row[data-chat-channel-id='#{channel_1.id}']",
|
|
)
|
|
end
|
|
|
|
it "shows unread indicator on channel row in both tabs when channel has unreads" do
|
|
Fabricate(:chat_message, chat_channel: channel_1, user: user_1)
|
|
channel_1.membership_for(current_user).update!(last_viewed_at: 1.minute.ago)
|
|
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
drawer_page.click_starred_channels
|
|
|
|
expect(page).to have_css(
|
|
".starred-channels .chat-channel-row[data-chat-channel-id='#{channel_1.id}'] .chat-channel-unread-indicator",
|
|
)
|
|
|
|
drawer_page.click_channels
|
|
|
|
expect(page).to have_css(
|
|
".public-channels .chat-channel-row[data-chat-channel-id='#{channel_1.id}'] .chat-channel-unread-indicator",
|
|
)
|
|
end
|
|
|
|
it "only shows footer unread indicator on starred tab, not on channels tab" do
|
|
Fabricate(
|
|
:chat_message,
|
|
chat_channel: channel_1,
|
|
user: user_1,
|
|
message: "hey @#{current_user.username}",
|
|
)
|
|
channel_1.membership_for(current_user).update!(last_viewed_at: 1.minute.ago)
|
|
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
|
|
expect(page).to have_css("#c-footer-starred .c-unread-indicator")
|
|
expect(page).to have_no_css("#c-footer-channels .c-unread-indicator")
|
|
end
|
|
end
|
|
|
|
context "when a DM channel is starred" do
|
|
fab!(:user_1) { Fabricate(:user, username: "alice") }
|
|
fab!(:dm_channel) { Fabricate(:direct_message_channel, users: [current_user, user_1]) }
|
|
|
|
before { dm_channel.membership_for(current_user).update!(starred: true) }
|
|
|
|
it "shows the starred DM in both the starred tab AND the DMs tab" do
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
drawer_page.click_starred_channels
|
|
|
|
expect(page).to have_css(
|
|
".starred-channels .chat-channel-row[data-chat-channel-id='#{dm_channel.id}']",
|
|
)
|
|
|
|
drawer_page.click_direct_messages
|
|
|
|
expect(page).to have_css(
|
|
".direct-message-channels .chat-channel-row[data-chat-channel-id='#{dm_channel.id}']",
|
|
)
|
|
end
|
|
|
|
it "only shows footer unread indicator on starred tab, not on DMs tab" do
|
|
Fabricate(:chat_message, chat_channel: dm_channel, user: user_1)
|
|
dm_channel.membership_for(current_user).update!(last_viewed_at: 1.minute.ago)
|
|
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
|
|
expect(page).to have_css("#c-footer-starred .c-unread-indicator")
|
|
expect(page).to have_no_css("#c-footer-direct-messages .c-unread-indicator")
|
|
end
|
|
end
|
|
|
|
context "when navigating back from a channel" do
|
|
before { channel_1.membership_for(current_user).update!(starred: true) }
|
|
|
|
it "returns to starred channels when starred channels exist" do
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
drawer_page.click_starred_channels
|
|
find(".chat-channel-row[data-chat-channel-id='#{channel_1.id}']").click
|
|
|
|
find(".c-navbar__back-button").click
|
|
expect(drawer_page).to have_open_starred_channels
|
|
end
|
|
|
|
it "redirects to channels list after unstarring the last channel" do
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
drawer_page.click_starred_channels
|
|
find(".chat-channel-row[data-chat-channel-id='#{channel_1.id}']").click
|
|
|
|
find(".c-navbar__star-channel-button").click
|
|
expect(page).to have_no_css(".c-navbar__star-channel-button.--starred")
|
|
|
|
find(".c-navbar__back-button").click
|
|
expect(drawer_page).to have_open_channels
|
|
end
|
|
|
|
it "returns to starred channels even after closing and reopening the drawer" do
|
|
visit("/")
|
|
chat_page.open_from_header
|
|
drawer_page.open_channel_row(channel_1)
|
|
expect(drawer_page).to have_open_channel(channel_1)
|
|
|
|
drawer_page.close
|
|
expect(chat_page).to have_no_drawer
|
|
|
|
chat_page.open_from_header
|
|
expect(drawer_page).to have_open_channel(channel_1)
|
|
|
|
drawer_page.back
|
|
|
|
expect(drawer_page).to have_open_starred_channels
|
|
end
|
|
end
|
|
end
|