import {
acceptance,
exists,
query,
queryAll,
} from "discourse/tests/helpers/qunit-helpers";
import { test } from "qunit";
import { click, currentURL, settled, visit } from "@ember/test-helpers";
import { directMessageChannels } from "discourse/plugins/chat/chat-fixtures";
import { cloneJSON } from "discourse-common/lib/object";
import I18n from "I18n";
import { withPluginApi } from "discourse/lib/plugin-api";
import { emojiUnescape } from "discourse/lib/text";
import User from "discourse/models/user";
acceptance("Discourse Chat - Core Sidebar", function (needs) {
needs.user({ has_chat_enabled: true });
needs.settings({
chat_enabled: true,
enable_experimental_sidebar_hamburger: true,
enable_sidebar: true,
});
needs.pretender((server, helper) => {
let directChannels = cloneJSON(directMessageChannels).mapBy("chat_channel");
directChannels[0].chatable.users = [directChannels[0].chatable.users[0]];
directChannels[0].current_user_membership.unread_count = 1;
directChannels.push({
chatable: {
users: [
{
id: 1,
username: "markvanlan",
avatar_template:
"/letter_avatar_proxy/v4/letter/t/f9ae1b/{size}.png",
},
{
id: 2,
username: "sam",
avatar_template:
"/letter_avatar_proxy/v4/letter/t/f9ae1b/{size}.png",
},
],
},
chatable_id: 59,
chatable_type: "DirectMessage",
chatable_url: null,
id: 76,
title: "@sam",
last_message_sent_at: "2021-06-01T11:15:00.000Z",
current_user_membership: {
unread_count: 0,
muted: true,
following: true,
},
});
directChannels.push({
chatable: {
users: [
{
id: 1,
username: "",
avatar_template:
"/letter_avatar_proxy/v4/letter/t/f9ae1b/{size}.png",
},
{
id: 2,
username: "",
avatar_template:
"/letter_avatar_proxy/v4/letter/t/f9ae1b/{size}.png",
},
],
},
chatable_type: "DirectMessage",
chatable_url: null,
id: 77,
title: "@",
last_message_sent_at: "2021-06-01T11:15:00.000Z",
current_user_membership: {
unread_count: 0,
muted: false,
following: true,
},
});
server.get("/chat/chat_channels.json", () => {
return helper.response({
public_channels: [
{
id: 1,
title: "dev :bug:",
chatable_type: "Category",
chatable: { slug: "dev", read_restricted: true },
last_message_sent_at: "2021-11-08T21:26:05.710Z",
current_user_membership: {
unread_count: 0,
unread_mentions: 0,
},
},
{
id: 2,
title: "general",
chatable_type: "Category",
chatable: { slug: "general" },
last_message_sent_at: "2021-11-08T21:26:05.710Z",
current_user_membership: {
unread_count: 1,
unread_mentions: 0,
},
},
{
id: 3,
title: "random",
description: "The channel for random things",
chatable_type: "Category",
chatable: { slug: "random" },
last_message_sent_at: "2021-11-08T21:26:05.710Z",
current_user_membership: {
muted: true,
unread_count: 1,
unread_mentions: 1,
},
},
{
id: 4,
title: "",
chatable_type: "Category",
chatable: { slug: "random" },
last_message_sent_at: "2021-11-08T21:26:05.710Z",
current_user_membership: {
unread_count: 1,
unread_mentions: 1,
},
},
],
direct_message_channels: directChannels,
});
});
server.get("/chat/1/messages.json", () =>
helper.response({
meta: { can_chat: true, user_silenced: false },
chat_messages: [],
})
);
server.get("/u/search/users", () => {
return helper.response({
users: [
{
username: "hawk",
id: 2,
name: "hawk",
avatar_template:
"/letter_avatar_proxy/v4/letter/t/41988e/{size}.png",
},
],
});
});
server.get("/chat/75/messages.json", () =>
helper.response({
meta: { can_chat: true, user_silenced: false },
chat_messages: [],
})
);
server.get("/chat/direct_messages.json", () => {
return helper.response({
chat_channel: {
id: 75,
title: "hawk",
chatable_type: "DirectMessage",
last_message_sent_at: "2021-07-20T08:14:16.950Z",
chatable: {
users: [{ username: "hawk" }],
},
},
});
});
});
needs.hooks.beforeEach(function () {
withPluginApi("1.3.0", (api) => {
api.addUsernameSelectorDecorator((username) => {
if (username === "hawk") {
return `${emojiUnescape(
":desert_island:"
)}`;
}
});
});
});
test("Public channels section", async function (assert) {
await visit("/");
assert.strictEqual(
query(
".sidebar-section-chat-channels .sidebar-section-header-text"
).textContent.trim(),
I18n.t("chat.chat_channels"),
"displays correct channels section title"
);
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-dev-bug .sidebar-section-link-prefix svg.prefix-icon.d-icon-hashtag"
),
"dev channel section link displays hash icon prefix"
);
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-dev-bug .sidebar-section-link-prefix svg.prefix-badge.d-icon-lock"
),
"dev channel section link displays lock badge for restricted channel"
);
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-dev-bug .emoji"
),
"unescapes emoji in channel title in the link"
);
assert.strictEqual(
query(
".sidebar-section-chat-channels .sidebar-section-link-dev-bug"
).textContent.trim(),
"dev",
"dev channel section link displays channel title in the link"
);
assert.ok(
query(
".sidebar-section-chat-channels .sidebar-section-link-dev-bug"
).href.endsWith("/chat/channel/1/dev-bug"),
"dev channel section link has the right href attribute"
);
assert.notOk(
exists(
".sidebar-section-chat-channels .sidebar-section-link-dev-bug .sidebar-section-link-suffix"
),
"does not display new messages indicator"
);
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-general .sidebar-section-link-prefix svg.prefix-icon.d-icon-hashtag"
),
"general channel section link displays hash icon prefix"
);
assert.notOk(
exists(
".sidebar-section-chat-channels .sidebar-section-link-general .sidebar-section-link-prefix svg.prefix-badge"
),
"general channel section link does not display lock badge for public channel"
);
assert.strictEqual(
query(
".sidebar-section-chat-channels .sidebar-section-link-general"
).textContent.trim(),
"general",
"general channel section link displays channel title in the link"
);
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-general .sidebar-section-link-suffix.unread"
),
"general section link has new messages indicator"
);
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-random .sidebar-section-link-prefix svg.prefix-icon.d-icon-hashtag"
),
"random channel section link displays hash icon prefix"
);
assert.strictEqual(
query(
".sidebar-section-chat-channels .sidebar-section-link-random"
).textContent.trim(),
"random",
"random channel section link displays channel title in the link"
);
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-random .sidebar-section-link-suffix.urgent"
),
"random section link has new messages mention indicator"
);
});
test("sidebar section link when direct message channel is muted by user", async function (assert) {
await visit("/");
assert.ok(
exists(
".sidebar-section-chat-dms .sidebar-section-link-sam.sidebar-section-link--muted"
),
"muted direct chat channel section link has right classname configured"
);
});
test("sidebar section link when public channel is muted by user", async function (assert) {
await visit("/");
assert.ok(
exists(
".sidebar-section-chat-channels .sidebar-section-link-random.sidebar-section-link--muted"
),
"muted random chat channel section link has right classname configured"
);
});
test("Direct messages section", async function (assert) {
const chatService = this.container.lookup("service:chat");
chatService.directMessagesLimit = 2;
await visit("/");
assert.strictEqual(
query(
".sidebar-section-chat-dms .sidebar-section-header-text"
).textContent.trim(),
I18n.t("chat.direct_messages.title"),
"displays correct direct messages section title"
);
let directLinks = queryAll(
".sidebar-section-chat-dms a.sidebar-section-link"
);
assert.strictEqual(
directLinks[0]
.querySelector(".sidebar-section-link-prefix img")
.classList.contains("prefix-image"),
true,
"displays avatar in prefix when two participants"
);
assert.strictEqual(
directLinks[0].textContent.trim(),
"hawk",
"displays user name in a link"
);
assert.ok(
directLinks[0].querySelector(
".sidebar-section-link-content-text .on-holiday img"
),
"displays flair when user is on holiday"
);
assert.strictEqual(
directLinks[0]
.querySelector(".sidebar-section-link-suffix")
.classList.contains("urgent"),
true,
"displays new messages indicator"
);
assert.strictEqual(
directLinks[1]
.querySelector("span.sidebar-section-link-prefix")
.classList.contains("text"),
true,
"displays text in prefix when more than two participants"
);
assert.strictEqual(
directLinks[1]
.querySelector(".sidebar-section-link-content-text")
.textContent.trim(),
"eviltrout, markvanlan",
"displays all participants name in a link"
);
assert.ok(
!directLinks[1].querySelector(".sidebar-section-link-suffix"),
"does not display new messages indicator"
);
User.current().chat_channel_tracking_state[76].set("unread_count", 99);
chatService.reSortDirectMessageChannels();
chatService.appEvents.trigger("chat:user-tracking-state-changed");
await settled();
directLinks = queryAll(".sidebar-section-chat-dms a.sidebar-section-link");
assert.strictEqual(
directLinks[0]
.querySelector(".sidebar-section-link-content-text")
.textContent.trim(),
"eviltrout, markvanlan",
"reorders private messages"
);
assert.equal(
directLinks.length,
2,
"limits number of displayed direct messages"
);
});
test("Plugin sidebar is hidden", async function (assert) {
await visit("/chat/channel/1/dev");
assert.notOk(exists(".full-page-chat .channels-list"));
});
test("Open a new direct conversation", async function (assert) {
await visit("/");
await click(".sidebar-section-chat-dms .sidebar-section-header-button");
assert.ok(exists(".direct-message-creator"));
assert.ok(exists(".chat-drawer.is-expanded"));
assert.strictEqual(currentURL(), "/");
});
test("Escaped channel description used as title when present", async function (assert) {
await visit("/");
const randomChannel = queryAll(
".sidebar-section-chat-channels .sidebar-section-link-wrapper .sidebar-section-link"
)[3];
assert.strictEqual(
randomChannel.title,
"The channel for random <script>evil</script> things"
);
});
test("Escapes public channel titles", async function (assert) {
await visit("/");
const evilChannel = query(
".sidebar-section-chat-channels .sidebar-section-link-wrapper .sidebar-section-link"
);
assert.strictEqual(
evilChannel.title,
"<script>evil</script> chat"
);
assert.ok(
evilChannel.className.includes(
"sidebar-section-link-ltscriptgtevilltscriptgt"
)
);
assert.strictEqual(
evilChannel
.querySelector(".sidebar-section-link-content-text")
.innerHTML.trim(),
"<script>evil</script>"
);
});
test("Escapes dm channel titles", async function (assert) {
await visit("/");
const evilChannel = queryAll(
".sidebar-section-chat-dms .sidebar-section-link-wrapper .sidebar-section-link"
)[3];
assert.strictEqual(
evilChannel.title,
"Chat with @<script>sam</script>"
);
assert.ok(
evilChannel.className.includes(
"sidebar-section-link-ltscriptgtsamltscriptgt"
)
);
assert.strictEqual(
evilChannel
.querySelector(".sidebar-section-link-content-text")
.innerHTML.trim(),
"<script>sam</script>"
);
});
});
acceptance("Discourse Chat - Plugin Sidebar", function (needs) {
needs.user({ has_chat_enabled: true });
needs.settings({
chat_enabled: true,
enable_sidebar: false,
});
needs.pretender((server, helper) => {
server.get("/chat/chat_channels.json", () => {
return helper.response({
public_channels: [
{
id: 1,
title: "dev :bug:",
chatable_type: "Category",
chatable: { slug: "dev", read_restricted: true },
last_message_sent_at: "2021-11-08T21:26:05.710Z",
current_user_membership: {
unread_count: 1,
unread_mentions: 1,
},
},
{
id: 2,
title: "general",
chatable_type: "Category",
chatable: { slug: "general" },
last_message_sent_at: "2021-11-08T21:26:05.710Z",
current_user_membership: {
unread_count: 1,
unread_mentions: 1,
},
},
{
id: 3,
title: "random",
chatable_type: "Category",
chatable: { slug: "random" },
last_message_sent_at: "2021-11-08T21:26:05.710Z",
current_user_membership: {
unread_count: 1,
unread_mentions: 1,
},
},
],
direct_message_channels: [],
});
});
server.get("/chat/1/messages.json", () =>
helper.response({
meta: { can_chat: true, user_silenced: false },
chat_messages: [],
})
);
});
test("Plugin sidebar is visible", async function (assert) {
await visit("/chat/channel/1/dev");
assert.ok(exists(".full-page-chat .channels-list"));
});
});
acceptance(
"Discourse Chat - Core Sidebar - no joinable public channels, staff",
function (needs) {
needs.user({ has_chat_enabled: true, has_joinable_public_channels: false });
needs.settings({
chat_enabled: true,
enable_experimental_sidebar_hamburger: true,
enable_sidebar: true,
});
needs.pretender((server, helper) => {
server.get("/chat/chat_channels.json", () => {
return helper.response({
public_channels: [],
direct_message_channels: [],
});
});
});
test("Chat channels section visibility", async function (assert) {
await visit("/");
assert.ok(
exists(".sidebar-section-chat-channels"),
"it shows the section for staff"
);
});
}
);
acceptance(
"Discourse Chat - Core Sidebar - no joinable public channels, regular user",
function (needs) {
needs.user({
has_chat_enabled: true,
has_joinable_public_channels: false,
moderator: false,
admin: false,
});
needs.settings({
chat_enabled: true,
enable_experimental_sidebar_hamburger: true,
enable_sidebar: true,
});
needs.pretender((server, helper) => {
server.get("/chat/chat_channels.json", () => {
return helper.response({
public_channels: [],
direct_message_channels: [],
});
});
});
test("Chat channels section visibility", async function (assert) {
await visit("/");
assert.notOk(
exists(".sidebar-section-chat-channels"),
"it doesn’t show the section for regular user"
);
});
}
);
acceptance(
"Discourse Chat - Core Sidebar - regular user with no direct message channels who cannot send direct messages",
function (needs) {
needs.user({
has_chat_enabled: true,
moderator: false,
admin: false,
});
needs.settings({
chat_enabled: true,
enable_experimental_sidebar_hamburger: true,
enable_sidebar: true,
direct_message_enabled_groups: "13", // trust_level_3 auto group ID;
});
needs.pretender((server, helper) => {
server.get("/chat/chat_channels.json", () => {
return helper.response({
public_channels: [],
direct_message_channels: [],
});
});
});
test("Direct message channels section visibility", async function (assert) {
await visit("/");
assert.notOk(
exists(".sidebar-section-chat-dms"),
"it doesn’t show the section for regular user"
);
});
}
);
acceptance(
"Discourse Chat - Core Sidebar - regular user with existing direct message channels who cannot send direct messages",
function (needs) {
needs.user({
has_chat_enabled: true,
moderator: false,
admin: false,
});
needs.settings({
chat_enabled: true,
enable_experimental_sidebar_hamburger: true,
enable_sidebar: true,
direct_message_enabled_groups: "13", // trust_level_3 auto group ID;
});
needs.pretender((server, helper) => {
let directChannels = cloneJSON(directMessageChannels).mapBy(
"chat_channel"
);
server.get("/chat/chat_channels.json", () => {
return helper.response({
public_channels: [],
direct_message_channels: directChannels,
});
});
});
test("Direct message channels section visibility", async function (assert) {
await visit("/");
assert.ok(
exists(".sidebar-section-chat-dms"),
"it does show the section for a regular user"
);
assert.notOk(
exists(".sidebar-section-chat-dms .sidebar-section-header-button"),
"user cannot see the create DM channel button"
);
});
}
);