320 lines
9.9 KiB
JavaScript
320 lines
9.9 KiB
JavaScript
|
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);
|
|||
|
this.chatService.set("chatWindowFullPage", false);
|
|||
|
|
|||
|
await click(".header-dropdown-toggle.open-chat");
|
|||
|
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) {
|
|||
|
await visit("/latest");
|
|||
|
this.chatService.set("sidebarActive", false);
|
|||
|
await click(".header-dropdown-toggle.open-chat");
|
|||
|
|
|||
|
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 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 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);
|
|||
|
this.chatService.set("chatWindowFullPage", 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) {
|
|||
|
await visit("/latest");
|
|||
|
this.chatService.set("sidebarActive", false);
|
|||
|
this.chatService.set("chatWindowFullPage", false);
|
|||
|
await click(".header-dropdown-toggle.open-chat");
|
|||
|
|
|||
|
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);
|
|||
|
this.chatService.set("chatWindowFullPage", true);
|
|||
|
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 doesn’t close full page chat"
|
|||
|
);
|
|||
|
|
|||
|
assert.ok(
|
|||
|
exists(".chat-message-container[data-id='177']"),
|
|||
|
"it doesn’t remove channel content"
|
|||
|
);
|
|||
|
});
|
|||
|
});
|