From e0798b88e013f9164ac180aa38858e3249b13c55 Mon Sep 17 00:00:00 2001 From: Suzanne Aitchison Date: Tue, 15 Jun 2021 11:13:31 +0100 Subject: [PATCH] Message context menu in connect is not accessible #12250 (#13806) * make connect message dropdown accessible * add a cypress test * use crayons buttons throughout * fix some unhandled error affecting cypress * make message options a list * minor tweak to test * guard against filter error being triggered in test * utilise newer dropdown helpers * wait for message to fully send * use optional chaining --- app/assets/stylesheets/chat.scss | 20 +++-- app/javascript/chat/chat.jsx | 32 +++----- app/javascript/chat/content.jsx | 10 +-- app/javascript/chat/message.jsx | 79 ++++++++++++++---- app/javascript/utilities/dropdownUtils.js | 27 ++---- cypress/fixtures/users/chatUser1.json | 5 ++ cypress/fixtures/users/chatUser2.json | 5 ++ .../chatFlows/messageOptions.spec.js | 82 +++++++++++++++++++ spec/support/seeds/seeds_e2e.rb | 56 +++++++++++++ 9 files changed, 244 insertions(+), 72 deletions(-) create mode 100644 cypress/fixtures/users/chatUser1.json create mode 100644 cypress/fixtures/users/chatUser2.json create mode 100644 cypress/integration/chatFlows/messageOptions.spec.js diff --git a/app/assets/stylesheets/chat.scss b/app/assets/stylesheets/chat.scss index 393bde756..97b48d233 100644 --- a/app/assets/stylesheets/chat.scss +++ b/app/assets/stylesheets/chat.scss @@ -920,20 +920,25 @@ } .message__actions { - display: none; position: relative; justify-content: end; -webkit-justify-content: flex-end; - .ellipsis__menubutton { + .ellipsis__menubutton img { height: 17px; - cursor: pointer; + vertical-align: middle; color: var(--theme-color, #0a0a0a); } &:hover { - .messagebody__dropdownmenu { - display: block; + .ellipsis__menubutton { + opacity: 1; + } + } + + &:focus-within { + .ellipsis__menubutton { + opacity: 1; } } @@ -943,15 +948,14 @@ } .messagebody__dropdownmenu { - display: none; position: absolute; background-color: var(--theme-container-background, #fff); border-style: solid; border-color: var(--theme-color, #0a0a0a); border-radius: 5px; border-width: 1px; - margin-top: 1em; - margin-right: -0.6em; + top: 100%; + right: 0; button { width: 100%; diff --git a/app/javascript/chat/chat.jsx b/app/javascript/chat/chat.jsx index 57e3b0df6..719eb7d9c 100644 --- a/app/javascript/chat/chat.jsx +++ b/app/javascript/chat/chat.jsx @@ -664,11 +664,11 @@ export class Chat extends Component { }); } if (messageIsEmpty) { - const messagesByCurrentUser = messages[activeChannelId].filter( + const messagesByCurrentUser = messages[activeChannelId]?.filter( (message) => message.user_id === currentUserId, ); const lastMessage = - messagesByCurrentUser[messagesByCurrentUser.length - 1]; + messagesByCurrentUser?.[messagesByCurrentUser.length - 1]; if (lastMessage) { if (upArrowPressed) { @@ -778,9 +778,8 @@ export class Chat extends Component { } }; hideChannelList = () => { - const chatContainer = document.getElementsByClassName( - 'chat__activechat', - )[0]; + const chatContainer = + document.getElementsByClassName('chat__activechat')[0]; chatContainer.classList.remove('chat__activechat--hidden'); }; handleSwitchChannel = (e) => { @@ -1371,9 +1370,8 @@ export class Chat extends Component { }; navigateToChannelsList = () => { - const chatContainer = document.getElementsByClassName( - 'chat__activechat', - )[0]; + const chatContainer = + document.getElementsByClassName('chat__activechat')[0]; chatContainer.classList.add('chat__activechat--hidden'); }; @@ -1390,12 +1388,8 @@ export class Chat extends Component { }; handleMessageScroll = () => { - const { - allMessagesLoaded, - messages, - activeChannelId, - messageOffset, - } = this.state; + const { allMessagesLoaded, messages, activeChannelId, messageOffset } = + this.state; if (!messages[activeChannelId]) { return; @@ -1608,7 +1602,7 @@ export class Chat extends Component { const enterPressed = e.keyCode === 13; if (enterPressed && showMemberlist) this.setState({ showMemberlist: false }); - if (activeChannel.channel_type !== 'direct') { + if (activeChannel?.channel_type !== 'direct') { if (startEditing) { this.setState({ markdownEdited: true }); } @@ -1705,12 +1699,8 @@ export class Chat extends Component { }; renderChannelMembersList = () => { - const { - showMemberlist, - activeChannelId, - channelUsers, - memberFilterQuery, - } = this.state; + const { showMemberlist, activeChannelId, channelUsers, memberFilterQuery } = + this.state; const filterRegx = new RegExp(memberFilterQuery, 'gi'); diff --git a/app/javascript/chat/content.jsx b/app/javascript/chat/content.jsx index f69db256c..96e297f15 100644 --- a/app/javascript/chat/content.jsx +++ b/app/javascript/chat/content.jsx @@ -39,12 +39,8 @@ export class Content extends Component { }; render() { - const { - onTriggerContent, - fullscreen, - resource, - closeReportAbuseForm, - } = this.props; + const { onTriggerContent, fullscreen, resource, closeReportAbuseForm } = + this.props; if (!resource) { return ''; } @@ -52,13 +48,13 @@ export class Content extends Component { return ( // TODO: A button (role="button") cannot contain other interactive elements, i.e. buttons. // TODO: These should have key click events as well. + // eslint-disable-next-line jsx-a11y/click-events-have-key-events