discourse/plugins/chat/test/javascripts/components/chat-channel-row-test.js
Martin Brennan 9953a6edd9
DEV: Rearchitect chat tracking state (#21550)
This moves chat tracking state calculation for channels
and threads into a central Chat::TrackingStateManager service, that
serves a similar purpose to the TopicTrackingState model
in core.

This service calls down to these query classes:

* ThreadUnreadsQuery
* ChannelUnreadsQuery

To get the unread_count and mention_count for the appropriate
channels and threads.

As well as this, this commit refactors the client-side chat
tracking state.

Now, there is a central ChatTrackingStateManager Ember Service
so all tracking is accessible and can be counted from one place,
which can also initialize tracking from an initial payload.

The actual tracking counts are now maintained in a ChatTrackingState
class that is initialized on the `.tracking` property of both channel and
thread objects.

This removes the attributes on UserChatChannelMembership and decoration
of said membership from ChannelFetcher, preferring instead to have an additional
object for tracking in the JSON.
2023-05-16 14:51:13 +02:00

176 lines
5.8 KiB
JavaScript

import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import fabricators from "../helpers/fabricators";
module("Discourse Chat | Component | chat-channel-row", function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
this.categoryChatChannel = fabricators.chatChannel();
this.directMessageChatChannel = fabricators.directMessageChatChannel();
});
test("links to correct channel", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert
.dom(".chat-channel-row")
.hasAttribute(
"href",
`/chat/c/${this.categoryChatChannel.slugifiedTitle}/${this.categoryChatChannel.id}`
);
});
test("allows tabbing", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").hasAttribute("tabindex", "0");
});
test("channel data attrite tabbing", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert
.dom(".chat-channel-row")
.hasAttribute(
"data-chat-channel-id",
this.categoryChatChannel.id.toString()
);
});
test("renders correct channel title", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-title").hasText(this.categoryChatChannel.title);
});
test("renders correct channel metadata", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert
.dom(".chat-channel-metadata")
.hasText(moment(this.categoryChatChannel.lastMessageSentAt).format("l"));
});
test("renders membership toggling button when necessary", async function (assert) {
this.site.desktopView = false;
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}}/>`);
assert.dom(".toggle-channel-membership-button").doesNotExist();
this.categoryChatChannel.currentUserMembership.following = true;
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".toggle-channel-membership-button").doesNotExist();
this.site.desktopView = true;
await render(
hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} @options={{hash leaveButton=true}}/>`
);
assert.dom(".toggle-channel-membership-button").exists();
});
test("focused channel has correct class", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").doesNotHaveClass("focused");
this.categoryChatChannel.focused = true;
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").hasClass("focused");
});
test("muted channel has correct class", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").doesNotHaveClass("muted");
this.categoryChatChannel.currentUserMembership.muted = true;
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").hasClass("muted");
});
test("leaveButton options adds correct class", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").doesNotHaveClass("can-leave");
await render(
hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} @options={{hash leaveButton=true}} />`
);
assert.dom(".chat-channel-row").hasClass("can-leave");
});
test("active channel adds correct class", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").doesNotHaveClass("active");
this.owner
.lookup("service:chat")
.set("activeChannel", { id: this.categoryChatChannel.id });
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").hasClass("active");
});
test("unreads adds correct class", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").doesNotHaveClass("has-unread");
this.categoryChatChannel.tracking.unreadCount = 1;
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".chat-channel-row").hasClass("has-unread");
});
test("user status with category channel", async function (assert) {
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
assert.dom(".user-status-message").doesNotExist();
});
test("user status with direct message channel", async function (assert) {
const status = { description: "Off to dentist", emoji: "tooth" };
this.directMessageChatChannel.chatable.users[0].status = status;
await render(
hbs`<ChatChannelRow @channel={{this.directMessageChatChannel}} />`
);
assert.dom(".user-status-message").exists();
});
test("user status with direct message channel and multiple users", async function (assert) {
const status = { description: "Off to dentist", emoji: "tooth" };
this.directMessageChatChannel.chatable.users[0].status = status;
this.directMessageChatChannel.chatable.users.push({
id: 2,
username: "bill",
name: null,
avatar_template: "/letter_avatar_proxy/v3/letter/t/31188e/{size}.png",
});
await render(
hbs`<ChatChannelRow @channel={{this.directMessageChatChannel}} />`
);
assert.dom(".user-status-message").doesNotExist();
});
});