discourse/plugins/chat/test/javascripts/components/chat-replying-indicator-test.js
Joffrey JAFFEUX 55c4a550c1
FEATURE: chat-replying indicator for threads (#21485)
This feature adds the replying indicator in threads, it uses the same `/chat-reply/CHANNEL_ID` prefix than the channel composer replying indicator as we don't have specific right on threads ATM (if you can access channel, you can access thread). Thread will however use a presence channel name of the following format: `/chat-reply/CHANNEL_ID/thread/THREAD_ID`

This commit also simplifies the computation of `users` to eventually avoid a race-condition leading to a leak of the indicator in another channel/thread.

<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
2023-05-11 08:02:04 +02:00

167 lines
4.8 KiB
JavaScript

import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { query } from "discourse/tests/helpers/qunit-helpers";
import hbs from "htmlbars-inline-precompile";
import fabricators from "../helpers/fabricators";
import { module, test } from "qunit";
import { render } from "@ember/test-helpers";
import {
joinChannel,
leaveChannel,
} from "discourse/tests/helpers/presence-pretender";
async function addUser(id, username, channelName = "/chat-reply/1") {
await joinChannel(channelName, {
id,
avatar_template: "/images/avatar.png",
username,
});
}
async function removeUser(id, channelName = "/chat-reply/1") {
await leaveChannel(channelName, {
id,
});
}
module(
"Discourse Chat | Component | chat-replying-indicator",
function (hooks) {
setupRenderingTest(hooks);
test("not displayed when no one is replying", async function (assert) {
await render(
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
);
assert.dom(".chat-replying-indicator__text").doesNotExist();
});
test("working for thread", async function (assert) {
await render(
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1/thread/1" />`
);
await addUser(1, "sam", "/chat-reply/1/thread/1");
assert.strictEqual(
query(".chat-replying-indicator__text").innerText,
"sam is typing"
);
});
test("doesn’t leak in other indicators", async function (assert) {
await render(
hbs`
<div class="channel"><ChatReplyingIndicator @presenceChannelName="/chat-reply/1" /></div>
<div class="thread"><ChatReplyingIndicator @presenceChannelName="/chat-reply/1/thread/1" /></div>
`
);
await addUser(1, "sam");
assert
.dom(".channel .chat-replying-indicator__text")
.hasText("sam is typing");
assert.dom(".thread .chat-replying-indicator__text").doesNotExist();
await addUser(2, "mark", "/chat-reply/1/thread/1");
await removeUser(1);
assert.dom(".channel .chat-replying-indicator__text").doesNotExist();
assert
.dom(".thread .chat-replying-indicator__text")
.hasText("mark is typing");
});
test("displays indicator when user is replying", async function (assert) {
await render(
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
);
await addUser(1, "sam");
assert.strictEqual(
query(".chat-replying-indicator__text").innerText,
`sam is typing`
);
});
test("displays indicator when 2 or 3 users are replying", async function (assert) {
this.channel = fabricators.chatChannel();
await render(
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
);
await addUser(1, "sam");
await addUser(2, "mark");
assert
.dom(".chat-replying-indicator__text")
.hasText("sam and mark are typing");
});
test("displays indicator when 3 users are replying", async function (assert) {
this.channel = fabricators.chatChannel();
await render(
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
);
await addUser(1, "sam");
await addUser(2, "mark");
await addUser(3, "joffrey");
assert
.dom(".chat-replying-indicator__text")
.hasText("sam, mark and joffrey are typing");
});
test("displays indicator when more than 3 users are replying", async function (assert) {
this.channel = fabricators.chatChannel();
await render(
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
);
await addUser(1, "sam");
await addUser(2, "mark");
await addUser(3, "joffrey");
await addUser(4, "taylor");
assert
.dom(".chat-replying-indicator__text")
.hasText("sam, mark and 2 others are typing");
});
test("filters current user from list of repliers", async function (assert) {
this.channel = fabricators.chatChannel();
await render(
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
);
await addUser(1, "sam");
await addUser(this.currentUser.id, this.currentUser.username);
assert.dom(".chat-replying-indicator__text").hasText("sam is typing");
});
test("resets presence when channel changes", async function (assert) {
this.set("presenceChannelName", "/chat-reply/1");
await addUser(1, "sam");
await render(
hbs`<ChatReplyingIndicator @presenceChannelName={{this.presenceChannelName}} />`
);
assert.dom(".chat-replying-indicator__text").hasText("sam is typing");
this.set("presenceChannelName", "/chat-reply/2");
assert.dom(".chat-replying-indicator__text").doesNotExist();
});
}
);