discourse/plugins/chat/test/javascripts/acceptance/chat-keyboard-shortcuts-test.js
Joffrey JAFFEUX 66130dc8c1
REFACTOR: handles every chat resource as an URL (#18961)
- Note this is also tweaking the UI a little bit as we are now using links/buttons in the header as needed
- It disables the find ideal channel in drawer mode, if loading `/chat` in drawer mode it will either reopen at the last position or just stay on index
2022-11-11 06:39:15 +01:00

322 lines
9.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import showModal from "discourse/lib/show-modal";
import {
acceptance,
exists,
loggedInUser,
query,
queryAll,
visible,
} from "discourse/tests/helpers/qunit-helpers";
import {
click,
currentURL,
fillIn,
focus,
settled,
triggerKeyEvent,
visit,
} from "@ember/test-helpers";
import {
chatChannels,
generateChatView,
} from "discourse/plugins/chat/chat-fixtures";
import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel";
import { KEY_MODIFIER } from "discourse/plugins/chat/discourse/initializers/chat-keyboard-shortcuts";
import { test } from "qunit";
const MODIFIER_OPTIONS =
KEY_MODIFIER === "meta" ? { metaKey: true } : { ctrlKey: true };
acceptance("Discourse Chat - Keyboard shortcuts", function (needs) {
needs.user({
admin: false,
moderator: false,
username: "eviltrout",
id: 1,
can_chat: true,
has_chat_enabled: true,
});
needs.pretender((server, helper) => {
// allows to create a staged message
server.post("/chat/:id.json", () =>
helper.response({
errors: [""],
})
);
server.get("/chat/chat_channels.json", () => helper.response(chatChannels));
server.get("/chat/:chatChannelId/messages.json", () =>
helper.response(generateChatView(loggedInUser()))
);
server.post("/uploads/lookup-urls", () => {
return helper.response([]);
});
server.post("/chat/drafts", () => {
return helper.response([]);
});
server.get("/chat/chat_channels/search", () => {
return helper.response({
public_channels: [ChatChannel.create({ id: 3, title: "seventeen" })],
direct_message_channels: [
ChatChannel.create({
id: 4,
users: [{ id: 10, username: "someone" }],
}),
],
users: [
{ id: 11, username: "smoothies" },
{ id: 12, username: "server" },
],
});
});
});
needs.settings({
chat_enabled: true,
});
needs.hooks.beforeEach(function () {
Object.defineProperty(this, "chatService", {
get: () => this.container.lookup("service:chat"),
});
});
test("channel selector opens channel in float", async function (assert) {
await visit("/latest");
await showModal("chat-channel-selector-modal");
await settled();
assert.ok(exists("#chat-channel-selector-modal-inner"));
// All channels should show because the input is blank
assert.equal(
queryAll("#chat-channel-selector-modal-inner .chat-channel-selection-row")
.length,
9
);
// Freaking keyup event isn't triggered by fillIn...
// Next line manually keyup's "r" to make the keyup event run.
// fillIn is needed for `this.filter` but triggerKeyEvent is needed to fire the JS event.
await fillIn("#chat-channel-selector-input", "s");
await triggerKeyEvent("#chat-channel-selector-input", "keyup", "R");
// Only 4 channels match this filter now!
assert.equal(
queryAll("#chat-channel-selector-modal-inner .chat-channel-selection-row")
.length,
4
);
await triggerKeyEvent(document.body, "keyup", "Enter");
assert.ok(exists(".topic-chat-container.visible"));
assert.notOk(exists("#chat-channel-selector-modal-inner"));
assert.equal(currentURL(), "/latest");
});
test("the current chat channel does not show in the channel selector list", async function (assert) {
await visit("/chat/channel/75/@hawk");
await showModal("chat-channel-selector-modal");
await settled();
// All channels minus 1
assert.equal(
queryAll("#chat-channel-selector-modal-inner .chat-channel-selection-row")
.length,
8
);
assert.notOk(
exists(
"#chat-channel-selector-modal-inner .chat-channel-selection-row.chat-channel-9"
)
);
});
test("switching channel with alt+arrow keys in full page chat", async function (assert) {
this.container.lookup("service:chat").set("chatWindowFullPage", true);
await visit("/chat/channel/75/@hawk");
await triggerKeyEvent(document.body, "keydown", "ArrowDown", {
altKey: true,
});
assert.equal(currentURL(), "/chat/channel/76/eviltrout-markvanlan");
await triggerKeyEvent(document.body, "keydown", "ArrowDown", {
altKey: true,
});
assert.equal(currentURL(), "/chat/channel/11/another-category");
await triggerKeyEvent(document.body, "keydown", "ArrowDown", {
altKey: true,
});
assert.equal(currentURL(), "/chat/channel/7/bug");
await triggerKeyEvent(document.body, "keydown", "ArrowUp", {
altKey: true,
});
assert.equal(currentURL(), "/chat/channel/11/another-category");
await triggerKeyEvent(document.body, "keydown", "ArrowUp", {
altKey: true,
});
assert.equal(currentURL(), "/chat/channel/76/eviltrout-markvanlan");
await triggerKeyEvent(document.body, "keydown", "ArrowUp", {
altKey: true,
});
assert.equal(currentURL(), "/chat/channel/75/hawk");
});
test("switching channel with alt+arrow keys in float", async function (assert) {
await visit("/latest");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat");
await click("#chat-channel-row-4");
assert.ok(visible(".topic-chat-float-container"), "chat float is open");
assert.ok(query(".topic-chat-container").classList.contains("channel-4"));
await triggerKeyEvent(document.body, "keydown", "ArrowDown", {
altKey: true,
});
assert.ok(query(".topic-chat-container").classList.contains("channel-10"));
await triggerKeyEvent(document.body, "keydown", "ArrowUp", {
altKey: true,
});
assert.ok(query(".topic-chat-container").classList.contains("channel-4"));
});
test("simple composer formatting shortcuts", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/latest");
await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row");
const composerInput = query(".chat-composer-input");
await fillIn(composerInput, "test text");
await focus(composerInput);
composerInput.selectionStart = 0;
composerInput.selectionEnd = 9;
await triggerKeyEvent(composerInput, "keydown", "B", MODIFIER_OPTIONS);
assert.strictEqual(
composerInput.value,
"**test text**",
"selection should get the bold markdown"
);
await fillIn(composerInput, "test text");
await focus(composerInput);
composerInput.selectionStart = 0;
composerInput.selectionEnd = 9;
await triggerKeyEvent(composerInput, "keydown", "I", MODIFIER_OPTIONS);
assert.strictEqual(
composerInput.value,
"_test text_",
"selection should get the italic markdown"
);
await fillIn(composerInput, "test text");
await focus(composerInput);
composerInput.selectionStart = 0;
composerInput.selectionEnd = 9;
await triggerKeyEvent(composerInput, "keydown", "E", MODIFIER_OPTIONS);
assert.strictEqual(
composerInput.value,
"`test text`",
"selection should get the code markdown"
);
});
test("editing last non staged message", async function (assert) {
const stagedMessageText = "This is a test";
await visit("/latest");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row");
await fillIn(".chat-composer-input", stagedMessageText);
await click(".chat-composer-inline-button");
await triggerKeyEvent(".chat-composer-input", "keydown", "ArrowUp");
assert.notEqual(
query(".chat-composer-input").value.trim(),
stagedMessageText
);
});
test("insert link shortcut", async function (assert) {
await visit("/latest");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row");
await focus(".chat-composer-input");
await fillIn(".chat-composer-input", "This is a link to ");
await triggerKeyEvent(
".chat-composer-input",
"keydown",
"L",
MODIFIER_OPTIONS
);
assert.ok(exists(".insert-link.modal-body"), "hyperlink modal visible");
await fillIn(".modal-body .link-url", "google.com");
await fillIn(".modal-body .link-text", "Google");
await click(".modal-footer button.btn-primary");
assert.strictEqual(
query(".chat-composer-input").value,
"This is a link to [Google](https://google.com)",
"adds link with url and text, prepends 'https://'"
);
assert.ok(
!exists(".insert-link.modal-body"),
"modal dismissed after submitting link"
);
});
test("Dash key (-) opens chat float", async function (assert) {
await visit("/latest");
this.chatService.set("sidebarActive", false);
await triggerKeyEvent(document.body, "keydown", "-");
assert.ok(exists(".topic-chat-drawer-content"), "chat float is open");
});
test("Pressing Escape when drawer is opened", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/latest");
await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row");
const composerInput = query(".chat-composer-input");
await focus(composerInput);
await triggerKeyEvent(composerInput, "keydown", "Escape");
assert.ok(
exists(".topic-chat-float-container.hidden"),
"it closes the drawer"
);
});
test("Pressing Escape when full page is opened", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/chat/channel/75/@hawk");
const composerInput = query(".chat-composer-input");
await focus(composerInput);
await triggerKeyEvent(composerInput, "keydown", "Escape");
assert.equal(
currentURL(),
"/chat/channel/75/hawk",
"it doesnt close full page chat"
);
assert.ok(
exists(".chat-message-container[data-id='177']"),
"it doesnt remove channel content"
);
});
});