]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19315 Delegate sub navigation accordion state to parent components
author7PH <benjamin.raymond@sonarsource.com>
Fri, 12 May 2023 08:53:03 +0000 (10:53 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 12 May 2023 20:02:41 +0000 (20:02 +0000)
server/sonar-web/design-system/src/components/subnavigation/SubnavigationAccordion.tsx
server/sonar-web/design-system/src/components/subnavigation/__tests__/SubnavigationAccordion-test.tsx

index 38c1d11a99632ab7d6248f23ee6fa3cdd38871cb..e38644eea629dcf44ada5e313c498214ed266aa3 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import styled from '@emotion/styled';
-import { ReactNode, useCallback, useState } from 'react';
+import { ReactNode, useCallback } from 'react';
 import tw from 'twin.macro';
 import { themeColor, themeContrast } from '../../helpers/theme';
 import { BareButton } from '../buttons';
@@ -28,17 +28,17 @@ import { SubnavigationGroup } from './SubnavigationGroup';
 interface Props {
   children: ReactNode;
   className?: string;
+  expanded?: boolean;
   header: ReactNode;
   id: string;
-  initExpanded?: boolean;
+  onSetExpanded?: (expanded: boolean) => void;
 }
 
 export function SubnavigationAccordion(props: Props) {
-  const { children, className, header, id, initExpanded } = props;
-  const [expanded, setExpanded] = useState(initExpanded);
+  const { children, className, header, id, expanded = true, onSetExpanded } = props;
   const toggleExpanded = useCallback(() => {
-    setExpanded((expanded) => !expanded);
-  }, [setExpanded]);
+    onSetExpanded?.(!expanded);
+  }, [expanded, onSetExpanded]);
 
   return (
     <SubnavigationGroup
index 4491543456d18429012813147a54b15fe696fbe8..ebf76171247315ede38bf1f9c80c5e85b9568b71 100644 (file)
@@ -24,33 +24,51 @@ import { FCProps } from '../../../types/misc';
 import { SubnavigationAccordion } from '../SubnavigationAccordion';
 
 it('should have correct style and html structure', () => {
-  setupWithProps();
+  setupWithProps({ expanded: false });
 
   expect(screen.getByRole('button', { expanded: false })).toBeVisible();
   expect(screen.queryByText('Foo')).not.toBeInTheDocument();
 });
 
 it('should display expanded', () => {
-  setupWithProps({ initExpanded: true });
+  setupWithProps({ expanded: true });
 
   expect(screen.getByRole('button', { expanded: true })).toBeVisible();
   expect(screen.getByText('Foo')).toBeVisible();
 });
 
-it('should toggle expand', async () => {
-  const user = userEvent.setup();
+it('should display expanded by default', () => {
   setupWithProps();
 
-  expect(screen.queryByText('Foo')).not.toBeInTheDocument();
-  await user.click(screen.getByRole('button'));
+  expect(screen.getByRole('button')).toBeVisible();
   expect(screen.getByText('Foo')).toBeVisible();
-  await user.click(screen.getByRole('button'));
-  expect(screen.queryByText('Foo')).not.toBeInTheDocument();
+});
+
+it('should toggle expand', async () => {
+  const user = userEvent.setup();
+  const onSetExpanded = jest.fn();
+  setupWithProps({ onSetExpanded, expanded: false });
+
+  expect(onSetExpanded).not.toHaveBeenCalled();
+  await user.click(screen.getByRole('button', { expanded: false }));
+
+  expect(onSetExpanded).toHaveBeenCalledWith(true);
+});
+
+it('should toggle collapse', async () => {
+  const user = userEvent.setup();
+  const onSetExpanded = jest.fn();
+  setupWithProps({ onSetExpanded, expanded: true });
+
+  expect(onSetExpanded).not.toHaveBeenCalled();
+  await user.click(screen.getByRole('button', { expanded: true }));
+
+  expect(onSetExpanded).toHaveBeenCalledWith(false);
 });
 
 function setupWithProps(props: Partial<FCProps<typeof SubnavigationAccordion>> = {}) {
   return render(
-    <SubnavigationAccordion header="Header" id="test" initExpanded={false} {...props}>
+    <SubnavigationAccordion header="Header" id="test" {...props}>
       <span>Foo</span>
     </SubnavigationAccordion>
   );