DEV: various improvements to devex on chat (#21612)
- Improves styleguide support - Adds toggle color scheme to styleguide - Adds properties mutators to styleguide - Attempts to quit a session as soon as done with it in system specs, this should at least free resources faster - Refactors fabricators to simplify them - Adds more fabricators (uploads for example) - Starts implementing components pattern in system specs - Uses Chat::Message creator to create messages in system specs, this should help to have more real specs as the side effects should now happen
This commit is contained in:
parent
4d0b997559
commit
60c67afba4
|
@ -41,7 +41,6 @@
|
||||||
{{#each @channel.messages key="id" as |message|}}
|
{{#each @channel.messages key="id" as |message|}}
|
||||||
<ChatMessage
|
<ChatMessage
|
||||||
@message={{message}}
|
@message={{message}}
|
||||||
@channel={{@channel}}
|
|
||||||
@resendStagedMessage={{this.resendStagedMessage}}
|
@resendStagedMessage={{this.resendStagedMessage}}
|
||||||
@messageDidEnterViewport={{this.messageDidEnterViewport}}
|
@messageDidEnterViewport={{this.messageDidEnterViewport}}
|
||||||
@messageDidLeaveViewport={{this.messageDidLeaveViewport}}
|
@messageDidLeaveViewport={{this.messageDidLeaveViewport}}
|
||||||
|
|
|
@ -113,11 +113,10 @@ export default class ChatLivePane extends Component {
|
||||||
if (this._loadedChannelId !== this.args.channel?.id) {
|
if (this._loadedChannelId !== this.args.channel?.id) {
|
||||||
this.unsubscribeToUpdates(this._loadedChannelId);
|
this.unsubscribeToUpdates(this._loadedChannelId);
|
||||||
this.chatChannelPane.selectingMessages = false;
|
this.chatChannelPane.selectingMessages = false;
|
||||||
this.chatChannelComposer.message =
|
|
||||||
this.args.channel.draft ||
|
if (this.args.channel.draft) {
|
||||||
ChatMessage.createDraftMessage(this.args.channel, {
|
this.chatChannelComposer.message = this.args.channel.draft;
|
||||||
user: this.currentUser,
|
}
|
||||||
});
|
|
||||||
|
|
||||||
this._loadedChannelId = this.args.channel?.id;
|
this._loadedChannelId = this.args.channel?.id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="chat-composer-message-details">
|
<div class="chat-composer-message-details" data-id={{@message.id}}>
|
||||||
<div class="chat-reply">
|
<div class="chat-reply">
|
||||||
{{d-icon @icon}}
|
{{d-icon (if @message.editing "pencil-alt" "reply")}}
|
||||||
<ChatUserAvatar @user={{@message.user}} />
|
<ChatUserAvatar @user={{@message.user}} />
|
||||||
<span class="chat-reply__username">{{@message.user.username}}</span>
|
<span class="chat-reply__username">{{@message.user.username}}</span>
|
||||||
<span class="chat-reply__excerpt">
|
<span class="chat-reply__excerpt">
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
this.currentMessage
|
this.currentMessage
|
||||||
this.currentMessage.inReplyTo
|
this.currentMessage.inReplyTo
|
||||||
}}
|
}}
|
||||||
@icon={{if this.currentMessage.editing "pencil-alt" "reply"}}
|
|
||||||
@cancelAction={{this.onCancel}}
|
@cancelAction={{this.onCancel}}
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -26,7 +25,7 @@
|
||||||
}}
|
}}
|
||||||
{{did-update this.didUpdateMessage this.currentMessage}}
|
{{did-update this.didUpdateMessage this.currentMessage}}
|
||||||
{{did-update this.didUpdateInReplyTo this.currentMessage.inReplyTo}}
|
{{did-update this.didUpdateInReplyTo this.currentMessage.inReplyTo}}
|
||||||
{{did-insert this.setupAppEvents}}
|
{{did-insert this.setup}}
|
||||||
{{will-destroy this.teardown}}
|
{{will-destroy this.teardown}}
|
||||||
{{will-destroy this.cancelPersistDraft}}
|
{{will-destroy this.cancelPersistDraft}}
|
||||||
>
|
>
|
||||||
|
@ -71,7 +70,7 @@
|
||||||
{{on "click" this.onSend}}
|
{{on "click" this.onSend}}
|
||||||
@icon="paper-plane"
|
@icon="paper-plane"
|
||||||
class="chat-composer__send-btn"
|
class="chat-composer__send-btn"
|
||||||
title="chat.composer.send"
|
title={{i18n "chat.composer.send"}}
|
||||||
disabled={{or this.disabled (not this.sendEnabled)}}
|
disabled={{or this.disabled (not this.sendEnabled)}}
|
||||||
tabindex={{if this.sendEnabled 0 -1}}
|
tabindex={{if this.sendEnabled 0 -1}}
|
||||||
{{on "focus" (fn this.computeIsFocused true)}}
|
{{on "focus" (fn this.computeIsFocused true)}}
|
||||||
|
|
|
@ -141,7 +141,10 @@ export default class ChatComposer extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
setupAppEvents() {
|
setup() {
|
||||||
|
this.composer.message = ChatMessage.createDraftMessage(this.args.channel, {
|
||||||
|
user: this.currentUser,
|
||||||
|
});
|
||||||
this.appEvents.on("chat:modify-selection", this, "modifySelection");
|
this.appEvents.on("chat:modify-selection", this, "modifySelection");
|
||||||
this.appEvents.on(
|
this.appEvents.on(
|
||||||
"chat:open-insert-link-modal",
|
"chat:open-insert-link-modal",
|
||||||
|
|
|
@ -54,6 +54,10 @@ export default class ChatMessageActionsDesktop extends Component {
|
||||||
this.context
|
this.context
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!messageContainer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const viewport = messageContainer.closest(".popper-viewport");
|
const viewport = messageContainer.closest(".popper-viewport");
|
||||||
this.size =
|
this.size =
|
||||||
viewport.clientWidth < REDUCED_WIDTH_THRESHOLD ? REDUCED : FULL;
|
viewport.clientWidth < REDUCED_WIDTH_THRESHOLD ? REDUCED : FULL;
|
||||||
|
|
|
@ -130,7 +130,7 @@ export default class ChatMessage extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
_chatMessageDecorators.forEach((decorator) => {
|
_chatMessageDecorators.forEach((decorator) => {
|
||||||
decorator.call(this, this.messageContainer, this.args.channel);
|
decorator.call(this, this.messageContainer, this.args.message.channel);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ export default class ChatMessage extends Component {
|
||||||
!this.args.message?.deletedAt ||
|
!this.args.message?.deletedAt ||
|
||||||
this.currentUser.id === this.args.message?.user?.id ||
|
this.currentUser.id === this.args.message?.user?.id ||
|
||||||
this.currentUser.staff ||
|
this.currentUser.staff ||
|
||||||
this.args.channel?.canModerate
|
this.args.message?.channel?.canModerate
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,10 @@ export default class ChatMessage extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
get threadingEnabled() {
|
get threadingEnabled() {
|
||||||
return this.args.channel?.threadingEnabled && !!this.args.message?.thread;
|
return (
|
||||||
|
this.args.message?.channel?.threadingEnabled &&
|
||||||
|
!!this.args.message?.thread
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showThreadIndicator() {
|
get showThreadIndicator() {
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
{{#each this.thread.messages key="id" as |message|}}
|
{{#each this.thread.messages key="id" as |message|}}
|
||||||
<ChatMessage
|
<ChatMessage
|
||||||
@message={{message}}
|
@message={{message}}
|
||||||
@channel={{this.channel}}
|
|
||||||
@resendStagedMessage={{this.resendStagedMessage}}
|
@resendStagedMessage={{this.resendStagedMessage}}
|
||||||
@messageDidEnterViewport={{this.messageDidEnterViewport}}
|
@messageDidEnterViewport={{this.messageDidEnterViewport}}
|
||||||
@messageDidLeaveViewport={{this.messageDidLeaveViewport}}
|
@messageDidLeaveViewport={{this.messageDidLeaveViewport}}
|
||||||
|
|
|
@ -20,10 +20,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Chat::Thread::OriginalMessage
|
<Chat::Thread::OriginalMessage @message={{@thread.originalMessage}} />
|
||||||
@thread={{@thread}}
|
|
||||||
@message={{@thread.originalMessage}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<StyleguideExample @title="<ChatComposerMessageDetails>">
|
||||||
|
<Styleguide::Component>
|
||||||
|
<ChatComposerMessageDetails @message={{this.message}} />
|
||||||
|
</Styleguide::Component>
|
||||||
|
|
||||||
|
<Styleguide::Controls>
|
||||||
|
<Styleguide::Controls::Row @name="Mode">
|
||||||
|
{{#if this.message.editing}}
|
||||||
|
<DButton @action={{this.toggleMode}} @translatedLabel="Reply" />
|
||||||
|
{{else}}
|
||||||
|
<DButton @action={{this.toggleMode}} @translatedLabel="Editing" />
|
||||||
|
{{/if}}
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
</Styleguide::Controls>
|
||||||
|
</StyleguideExample>
|
|
@ -0,0 +1,27 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { cached } from "@glimmer/tracking";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
|
||||||
|
export default class ChatStyleguideChatComposerMessageDetails extends Component {
|
||||||
|
@service site;
|
||||||
|
@service session;
|
||||||
|
@service keyValueStore;
|
||||||
|
|
||||||
|
@cached
|
||||||
|
get message() {
|
||||||
|
return fabricators.message();
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleMode() {
|
||||||
|
if (this.message.editing) {
|
||||||
|
this.message.editing = false;
|
||||||
|
this.message.inReplyTo = fabricators.message();
|
||||||
|
} else {
|
||||||
|
this.message.editing = true;
|
||||||
|
this.message.inReplyTo = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<StyleguideExample @title="<ChatComposer>">
|
||||||
|
<Styleguide::Component>
|
||||||
|
<Chat::Composer::Channel
|
||||||
|
@channel={{this.channel}}
|
||||||
|
@onSendMessage={{this.onSendMessage}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Component>
|
||||||
|
|
||||||
|
<Styleguide::Controls>
|
||||||
|
<Styleguide::Controls::Row @name="Disabled">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{this.channel.isReadOnly}}
|
||||||
|
{{on "click" this.toggleDisabled}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
<Styleguide::Controls::Row @name="Sending">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{this.chatChannelPane.sending}}
|
||||||
|
{{on "click" this.toggleSending}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
</Styleguide::Controls>
|
||||||
|
</StyleguideExample>
|
|
@ -0,0 +1,30 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
import { CHANNEL_STATUSES } from "discourse/plugins/chat/discourse/models/chat-channel";
|
||||||
|
|
||||||
|
export default class ChatStyleguideChatComposer extends Component {
|
||||||
|
@service chatChannelComposer;
|
||||||
|
@service chatChannelPane;
|
||||||
|
|
||||||
|
channel = fabricators.channel();
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleDisabled() {
|
||||||
|
if (this.channel.status === CHANNEL_STATUSES.open) {
|
||||||
|
this.channel.status = CHANNEL_STATUSES.readOnly;
|
||||||
|
} else {
|
||||||
|
this.channel.status = CHANNEL_STATUSES.open;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@action
|
||||||
|
toggleSending() {
|
||||||
|
this.chatChannelPane.sending = !this.chatChannelPane.sending;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onSendMessage() {
|
||||||
|
this.chatChannelComposer.reset();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
<StyleguideExample @title="<ChatMessage>">
|
||||||
|
<Styleguide::Component>
|
||||||
|
<ChatMessage
|
||||||
|
@message={{this.message}}
|
||||||
|
@context="channel"
|
||||||
|
@messageDidEnterViewport={{(noop)}}
|
||||||
|
@messageDidLeaveViewport={{(noop)}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Component>
|
||||||
|
|
||||||
|
<Styleguide::Controls>
|
||||||
|
<Styleguide::Controls::Row @name="Last Visit">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{this.message.newest}}
|
||||||
|
{{on "click" this.toggleLastVisit}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
<Styleguide::Controls::Row @name="Deleted">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{not (not this.message.deletedAt)}}
|
||||||
|
{{on "click" this.toggleDeleted}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
<Styleguide::Controls::Row @name="Bookmark">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{not (not this.message.bookmark)}}
|
||||||
|
{{on "click" this.toggleBookmarked}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
<Styleguide::Controls::Row @name="Thread">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{not (not this.message.thread)}}
|
||||||
|
{{on "click" this.toggleThread}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
<Styleguide::Controls::Row @name="Reactions">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{not (not this.message.reactions)}}
|
||||||
|
{{on "click" this.toggleReaction}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
<Styleguide::Controls::Row @name="Upload">
|
||||||
|
<DToggleSwitch
|
||||||
|
@state={{not (not this.message.uploads)}}
|
||||||
|
{{on "click" this.toggleUpload}}
|
||||||
|
/>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
<Styleguide::Controls::Row @name="Message">
|
||||||
|
<textarea
|
||||||
|
{{on "input" this.updateMessage}}
|
||||||
|
>{{this.message.message}}</textarea>
|
||||||
|
</Styleguide::Controls::Row>
|
||||||
|
</Styleguide::Controls>
|
||||||
|
</StyleguideExample>
|
|
@ -0,0 +1,86 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import ChatMessagesManager from "discourse/plugins/chat/discourse/lib/chat-messages-manager";
|
||||||
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
|
||||||
|
export default class ChatStyleguideChatMessage extends Component {
|
||||||
|
manager = new ChatMessagesManager(getOwner(this));
|
||||||
|
|
||||||
|
message = fabricators.message();
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleDeleted() {
|
||||||
|
if (this.message.deletedAt) {
|
||||||
|
this.message.deletedAt = null;
|
||||||
|
} else {
|
||||||
|
this.message.deletedAt = moment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleBookmarked() {
|
||||||
|
if (this.message.bookmark) {
|
||||||
|
this.message.bookmark = null;
|
||||||
|
} else {
|
||||||
|
this.message.bookmark = fabricators.bookmark();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleHighlighted() {
|
||||||
|
this.message.highlighted = !this.message.highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleEdited() {
|
||||||
|
this.message.edited = !this.message.edited;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleLastVisit() {
|
||||||
|
this.message.newest = !this.message.newest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleThread() {
|
||||||
|
if (this.message.thread) {
|
||||||
|
this.message.channel.threadingEnabled = false;
|
||||||
|
this.message.thread = null;
|
||||||
|
this.message.threadReplyCount = 0;
|
||||||
|
} else {
|
||||||
|
this.message.thread = fabricators.thread({
|
||||||
|
channel: this.message.channel,
|
||||||
|
});
|
||||||
|
this.message.threadReplyCount = 1;
|
||||||
|
this.message.channel.threadingEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
updateMessage(event) {
|
||||||
|
this.message.message = event.target.value;
|
||||||
|
this.message.cook();
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleReaction() {
|
||||||
|
if (this.message.reactions?.length) {
|
||||||
|
this.message.reactions = [];
|
||||||
|
} else {
|
||||||
|
this.message.reactions = [
|
||||||
|
fabricators.reaction({ emoji: "heart" }),
|
||||||
|
fabricators.reaction({ emoji: "rocket", reacted: true }),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleUpload() {
|
||||||
|
if (this.message.uploads?.length) {
|
||||||
|
this.message.uploads = [];
|
||||||
|
} else {
|
||||||
|
this.message.uploads = [fabricators.upload(), fabricators.upload()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<StyleguideExample @title="<ChatThreadOriginalMessage>">
|
||||||
|
<Styleguide::Component>
|
||||||
|
<Chat::Thread::OriginalMessage @message={{this.message}} />
|
||||||
|
</Styleguide::Component>
|
||||||
|
</StyleguideExample>
|
|
@ -0,0 +1,6 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
|
export default class ChatStyleguideChatThreadOriginalMessage extends Component {
|
||||||
|
message = fabricators.message();
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
Fabricators are used to create fake data for testing purposes.
|
||||||
|
The following fabricators are available in lib folder to allow
|
||||||
|
styleguide to use them, and eventually to generate dummy data
|
||||||
|
in a placeholder component. It should not be used for any other case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ChatChannel, {
|
||||||
|
CHANNEL_STATUSES,
|
||||||
|
CHATABLE_TYPES,
|
||||||
|
} from "discourse/plugins/chat/discourse/models/chat-channel";
|
||||||
|
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
||||||
|
import ChatThread from "discourse/plugins/chat/discourse/models/chat-thread";
|
||||||
|
import ChatDirectMessage from "discourse/plugins/chat/discourse/models/chat-direct-message";
|
||||||
|
import ChatMessageReaction from "discourse/plugins/chat/discourse/models/chat-message-reaction";
|
||||||
|
import User from "discourse/models/user";
|
||||||
|
import Bookmark from "discourse/models/bookmark";
|
||||||
|
import Category from "discourse/models/category";
|
||||||
|
|
||||||
|
let sequence = 0;
|
||||||
|
|
||||||
|
function messageFabricator(args = {}) {
|
||||||
|
const channel = args.channel || channelFabricator();
|
||||||
|
|
||||||
|
const message = ChatMessage.create(
|
||||||
|
channel,
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
id: args.id || sequence++,
|
||||||
|
user: args.user || userFabricator(),
|
||||||
|
message:
|
||||||
|
args.message ||
|
||||||
|
"@discobot **abc**defghijklmnopqrstuvwxyz [discourse](discourse.org) :rocket: ",
|
||||||
|
created_at: args.created_at || moment(),
|
||||||
|
},
|
||||||
|
args
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const excerptLength = 50;
|
||||||
|
const text = message.message.toString();
|
||||||
|
if (text.length <= excerptLength) {
|
||||||
|
message.excerpt = text;
|
||||||
|
} else {
|
||||||
|
message.excerpt = text.slice(0, excerptLength) + "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
message.cook();
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
function channelFabricator(args = {}) {
|
||||||
|
const id = args.id || sequence++;
|
||||||
|
|
||||||
|
return ChatChannel.create(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
chatable_type:
|
||||||
|
args.chatable?.type ||
|
||||||
|
args.chatable_type ||
|
||||||
|
CHATABLE_TYPES.categoryChannel,
|
||||||
|
last_message_sent_at: args.last_message_sent_at,
|
||||||
|
chatable_id: args.chatable?.id || args.chatable_id,
|
||||||
|
title: args.title || "General",
|
||||||
|
description: args.description,
|
||||||
|
chatable: args.chatable || categoryFabricator(),
|
||||||
|
status: CHANNEL_STATUSES.open,
|
||||||
|
},
|
||||||
|
args
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function categoryFabricator(args = {}) {
|
||||||
|
return Category.create({
|
||||||
|
id: args.id || sequence++,
|
||||||
|
color: args.color || "D56353",
|
||||||
|
read_restricted: false,
|
||||||
|
name: args.name || "General",
|
||||||
|
slug: args.slug || "general",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function directMessageFabricator(args = {}) {
|
||||||
|
return ChatDirectMessage.create({
|
||||||
|
id: args.id || sequence++,
|
||||||
|
users: args.users || [userFabricator(), userFabricator()],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function directMessageChannelFabricator(args = {}) {
|
||||||
|
const directMessage =
|
||||||
|
args.chatable ||
|
||||||
|
directMessageFabricator({
|
||||||
|
id: args.chatable_id || sequence++,
|
||||||
|
});
|
||||||
|
|
||||||
|
return channelFabricator(
|
||||||
|
Object.assign(args, {
|
||||||
|
chatable_type: CHATABLE_TYPES.directMessageChannel,
|
||||||
|
chatable_id: directMessage.id,
|
||||||
|
chatable: directMessage,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function userFabricator(args = {}) {
|
||||||
|
return User.create({
|
||||||
|
id: args.id || sequence++,
|
||||||
|
username: args.username || "hawk",
|
||||||
|
name: args.name,
|
||||||
|
avatar_template: "/letter_avatar_proxy/v3/letter/t/41988e/{size}.png",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bookmarkFabricator(args = {}) {
|
||||||
|
return Bookmark.create({
|
||||||
|
id: args.id || sequence++,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function threadFabricator(args = {}) {
|
||||||
|
const channel = args.channel || channelFabricator();
|
||||||
|
return ChatThread.create(channel, {
|
||||||
|
id: args.id || sequence++,
|
||||||
|
original_message: args.original_message || messageFabricator({ channel }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function reactionFabricator(args = {}) {
|
||||||
|
return ChatMessageReaction.create({
|
||||||
|
count: args.count || 1,
|
||||||
|
users: args.users || [userFabricator()],
|
||||||
|
emoji: args.emoji || "heart",
|
||||||
|
reacted: args.reacted || false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadFabricator() {
|
||||||
|
return {
|
||||||
|
extension: "jpeg",
|
||||||
|
filesize: 126177,
|
||||||
|
height: 800,
|
||||||
|
human_filesize: "123 KB",
|
||||||
|
id: 202,
|
||||||
|
original_filename: "avatar.PNG.jpg",
|
||||||
|
retain_hours: null,
|
||||||
|
short_path: "/images/avatar.png",
|
||||||
|
short_url: "upload://yoj8pf9DdIeHRRULyw7i57GAYdz.jpeg",
|
||||||
|
thumbnail_height: 320,
|
||||||
|
thumbnail_width: 690,
|
||||||
|
url: "/images/avatar.png",
|
||||||
|
width: 1920,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
bookmark: bookmarkFabricator,
|
||||||
|
user: userFabricator,
|
||||||
|
channel: channelFabricator,
|
||||||
|
directMessageChannel: directMessageChannelFabricator,
|
||||||
|
message: messageFabricator,
|
||||||
|
thread: threadFabricator,
|
||||||
|
reaction: reactionFabricator,
|
||||||
|
upload: uploadFabricator,
|
||||||
|
category: categoryFabricator,
|
||||||
|
directMessage: directMessageFabricator,
|
||||||
|
};
|
|
@ -89,6 +89,7 @@ export default class ChatChannel {
|
||||||
@tracked membershipsCount = 0;
|
@tracked membershipsCount = 0;
|
||||||
@tracked archive;
|
@tracked archive;
|
||||||
@tracked tracking;
|
@tracked tracking;
|
||||||
|
@tracked threadingEnabled = false;
|
||||||
|
|
||||||
threadsManager = new ChatThreadsManager(getOwner(this));
|
threadsManager = new ChatThreadsManager(getOwner(this));
|
||||||
messagesManager = new ChatMessagesManager(getOwner(this));
|
messagesManager = new ChatMessagesManager(getOwner(this));
|
||||||
|
@ -114,7 +115,10 @@ export default class ChatChannel {
|
||||||
this.autoJoinUsers = args.auto_join_users;
|
this.autoJoinUsers = args.auto_join_users;
|
||||||
this.allowChannelWideMentions = args.allow_channel_wide_mentions;
|
this.allowChannelWideMentions = args.allow_channel_wide_mentions;
|
||||||
this.chatable = this.isDirectMessageChannel
|
this.chatable = this.isDirectMessageChannel
|
||||||
? ChatDirectMessage.create(args)
|
? ChatDirectMessage.create({
|
||||||
|
id: args.chatable?.id,
|
||||||
|
users: args.chatable?.users,
|
||||||
|
})
|
||||||
: Category.create(args.chatable);
|
: Category.create(args.chatable);
|
||||||
this.currentUserMembership = UserChatChannelMembership.create(
|
this.currentUserMembership = UserChatChannelMembership.create(
|
||||||
args.current_user_membership
|
args.current_user_membership
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import User from "discourse/models/user";
|
import User from "discourse/models/user";
|
||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { CHATABLE_TYPES } from "discourse/plugins/chat/discourse/models/chat-channel";
|
||||||
|
|
||||||
export default class ChatDirectMessage {
|
export default class ChatDirectMessage {
|
||||||
static create(args = {}) {
|
static create(args = {}) {
|
||||||
|
@ -9,9 +10,11 @@ export default class ChatDirectMessage {
|
||||||
@tracked id;
|
@tracked id;
|
||||||
@tracked users = null;
|
@tracked users = null;
|
||||||
|
|
||||||
|
type = CHATABLE_TYPES.drectMessageChannel;
|
||||||
|
|
||||||
constructor(args = {}) {
|
constructor(args = {}) {
|
||||||
this.id = args.chatable.id;
|
this.id = args.id;
|
||||||
this.users = this.#initUsers(args.chatable.users || []);
|
this.users = this.#initUsers(args.users || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
#initUsers(users) {
|
#initUsers(users) {
|
||||||
|
|
|
@ -12,9 +12,9 @@ export default class ChatMessageReaction {
|
||||||
@tracked count = 0;
|
@tracked count = 0;
|
||||||
@tracked reacted = false;
|
@tracked reacted = false;
|
||||||
@tracked users = [];
|
@tracked users = [];
|
||||||
|
@tracked emoji;
|
||||||
|
|
||||||
constructor(args = {}) {
|
constructor(args = {}) {
|
||||||
this.messageId = args.messageId;
|
|
||||||
this.count = args.count;
|
this.count = args.count;
|
||||||
this.emoji = args.emoji;
|
this.emoji = args.emoji;
|
||||||
this.users = this.#initUsersModels(args.users);
|
this.users = this.#initUsersModels(args.users);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import I18n from "I18n";
|
||||||
import { generateCookFunction } from "discourse/lib/text";
|
import { generateCookFunction } from "discourse/lib/text";
|
||||||
import simpleCategoryHashMentionTransform from "discourse/plugins/chat/discourse/lib/simple-category-hash-mention-transform";
|
import simpleCategoryHashMentionTransform from "discourse/plugins/chat/discourse/lib/simple-category-hash-mention-transform";
|
||||||
import { getOwner } from "discourse-common/lib/get-owner";
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
import { next } from "@ember/runloop";
|
||||||
export default class ChatMessage {
|
export default class ChatMessage {
|
||||||
static cookFunction = null;
|
static cookFunction = null;
|
||||||
|
|
||||||
|
@ -38,9 +38,10 @@ export default class ChatMessage {
|
||||||
@tracked expanded;
|
@tracked expanded;
|
||||||
@tracked bookmark;
|
@tracked bookmark;
|
||||||
@tracked userFlagStatus;
|
@tracked userFlagStatus;
|
||||||
@tracked hidden;
|
@tracked hidden = false;
|
||||||
@tracked version = 0;
|
@tracked version = 0;
|
||||||
@tracked edited;
|
@tracked edited = false;
|
||||||
|
@tracked editing = false;
|
||||||
@tracked chatWebhookEvent = new TrackedObject();
|
@tracked chatWebhookEvent = new TrackedObject();
|
||||||
@tracked mentionWarning;
|
@tracked mentionWarning;
|
||||||
@tracked availableFlags;
|
@tracked availableFlags;
|
||||||
|
@ -62,6 +63,7 @@ export default class ChatMessage {
|
||||||
this.firstOfResults = args.firstOfResults;
|
this.firstOfResults = args.firstOfResults;
|
||||||
this.staged = args.staged;
|
this.staged = args.staged;
|
||||||
this.edited = args.edited;
|
this.edited = args.edited;
|
||||||
|
this.editing = args.editing;
|
||||||
this.availableFlags = args.availableFlags || args.available_flags;
|
this.availableFlags = args.availableFlags || args.available_flags;
|
||||||
this.hidden = args.hidden;
|
this.hidden = args.hidden;
|
||||||
this.threadReplyCount = args.threadReplyCount || args.thread_reply_count;
|
this.threadReplyCount = args.threadReplyCount || args.thread_reply_count;
|
||||||
|
@ -82,10 +84,7 @@ export default class ChatMessage {
|
||||||
? ChatMessage.create(channel, args.in_reply_to || args.replyToMsg)
|
? ChatMessage.create(channel, args.in_reply_to || args.replyToMsg)
|
||||||
: null);
|
: null);
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.reactions = this.#initChatMessageReactionModel(
|
this.reactions = this.#initChatMessageReactionModel(args.reactions);
|
||||||
args.id,
|
|
||||||
args.reactions
|
|
||||||
);
|
|
||||||
this.uploads = new TrackedArray(args.uploads || []);
|
this.uploads = new TrackedArray(args.uploads || []);
|
||||||
this.user = this.#initUserModel(args.user);
|
this.user = this.#initUserModel(args.user);
|
||||||
this.bookmark = args.bookmark ? Bookmark.create(args.bookmark) : null;
|
this.bookmark = args.bookmark ? Bookmark.create(args.bookmark) : null;
|
||||||
|
@ -138,33 +137,35 @@ export default class ChatMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
cook() {
|
cook() {
|
||||||
const site = getOwner(this).lookup("service:site");
|
next(() => {
|
||||||
|
const site = getOwner(this).lookup("service:site");
|
||||||
|
|
||||||
const markdownOptions = {
|
const markdownOptions = {
|
||||||
featuresOverride:
|
featuresOverride:
|
||||||
site.markdown_additional_options?.chat?.limited_pretty_text_features,
|
site.markdown_additional_options?.chat?.limited_pretty_text_features,
|
||||||
markdownItRules:
|
markdownItRules:
|
||||||
site.markdown_additional_options?.chat
|
site.markdown_additional_options?.chat
|
||||||
?.limited_pretty_text_markdown_rules,
|
?.limited_pretty_text_markdown_rules,
|
||||||
hashtagTypesInPriorityOrder:
|
hashtagTypesInPriorityOrder:
|
||||||
site.hashtag_configurations?.["chat-composer"],
|
site.hashtag_configurations?.["chat-composer"],
|
||||||
hashtagIcons: site.hashtag_icons,
|
hashtagIcons: site.hashtag_icons,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ChatMessage.cookFunction) {
|
|
||||||
this.cooked = ChatMessage.cookFunction(this.message);
|
|
||||||
} else {
|
|
||||||
generateCookFunction(markdownOptions).then((cookFunction) => {
|
|
||||||
ChatMessage.cookFunction = (raw) => {
|
|
||||||
return simpleCategoryHashMentionTransform(
|
|
||||||
cookFunction(raw),
|
|
||||||
site.categories
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if (ChatMessage.cookFunction) {
|
||||||
this.cooked = ChatMessage.cookFunction(this.message);
|
this.cooked = ChatMessage.cookFunction(this.message);
|
||||||
});
|
} else {
|
||||||
}
|
generateCookFunction(markdownOptions).then((cookFunction) => {
|
||||||
|
ChatMessage.cookFunction = (raw) => {
|
||||||
|
return simpleCategoryHashMentionTransform(
|
||||||
|
cookFunction(raw),
|
||||||
|
site.categories
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.cooked = ChatMessage.cookFunction(this.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get read() {
|
get read() {
|
||||||
|
@ -306,10 +307,8 @@ export default class ChatMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#initChatMessageReactionModel(messageId, reactions = []) {
|
#initChatMessageReactionModel(reactions = []) {
|
||||||
return reactions.map((reaction) =>
|
return reactions.map((reaction) => ChatMessageReaction.create(reaction));
|
||||||
ChatMessageReaction.create(Object.assign({ messageId }, reaction))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#initUserModel(user) {
|
#initUserModel(user) {
|
||||||
|
|
|
@ -13,6 +13,10 @@ export const THREAD_STATUSES = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ChatThread {
|
export default class ChatThread {
|
||||||
|
static create(channel, args = {}) {
|
||||||
|
return new ChatThread(channel, args);
|
||||||
|
}
|
||||||
|
|
||||||
@tracked id;
|
@tracked id;
|
||||||
@tracked title;
|
@tracked title;
|
||||||
@tracked status;
|
@tracked status;
|
||||||
|
|
|
@ -4,7 +4,6 @@ import ChatComposer from "./chat-composer";
|
||||||
|
|
||||||
export default class ChatChannelComposer extends ChatComposer {
|
export default class ChatChannelComposer extends ChatComposer {
|
||||||
@service chat;
|
@service chat;
|
||||||
@service chatChannelThreadComposer;
|
|
||||||
@service router;
|
@service router;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<Styleguide::ChatMessage />
|
||||||
|
<Styleguide::ChatComposer />
|
||||||
|
<Styleguide::ChatThreadOriginalMessage />
|
||||||
|
<Styleguide::ChatComposerMessageDetails />
|
|
@ -641,3 +641,8 @@ en:
|
||||||
chat_notifications_with_unread:
|
chat_notifications_with_unread:
|
||||||
one: "Chat notifications - %{count} unread notification"
|
one: "Chat notifications - %{count} unread notification"
|
||||||
other: "Chat notifications - %{count} unread notifications"
|
other: "Chat notifications - %{count} unread notifications"
|
||||||
|
|
||||||
|
styleguide:
|
||||||
|
sections:
|
||||||
|
chat:
|
||||||
|
title: Chat
|
||||||
|
|
|
@ -49,13 +49,29 @@ Fabricator(:direct_message_channel, from: :chat_channel) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Fabricator(:chat_message, class_name: "Chat::Message") do
|
Fabricator(:chat_message, class_name: "Chat::MessageCreator") do
|
||||||
chat_channel
|
transient :chat_channel
|
||||||
user
|
transient :user
|
||||||
message "Beep boop"
|
transient :message
|
||||||
cooked { |attrs| Chat::Message.cook(attrs[:message]) }
|
transient :in_reply_to
|
||||||
cooked_version Chat::Message::BAKED_VERSION
|
transient :thread
|
||||||
in_reply_to nil
|
transient :upload_ids
|
||||||
|
|
||||||
|
initialize_with do |transients|
|
||||||
|
user = transients[:user] || Fabricate(:user)
|
||||||
|
channel =
|
||||||
|
transients[:chat_channel] || transients[:thread]&.channel ||
|
||||||
|
transients[:in_reply_to]&.chat_channel || Fabricate(:chat_channel)
|
||||||
|
|
||||||
|
resolved_class.create(
|
||||||
|
chat_channel: channel,
|
||||||
|
user: user,
|
||||||
|
content: transients[:message] || Faker::Lorem.paragraph,
|
||||||
|
thread_id: transients[:thread]&.id,
|
||||||
|
in_reply_to_id: transients[:in_reply_to]&.id,
|
||||||
|
upload_ids: transients[:upload_ids],
|
||||||
|
).chat_message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Fabricator(:chat_mention, class_name: "Chat::Mention") do
|
Fabricator(:chat_mention, class_name: "Chat::Mention") do
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe "Chat | composer | shortcuts | thread", type: :system, js: true do
|
||||||
|
fab!(:channel_1) { Fabricate(:chat_channel, threading_enabled: true) }
|
||||||
|
fab!(:current_user) { Fabricate(:user) }
|
||||||
|
fab!(:message_1) { Fabricate(:chat_message, chat_channel: channel_1) }
|
||||||
|
let(:chat_page) { PageObjects::Pages::Chat.new }
|
||||||
|
let(:thread_page) { PageObjects::Pages::ChatThread.new }
|
||||||
|
|
||||||
|
before do
|
||||||
|
SiteSetting.enable_experimental_chat_threaded_discussions = true
|
||||||
|
chat_system_bootstrap
|
||||||
|
channel_1.add(current_user)
|
||||||
|
sign_in(current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "ArrowUp" do
|
||||||
|
let(:thread_1) { message_1.reload.thread }
|
||||||
|
|
||||||
|
context "when there are editable messages" do
|
||||||
|
let(:last_thread_message) { thread_1.replies.last }
|
||||||
|
|
||||||
|
before do
|
||||||
|
thread_message_1 = Fabricate(:chat_message, user: current_user, in_reply_to: message_1)
|
||||||
|
Fabricate(:chat_message, user: current_user, thread: thread_message_1.reload.thread)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "starts editing the last editable message" do
|
||||||
|
chat_page.visit_thread(thread_1)
|
||||||
|
|
||||||
|
thread_page.composer.edit_last_message_shortcut
|
||||||
|
|
||||||
|
expect(thread_page.composer_message_details).to have_message(last_thread_message)
|
||||||
|
expect(thread_page.composer.value).to eq(last_thread_message.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there are no editable messages" do
|
||||||
|
before { Fabricate(:chat_message, in_reply_to: message_1) }
|
||||||
|
|
||||||
|
it "does nothing" do
|
||||||
|
chat_page.visit_thread(thread_1)
|
||||||
|
|
||||||
|
thread_page.composer.edit_last_message_shortcut
|
||||||
|
|
||||||
|
expect(thread_page.composer_message_details).to have_no_message
|
||||||
|
expect(thread_page.composer.value).to be_blank
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -45,9 +45,15 @@ RSpec.describe "Chat channel", type: :system, js: true do
|
||||||
chat.visit_channel(channel_1)
|
chat.visit_channel(channel_1)
|
||||||
end
|
end
|
||||||
|
|
||||||
using_session(:tab_1) { channel.send_message("test_message") }
|
using_session(:tab_1) do |session|
|
||||||
|
channel.send_message("test_message")
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
using_session(:tab_2) { expect(channel).to have_message(text: "test_message") }
|
using_session(:tab_2) do |session|
|
||||||
|
expect(channel).to have_message(text: "test_message")
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,12 @@ RSpec.describe "Edited message", type: :system, js: true do
|
||||||
it "shows as edited for all users" do
|
it "shows as edited for all users" do
|
||||||
chat_page.visit_channel(channel_1)
|
chat_page.visit_channel(channel_1)
|
||||||
|
|
||||||
using_session(:user_1) do
|
using_session(:user_1) do |session|
|
||||||
sign_in(editing_user)
|
sign_in(editing_user)
|
||||||
chat_page.visit_channel(channel_1)
|
chat_page.visit_channel(channel_1)
|
||||||
channel_page.edit_message(message_1, "a different message")
|
channel_page.edit_message(message_1, "a different message")
|
||||||
expect(page).to have_content(I18n.t("js.chat.edited"))
|
expect(page).to have_content(I18n.t("js.chat.edited"))
|
||||||
|
session.quit
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content(I18n.t("js.chat.edited"))
|
expect(page).to have_content(I18n.t("js.chat.edited"))
|
||||||
|
|
|
@ -35,7 +35,10 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
|
|
||||||
visit("/chat")
|
visit("/chat")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
||||||
expect(page).to have_no_css(
|
expect(page).to have_no_css(
|
||||||
|
@ -62,7 +65,10 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
|
|
||||||
visit("/chat")
|
visit("/chat")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".do-not-disturb-background")
|
expect(page).to have_css(".do-not-disturb-background")
|
||||||
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
||||||
|
@ -77,7 +83,10 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
|
|
||||||
visit("/chat")
|
visit("/chat")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
||||||
expect(page).to have_no_css(
|
expect(page).to have_no_css(
|
||||||
|
@ -92,7 +101,10 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
|
|
||||||
visit("/chat")
|
visit("/chat")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
|
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
|
||||||
expect(page).to have_css(
|
expect(page).to have_css(
|
||||||
|
@ -138,14 +150,20 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
|
|
||||||
visit("/chat")
|
visit("/chat")
|
||||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: dm_channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "1")
|
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "1")
|
||||||
expect(page).to have_css(
|
expect(page).to have_css(
|
||||||
".chat-channel-row[data-chat-channel-id=\"#{dm_channel_1.id}\"] .chat-channel-unread-indicator",
|
".chat-channel-row[data-chat-channel-id=\"#{dm_channel_1.id}\"] .chat-channel-unread-indicator",
|
||||||
)
|
)
|
||||||
|
|
||||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: dm_channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "2")
|
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "2")
|
||||||
end
|
end
|
||||||
|
@ -162,7 +180,10 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||||
".chat-channel-row:nth-child(2)[data-chat-channel-id=\"#{dm_channel_2.id}\"]",
|
".chat-channel-row:nth-child(2)[data-chat-channel-id=\"#{dm_channel_2.id}\"]",
|
||||||
)
|
)
|
||||||
|
|
||||||
using_session(:user_1) { create_message(channel: dm_channel_2, creator: user_2) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: dm_channel_2, creator: user_2)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(
|
expect(page).to have_css(
|
||||||
".chat-channel-row:nth-child(1)[data-chat-channel-id=\"#{dm_channel_2.id}\"]",
|
".chat-channel-row:nth-child(1)[data-chat-channel-id=\"#{dm_channel_2.id}\"]",
|
||||||
|
@ -190,14 +211,20 @@ RSpec.describe "Message notifications - mobile", type: :system, js: true, mobile
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
|
|
||||||
visit("/chat")
|
visit("/chat")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
|
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
|
||||||
expect(page).to have_css(
|
expect(page).to have_css(
|
||||||
".chat-channel-row[data-chat-channel-id=\"#{channel_1.id}\"] .chat-channel-unread-indicator",
|
".chat-channel-row[data-chat-channel-id=\"#{channel_1.id}\"] .chat-channel-unread-indicator",
|
||||||
)
|
)
|
||||||
|
|
||||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: dm_channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(
|
expect(page).to have_css(
|
||||||
".chat-channel-row[data-chat-channel-id=\"#{dm_channel_1.id}\"] .chat-channel-unread-indicator",
|
".chat-channel-row[data-chat-channel-id=\"#{dm_channel_1.id}\"] .chat-channel-unread-indicator",
|
||||||
|
|
|
@ -34,7 +34,10 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
context "when a message is created" do
|
context "when a message is created" do
|
||||||
it "doesn't show anything" do
|
it "doesn't show anything" do
|
||||||
visit("/")
|
visit("/")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
||||||
expect(page).to have_no_css(".sidebar-row.channel-#{channel_1.id}")
|
expect(page).to have_no_css(".sidebar-row.channel-#{channel_1.id}")
|
||||||
|
@ -59,7 +62,10 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
Jobs.run_immediately!
|
Jobs.run_immediately!
|
||||||
|
|
||||||
visit("/")
|
visit("/")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".do-not-disturb-background")
|
expect(page).to have_css(".do-not-disturb-background")
|
||||||
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
||||||
|
@ -72,7 +78,10 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
context "when a message is created" do
|
context "when a message is created" do
|
||||||
it "doesn't show anything" do
|
it "doesn't show anything" do
|
||||||
visit("/")
|
visit("/")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
||||||
expect(page).to have_no_css(".sidebar-row.channel-#{channel_1.id} .unread")
|
expect(page).to have_no_css(".sidebar-row.channel-#{channel_1.id} .unread")
|
||||||
|
@ -91,7 +100,10 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
context "when a message is created" do
|
context "when a message is created" do
|
||||||
it "doesn't show any indicator on chat-header-icon" do
|
it "doesn't show any indicator on chat-header-icon" do
|
||||||
visit("/")
|
visit("/")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
|
||||||
end
|
end
|
||||||
|
@ -109,7 +121,10 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
context "when a message is created" do
|
context "when a message is created" do
|
||||||
it "doesn't show any indicator on chat-header-icon" do
|
it "doesn't show any indicator on chat-header-icon" do
|
||||||
visit("/")
|
visit("/")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_no_css(
|
expect(page).to have_no_css(
|
||||||
".chat-header-icon .chat-channel-unread-indicator.urgent",
|
".chat-header-icon .chat-channel-unread-indicator.urgent",
|
||||||
|
@ -137,7 +152,10 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
context "when a message is created" do
|
context "when a message is created" do
|
||||||
it "correctly renders notifications" do
|
it "correctly renders notifications" do
|
||||||
visit("/")
|
visit("/")
|
||||||
using_session(:user_1) { create_message(channel: channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
|
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
|
||||||
expect(page).to have_css(".sidebar-row.channel-#{channel_1.id} .unread")
|
expect(page).to have_css(".sidebar-row.channel-#{channel_1.id} .unread")
|
||||||
|
@ -178,12 +196,18 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
context "when a message is created" do
|
context "when a message is created" do
|
||||||
it "correctly renders notifications" do
|
it "correctly renders notifications" do
|
||||||
visit("/")
|
visit("/")
|
||||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: dm_channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "1")
|
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "1")
|
||||||
expect(page).to have_css(".sidebar-row.channel-#{dm_channel_1.id} .icon.urgent")
|
expect(page).to have_css(".sidebar-row.channel-#{dm_channel_1.id} .icon.urgent")
|
||||||
|
|
||||||
using_session(:user_1) { create_message(channel: dm_channel_1, creator: user_1) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: dm_channel_1, creator: user_1)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "2")
|
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "2")
|
||||||
end
|
end
|
||||||
|
@ -198,7 +222,10 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
"#sidebar-section-content-chat-dms .sidebar-section-link-wrapper:nth-child(2) .channel-#{dm_channel_2.id}",
|
"#sidebar-section-content-chat-dms .sidebar-section-link-wrapper:nth-child(2) .channel-#{dm_channel_2.id}",
|
||||||
)
|
)
|
||||||
|
|
||||||
using_session(:user_1) { create_message(channel: dm_channel_2, creator: user_2) }
|
using_session(:user_1) do |session|
|
||||||
|
create_message(channel: dm_channel_2, creator: user_2)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
expect(page).to have_css(
|
expect(page).to have_css(
|
||||||
"#sidebar-section-content-chat-dms .sidebar-section-link-wrapper:nth-child(1) .channel-#{dm_channel_2.id}",
|
"#sidebar-section-content-chat-dms .sidebar-section-link-wrapper:nth-child(1) .channel-#{dm_channel_2.id}",
|
||||||
|
@ -237,12 +264,13 @@ RSpec.describe "Message notifications - with sidebar", type: :system, js: true d
|
||||||
session.quit
|
session.quit
|
||||||
end
|
end
|
||||||
|
|
||||||
using_session(:current_user) do
|
using_session(:current_user) do |session|
|
||||||
expect(page).to have_css(".sidebar-row.channel-#{dm_channel_1.id} .icon.urgent")
|
expect(page).to have_css(".sidebar-row.channel-#{dm_channel_1.id} .icon.urgent")
|
||||||
expect(page).to have_css(
|
expect(page).to have_css(
|
||||||
".chat-header-icon .chat-channel-unread-indicator",
|
".chat-header-icon .chat-channel-unread-indicator",
|
||||||
text: "1",
|
text: "1",
|
||||||
)
|
)
|
||||||
|
session.quit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,8 +17,8 @@ module PageObjects
|
||||||
visit("/chat")
|
visit("/chat")
|
||||||
end
|
end
|
||||||
|
|
||||||
def visit_channel(channel, mobile: false)
|
def visit_channel(channel)
|
||||||
visit(channel.url + (mobile ? "?mobile_view=1" : ""))
|
visit(channel.url)
|
||||||
has_no_css?(".chat-channel--not-loaded-once")
|
has_no_css?(".chat-channel--not-loaded-once")
|
||||||
has_no_css?(".chat-skeleton")
|
has_no_css?(".chat-skeleton")
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,15 @@
|
||||||
module PageObjects
|
module PageObjects
|
||||||
module Pages
|
module Pages
|
||||||
class ChatThread < PageObjects::Pages::Base
|
class ChatThread < PageObjects::Pages::Base
|
||||||
|
def composer
|
||||||
|
@composer ||= PageObjects::Components::Chat::Composer.new(".chat-thread")
|
||||||
|
end
|
||||||
|
|
||||||
|
def composer_message_details
|
||||||
|
@composer_message_details ||=
|
||||||
|
PageObjects::Components::Chat::ComposerMessageDetails.new(".chat-thread")
|
||||||
|
end
|
||||||
|
|
||||||
def header
|
def header
|
||||||
find(".chat-thread__header")
|
find(".chat-thread__header")
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module PageObjects
|
||||||
|
module Components
|
||||||
|
module Chat
|
||||||
|
class Composer < PageObjects::Components::Base
|
||||||
|
attr_reader :context
|
||||||
|
|
||||||
|
SELECTOR = ".chat-composer__wrapper"
|
||||||
|
|
||||||
|
def initialize(context)
|
||||||
|
@context = context
|
||||||
|
end
|
||||||
|
|
||||||
|
def input
|
||||||
|
find(context).find(SELECTOR).find(".chat-composer__input")
|
||||||
|
end
|
||||||
|
|
||||||
|
def value
|
||||||
|
input.value
|
||||||
|
end
|
||||||
|
|
||||||
|
def reply_to_last_message_shortcut
|
||||||
|
input.send_keys(%i[shift arrow_up])
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit_last_message_shortcut
|
||||||
|
input.send_keys(%i[arrow_up])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,25 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module PageObjects
|
||||||
|
module Components
|
||||||
|
module Chat
|
||||||
|
class ComposerMessageDetails < PageObjects::Components::Base
|
||||||
|
attr_reader :context
|
||||||
|
|
||||||
|
SELECTOR = ".chat-composer-message-details"
|
||||||
|
|
||||||
|
def initialize(context)
|
||||||
|
@context = context
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_message?(message)
|
||||||
|
find(context).find(SELECTOR + "[data-id=\"#{message.id}\"]")
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_no_message?
|
||||||
|
find(context).has_no_css?(SELECTOR)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -87,7 +87,7 @@ RSpec.describe "Reply to message - channel - drawer", type: :system, js: true do
|
||||||
|
|
||||||
expect(page).to have_selector(
|
expect(page).to have_selector(
|
||||||
".chat-channel .chat-reply__excerpt",
|
".chat-channel .chat-reply__excerpt",
|
||||||
text: original_message.message,
|
text: original_message.excerpt,
|
||||||
)
|
)
|
||||||
|
|
||||||
channel_page.fill_composer("reply to message")
|
channel_page.fill_composer("reply to message")
|
||||||
|
|
|
@ -91,7 +91,7 @@ RSpec.describe "Reply to message - channel - full page", type: :system, js: true
|
||||||
|
|
||||||
expect(page).to have_selector(
|
expect(page).to have_selector(
|
||||||
".chat-channel .chat-reply__excerpt",
|
".chat-channel .chat-reply__excerpt",
|
||||||
text: original_message.message,
|
text: original_message.excerpt,
|
||||||
)
|
)
|
||||||
|
|
||||||
channel_page.fill_composer("reply to message")
|
channel_page.fill_composer("reply to message")
|
||||||
|
|
|
@ -97,7 +97,7 @@ RSpec.describe "Reply to message - channel - mobile", type: :system, js: true, m
|
||||||
|
|
||||||
expect(page).to have_selector(
|
expect(page).to have_selector(
|
||||||
".chat-channel .chat-reply__excerpt",
|
".chat-channel .chat-reply__excerpt",
|
||||||
text: original_message.message,
|
text: original_message.excerpt,
|
||||||
)
|
)
|
||||||
|
|
||||||
channel_page.fill_composer("reply to message")
|
channel_page.fill_composer("reply to message")
|
||||||
|
|
|
@ -161,15 +161,17 @@ describe "Single thread in side panel", type: :system, js: true do
|
||||||
expect(thread_page).to have_message(thread_id: thread.id, text: "the other user message")
|
expect(thread_page).to have_message(thread_id: thread.id, text: "the other user message")
|
||||||
end
|
end
|
||||||
|
|
||||||
using_session(:tab_1) do
|
using_session(:tab_1) do |session|
|
||||||
expect(side_panel).to have_open_thread(thread)
|
expect(side_panel).to have_open_thread(thread)
|
||||||
expect(thread_page).to have_message(thread_id: thread.id, text: "the other user message")
|
expect(thread_page).to have_message(thread_id: thread.id, text: "the other user message")
|
||||||
thread_page.send_message("this is a test message")
|
thread_page.send_message("this is a test message")
|
||||||
expect(thread_page).to have_message(thread_id: thread.id, text: "this is a test message")
|
expect(thread_page).to have_message(thread_id: thread.id, text: "this is a test message")
|
||||||
|
session.quit
|
||||||
end
|
end
|
||||||
|
|
||||||
using_session(:tab_2) do
|
using_session(:tab_2) do |session|
|
||||||
expect(thread_page).to have_message(thread_id: thread.id, text: "this is a test message")
|
expect(thread_page).to have_message(thread_id: thread.id, text: "this is a test message")
|
||||||
|
session.quit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,13 @@ RSpec.describe "Unfollow dm channel", type: :system, js: true do
|
||||||
|
|
||||||
expect(page).to have_no_css(".channel-#{dm_channel_1.id}")
|
expect(page).to have_no_css(".channel-#{dm_channel_1.id}")
|
||||||
|
|
||||||
using_session(:user_1) do
|
using_session(:user_1) do |session|
|
||||||
text = "this is fine"
|
text = "this is fine"
|
||||||
sign_in(other_user)
|
sign_in(other_user)
|
||||||
chat_page.visit_channel(dm_channel_1)
|
chat_page.visit_channel(dm_channel_1)
|
||||||
chat_channel_page.send_message(text)
|
chat_channel_page.send_message(text)
|
||||||
expect(chat_channel_page).to have_message(text: text)
|
expect(chat_channel_page).to have_message(text: text)
|
||||||
|
session.quit
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_css(".channel-#{dm_channel_1.id} .urgent")
|
expect(page).to have_css(".channel-#{dm_channel_1.id} .urgent")
|
||||||
|
|
|
@ -198,13 +198,14 @@ RSpec.describe "User menu notifications | sidebar", type: :system, js: true do
|
||||||
channel.send_message("this is fine @#{other_user.username}")
|
channel.send_message("this is fine @#{other_user.username}")
|
||||||
find(".invite-link", wait: 5).click
|
find(".invite-link", wait: 5).click
|
||||||
|
|
||||||
using_session(:user_1) do
|
using_session(:user_1) do |session|
|
||||||
sign_in(other_user)
|
sign_in(other_user)
|
||||||
visit("/")
|
visit("/")
|
||||||
find(".header-dropdown-toggle.current-user").click
|
find(".header-dropdown-toggle.current-user").click
|
||||||
|
|
||||||
expect(find("#user-menu-button-chat-notifications")).to have_content(1)
|
expect(find("#user-menu-button-chat-notifications")).to have_content(1)
|
||||||
expect(find("#quick-access-all-notifications")).to have_css(".chat-invitation.unread")
|
expect(find("#quick-access-all-notifications")).to have_css(".chat-invitation.unread")
|
||||||
|
session.quit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
|
@ -13,7 +13,7 @@ module(
|
||||||
test("channel title is escaped in instructions correctly", async function (assert) {
|
test("channel title is escaped in instructions correctly", async function (assert) {
|
||||||
this.set(
|
this.set(
|
||||||
"channel",
|
"channel",
|
||||||
fabricators.chatChannel({
|
fabricators.channel({
|
||||||
title: `<script>someeviltitle</script>`,
|
title: `<script>someeviltitle</script>`,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
@ -10,7 +10,7 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function () {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
this.channel.description =
|
this.channel.description =
|
||||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
|
@ -13,7 +13,7 @@ module(
|
||||||
test("channel title is escaped in instructions correctly", async function (assert) {
|
test("channel title is escaped in instructions correctly", async function (assert) {
|
||||||
this.set(
|
this.set(
|
||||||
"channel",
|
"channel",
|
||||||
fabricators.chatChannel({
|
fabricators.channel({
|
||||||
title: `<script>someeviltitle</script>`,
|
title: `<script>someeviltitle</script>`,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import hbs from "htmlbars-inline-precompile";
|
||||||
import pretender from "discourse/tests/helpers/create-pretender";
|
import pretender from "discourse/tests/helpers/create-pretender";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) {
|
module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
@ -13,7 +13,7 @@ module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) {
|
||||||
test("accepts an optional onLeaveChannel callback", async function (assert) {
|
test("accepts an optional onLeaveChannel callback", async function (assert) {
|
||||||
this.foo = 1;
|
this.foo = 1;
|
||||||
this.onLeaveChannel = () => (this.foo = 2);
|
this.onLeaveChannel = () => (this.foo = 2);
|
||||||
this.channel = fabricators.directMessageChatChannel({ users: [{ id: 1 }] });
|
this.channel = fabricators.directMessageChannel();
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<ChatChannelLeaveBtn @channel={{this.channel}} @onLeaveChannel={{this.onLeaveChannel}} />`
|
hbs`<ChatChannelLeaveBtn @channel={{this.channel}} @onLeaveChannel={{this.onLeaveChannel}} />`
|
||||||
|
@ -29,7 +29,7 @@ module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("has a specific title for direct message channel", async function (assert) {
|
test("has a specific title for direct message channel", async function (assert) {
|
||||||
this.channel = fabricators.directMessageChatChannel();
|
this.channel = fabricators.directMessageChannel();
|
||||||
|
|
||||||
await render(hbs`<ChatChannelLeaveBtn @channel={{this.channel}} />`);
|
await render(hbs`<ChatChannelLeaveBtn @channel={{this.channel}} />`);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("has a specific title for message channel", async function (assert) {
|
test("has a specific title for message channel", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
|
|
||||||
await render(hbs`<ChatChannelLeaveBtn @channel={{this.channel}} />`);
|
await render(hbs`<ChatChannelLeaveBtn @channel={{this.channel}} />`);
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) {
|
||||||
|
|
||||||
test("is not visible on mobile", async function (assert) {
|
test("is not visible on mobile", async function (assert) {
|
||||||
this.site.mobileView = true;
|
this.site.mobileView = true;
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
|
|
||||||
await render(hbs`<ChatChannelLeaveBtn @channel={{this.channel}} />`);
|
await render(hbs`<ChatChannelLeaveBtn @channel={{this.channel}} />`);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ module("Discourse Chat | Component | chat-channel-metadata", function (hooks) {
|
||||||
|
|
||||||
test("displays last message sent at", async function (assert) {
|
test("displays last message sent at", async function (assert) {
|
||||||
let lastMessageSentAt = moment().subtract(1, "day").format();
|
let lastMessageSentAt = moment().subtract(1, "day").format();
|
||||||
this.channel = fabricators.directMessageChatChannel({
|
this.channel = fabricators.directMessageChannel({
|
||||||
last_message_sent_at: lastMessageSentAt,
|
last_message_sent_at: lastMessageSentAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ module("Discourse Chat | Component | chat-channel-metadata", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("unreadIndicator", async function (assert) {
|
test("unreadIndicator", async function (assert) {
|
||||||
this.channel = fabricators.directMessageChatChannel();
|
this.channel = fabricators.directMessageChannel();
|
||||||
this.channel.tracking.unreadCount = 1;
|
this.channel.tracking.unreadCount = 1;
|
||||||
|
|
||||||
this.unreadIndicator = true;
|
this.unreadIndicator = true;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
module(
|
module(
|
||||||
"Discourse Chat | Component | chat-channel-preview-card",
|
"Discourse Chat | Component | chat-channel-preview-card",
|
||||||
|
@ -11,10 +11,7 @@ module(
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function () {
|
||||||
this.set(
|
this.set("channel", fabricators.channel({ chatable_type: "Category" }));
|
||||||
"channel",
|
|
||||||
fabricators.chatChannel({ chatable_type: "Category" })
|
|
||||||
);
|
|
||||||
|
|
||||||
this.channel.description = "Important stuff is announced here.";
|
this.channel.description = "Important stuff is announced here.";
|
||||||
this.channel.title = "announcements";
|
this.channel.title = "announcements";
|
||||||
|
|
|
@ -2,14 +2,14 @@ import { module, test } from "qunit";
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
module("Discourse Chat | Component | chat-channel-row", function (hooks) {
|
module("Discourse Chat | Component | chat-channel-row", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function () {
|
||||||
this.categoryChatChannel = fabricators.chatChannel();
|
this.categoryChatChannel = fabricators.channel();
|
||||||
this.directMessageChatChannel = fabricators.directMessageChatChannel();
|
this.directMessageChannel = fabricators.directMessageChannel();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("links to correct channel", async function (assert) {
|
test("links to correct channel", async function (assert) {
|
||||||
|
@ -47,11 +47,14 @@ module("Discourse Chat | Component | chat-channel-row", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("renders correct channel metadata", async function (assert) {
|
test("renders correct channel metadata", async function (assert) {
|
||||||
|
this.categoryChatChannel.lastMessageSentAt = moment().toISOString();
|
||||||
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
|
await render(hbs`<ChatChannelRow @channel={{this.categoryChatChannel}} />`);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(".chat-channel-metadata")
|
.dom(".chat-channel-metadata")
|
||||||
.hasText(moment(this.categoryChatChannel.lastMessageSentAt).format("l"));
|
.hasText(
|
||||||
|
moment(this.categoryChatChannel.lastMessageSentAt).format("h:mm A")
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("renders membership toggling button when necessary", async function (assert) {
|
test("renders membership toggling button when necessary", async function (assert) {
|
||||||
|
@ -145,11 +148,14 @@ module("Discourse Chat | Component | chat-channel-row", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("user status with direct message channel", async function (assert) {
|
test("user status with direct message channel", async function (assert) {
|
||||||
|
this.directMessageChannel.chatable = fabricators.directMessage({
|
||||||
|
users: [fabricators.user()],
|
||||||
|
});
|
||||||
const status = { description: "Off to dentist", emoji: "tooth" };
|
const status = { description: "Off to dentist", emoji: "tooth" };
|
||||||
this.directMessageChatChannel.chatable.users[0].status = status;
|
this.directMessageChannel.chatable.users[0].status = status;
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<ChatChannelRow @channel={{this.directMessageChatChannel}} />`
|
hbs`<ChatChannelRow @channel={{this.directMessageChannel}} />`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.dom(".user-status-message").exists();
|
assert.dom(".user-status-message").exists();
|
||||||
|
@ -157,9 +163,9 @@ module("Discourse Chat | Component | chat-channel-row", function (hooks) {
|
||||||
|
|
||||||
test("user status with direct message channel and multiple users", async function (assert) {
|
test("user status with direct message channel and multiple users", async function (assert) {
|
||||||
const status = { description: "Off to dentist", emoji: "tooth" };
|
const status = { description: "Off to dentist", emoji: "tooth" };
|
||||||
this.directMessageChatChannel.chatable.users[0].status = status;
|
this.directMessageChannel.chatable.users[0].status = status;
|
||||||
|
|
||||||
this.directMessageChatChannel.chatable.users.push({
|
this.directMessageChannel.chatable.users.push({
|
||||||
id: 2,
|
id: 2,
|
||||||
username: "bill",
|
username: "bill",
|
||||||
name: null,
|
name: null,
|
||||||
|
@ -167,7 +173,7 @@ module("Discourse Chat | Component | chat-channel-row", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<ChatChannelRow @channel={{this.directMessageChatChannel}} />`
|
hbs`<ChatChannelRow @channel={{this.directMessageChannel}} />`
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.dom(".user-status-message").doesNotExist();
|
assert.dom(".user-status-message").doesNotExist();
|
||||||
|
|
|
@ -3,7 +3,7 @@ import hbs from "htmlbars-inline-precompile";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import {
|
import {
|
||||||
CHANNEL_STATUSES,
|
CHANNEL_STATUSES,
|
||||||
channelStatusIcon,
|
channelStatusIcon,
|
||||||
|
@ -13,7 +13,7 @@ module("Discourse Chat | Component | chat-channel-status", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("renders nothing when channel is opened", async function (assert) {
|
test("renders nothing when channel is opened", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
|
|
||||||
await render(hbs`<ChatChannelStatus @channel={{this.channel}} />`);
|
await render(hbs`<ChatChannelStatus @channel={{this.channel}} />`);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ module("Discourse Chat | Component | chat-channel-status", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("defaults to long format", async function (assert) {
|
test("defaults to long format", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel({ status: CHANNEL_STATUSES.closed });
|
this.channel = fabricators.channel({ status: CHANNEL_STATUSES.closed });
|
||||||
|
|
||||||
await render(hbs`<ChatChannelStatus @channel={{this.channel}} />`);
|
await render(hbs`<ChatChannelStatus @channel={{this.channel}} />`);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ module("Discourse Chat | Component | chat-channel-status", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("accepts a format argument", async function (assert) {
|
test("accepts a format argument", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel({
|
this.channel = fabricators.channel({
|
||||||
status: CHANNEL_STATUSES.archived,
|
status: CHANNEL_STATUSES.archived,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ module("Discourse Chat | Component | chat-channel-status", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("renders the correct icon", async function (assert) {
|
test("renders the correct icon", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel({
|
this.channel = fabricators.channel({
|
||||||
status: CHANNEL_STATUSES.archived,
|
status: CHANNEL_STATUSES.archived,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ module("Discourse Chat | Component | chat-channel-status", function (hooks) {
|
||||||
|
|
||||||
test("renders archive status", async function (assert) {
|
test("renders archive status", async function (assert) {
|
||||||
this.currentUser.admin = true;
|
this.currentUser.admin = true;
|
||||||
this.channel = fabricators.chatChannel({
|
this.channel = fabricators.channel({
|
||||||
status: CHANNEL_STATUSES.archived,
|
status: CHANNEL_STATUSES.archived,
|
||||||
archive_failed: true,
|
archive_failed: true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { CHATABLE_TYPES } from "discourse/plugins/chat/discourse/models/chat-channel";
|
import { CHATABLE_TYPES } from "discourse/plugins/chat/discourse/models/chat-channel";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
|
@ -10,7 +10,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("category channel", async function (assert) {
|
test("category channel", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel({
|
this.channel = fabricators.channel({
|
||||||
chatable_type: CHATABLE_TYPES.categoryChannel,
|
chatable_type: CHATABLE_TYPES.categoryChannel,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("category channel - escapes title", async function (assert) {
|
test("category channel - escapes title", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel({
|
this.channel = fabricators.channel({
|
||||||
chatable_type: CHATABLE_TYPES.categoryChannel,
|
chatable_type: CHATABLE_TYPES.categoryChannel,
|
||||||
title: "<div class='xss'>evil</div>",
|
title: "<div class='xss'>evil</div>",
|
||||||
});
|
});
|
||||||
|
@ -38,7 +38,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("category channel - read restricted", async function (assert) {
|
test("category channel - read restricted", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel({
|
this.channel = fabricators.channel({
|
||||||
chatable_type: CHATABLE_TYPES.categoryChannel,
|
chatable_type: CHATABLE_TYPES.categoryChannel,
|
||||||
chatable: { read_restricted: true },
|
chatable: { read_restricted: true },
|
||||||
});
|
});
|
||||||
|
@ -49,7 +49,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("category channel - not read restricted", async function (assert) {
|
test("category channel - not read restricted", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel({
|
this.channel = fabricators.channel({
|
||||||
chatable_type: CHATABLE_TYPES.categoryChannel,
|
chatable_type: CHATABLE_TYPES.categoryChannel,
|
||||||
chatable: { read_restricted: false },
|
chatable: { read_restricted: false },
|
||||||
});
|
});
|
||||||
|
@ -60,7 +60,11 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("direct message channel - one user", async function (assert) {
|
test("direct message channel - one user", async function (assert) {
|
||||||
this.channel = fabricators.directMessageChatChannel();
|
this.channel = fabricators.directMessageChannel({
|
||||||
|
chatable: fabricators.directMessage({
|
||||||
|
users: [fabricators.user()],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
await render(hbs`<ChatChannelTitle @channel={{this.channel}} />`);
|
await render(hbs`<ChatChannelTitle @channel={{this.channel}} />`);
|
||||||
|
|
||||||
|
@ -77,7 +81,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("direct message channel - multiple users", async function (assert) {
|
test("direct message channel - multiple users", async function (assert) {
|
||||||
const channel = fabricators.directMessageChatChannel();
|
const channel = fabricators.directMessageChannel();
|
||||||
|
|
||||||
channel.chatable.users.push({
|
channel.chatable.users.push({
|
||||||
id: 2,
|
id: 2,
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
|
import hbs from "htmlbars-inline-precompile";
|
||||||
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
import { module, test } from "qunit";
|
||||||
|
import { render } from "@ember/test-helpers";
|
||||||
|
|
||||||
|
module(
|
||||||
|
"Discourse Chat | Component | chat-composer-message-details",
|
||||||
|
function (hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
|
test("data-id attribute", async function (assert) {
|
||||||
|
this.message = fabricators.message();
|
||||||
|
|
||||||
|
await render(
|
||||||
|
hbs`<ChatComposerMessageDetails @message={{this.message}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom(".chat-composer-message-details")
|
||||||
|
.hasAttribute("data-id", this.message.id.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("editing a message has the pencil icon", async function (assert) {
|
||||||
|
this.message = fabricators.message({ editing: true });
|
||||||
|
|
||||||
|
await render(
|
||||||
|
hbs`<ChatComposerMessageDetails @message={{this.message}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.dom(".chat-composer-message-details .d-icon-pencil-alt").exists();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("replying to a message has the reply icon", async function (assert) {
|
||||||
|
const firstMessage = fabricators.message();
|
||||||
|
this.message = fabricators.message({ inReplyTo: firstMessage });
|
||||||
|
|
||||||
|
await render(
|
||||||
|
hbs`<ChatComposerMessageDetails @message={{this.message}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.dom(".chat-composer-message-details .d-icon-reply").exists();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("displays user avatar", async function (assert) {
|
||||||
|
this.message = fabricators.message();
|
||||||
|
|
||||||
|
await render(
|
||||||
|
hbs`<ChatComposerMessageDetails @message={{this.message}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom(".chat-composer-message-details .chat-user-avatar .avatar")
|
||||||
|
.hasAttribute("title", this.message.user.username);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("displays message excerpt", async function (assert) {
|
||||||
|
this.message = fabricators.message();
|
||||||
|
|
||||||
|
await render(
|
||||||
|
hbs`<ChatComposerMessageDetails @message={{this.message}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.dom(".chat-reply__excerpt").hasText(this.message.excerpt);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("displays user’s username", async function (assert) {
|
||||||
|
this.message = fabricators.message();
|
||||||
|
|
||||||
|
await render(
|
||||||
|
hbs`<ChatComposerMessageDetails @message={{this.message}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.dom(".chat-reply__username").hasText(this.message.user.username);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
|
@ -4,13 +4,13 @@ import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
module("Discourse Chat | Component | chat-message-avatar", function (hooks) {
|
module("Discourse Chat | Component | chat-message-avatar", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("chat_webhook_event", async function (assert) {
|
test("chat_webhook_event", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
chat_webhook_event: { emoji: ":heart:" },
|
chat_webhook_event: { emoji: ":heart:" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ module("Discourse Chat | Component | chat-message-avatar", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("user", async function (assert) {
|
test("user", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,13 @@ import I18n from "I18n";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("chat_webhook_event", async function (assert) {
|
test("chat_webhook_event", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
chat_webhook_event: { username: "discobot" },
|
chat_webhook_event: { username: "discobot" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("user", async function (assert) {
|
test("user", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("date", async function (assert) {
|
test("date", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
created_at: moment(),
|
created_at: moment(),
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("bookmark (with reminder)", async function (assert) {
|
test("bookmark (with reminder)", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
bookmark: Bookmark.create({
|
bookmark: Bookmark.create({
|
||||||
reminder_at: moment(),
|
reminder_at: moment(),
|
||||||
|
@ -69,7 +69,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("bookmark (no reminder)", async function (assert) {
|
test("bookmark (no reminder)", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
bookmark: Bookmark.create({
|
bookmark: Bookmark.create({
|
||||||
name: "some name",
|
name: "some name",
|
||||||
|
@ -83,7 +83,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
|
|
||||||
test("user status", async function (assert) {
|
test("user status", async function (assert) {
|
||||||
const status = { description: "off to dentist", emoji: "tooth" };
|
const status = { description: "off to dentist", emoji: "tooth" };
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { status },
|
user: { status },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("reviewable", async function (assert) {
|
test("reviewable", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
user_flag_status: 0,
|
user_flag_status: 0,
|
||||||
});
|
});
|
||||||
|
@ -105,7 +105,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
I18n.t("chat.you_flagged")
|
I18n.t("chat.you_flagged")
|
||||||
);
|
);
|
||||||
|
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
reviewable_id: 1,
|
reviewable_id: 1,
|
||||||
});
|
});
|
||||||
|
@ -119,7 +119,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("with username classes", async function (assert) {
|
test("with username classes", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: {
|
user: {
|
||||||
username: "discobot",
|
username: "discobot",
|
||||||
admin: true,
|
admin: true,
|
||||||
|
@ -139,7 +139,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("without username classes", async function (assert) {
|
test("without username classes", async function (assert) {
|
||||||
this.message = ChatMessage.create(fabricators.chatChannel(), {
|
this.message = ChatMessage.create(fabricators.channel(), {
|
||||||
user: { username: "discobot" },
|
user: { username: "discobot" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
|
@ -13,7 +13,7 @@ module(
|
||||||
test("channel title is escaped in instructions correctly", async function (assert) {
|
test("channel title is escaped in instructions correctly", async function (assert) {
|
||||||
this.set(
|
this.set(
|
||||||
"channel",
|
"channel",
|
||||||
fabricators.chatChannel({ title: "<script>someeviltitle</script>" })
|
fabricators.channel({ title: "<script>someeviltitle</script>" })
|
||||||
);
|
);
|
||||||
this.set("chat", { publicChannels: [this.channel] });
|
this.set("chat", { publicChannels: [this.channel] });
|
||||||
this.set("selectedMessageIds", [1]);
|
this.set("selectedMessageIds", [1]);
|
||||||
|
|
|
@ -55,7 +55,6 @@ module("Discourse Chat | Component | chat-message", function (hooks) {
|
||||||
const template = hbs`
|
const template = hbs`
|
||||||
<ChatMessage
|
<ChatMessage
|
||||||
@message={{this.message}}
|
@message={{this.message}}
|
||||||
@channel={{this.channel}}
|
|
||||||
@messageDidEnterViewport={{this.messageDidEnterViewport}}
|
@messageDidEnterViewport={{this.messageDidEnterViewport}}
|
||||||
@messageDidLeaveViewport={{this.messageDidLeaveViewport}}
|
@messageDidLeaveViewport={{this.messageDidLeaveViewport}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import {
|
import {
|
||||||
|
@ -87,7 +87,7 @@ module(
|
||||||
});
|
});
|
||||||
|
|
||||||
test("displays indicator when 2 or 3 users are replying", async function (assert) {
|
test("displays indicator when 2 or 3 users are replying", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
||||||
|
@ -102,7 +102,7 @@ module(
|
||||||
});
|
});
|
||||||
|
|
||||||
test("displays indicator when 3 users are replying", async function (assert) {
|
test("displays indicator when 3 users are replying", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
||||||
|
@ -118,7 +118,7 @@ module(
|
||||||
});
|
});
|
||||||
|
|
||||||
test("displays indicator when more than 3 users are replying", async function (assert) {
|
test("displays indicator when more than 3 users are replying", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
||||||
|
@ -135,7 +135,7 @@ module(
|
||||||
});
|
});
|
||||||
|
|
||||||
test("filters current user from list of repliers", async function (assert) {
|
test("filters current user from list of repliers", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
hbs`<ChatReplyingIndicator @presenceChannelName="/chat-reply/1" />`
|
||||||
|
|
|
@ -3,7 +3,7 @@ import hbs from "htmlbars-inline-precompile";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
module(
|
module(
|
||||||
"Discourse Chat | Component | chat-retention-reminder-text",
|
"Discourse Chat | Component | chat-retention-reminder-text",
|
||||||
|
@ -11,7 +11,7 @@ module(
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("when setting is set on 0", async function (assert) {
|
test("when setting is set on 0", async function (assert) {
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
this.siteSettings.chat_channel_retention_days = 0;
|
this.siteSettings.chat_channel_retention_days = 0;
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
|
@ -25,7 +25,7 @@ module(
|
||||||
|
|
||||||
test("when channel is a public channel", async function (assert) {
|
test("when channel is a public channel", async function (assert) {
|
||||||
const count = 10;
|
const count = 10;
|
||||||
this.channel = fabricators.chatChannel();
|
this.channel = fabricators.channel();
|
||||||
this.siteSettings.chat_channel_retention_days = count;
|
this.siteSettings.chat_channel_retention_days = count;
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
|
@ -39,7 +39,7 @@ module(
|
||||||
|
|
||||||
test("when channel is a DM channel", async function (assert) {
|
test("when channel is a DM channel", async function (assert) {
|
||||||
const count = 10;
|
const count = 10;
|
||||||
this.channel = fabricators.directMessageChatChannel();
|
this.channel = fabricators.directMessageChannel();
|
||||||
this.siteSettings.chat_dm_retention_days = count;
|
this.siteSettings.chat_dm_retention_days = count;
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import hbs from "htmlbars-inline-precompile";
|
||||||
import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel";
|
import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
import fabricators from "../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
|
|
||||||
function mockChat(context, options = {}) {
|
function mockChat(context, options = {}) {
|
||||||
|
@ -15,7 +15,7 @@ function mockChat(context, options = {}) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
mock.getDmChannelForUsernames = () => {
|
mock.getDmChannelForUsernames = () => {
|
||||||
return Promise.resolve({ chat_channel: fabricators.chatChannel() });
|
return Promise.resolve({ chat_channel: fabricators.channel() });
|
||||||
};
|
};
|
||||||
return mock;
|
return mock;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) {
|
||||||
await fillIn(".filter-usernames", "hawk");
|
await fillIn(".filter-usernames", "hawk");
|
||||||
assert.strictEqual(query(".filter-usernames").value, "hawk");
|
assert.strictEqual(query(".filter-usernames").value, "hawk");
|
||||||
|
|
||||||
this.set("channel", fabricators.chatChannel());
|
this.set("channel", fabricators.channel());
|
||||||
this.set("channel", ChatChannel.createDirectMessageChannelDraft());
|
this.set("channel", ChatChannel.createDirectMessageChannelDraft());
|
||||||
|
|
||||||
assert.strictEqual(query(".filter-usernames").value, "");
|
assert.strictEqual(query(".filter-usernames").value, "");
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { cloneJSON } from "discourse-common/lib/object";
|
|
||||||
|
|
||||||
// heavily inspired by https://github.com/travelperk/fabricator
|
|
||||||
export function Fabricator(Model, attributes = {}) {
|
|
||||||
return (opts) => fabricate(Model, attributes, opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fabricate(Model, attributes, opts = {}) {
|
|
||||||
if (typeof attributes === "function") {
|
|
||||||
return attributes();
|
|
||||||
}
|
|
||||||
|
|
||||||
const extendedModel = cloneJSON({ ...attributes, ...opts });
|
|
||||||
const props = {};
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(extendedModel)) {
|
|
||||||
props[key] = typeof value === "function" ? value() : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Model.create(props);
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
import ChatChannel, {
|
|
||||||
CHATABLE_TYPES,
|
|
||||||
} from "discourse/plugins/chat/discourse/models/chat-channel";
|
|
||||||
import EmberObject from "@ember/object";
|
|
||||||
import { Fabricator } from "./fabricator";
|
|
||||||
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
|
||||||
|
|
||||||
const userFabricator = Fabricator(EmberObject, {
|
|
||||||
id: 1,
|
|
||||||
username: "hawk",
|
|
||||||
name: null,
|
|
||||||
avatar_template: "/letter_avatar_proxy/v3/letter/t/41988e/{size}.png",
|
|
||||||
});
|
|
||||||
|
|
||||||
const categoryChatableFabricator = Fabricator(EmberObject, {
|
|
||||||
id: 1,
|
|
||||||
color: "D56353",
|
|
||||||
read_restricted: false,
|
|
||||||
name: "My category",
|
|
||||||
});
|
|
||||||
|
|
||||||
const directChannelChatableFabricator = Fabricator(EmberObject, {
|
|
||||||
users: [userFabricator({ id: 1, username: "bob" })],
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
|
||||||
chatChannel: Fabricator(ChatChannel, {
|
|
||||||
id: 1,
|
|
||||||
chatable_type: CHATABLE_TYPES.categoryChannel,
|
|
||||||
status: "open",
|
|
||||||
title: "My category title",
|
|
||||||
name: "My category name",
|
|
||||||
chatable: categoryChatableFabricator(),
|
|
||||||
last_message_sent_at: "2021-11-08T21:26:05.710Z",
|
|
||||||
allow_channel_wide_mentions: true,
|
|
||||||
message_bus_last_ids: {
|
|
||||||
new_mentions: 0,
|
|
||||||
new_messages: 0,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
chatChannelMessage: Fabricator(ChatMessage, {
|
|
||||||
id: 1,
|
|
||||||
chat_channel_id: 1,
|
|
||||||
user_id: 1,
|
|
||||||
cooked: "This is a test message",
|
|
||||||
}),
|
|
||||||
|
|
||||||
directMessageChatChannel: Fabricator(ChatChannel, {
|
|
||||||
id: 1,
|
|
||||||
chatable_type: CHATABLE_TYPES.directMessageChannel,
|
|
||||||
status: "open",
|
|
||||||
chatable: directChannelChatableFabricator(),
|
|
||||||
last_message_sent_at: "2021-11-08T21:26:05.710Z",
|
|
||||||
message_bus_last_ids: {
|
|
||||||
new_mentions: 0,
|
|
||||||
new_messages: 0,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
|
|
@ -3,21 +3,20 @@ import hbs from "htmlbars-inline-precompile";
|
||||||
import { render } from "@ember/test-helpers";
|
import { render } from "@ember/test-helpers";
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import fabricators from "../../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
|
||||||
|
|
||||||
module("Discourse Chat | Unit | Helpers | format-chat-date", function (hooks) {
|
module("Discourse Chat | Unit | Helpers | format-chat-date", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("link to chat message", async function (assert) {
|
test("link to chat message", async function (assert) {
|
||||||
const channel = fabricators.chatChannel();
|
const channel = fabricators.channel();
|
||||||
this.message = ChatMessage.create(channel, {
|
this.message = fabricators.message({ channel });
|
||||||
id: 1,
|
|
||||||
chat_channel_id: channel.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
await render(hbs`{{format-chat-date this.message}}`);
|
await render(hbs`{{format-chat-date this.message}}`);
|
||||||
|
|
||||||
assert.equal(query(".chat-time").getAttribute("href"), "/chat/c/-/1/1");
|
assert.equal(
|
||||||
|
query(".chat-time").getAttribute("href"),
|
||||||
|
`/chat/c/-/${channel.id}/${this.message.id}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { set } from "@ember/object";
|
import { set } from "@ember/object";
|
||||||
import fabricators from "../../helpers/fabricators";
|
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||||
|
|
||||||
acceptance("Discourse Chat | Unit | Service | chat-guardian", function (needs) {
|
acceptance("Discourse Chat | Unit | Service | chat-guardian", function (needs) {
|
||||||
needs.hooks.beforeEach(function () {
|
needs.hooks.beforeEach(function () {
|
||||||
|
@ -69,7 +69,7 @@ acceptance("Discourse Chat | Unit | Service | chat-guardian", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#canArchiveChannel", async function (assert) {
|
test("#canArchiveChannel", async function (assert) {
|
||||||
const channel = fabricators.chatChannel();
|
const channel = fabricators.channel();
|
||||||
|
|
||||||
set(this.currentUser, "has_chat_enabled", true);
|
set(this.currentUser, "has_chat_enabled", true);
|
||||||
set(this.currentUser, "admin", true);
|
set(this.currentUser, "admin", true);
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div class="component">
|
||||||
|
{{yield}}
|
||||||
|
</div>
|
|
@ -0,0 +1,3 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
|
||||||
|
export default class StyleguideComponent extends Component {}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<table class="component-properties">
|
||||||
|
<tbody>
|
||||||
|
{{yield}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
3
plugins/styleguide/assets/javascripts/discourse/components/styleguide/controls.js
vendored
Normal file
3
plugins/styleguide/assets/javascripts/discourse/components/styleguide/controls.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
|
||||||
|
export default class StyleguideControls extends Component {}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<tr class="component-properties__row">
|
||||||
|
<td class="component-properties__cell">{{@name}}</td>
|
||||||
|
<td class="component-properties__cell">
|
||||||
|
{{yield}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
|
@ -0,0 +1 @@
|
||||||
|
<DToggleSwitch @state={{@enabled}} {{on "click" @action}} />
|
|
@ -0,0 +1,3 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
|
||||||
|
export default class StyleguideControlsToggle extends Component {}
|
|
@ -0,0 +1 @@
|
||||||
|
<DButton @action={{this.toggle}} class="toggle-color-mode">Toggle color</DButton>
|
|
@ -0,0 +1,45 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
|
||||||
|
const DARK = "dark";
|
||||||
|
const LIGHT = "light";
|
||||||
|
|
||||||
|
function colorSchemeOverride(type) {
|
||||||
|
const lightScheme = document.querySelector("link.light-scheme");
|
||||||
|
const darkScheme = document.querySelector("link.dark-scheme");
|
||||||
|
|
||||||
|
if (!lightScheme || !darkScheme) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DARK:
|
||||||
|
lightScheme.media = "none";
|
||||||
|
darkScheme.media = "all";
|
||||||
|
break;
|
||||||
|
case LIGHT:
|
||||||
|
lightScheme.media = "all";
|
||||||
|
darkScheme.media = "none";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ToggleColorMode extends Component {
|
||||||
|
@service keyValueStore;
|
||||||
|
|
||||||
|
@tracked colorSchemeOverride = this.default;
|
||||||
|
|
||||||
|
get default() {
|
||||||
|
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
|
? DARK
|
||||||
|
: LIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggle() {
|
||||||
|
this.colorSchemeOverride = this.colorSchemeOverride === DARK ? LIGHT : DARK;
|
||||||
|
colorSchemeOverride(this.colorSchemeOverride);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
<section class="styleguide">
|
<section class="styleguide">
|
||||||
<section class="styleguide-menu">
|
<section class="styleguide-menu">
|
||||||
|
<ToggleColorMode />
|
||||||
{{#each this.categories as |c|}}
|
{{#each this.categories as |c|}}
|
||||||
<ul>
|
<ul>
|
||||||
<li class="styleguide-heading">{{i18n
|
<li class="styleguide-heading">{{i18n
|
||||||
|
|
|
@ -73,6 +73,36 @@
|
||||||
|
|
||||||
.rendered {
|
.rendered {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.component {
|
||||||
|
padding: 2rem;
|
||||||
|
border: 2px dotted var(--primary-low);
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-properties {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__cell {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea,
|
||||||
|
input {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
|
|
|
@ -101,7 +101,10 @@ module SystemHelpers
|
||||||
|
|
||||||
ENV["TZ"] = timezone
|
ENV["TZ"] = timezone
|
||||||
|
|
||||||
using_session(timezone) { freeze_time(&example) }
|
using_session(timezone) do |session|
|
||||||
|
freeze_time(&example)
|
||||||
|
session.quit
|
||||||
|
end
|
||||||
|
|
||||||
ENV["TZ"] = previous_browser_timezone
|
ENV["TZ"] = previous_browser_timezone
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue