diff --git a/e2e-tests/cypress/tests/integration/channels/keyboard_shortcuts/shift_up_focuses_on_rhs_spec.js b/e2e-tests/cypress/tests/integration/channels/keyboard_shortcuts/shift_up_focuses_on_rhs_spec.js index 125fbe5cfc..69e6928319 100644 --- a/e2e-tests/cypress/tests/integration/channels/keyboard_shortcuts/shift_up_focuses_on_rhs_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/keyboard_shortcuts/shift_up_focuses_on_rhs_spec.js @@ -21,7 +21,7 @@ describe('Keyboard Shortcuts', () => { it('MM-T1277 SHIFT+UP', () => { // # Press shift+up to open the latest thread in the channel in the RHS - cy.uiGetPostTextBox().type('{shift}{uparrow}'); + cy.uiGetPostTextBox().type('{shift+uparrow}', {delay: 50}); // * RHS Opens up cy.get('.sidebar--right__header').should('be.visible'); @@ -33,7 +33,28 @@ describe('Keyboard Shortcuts', () => { cy.uiGetPostTextBox().click(); // # Press shift+up again - cy.uiGetPostTextBox().type('{shift}{uparrow}'); + cy.uiGetPostTextBox().type('{shift+uparrow}', {delay: 50}); + + // * RHS textbox should be focused + cy.uiGetReplyTextBox().should('be.focused'); + + // # Post a reply in the thread + cy.uiGetReplyTextBox().type('This is a reply{enter}'); + + // # Close the RHS by clicking the X button + cy.get('#rhsCloseButton').click(); + + // * Verify RHS is closed + cy.get('.sidebar--right__header').should('not.exist'); + + // # Click into the center channel post textbox + cy.uiGetPostTextBox().click(); + + // # Press shift+up to open the thread with replies + cy.uiGetPostTextBox().type('{shift+uparrow}', {delay: 50}); + + // * RHS Opens up + cy.get('.sidebar--right__header').should('be.visible'); // * RHS textbox should be focused cy.uiGetReplyTextBox().should('be.focused'); diff --git a/e2e-tests/cypress/tests/integration/channels/messaging/focus_move_spec.js b/e2e-tests/cypress/tests/integration/channels/messaging/focus_move_spec.js index 77d2e46666..41ba26aabf 100644 --- a/e2e-tests/cypress/tests/integration/channels/messaging/focus_move_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/messaging/focus_move_spec.js @@ -15,12 +15,14 @@ import * as TIMEOUTS from '../../../fixtures/timeouts'; describe('Messaging', () => { let offTopicUrl; let testChannelName; + let user; before(() => { // # Login as test user cy.apiInitSetup({loginAfter: true}).then((out) => { offTopicUrl = out.offTopicUrl; testChannelName = out.channel.display_name; + user = out.user; }); }); @@ -97,6 +99,43 @@ describe('Messaging', () => { cy.uiGetReplyTextBox().should('be.focused'); }); + it('MM-T205 Focus to remain in RHS textbox when replying to reply post in center channel (CRT disabled)', () => { + // # Ensure collapsed reply threads is disabled + cy.apiSaveCRTPreference(user.id, 'off'); + + // # Post a thread root message + cy.postMessage('Thread root message'); + + // # Open RHS and post a reply + cy.clickPostCommentIcon(); + cy.uiGetReplyTextBox().type('First reply{enter}'); + + // # Close RHS + cy.get('#rhsCloseButton').click(); + + // * Verify RHS is closed + cy.get('.sidebar--right__header').should('not.exist'); + + // # Get the reply post ID and click its comment icon + cy.getLastPostId().then((postId) => { + // # Click the reply arrow on the reply post + cy.clickPostCommentIcon(postId); + + // * Verify RHS opens and textbox is focused + cy.get('.sidebar--right__header').should('be.visible'); + cy.uiGetReplyTextBox().should('be.focused'); + + // # Focus away from RHS textbox + cy.get('#rhsContainer .post-right__content').click(); + + // # Click reply arrow on the same reply post again + cy.clickPostCommentIcon(postId); + }); + + // * Verify RHS textbox is focused again + cy.uiGetReplyTextBox().should('be.focused'); + }); + it('MM-T203 Focus does not move when it has already been set elsewhere', () => { // # Verify Focus in add channel member modal verifyFocusInAddChannelMemberModal(); @@ -157,8 +196,8 @@ function verifyFocusInAddChannelMemberModal() { // * Check that input box has character A cy.get('#selectItems input').should('have.value', 'A'); - // # Click anywhere in the modal that is not on a field that can take focus - cy.get('#deletePostModalLabel > span').click(); + // # Remove the focus from the input box + cy.get('#selectItems input').blur(); // * Note the focus has been removed from the search box cy.get('#selectItems input').should('not.be.focused'); diff --git a/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.test.tsx b/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.test.tsx index daa9e29f62..64da39c015 100644 --- a/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.test.tsx +++ b/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.test.tsx @@ -236,7 +236,9 @@ describe('components/avanced_text_editor/advanced_text_editor', () => { expect(textbox).not.toHaveFocus(); // save is called with a short delayed after pressing escape key - jest.advanceTimersByTime(Constants.SAVE_DRAFT_TIMEOUT + 50); + act(() => { + jest.advanceTimersByTime(Constants.SAVE_DRAFT_TIMEOUT + 50); + }); expect(mockedRemoveDraft).toHaveBeenCalled(); expect(mockedUpdateDraft).not.toHaveBeenCalled(); }); diff --git a/webapp/channels/src/components/advanced_text_editor/use_textbox_focus.tsx b/webapp/channels/src/components/advanced_text_editor/use_textbox_focus.tsx index 01ef01da4d..aaefb654ee 100644 --- a/webapp/channels/src/components/advanced_text_editor/use_textbox_focus.tsx +++ b/webapp/channels/src/components/advanced_text_editor/use_textbox_focus.tsx @@ -33,11 +33,20 @@ const useTextboxFocus = ( const focusTextbox = useCallback((keepFocus = false) => { const postTextboxDisabled = !canPost; if (textboxRef.current && postTextboxDisabled) { - textboxRef.current.blur(); // Fixes Firefox bug which causes keyboard shortcuts to be ignored (MM-22482) + // Fixes Firefox bug which causes keyboard shortcuts to be ignored (MM-22482) + requestAnimationFrame(() => { + textboxRef.current?.blur(); + }); return; } if (textboxRef.current && (keepFocus || !UserAgent.isMobile())) { - textboxRef.current.focus(); + // Focus immediately, so we capture any typed text. + textboxRef.current?.focus(); + + // Also re-focus after the next animation frame, to work around issues where the RHS is "opening". + requestAnimationFrame(() => { + textboxRef.current?.focus(); + }); } }, [canPost, textboxRef]);