2022-12-23 08:04:41 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
RSpec.describe "Quoting chat message transcripts", type: :system, js: true do
|
|
|
|
fab!(:current_user) { Fabricate(:user) }
|
|
|
|
fab!(:chat_channel_1) { Fabricate(:chat_channel) }
|
|
|
|
|
|
|
|
let(:chat_page) { PageObjects::Pages::Chat.new }
|
|
|
|
let(:chat_channel_page) { PageObjects::Pages::ChatChannel.new }
|
|
|
|
let(:topic_page) { PageObjects::Pages::Topic.new }
|
|
|
|
|
|
|
|
before do
|
|
|
|
chat_system_bootstrap(Fabricate(:admin), [chat_channel_1])
|
|
|
|
chat_channel_1.add(current_user)
|
|
|
|
sign_in(current_user)
|
|
|
|
end
|
|
|
|
|
|
|
|
def select_message_desktop(message)
|
|
|
|
if page.has_css?(".chat-message-container.selecting-messages")
|
|
|
|
chat_channel_page.message_by_id(message.id).find(".chat-message-selector").click
|
|
|
|
else
|
|
|
|
chat_channel_page.message_by_id(message.id).hover
|
|
|
|
expect(page).to have_css(".chat-message-actions .more-buttons")
|
|
|
|
find(".chat-message-actions .more-buttons").click
|
|
|
|
find(".select-kit-row[data-value=\"selectMessage\"]").click
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def select_message_mobile(message)
|
2023-02-01 23:39:23 +08:00
|
|
|
i = 0.5
|
|
|
|
try_until_success(timeout: 20) do
|
|
|
|
chat_channel_page.message_by_id(message.id).click(delay: i)
|
|
|
|
first(".chat-message-action-item[data-id=\"selectMessage\"]")
|
2022-12-23 08:04:41 +08:00
|
|
|
end
|
2023-02-01 23:39:23 +08:00
|
|
|
find(".chat-message-action-item[data-id=\"selectMessage\"] button").click
|
2022-12-23 08:04:41 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def cdp_allow_clipboard_access!
|
|
|
|
cdp_params = {
|
|
|
|
origin: page.server_url,
|
|
|
|
permission: {
|
|
|
|
name: "clipboard-read",
|
|
|
|
},
|
|
|
|
setting: "granted",
|
|
|
|
}
|
|
|
|
page.driver.browser.execute_cdp("Browser.setPermission", **cdp_params)
|
|
|
|
|
|
|
|
cdp_params = {
|
|
|
|
origin: page.server_url,
|
|
|
|
permission: {
|
|
|
|
name: "clipboard-write",
|
|
|
|
},
|
|
|
|
setting: "granted",
|
|
|
|
}
|
|
|
|
page.driver.browser.execute_cdp("Browser.setPermission", **cdp_params)
|
|
|
|
end
|
|
|
|
|
|
|
|
def read_clipboard
|
|
|
|
page.evaluate_async_script("navigator.clipboard.readText().then(arguments[0])")
|
|
|
|
end
|
|
|
|
|
|
|
|
def click_selection_button(button)
|
|
|
|
selector =
|
|
|
|
case button
|
|
|
|
when "quote"
|
2023-02-01 23:39:23 +08:00
|
|
|
"chat-quote-btn"
|
2022-12-23 08:04:41 +08:00
|
|
|
when "copy"
|
2023-02-01 23:39:23 +08:00
|
|
|
"chat-copy-btn"
|
2022-12-23 08:04:41 +08:00
|
|
|
when "cancel"
|
2023-02-01 23:39:23 +08:00
|
|
|
"chat-cancel-selection-btn"
|
2022-12-23 08:04:41 +08:00
|
|
|
when "move"
|
2023-02-01 23:39:23 +08:00
|
|
|
"chat-move-to-channel-btn"
|
2022-12-23 08:04:41 +08:00
|
|
|
end
|
2023-02-01 23:39:23 +08:00
|
|
|
find_button(selector, disabled: false, wait: 5).click
|
2022-12-23 08:04:41 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def copy_messages_to_clipboard(messages)
|
|
|
|
messages = Array.wrap(messages)
|
|
|
|
messages.each { |message| select_message_desktop(message) }
|
|
|
|
expect(chat_channel_page).to have_selection_management
|
|
|
|
click_selection_button("copy")
|
2023-02-01 23:39:23 +08:00
|
|
|
expect(page).to have_selector(".chat-copy-success")
|
2022-12-23 08:04:41 +08:00
|
|
|
clip_text = read_clipboard
|
|
|
|
expect(clip_text.chomp).to eq(generate_transcript(messages, current_user))
|
|
|
|
clip_text
|
|
|
|
end
|
|
|
|
|
|
|
|
def generate_transcript(messages, acting_user)
|
|
|
|
messages = Array.wrap(messages)
|
|
|
|
ChatTranscriptService
|
|
|
|
.new(messages.first.chat_channel, acting_user, messages_or_ids: messages.map(&:id))
|
|
|
|
.generate_markdown
|
|
|
|
.chomp
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "copying quote transcripts with the clipboard" do
|
|
|
|
before { cdp_allow_clipboard_access! }
|
|
|
|
|
|
|
|
context "when quoting a single message into a topic" do
|
|
|
|
fab!(:post_1) { Fabricate(:post) }
|
|
|
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: chat_channel_1) }
|
|
|
|
|
|
|
|
it "quotes the message" do
|
|
|
|
chat_page.visit_channel(chat_channel_1)
|
|
|
|
|
|
|
|
expect(chat_channel_page).to have_no_loading_skeleton
|
|
|
|
|
|
|
|
clip_text = copy_messages_to_clipboard(message_1)
|
|
|
|
topic_page.visit_topic_and_open_composer(post_1.topic)
|
|
|
|
topic_page.fill_in_composer("This is a new post!\n\n" + clip_text)
|
|
|
|
|
|
|
|
within(".d-editor-preview") { expect(page).to have_css(".chat-transcript") }
|
|
|
|
|
|
|
|
topic_page.send_reply
|
|
|
|
selector = topic_page.post_by_number_selector(2)
|
|
|
|
|
|
|
|
expect(page).to have_css(selector)
|
|
|
|
within(selector) { expect(page).to have_css(".chat-transcript") }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when quoting multiple messages into a topic" do
|
|
|
|
fab!(:post_1) { Fabricate(:post) }
|
|
|
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: chat_channel_1) }
|
|
|
|
fab!(:message_2) { Fabricate(:chat_message, chat_channel: chat_channel_1) }
|
|
|
|
|
|
|
|
it "quotes the messages" do
|
|
|
|
chat_page.visit_channel(chat_channel_1)
|
|
|
|
|
|
|
|
expect(chat_channel_page).to have_no_loading_skeleton
|
|
|
|
|
|
|
|
clip_text = copy_messages_to_clipboard([message_1, message_2])
|
|
|
|
topic_page.visit_topic_and_open_composer(post_1.topic)
|
|
|
|
topic_page.fill_in_composer("This is a new post!\n\n" + clip_text)
|
|
|
|
|
|
|
|
within(".d-editor-preview") { expect(page).to have_css(".chat-transcript", count: 2) }
|
|
|
|
expect(page).to have_content("Originally sent in #{chat_channel_1.name}")
|
|
|
|
|
|
|
|
topic_page.send_reply
|
|
|
|
|
|
|
|
selector = topic_page.post_by_number_selector(2)
|
|
|
|
expect(page).to have_css(selector)
|
|
|
|
within(selector) { expect(page).to have_css(".chat-transcript", count: 2) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when quoting a message containing a onebox" do
|
|
|
|
fab!(:post_1) { Fabricate(:post) }
|
|
|
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: chat_channel_1) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
Oneboxer.stubs(:preview).returns(
|
|
|
|
"<aside class=\"onebox\"><article class=\"onebox-body\"><h3><a href=\"http://www.example.com/article.html\" tabindex=\"-1\">An interesting article</a></h3></article></aside>",
|
|
|
|
)
|
|
|
|
message_1.update!(message: "http://www.example.com/has-title.html")
|
|
|
|
message_1.rebake!
|
|
|
|
end
|
|
|
|
|
|
|
|
it "works" do
|
|
|
|
chat_page.visit_channel(chat_channel_1)
|
|
|
|
|
|
|
|
expect(chat_channel_page).to have_no_loading_skeleton
|
|
|
|
|
|
|
|
clip_text = copy_messages_to_clipboard(message_1)
|
|
|
|
topic_page.visit_topic_and_open_composer(post_1.topic)
|
|
|
|
topic_page.fill_in_composer(clip_text)
|
|
|
|
|
|
|
|
within(".chat-transcript-messages") do
|
|
|
|
expect(page).to have_content("An interesting article")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when quoting a message in another message" do
|
|
|
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: chat_channel_1) }
|
|
|
|
|
2023-01-06 07:04:38 +08:00
|
|
|
it "quotes the message" do
|
2022-12-23 08:04:41 +08:00
|
|
|
chat_page.visit_channel(chat_channel_1)
|
|
|
|
|
|
|
|
expect(chat_channel_page).to have_no_loading_skeleton
|
|
|
|
|
|
|
|
clip_text = copy_messages_to_clipboard(message_1)
|
|
|
|
click_selection_button("cancel")
|
2023-01-02 22:17:21 +08:00
|
|
|
chat_channel_page.send_message(clip_text)
|
2022-12-23 08:04:41 +08:00
|
|
|
|
|
|
|
expect(page).to have_selector(".chat-message", count: 2)
|
|
|
|
|
|
|
|
message = ChatMessage.find_by(user: current_user, message: clip_text.chomp)
|
|
|
|
|
|
|
|
within(chat_channel_page.message_by_id(message.id)) do
|
|
|
|
expect(page).to have_css(".chat-transcript")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when quoting into a topic directly" do
|
|
|
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: chat_channel_1) }
|
|
|
|
let(:topic_title) { "Some topic title for testing" }
|
|
|
|
|
|
|
|
it "opens the topic composer with correct state" do
|
|
|
|
chat_page.visit_channel(chat_channel_1)
|
|
|
|
|
|
|
|
expect(chat_channel_page).to have_no_loading_skeleton
|
|
|
|
|
|
|
|
select_message_desktop(message_1)
|
|
|
|
click_selection_button("quote")
|
|
|
|
|
|
|
|
expect(topic_page).to have_expanded_composer
|
|
|
|
expect(topic_page).to have_composer_content(generate_transcript(message_1, current_user))
|
|
|
|
expect(page).to have_css(
|
|
|
|
".category-input .select-kit-header[data-value='#{chat_channel_1.chatable.id}']",
|
|
|
|
)
|
|
|
|
expect(page).not_to have_current_path(chat_channel_1.chatable.url)
|
|
|
|
|
|
|
|
topic_page.fill_in_composer_title(topic_title)
|
|
|
|
topic_page.send_reply
|
|
|
|
|
|
|
|
selector = topic_page.post_by_number_selector(1)
|
|
|
|
expect(page).to have_css(selector)
|
|
|
|
within(selector) { expect(page).to have_css(".chat-transcript") }
|
|
|
|
|
|
|
|
topic = Topic.find_by(user: current_user, title: topic_title)
|
|
|
|
expect(page).to have_current_path(topic.url)
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when on mobile" do
|
|
|
|
it "first navigates to the channel's category before opening the topic composer with the quote prefilled",
|
|
|
|
mobile: true do
|
|
|
|
chat_page.visit_channel(chat_channel_1)
|
2023-02-01 23:39:23 +08:00
|
|
|
|
2022-12-23 08:04:41 +08:00
|
|
|
expect(chat_channel_page).to have_no_loading_skeleton
|
|
|
|
|
|
|
|
select_message_mobile(message_1)
|
|
|
|
click_selection_button("quote")
|
|
|
|
|
|
|
|
expect(topic_page).to have_expanded_composer
|
|
|
|
expect(topic_page).to have_composer_content(generate_transcript(message_1, current_user))
|
|
|
|
expect(page).to have_current_path(chat_channel_1.chatable.url)
|
|
|
|
expect(page).to have_css(
|
|
|
|
".category-input .select-kit-header[data-value='#{chat_channel_1.chatable.id}']",
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|