diff --git a/webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_bar.test.tsx b/webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_bar.test.tsx
new file mode 100644
index 0000000000..222ef11276
--- /dev/null
+++ b/webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_bar.test.tsx
@@ -0,0 +1,86 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {screen} from '@testing-library/react';
+import React from 'react';
+
+import {renderWithContext, userEvent} from 'tests/react_testing_utils';
+import {Locations} from 'utils/constants';
+
+import FormattingBar from './formatting_bar';
+import * as Hooks from './hooks';
+
+global.ResizeObserver = require('resize-observer-polyfill');
+
+jest.mock('./hooks');
+
+const {splitFormattingBarControls} = jest.requireActual('./hooks');
+
+describe('FormattingBar', () => {
+ const baseProps = {
+ getCurrentMessage: jest.fn(() => ''),
+ getCurrentSelection: jest.fn(() => ({start: 0, end: 0})),
+ applyMarkdown: jest.fn(),
+ disableControls: false,
+ location: Locations.CENTER,
+ };
+
+ test('should render hidden formatting button when screen size is min', () => {
+ jest.spyOn(Hooks, 'useFormattingBarControls').mockReturnValue({wideMode: 'min', ...splitFormattingBarControls('min')});
+
+ renderWithContext(
+ ,
+ );
+
+ expect(screen.getByLabelText('show hidden formatting options')).toBeInTheDocument();
+ });
+
+ test('should render hidden formatting button when screen size is narrow', () => {
+ jest.spyOn(Hooks, 'useFormattingBarControls').mockReturnValue({wideMode: 'narrow', ...splitFormattingBarControls('narrow')});
+
+ renderWithContext(
+ ,
+ );
+
+ expect(screen.getByLabelText('show hidden formatting options')).toBeInTheDocument();
+ });
+
+ test('should render hidden formatting button when screen size is normal', () => {
+ jest.spyOn(Hooks, 'useFormattingBarControls').mockReturnValue({wideMode: 'normal', ...splitFormattingBarControls('normal')});
+
+ renderWithContext(
+ ,
+ );
+
+ expect(screen.getByLabelText('show hidden formatting options')).toBeInTheDocument();
+ });
+
+ test('should not render hidden formatting button when screen size is wide', () => {
+ jest.spyOn(Hooks, 'useFormattingBarControls').mockReturnValue({wideMode: 'wide', ...splitFormattingBarControls('wide')});
+
+ renderWithContext(
+ ,
+ );
+
+ expect(screen.queryByLabelText('show hidden formatting options')).not.toBeInTheDocument();
+ });
+
+ test('MM-56705 should not submit form when clicking on hidden formatting button', () => {
+ jest.spyOn(Hooks, 'useFormattingBarControls').mockReturnValue({wideMode: 'narrow', ...splitFormattingBarControls('narrow')});
+
+ const onSubmit = jest.fn();
+
+ renderWithContext(
+
,
+ );
+
+ expect(screen.queryByLabelText('heading')).not.toBeVisible();
+
+ userEvent.click(screen.getByLabelText('show hidden formatting options'));
+
+ expect(screen.queryByLabelText('heading')).toBeVisible();
+ expect(onSubmit).not.toHaveBeenCalled();
+ });
+});
diff --git a/webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_bar.tsx b/webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_bar.tsx
index b4ddd7985b..f4a51e6c2f 100644
--- a/webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_bar.tsx
+++ b/webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_bar.tsx
@@ -243,6 +243,7 @@ const FormattingBar = (props: FormattingBarProps): JSX.Element => {
ref={setReference}
className={classNames({active: showHiddenControls})}
aria-label={HiddenControlsButtonAriaLabel}
+ type='button'
{...getClickReferenceProps()}
{...getDismissReferenceProps()}
>
diff --git a/webapp/channels/src/components/advanced_text_editor/formatting_bar/hooks.tsx b/webapp/channels/src/components/advanced_text_editor/formatting_bar/hooks.tsx
index 86aca70825..9d423816d0 100644
--- a/webapp/channels/src/components/advanced_text_editor/formatting_bar/hooks.tsx
+++ b/webapp/channels/src/components/advanced_text_editor/formatting_bar/hooks.tsx
@@ -56,6 +56,20 @@ const MAP_WIDE_MODE_TO_CONTROLS_QUANTITY: {[key in WideMode]: number} = {
min: 1,
};
+export function splitFormattingBarControls(wideMode: WideMode) {
+ const allControls: MarkdownMode[] = ['bold', 'italic', 'strike', 'heading', 'link', 'code', 'quote', 'ul', 'ol'];
+
+ const controlsLength = MAP_WIDE_MODE_TO_CONTROLS_QUANTITY[wideMode];
+
+ const controls = allControls.slice(0, controlsLength);
+ const hiddenControls = allControls.slice(controlsLength);
+
+ return {
+ controls,
+ hiddenControls,
+ };
+}
+
export const useFormattingBarControls = (
formattingBarRef: React.RefObject,
): {
@@ -65,12 +79,7 @@ export const useFormattingBarControls = (
} => {
const wideMode = useResponsiveFormattingBar(formattingBarRef);
- const allControls: MarkdownMode[] = ['bold', 'italic', 'strike', 'heading', 'link', 'code', 'quote', 'ul', 'ol'];
-
- const controlsLength = MAP_WIDE_MODE_TO_CONTROLS_QUANTITY[wideMode];
-
- const controls = allControls.slice(0, controlsLength);
- const hiddenControls = allControls.slice(controlsLength);
+ const {controls, hiddenControls} = splitFormattingBarControls(wideMode);
return {
controls,