mirror of
https://github.com/discourse/discourse.git
synced 2024-11-26 11:23:36 +08:00
DEV: convert PrivateMessageMap widget to glimmer components (#25837)
* DEV: add map system test for private message map * DEV: convert PrivateMessageMap to glimmer components
This commit is contained in:
parent
13230ae4c2
commit
1a76c4e099
|
@ -0,0 +1,215 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { hash } from "@ember/helper";
|
||||
import { action } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import avatar from "discourse/helpers/bound-avatar-template";
|
||||
import { groupPath } from "discourse/lib/url";
|
||||
import dIcon from "discourse-common/helpers/d-icon";
|
||||
import I18n from "discourse-i18n";
|
||||
import and from "truth-helpers/helpers/and";
|
||||
|
||||
export default class PrivateMessageMap extends Component {
|
||||
@service site;
|
||||
@tracked isEditing = false;
|
||||
|
||||
get participantsClasses() {
|
||||
return !this.isEditing &&
|
||||
this.site.mobileView &&
|
||||
this.args.postAttrs.allowedGroups.length > 4
|
||||
? "participants hide-names"
|
||||
: "participants";
|
||||
}
|
||||
|
||||
get canInvite() {
|
||||
return this.args.postAttrs.canInvite;
|
||||
}
|
||||
|
||||
get canRemove() {
|
||||
return (
|
||||
this.args.postAttrs.canRemoveAllowedUsers ||
|
||||
this.args.postAttrs.canRemoveSelfId
|
||||
);
|
||||
}
|
||||
|
||||
get canShowControls() {
|
||||
return this.canInvite || this.canRemove;
|
||||
}
|
||||
|
||||
get actionAllowed() {
|
||||
return this.canRemove ? this.toggleEditing : this.args.showInvite;
|
||||
}
|
||||
|
||||
get actionAllowedLabel() {
|
||||
if (this.canInvite && this.canRemove) {
|
||||
return "private_message_info.edit";
|
||||
}
|
||||
if (!this.canInvite && this.canRemove) {
|
||||
return "private_message_info.remove";
|
||||
}
|
||||
return "private_message_info.add";
|
||||
}
|
||||
|
||||
@action
|
||||
toggleEditing() {
|
||||
this.isEditing = !this.isEditing;
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class={{this.participantsClasses}}>
|
||||
{{#each @postAttrs.allowedGroups as |group|}}
|
||||
<PmMapUserGroup
|
||||
@model={{group}}
|
||||
@isEditing={{this.isEditing}}
|
||||
@canRemoveAllowedUsers={{@postAttrs.canRemoveAllowedUsers}}
|
||||
@removeAllowedGroup={{@removeAllowedGroup}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{#each @postAttrs.allowedUsers as |user|}}
|
||||
<PmMapUser
|
||||
@model={{user}}
|
||||
@isEditing={{this.isEditing}}
|
||||
@canRemoveAllowedUsers={{@postAttrs.canRemoveAllowedUsers}}
|
||||
@canRemoveSelfId={{@postAttrs.canRemoveSelfId}}
|
||||
@removeAllowedUser={{@removeAllowedUser}}
|
||||
/>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
{{#if this.canShowControls}}
|
||||
<div class="controls">
|
||||
<DButton
|
||||
@action={{this.actionAllowed}}
|
||||
@label={{this.actionAllowedLabel}}
|
||||
class="btn-default add-remove-participant-btn"
|
||||
/>
|
||||
|
||||
{{#if (and this.canInvite this.isEditing)}}
|
||||
<DButton
|
||||
@action={{@showInvite}}
|
||||
@icon="plus"
|
||||
class="btn-default add-participant-btn"
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
||||
|
||||
class PmMapUserGroup extends Component {
|
||||
get canRemoveLink() {
|
||||
return this.args.isEditing && this.args.canRemoveAllowedUsers;
|
||||
}
|
||||
|
||||
get groupUrl() {
|
||||
return groupPath(this.args.model.name);
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="user group">
|
||||
<a href={{this.groupUrl}} class="group-link">
|
||||
{{dIcon "users"}}
|
||||
<span class="group-name">{{@model.name}}</span>
|
||||
</a>
|
||||
{{#if this.canRemoveLink}}
|
||||
<PmRemoveGroupLink
|
||||
@model={{@model}}
|
||||
@removeAllowedGroup={{@removeAllowedGroup}}
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
|
||||
class PmRemoveGroupLink extends Component {
|
||||
@service dialog;
|
||||
|
||||
@action
|
||||
showConfirmDialog() {
|
||||
this.dialog.deleteConfirm({
|
||||
message: I18n.t("private_message_info.remove_allowed_group", {
|
||||
name: this.args.model.name,
|
||||
}),
|
||||
confirmButtonLabel: "private_message_info.remove_group",
|
||||
didConfirm: () => this.args.removeAllowedGroup(this.args.model),
|
||||
});
|
||||
}
|
||||
|
||||
<template>
|
||||
<DButton
|
||||
class="remove-invited"
|
||||
@action={{this.showConfirmDialog}}
|
||||
@icon="times"
|
||||
/>
|
||||
</template>
|
||||
}
|
||||
|
||||
class PmMapUser extends Component {
|
||||
get avatarTitle() {
|
||||
return this.args.model.name || this.args.model.username;
|
||||
}
|
||||
|
||||
get isCurrentUser() {
|
||||
return this.args.canRemoveSelfId === this.args.model.id;
|
||||
}
|
||||
|
||||
get canRemoveLink() {
|
||||
return (
|
||||
this.args.isEditing &&
|
||||
(this.args.canRemoveAllowedUsers || this.isCurrentUser)
|
||||
);
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="user">
|
||||
<a class="user-link" href={{@model.path}}>
|
||||
<a
|
||||
class="trigger-user-card"
|
||||
data-user-card={{@model.username}}
|
||||
title={{@model.username}}
|
||||
aria-hidden="true"
|
||||
>
|
||||
{{avatar @model.avatar_template "tiny" (hash title=this.avatarTitle)}}
|
||||
</a>
|
||||
<span class="username">{{@model.username}}</span>
|
||||
</a>
|
||||
|
||||
{{#if this.canRemoveLink}}
|
||||
<PmRemoveLink
|
||||
@model={{@model}}
|
||||
@isCurrentUser={{this.isCurrentUser}}
|
||||
@removeAllowedUser={{@removeAllowedUser}}
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
|
||||
class PmRemoveLink extends Component {
|
||||
@service dialog;
|
||||
|
||||
@action
|
||||
showConfirmDialog() {
|
||||
const messageKey = this.args.isCurrentUser
|
||||
? "private_message_info.leave_message"
|
||||
: "private_message_info.remove_allowed_user";
|
||||
|
||||
this.dialog.deleteConfirm({
|
||||
message: I18n.t(messageKey, {
|
||||
name: this.args.model.username,
|
||||
}),
|
||||
confirmButtonLabel: this.args.isCurrentUser
|
||||
? "private_message_info.leave"
|
||||
: "private_message_info.remove_user",
|
||||
didConfirm: () => this.args.removeAllowedUser(this.args.model),
|
||||
});
|
||||
}
|
||||
<template>
|
||||
<DButton
|
||||
class="remove-invited"
|
||||
@action={{this.showConfirmDialog}}
|
||||
@icon="times"
|
||||
/>
|
||||
</template>
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
import { h } from "virtual-dom";
|
||||
import hbs from "discourse/widgets/hbs-compiler";
|
||||
import { avatarFor, avatarImg } from "discourse/widgets/post";
|
||||
import { createWidget } from "discourse/widgets/widget";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import { makeArray } from "discourse-common/lib/helpers";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
createWidget("pm-remove-group-link", {
|
||||
tagName: "a.remove-invited.no-text.btn-icon.btn",
|
||||
template: hbs`{{d-icon "times"}}`,
|
||||
services: ["dialog"],
|
||||
|
||||
click() {
|
||||
this.dialog.deleteConfirm({
|
||||
message: I18n.t("private_message_info.remove_allowed_group", {
|
||||
name: this.attrs.name,
|
||||
}),
|
||||
confirmButtonLabel: "private_message_info.remove_group",
|
||||
didConfirm: () => this.sendWidgetAction("removeAllowedGroup", this.attrs),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
createWidget("pm-map-user-group", {
|
||||
tagName: "div.user.group",
|
||||
|
||||
transform(attrs) {
|
||||
return { href: getURL(`/g/${attrs.group.name}`) };
|
||||
},
|
||||
|
||||
template: hbs`
|
||||
<a href={{transformed.href}} class="group-link">
|
||||
{{d-icon "users"}}
|
||||
<span class="group-name">{{attrs.group.name}}</span>
|
||||
</a>
|
||||
{{#if attrs.isEditing}}
|
||||
{{#if attrs.canRemoveAllowedUsers}}
|
||||
{{pm-remove-group-link attrs=attrs.group}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
`,
|
||||
});
|
||||
|
||||
createWidget("pm-remove-link", {
|
||||
tagName: "a.remove-invited.no-text.btn-icon.btn",
|
||||
template: hbs`{{d-icon "times"}}`,
|
||||
services: ["dialog"],
|
||||
|
||||
click() {
|
||||
const messageKey = this.attrs.isCurrentUser
|
||||
? "leave_message"
|
||||
: "remove_allowed_user";
|
||||
|
||||
this.dialog.deleteConfirm({
|
||||
message: I18n.t(`private_message_info.${messageKey}`, {
|
||||
name: this.attrs.user.username,
|
||||
}),
|
||||
confirmButtonLabel: this.attrs.isCurrentUser
|
||||
? "private_message_info.leave"
|
||||
: "private_message_info.remove_user",
|
||||
didConfirm: () =>
|
||||
this.sendWidgetAction("removeAllowedUser", this.attrs.user),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
createWidget("pm-map-user", {
|
||||
tagName: "div.user",
|
||||
|
||||
html(attrs) {
|
||||
const user = attrs.user;
|
||||
const username = h("span.username", user.username);
|
||||
|
||||
let link;
|
||||
|
||||
if (this.site && this.site.mobileView) {
|
||||
const avatar = avatarImg("tiny", {
|
||||
template: user.avatar_template,
|
||||
username: user.username,
|
||||
});
|
||||
link = h("a", { attributes: { href: user.get("path") } }, [
|
||||
avatar,
|
||||
username,
|
||||
]);
|
||||
} else {
|
||||
const avatar = avatarFor("tiny", {
|
||||
template: user.avatar_template,
|
||||
username: user.username,
|
||||
});
|
||||
|
||||
link = h(
|
||||
"a",
|
||||
{ attributes: { class: "user-link", href: user.get("path") } },
|
||||
[avatar, username]
|
||||
);
|
||||
}
|
||||
|
||||
const result = [link];
|
||||
const isCurrentUser = attrs.canRemoveSelfId === user.get("id");
|
||||
|
||||
if (attrs.isEditing && (attrs.canRemoveAllowedUsers || isCurrentUser)) {
|
||||
result.push(this.attach("pm-remove-link", { user, isCurrentUser }));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
|
||||
export default createWidget("private-message-map", {
|
||||
tagName: "section.information.private-message-map",
|
||||
|
||||
buildKey: (attrs) => `private-message-map-${attrs.id}`,
|
||||
|
||||
defaultState() {
|
||||
return { isEditing: false };
|
||||
},
|
||||
|
||||
html(attrs) {
|
||||
const participants = [];
|
||||
|
||||
if (attrs.allowedGroups.length) {
|
||||
participants.push(
|
||||
attrs.allowedGroups.map((group) => {
|
||||
return this.attach("pm-map-user-group", {
|
||||
group,
|
||||
canRemoveAllowedUsers: attrs.canRemoveAllowedUsers,
|
||||
isEditing: this.state.isEditing,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (attrs.allowedUsers.length) {
|
||||
participants.push(
|
||||
attrs.allowedUsers.map((au) => {
|
||||
return this.attach("pm-map-user", {
|
||||
user: au,
|
||||
canRemoveAllowedUsers: attrs.canRemoveAllowedUsers,
|
||||
canRemoveSelfId: attrs.canRemoveSelfId,
|
||||
isEditing: this.state.isEditing,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
let hideNamesClass = "";
|
||||
if (
|
||||
!this.state.isEditing &&
|
||||
this.site.mobileView &&
|
||||
makeArray(participants[0]).length > 4
|
||||
) {
|
||||
hideNamesClass = ".hide-names";
|
||||
}
|
||||
|
||||
const result = [h(`div.participants${hideNamesClass}`, participants)];
|
||||
const controls = [];
|
||||
|
||||
const canRemove = attrs.canRemoveAllowedUsers || attrs.canRemoveSelfId;
|
||||
|
||||
if (attrs.canInvite || canRemove) {
|
||||
let key;
|
||||
let action = "toggleEditing";
|
||||
|
||||
if (attrs.canInvite && canRemove) {
|
||||
key = "edit";
|
||||
} else if (!attrs.canInvite && canRemove) {
|
||||
key = "remove";
|
||||
} else {
|
||||
key = "add";
|
||||
action = "showInvite";
|
||||
}
|
||||
|
||||
controls.push(
|
||||
this.attach("button", {
|
||||
action,
|
||||
label: `private_message_info.${key}`,
|
||||
className: "btn btn-default add-remove-participant-btn",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (attrs.canInvite && this.state.isEditing) {
|
||||
controls.push(
|
||||
this.attach("button", {
|
||||
action: "showInvite",
|
||||
icon: "plus",
|
||||
className: "btn btn-default no-text btn-icon add-participant-btn",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (controls.length) {
|
||||
result.push(h("div.controls", controls));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
toggleEditing() {
|
||||
this.state.isEditing = !this.state.isEditing;
|
||||
},
|
||||
});
|
|
@ -171,7 +171,7 @@ export default createWidget("topic-map", {
|
|||
}
|
||||
|
||||
if (attrs.showPMMap) {
|
||||
contents.push(this.attach("private-message-map", attrs));
|
||||
contents.push(this.buildPrivateMessageMap(attrs));
|
||||
}
|
||||
return contents;
|
||||
},
|
||||
|
@ -219,4 +219,25 @@ export default createWidget("topic-map", {
|
|||
}
|
||||
);
|
||||
},
|
||||
|
||||
buildPrivateMessageMap(attrs) {
|
||||
return new RenderGlimmer(
|
||||
this,
|
||||
"section.information.private-message-map",
|
||||
hbs`<TopicMap::PrivateMessageMap
|
||||
@postAttrs={{@data.postAttrs}}
|
||||
@showInvite={{@data.showInvite}}
|
||||
@removeAllowedGroup={{@data.removeAllowedGroup}}
|
||||
@removeAllowedUser={{@data.removeAllowedUser}}
|
||||
/>`,
|
||||
{
|
||||
postAttrs: attrs,
|
||||
showInvite: () => this.sendWidgetAction("showInvite"),
|
||||
removeAllowedGroup: (group) =>
|
||||
this.sendWidgetAction("removeAllowedGroup", group),
|
||||
removeAllowedUser: (user) =>
|
||||
this.sendWidgetAction("removeAllowedUser", user),
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
57
spec/system/page_objects/components/private_message_map.rb
Normal file
57
spec/system/page_objects/components/private_message_map.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PageObjects
|
||||
module Components
|
||||
class PrivateMessageMap < PageObjects::Components::Base
|
||||
PRIVATE_MESSAGE_MAP_KLASS = ".private-message-map"
|
||||
def is_visible?
|
||||
has_css?(PRIVATE_MESSAGE_MAP_KLASS)
|
||||
end
|
||||
|
||||
def participants_details
|
||||
find("#{PRIVATE_MESSAGE_MAP_KLASS} .participants").all(".user")
|
||||
end
|
||||
|
||||
def participants_count
|
||||
participants_details.length
|
||||
end
|
||||
|
||||
def controls
|
||||
find("#{PRIVATE_MESSAGE_MAP_KLASS} .controls")
|
||||
end
|
||||
|
||||
def toggle_edit_participants_button
|
||||
controls.click_button(class: "add-remove-participant-btn")
|
||||
end
|
||||
|
||||
def has_add_participants_button?
|
||||
controls.has_button?(class: "add-participant-btn")
|
||||
end
|
||||
|
||||
def has_no_add_participants_button?
|
||||
controls.has_no_button?(class: "add-participant-btn")
|
||||
end
|
||||
def click_add_participants_button
|
||||
controls.click_button(class: "add-participant-btn")
|
||||
end
|
||||
|
||||
def click_remove_participant_button(user)
|
||||
find_link(user.username).sibling(".remove-invited").click
|
||||
end
|
||||
|
||||
def has_participant_details_for?(user)
|
||||
find("#{PRIVATE_MESSAGE_MAP_KLASS} .participants").has_link?(
|
||||
class: "user-link",
|
||||
href: "/u/#{user.username}",
|
||||
)
|
||||
end
|
||||
|
||||
def has_no_participant_details_for?(user)
|
||||
find("#{PRIVATE_MESSAGE_MAP_KLASS} .participants").has_no_link?(
|
||||
class: "user-link",
|
||||
href: "/u/#{user.username}",
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
29
spec/system/page_objects/modals/private_message_invite.rb
Normal file
29
spec/system/page_objects/modals/private_message_invite.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PageObjects
|
||||
module Modals
|
||||
class PrivateMessageInvite < PageObjects::Modals::Base
|
||||
MODAL_SELECTOR = ".add-pm-participants"
|
||||
BODY_SELECTOR = ".invite.modal-panel"
|
||||
|
||||
def select_invitee(user)
|
||||
select_kit = PageObjects::Components::SelectKit.new(".invite-user-input")
|
||||
select_kit.expand
|
||||
select_kit.search(user.username)
|
||||
select_kit.select_row_by_value(user.username)
|
||||
end
|
||||
|
||||
def has_invitee_already_exists_error?
|
||||
body.find(".alert-error").has_text?(I18n.t("topic_invite.user_exists"))
|
||||
end
|
||||
|
||||
def click_primary_button
|
||||
body.find(".btn-primary").click
|
||||
end
|
||||
|
||||
def has_successful_invite_message?
|
||||
has_content?(I18n.t("js.topic.invite_private.success"))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PageObjects
|
||||
module Modals
|
||||
class PrivateMessageRemoveParticipant < PageObjects::Components::Base
|
||||
def open?
|
||||
has_css?("#dialog-holder .dialog-content")
|
||||
end
|
||||
|
||||
def closed?
|
||||
has_no_css?("#dialog-holder .dialog-content")
|
||||
end
|
||||
|
||||
def body
|
||||
find("#dialog-holder .dialog-content .dialog-body")
|
||||
end
|
||||
|
||||
def confirm_removal
|
||||
find("#dialog-holder .dialog-content .dialog-footer .btn-danger").click
|
||||
end
|
||||
|
||||
def cancel
|
||||
find("#dialog-holder .dialog-content .dialog-footer .btn-default").click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,6 +7,7 @@ module PageObjects
|
|||
@composer_component = PageObjects::Components::Composer.new
|
||||
@fast_edit_component = PageObjects::Components::FastEditor.new
|
||||
@topic_map_component = PageObjects::Components::TopicMap.new
|
||||
@private_message_map_component = PageObjects::Components::PrivateMessageMap.new
|
||||
end
|
||||
|
||||
def visit_topic(topic, post_number: nil)
|
||||
|
@ -205,6 +206,10 @@ module PageObjects
|
|||
@topic_map_component.is_not_visible?
|
||||
end
|
||||
|
||||
def has_private_message_map?
|
||||
@private_message_map_component.is_visible?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def topic_footer_button_id(button)
|
||||
|
|
146
spec/system/private_message_map_spec.rb
Normal file
146
spec/system/private_message_map_spec.rb
Normal file
|
@ -0,0 +1,146 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
describe "Topic Map - Private Message", type: :system do
|
||||
fab!(:user) { Fabricate(:admin, refresh_auto_groups: true) }
|
||||
fab!(:other_user) { Fabricate(:user, refresh_auto_groups: true) }
|
||||
fab!(:last_post_user) { Fabricate(:user, refresh_auto_groups: true) }
|
||||
fab!(:topic) do
|
||||
Fabricate(
|
||||
:private_message_topic,
|
||||
created_at: 1.day.ago,
|
||||
user: user,
|
||||
topic_allowed_users: [
|
||||
Fabricate.build(:topic_allowed_user, user: user),
|
||||
Fabricate.build(:topic_allowed_user, user: other_user),
|
||||
Fabricate.build(:topic_allowed_user, user: last_post_user),
|
||||
],
|
||||
)
|
||||
end
|
||||
fab!(:original_post) { Fabricate(:post, topic: topic, user: user, created_at: 1.day.ago) }
|
||||
|
||||
let(:topic_page) { PageObjects::Pages::Topic.new }
|
||||
let(:topic_map) { PageObjects::Components::TopicMap.new }
|
||||
let(:private_message_map) { PageObjects::Components::PrivateMessageMap.new }
|
||||
let(:private_message_invite_modal) { PageObjects::Modals::PrivateMessageInvite.new }
|
||||
let(:private_message_remove_participant_modal) do
|
||||
PageObjects::Modals::PrivateMessageRemoveParticipant.new
|
||||
end
|
||||
|
||||
def avatar_url(user, size)
|
||||
URI(user.avatar_template_url.gsub("{size}", size.to_s)).path
|
||||
end
|
||||
|
||||
it "updates the various topic stats, avatars" do
|
||||
freeze_time
|
||||
sign_in(user)
|
||||
topic_page.visit_topic(topic)
|
||||
|
||||
# topic map appears after OP
|
||||
expect(topic_page).to have_topic_map
|
||||
|
||||
# created avatar display
|
||||
expect(topic_map.created_details).to have_selector("img[src=\"#{avatar_url(user, 24)}\"]")
|
||||
expect(topic_map.created_relative_date).to eq "1d"
|
||||
|
||||
# replies, user count
|
||||
expect {
|
||||
Fabricate(:post, topic: topic, user: user, created_at: 1.day.ago)
|
||||
sign_in(last_post_user)
|
||||
topic_page.visit_topic_and_open_composer(topic)
|
||||
topic_page.send_reply("this is a cool-cat post") # fabricating posts doesn't update the last post details
|
||||
topic_page.visit_topic(topic)
|
||||
}.to change(topic_map, :replies_count).by(2).and change(topic_map, :users_count).by(1)
|
||||
|
||||
#last reply avatar display
|
||||
expect(topic_map.last_reply_details).to have_selector(
|
||||
"img[src=\"#{avatar_url(last_post_user, 24)}\"]",
|
||||
)
|
||||
expect(topic_map.last_reply_relative_date).to eq "1m"
|
||||
|
||||
# avatars details with post counts
|
||||
2.times { Fabricate(:post, topic: topic) }
|
||||
Fabricate(:post, user: user, topic: topic)
|
||||
Fabricate(:post, user: last_post_user, topic: topic)
|
||||
page.refresh
|
||||
avatars = topic_map.avatars_details
|
||||
expect(avatars.length).to eq 3 # max no. of avatars in a collapsed map
|
||||
expect(avatars[0]).to have_selector("img[src=\"#{avatar_url(user, 48)}\"]")
|
||||
expect(avatars[0].find(".post-count").text).to eq "3"
|
||||
expect(avatars[1]).to have_selector("img[src=\"#{avatar_url(last_post_user, 48)}\"]")
|
||||
expect(avatars[1].find(".post-count").text).to eq "2"
|
||||
expect(avatars[2]).to have_no_css(".post-count")
|
||||
|
||||
topic_map.expand
|
||||
expect(topic_map).to have_no_avatars_details_in_map
|
||||
expect(topic_map.expanded_map_avatars_details.length).to eq 4
|
||||
|
||||
# views count
|
||||
expect {
|
||||
sign_in(other_user)
|
||||
topic_page.visit_topic(topic)
|
||||
page.refresh
|
||||
}.to change(topic_map, :views_count).by 1
|
||||
|
||||
# likes count
|
||||
expect(topic_map).to have_no_likes
|
||||
topic_page.click_like_reaction_for(original_post)
|
||||
expect(topic_map.likes_count).to eq 1
|
||||
end
|
||||
|
||||
it "has private message map that shows correct participants and allows editing of participant invites" do
|
||||
freeze_time
|
||||
sign_in(user)
|
||||
topic_page.visit_topic(topic)
|
||||
|
||||
expect(topic_page).to have_private_message_map
|
||||
|
||||
# participants' links and avatars
|
||||
private_message_map
|
||||
.participants_details
|
||||
.zip([user, other_user, last_post_user]) do |details, usr|
|
||||
expect(details).to have_link(usr.username, href: "/u/#{usr.username}")
|
||||
expect(details.find(".trigger-user-card")).to have_selector(
|
||||
"img[src=\"#{avatar_url(usr, 24)}\"]",
|
||||
)
|
||||
end
|
||||
|
||||
# toggle ability to edit participants
|
||||
private_message_map.toggle_edit_participants_button
|
||||
expect(private_message_map).to have_add_participants_button
|
||||
private_message_map.toggle_edit_participants_button
|
||||
expect(private_message_map).to have_no_add_participants_button
|
||||
|
||||
# removing participants
|
||||
private_message_map.toggle_edit_participants_button
|
||||
private_message_map.participants_details.each do |details|
|
||||
expect(details).to have_css(".remove-invited .d-icon-times")
|
||||
end
|
||||
private_message_map.click_remove_participant_button(last_post_user)
|
||||
expect(private_message_remove_participant_modal).to be_open
|
||||
expect(private_message_remove_participant_modal.body).to have_text(
|
||||
I18n.t("js.private_message_info.remove_allowed_user", name: last_post_user.username),
|
||||
)
|
||||
private_message_remove_participant_modal.cancel
|
||||
expect(private_message_remove_participant_modal).to be_closed
|
||||
expect(private_message_map).to have_participant_details_for(last_post_user)
|
||||
private_message_map.click_remove_participant_button(last_post_user)
|
||||
expect(private_message_remove_participant_modal).to be_open
|
||||
private_message_remove_participant_modal.confirm_removal
|
||||
expect(private_message_map).to have_no_participant_details_for(last_post_user)
|
||||
|
||||
# adding participants
|
||||
expect {
|
||||
expect(private_message_map).to have_add_participants_button
|
||||
private_message_map.click_add_participants_button
|
||||
expect(private_message_invite_modal).to be_open
|
||||
private_message_invite_modal.select_invitee(other_user)
|
||||
private_message_invite_modal.click_primary_button
|
||||
expect(private_message_invite_modal).to have_invitee_already_exists_error
|
||||
private_message_invite_modal.select_invitee(last_post_user)
|
||||
private_message_invite_modal.click_primary_button #sends invite
|
||||
expect(private_message_invite_modal).to have_successful_invite_message
|
||||
private_message_invite_modal.click_primary_button #closes modal
|
||||
expect(private_message_invite_modal).to be_closed
|
||||
}.to change(private_message_map, :participants_count).by 1
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user