box-ui-elements 23.4.0-beta.22 → 23.4.0-beta.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/explorer.js +1 -1
  2. package/dist/preview.js +1 -1
  3. package/dist/sidebar.js +1 -1
  4. package/es/components/flyout/OverlayHeader.js +6 -3
  5. package/es/components/flyout/OverlayHeader.js.map +1 -1
  6. package/es/elements/common/nav-router/NavRouter.js +7 -3
  7. package/es/elements/common/nav-router/NavRouter.js.flow +10 -1
  8. package/es/elements/common/nav-router/NavRouter.js.map +1 -1
  9. package/es/elements/common/nav-router/types.js.map +1 -1
  10. package/es/elements/common/nav-router/withNavRouter.js +10 -1
  11. package/es/elements/common/nav-router/withNavRouter.js.flow +5 -0
  12. package/es/elements/common/nav-router/withNavRouter.js.map +1 -1
  13. package/es/elements/common/routing/withRouterAndRef.js +17 -3
  14. package/es/elements/common/routing/withRouterAndRef.js.flow +11 -3
  15. package/es/elements/common/routing/withRouterAndRef.js.map +1 -1
  16. package/es/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js +22 -13
  17. package/es/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js.flow +30 -17
  18. package/es/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js.map +1 -1
  19. package/es/elements/content-sidebar/ContentSidebar.js +3 -1
  20. package/es/elements/content-sidebar/ContentSidebar.js.flow +2 -1
  21. package/es/elements/content-sidebar/ContentSidebar.js.map +1 -1
  22. package/es/elements/content-sidebar/SidebarToggle.js +27 -9
  23. package/es/elements/content-sidebar/SidebarToggle.js.flow +29 -6
  24. package/es/elements/content-sidebar/SidebarToggle.js.map +1 -1
  25. package/es/elements/content-sidebar/stories/tests/MetadataSidebarRedesign-visual.stories.js +12 -1
  26. package/es/elements/content-sidebar/stories/tests/MetadataSidebarRedesign-visual.stories.js.map +1 -1
  27. package/es/features/header-flyout/HeaderFlyout.js +6 -3
  28. package/es/features/header-flyout/HeaderFlyout.js.flow +15 -2
  29. package/es/features/header-flyout/HeaderFlyout.js.map +1 -1
  30. package/es/src/components/flyout/OverlayHeader.d.ts +3 -1
  31. package/es/src/elements/common/nav-router/NavRouter.d.ts +3 -1
  32. package/es/src/elements/common/nav-router/types.d.ts +2 -0
  33. package/package.json +1 -1
  34. package/src/components/flyout/OverlayHeader.tsx +7 -3
  35. package/src/components/flyout/__tests__/OverlayHeader.test.js +25 -0
  36. package/src/elements/common/nav-router/NavRouter.js.flow +10 -1
  37. package/src/elements/common/nav-router/NavRouter.tsx +9 -3
  38. package/src/elements/common/nav-router/__tests__/withNavRouter.test.tsx +34 -20
  39. package/src/elements/common/nav-router/types.ts +2 -0
  40. package/src/elements/common/nav-router/withNavRouter.js.flow +5 -0
  41. package/src/elements/common/nav-router/withNavRouter.tsx +9 -1
  42. package/src/elements/common/routing/__tests__/withRouterAndRef.test.js +64 -12
  43. package/src/elements/common/routing/withRouterAndRef.js +11 -3
  44. package/src/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js +30 -17
  45. package/src/elements/content-sidebar/ContentSidebar.js +2 -1
  46. package/src/elements/content-sidebar/SidebarToggle.js +29 -6
  47. package/src/elements/content-sidebar/__tests__/SidebarToggle.test.js +74 -10
  48. package/src/elements/content-sidebar/stories/tests/MetadataSidebarRedesign-visual.stories.tsx +14 -1
  49. package/src/features/header-flyout/HeaderFlyout.js +15 -2
  50. package/src/features/header-flyout/__tests__/__snapshots__/HeaderFlyout.test.js.snap +9 -3
  51. package/src/elements/content-sidebar/__tests__/__snapshots__/SidebarToggle.test.js.snap +0 -19
@@ -52,5 +52,30 @@ describe('components/flyout/OverlayHeader', () => {
52
52
  fireEvent.click(screen.getByRole('button'));
53
53
  expect(overlayClick).toHaveBeenCalledTimes(0);
54
54
  });
55
+
56
+ test.each([
57
+ {
58
+ isOverlayHeaderActionEnabled: false,
59
+ expectedCallCount: 0,
60
+ behavior: 'prevent default and stop propagation',
61
+ },
62
+ { isOverlayHeaderActionEnabled: true, expectedCallCount: 1, behavior: 'allow default and propagation' },
63
+ ])(
64
+ 'should $behavior when isOverlayHeaderActionEnabled is $isOverlayHeaderActionEnabled',
65
+ ({ isOverlayHeaderActionEnabled, expectedCallCount }) => {
66
+ const overlayClick = jest.fn();
67
+
68
+ render(
69
+ <div role="presentation" onClick={overlayClick}>
70
+ <OverlayHeader isOverlayHeaderActionEnabled={isOverlayHeaderActionEnabled}>
71
+ <p>Hi</p>
72
+ </OverlayHeader>
73
+ </div>,
74
+ );
75
+
76
+ fireEvent.click(screen.getByRole('button'));
77
+ expect(overlayClick).toHaveBeenCalledTimes(expectedCallCount);
78
+ },
79
+ );
55
80
  });
56
81
  });
@@ -6,13 +6,22 @@
6
6
  import * as React from 'react';
7
7
  import { MemoryRouter, Router } from 'react-router-dom';
8
8
  import type { RouterHistory } from 'react-router-dom';
9
+ import { isFeatureEnabled, type FeatureConfig } from '../feature-checking';
9
10
 
10
11
  type Props = {
11
12
  children: React.Node,
13
+ features?: FeatureConfig,
12
14
  history?: RouterHistory,
15
+ initialEntries?: Array<any>,
13
16
  };
14
17
 
15
- const NavRouter = ({ children, history, ...rest }: Props) => {
18
+ const NavRouter = ({ children, features, history, ...rest }: Props) => {
19
+ const isRouterDisabled = isFeatureEnabled(features, 'routerDisabled.value');
20
+
21
+ if (isRouterDisabled) {
22
+ return <>{children}</>;
23
+ }
24
+
16
25
  if (history) {
17
26
  return <Router history={history}>{children}</Router>;
18
27
  }
@@ -1,17 +1,23 @@
1
1
  import * as React from 'react';
2
2
  import { MemoryRouter, Router } from 'react-router';
3
3
  import { History } from 'history';
4
+ import { isFeatureEnabled, type FeatureConfig } from '../feature-checking';
4
5
 
5
6
  type Props = {
6
7
  children: React.ReactNode;
8
+ features?: FeatureConfig;
7
9
  history?: History;
8
10
  initialEntries?: History.LocationDescriptor[];
9
11
  };
10
12
 
11
- const NavRouter = ({ children, history, ...rest }: Props) => {
13
+ const NavRouter = ({ children, features, history, ...rest }: Props) => {
14
+ const isRouterDisabled = isFeatureEnabled(features, 'routerDisabled.value');
15
+
16
+ if (isRouterDisabled) {
17
+ return <>{children}</>;
18
+ }
19
+
12
20
  if (history) {
13
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
14
- // @ts-ignore
15
21
  return <Router history={history}>{children}</Router>;
16
22
  }
17
23
 
@@ -1,41 +1,55 @@
1
1
  import * as React from 'react';
2
- import { shallow } from 'enzyme';
3
- import { createMemoryHistory } from 'history';
4
- import NavRouter from '../NavRouter';
2
+ import { render } from '../../../../test-utils/testing-library';
5
3
  import withNavRouter from '../withNavRouter';
6
4
  import { WithNavRouterProps } from '../types';
7
5
 
6
+ jest.mock('../NavRouter', () => ({ children }: { children: React.ReactNode }) => (
7
+ <div data-testid="nav-router-wrapper">{children}</div>
8
+ ));
9
+
8
10
  type Props = {
9
11
  value?: string;
10
12
  };
11
13
 
12
14
  describe('src/eleemnts/common/nav-router/withNavRouter', () => {
13
- const TestComponent = ({ value }: Props) => <div>{`Test ${value}`}</div>;
15
+ const TestComponent = ({ value }: Props) => <div data-testid="test-component">{`Test ${value}`}</div>;
14
16
  const WrappedComponent = withNavRouter(TestComponent);
15
17
 
16
- const getWrapper = (props?: Props & WithNavRouterProps) => shallow(<WrappedComponent {...props} />);
18
+ const renderComponent = (props?: Props & WithNavRouterProps) =>
19
+ render(<WrappedComponent {...props} />);
17
20
 
18
21
  test('should wrap component with NavRouter', () => {
19
- const wrapper = getWrapper();
22
+ const { getByTestId } = renderComponent();
23
+
24
+ expect(getByTestId('test-component')).toBeInTheDocument();
25
+ expect(getByTestId('test-component')).toHaveTextContent('Test undefined');
26
+ expect(getByTestId('nav-router-wrapper')).toBeInTheDocument();
27
+ });
20
28
 
21
- expect(wrapper.find(NavRouter)).toBeTruthy();
22
- expect(wrapper.find(TestComponent)).toBeTruthy();
29
+ test('should pass props to wrapped component', () => {
30
+ const { getByTestId } = renderComponent({ value: 'test-value' });
31
+
32
+ expect(getByTestId('test-component')).toBeInTheDocument();
33
+ expect(getByTestId('test-component')).toHaveTextContent('Test test-value');
23
34
  });
24
35
 
25
- test('should provide the appropriate props to NavRouter and the wrapped component', () => {
26
- const history = createMemoryHistory();
27
- const initialEntries = ['foo'];
28
- const value = 'foo';
29
- const wrapper = getWrapper({
30
- history,
31
- initialEntries,
32
- value,
36
+ describe('when routerDisabled feature flag is provided', () => {
37
+ test('should return unwrapped component when feature flag is true', () => {
38
+ const features = { routerDisabled: { value: true } };
39
+ const { getByTestId, queryByTestId } = renderComponent({ features });
40
+
41
+ expect(getByTestId('test-component')).toBeInTheDocument();
42
+ expect(getByTestId('test-component')).toHaveTextContent('Test undefined');
43
+ expect(queryByTestId('nav-router-wrapper')).not.toBeInTheDocument();
33
44
  });
34
45
 
35
- const navRouter = wrapper.find(NavRouter);
36
- expect(navRouter.prop('history')).toEqual(history);
37
- expect(navRouter.prop('initialEntries')).toEqual(initialEntries);
46
+ test('should wrap component with NavRouter when feature flag is false', () => {
47
+ const features = { routerDisabled: { value: false } };
48
+ const { getByTestId } = renderComponent({ features });
38
49
 
39
- expect(wrapper.find(TestComponent).prop('value')).toEqual(value);
50
+ expect(getByTestId('test-component')).toBeInTheDocument();
51
+ expect(getByTestId('test-component')).toHaveTextContent('Test undefined');
52
+ expect(getByTestId('nav-router-wrapper')).toBeInTheDocument();
53
+ });
40
54
  });
41
55
  });
@@ -1,6 +1,8 @@
1
1
  import { History } from 'history';
2
+ import { FeatureConfig } from '../feature-checking';
2
3
 
3
4
  export type WithNavRouterProps = {
5
+ features?: FeatureConfig;
4
6
  history?: History;
5
7
  initialEntries?: History.LocationDescriptor[];
6
8
  };
@@ -6,9 +6,14 @@
6
6
 
7
7
  import React from "react";
8
8
  import { History } from "history";
9
+ import { type FeatureConfig } from '../feature-checking';
9
10
  import NavRouter from "./NavRouter";
11
+
10
12
  export type WithNavRouterProps = {
13
+ features?: FeatureConfig,
11
14
  history?: History,
15
+ initialEntries?: Array<any>,
12
16
  ...
13
17
  };
18
+
14
19
  declare export var withNavRouter: any; // /* NO PRINT IMPLEMENTED: ArrowFunction */ any
@@ -1,11 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import NavRouter from './NavRouter';
3
3
  import { WithNavRouterProps } from './types';
4
+ import { isFeatureEnabled } from '../feature-checking';
4
5
 
5
6
  const withNavRouter = <P extends object>(Component: React.ComponentType<P>): React.FC<P & WithNavRouterProps> => {
6
7
  function WithNavRouter({ history, initialEntries, ...rest }: P & WithNavRouterProps) {
8
+ const { features } = rest;
9
+ const isRouterDisabled = isFeatureEnabled(features, 'routerDisabled.value');
10
+
11
+ if (isRouterDisabled) {
12
+ return <Component {...(rest as P)} />;
13
+ }
14
+
7
15
  return (
8
- <NavRouter history={history} initialEntries={initialEntries}>
16
+ <NavRouter history={history} initialEntries={initialEntries} features={features}>
9
17
  <Component {...(rest as P)} />
10
18
  </NavRouter>
11
19
  );
@@ -1,26 +1,78 @@
1
1
  // @flow
2
2
  import * as React from 'react';
3
3
  import { MemoryRouter } from 'react-router-dom';
4
- import { mount } from 'enzyme';
4
+ import { render } from '../../../../test-utils/testing-library';
5
5
  import withRouterAndRef from '../withRouterAndRef';
6
6
 
7
7
  describe('elements/common/routing/withRouterAndRef', () => {
8
8
  type Props = {
9
9
  value: string,
10
+ routerDisabled?: boolean,
10
11
  };
11
12
 
12
- const TestComponent = React.forwardRef(({ value }: Props, ref) => <div ref={ref}>{value}</div>);
13
+ const TestComponent = React.forwardRef(({ value, staticContext, routerDisabled, ...props }: Props, ref) => (
14
+ <div ref={ref} data-testid="test-component" data-router-disabled={routerDisabled} {...props}>
15
+ {value}
16
+ </div>
17
+ ));
18
+ TestComponent.displayName = 'TestComponent';
19
+
13
20
  const WithRouterComponent = withRouterAndRef(TestComponent);
14
21
 
15
- test('should pass ref down to wrapped component', () => {
16
- const ref = React.createRef();
17
- const wrapper = mount(
18
- <MemoryRouter>
19
- <WithRouterComponent ref={ref} value="foo" />
20
- </MemoryRouter>,
21
- );
22
- const referenced = wrapper.find('div').getDOMNode();
23
- expect(ref.current).toEqual(referenced);
24
- expect(referenced.innerHTML).toEqual('foo');
22
+ describe('router enabled (default)', () => {
23
+ test('should pass ref and router props to wrapped component', () => {
24
+ const ref = React.createRef();
25
+ const { getByTestId } = render(
26
+ <MemoryRouter initialEntries={['/test']}>
27
+ <WithRouterComponent ref={ref} value="test" />
28
+ </MemoryRouter>,
29
+ );
30
+
31
+ const element = getByTestId('test-component');
32
+ expect(ref.current).toBe(element);
33
+ expect(element).toHaveTextContent('test');
34
+ expect(element).not.toHaveAttribute('data-router-disabled');
35
+ });
36
+ });
37
+
38
+ describe('router disabled', () => {
39
+ test('should pass ref down to wrapped component without router', () => {
40
+ const ref = React.createRef();
41
+ const { getByTestId } = render(
42
+ <WithRouterComponent ref={ref} value="foo" routerDisabled />
43
+ );
44
+
45
+ const element = getByTestId('test-component');
46
+ expect(ref.current).toBe(element);
47
+ expect(element).toHaveTextContent('foo');
48
+ expect(element).toHaveAttribute('data-router-disabled', 'true');
49
+ });
50
+
51
+ test('should render component directly without Route wrapper', () => {
52
+ const { getByTestId } = render(
53
+ <WithRouterComponent value="direct" routerDisabled />
54
+ );
55
+
56
+ const element = getByTestId('test-component');
57
+ expect(element).toHaveTextContent('direct');
58
+ expect(element).toHaveAttribute('data-router-disabled', 'true');
59
+ });
60
+
61
+ test('should pass through all props including routerDisabled', () => {
62
+ const { getByTestId } = render(
63
+ <WithRouterComponent
64
+ value="test"
65
+ routerDisabled
66
+ data-custom="custom-value"
67
+ className="test-class"
68
+ />
69
+ );
70
+
71
+ const element = getByTestId('test-component');
72
+ expect(element).toHaveTextContent('test');
73
+ expect(element).toHaveAttribute('data-custom', 'custom-value');
74
+ expect(element).toHaveClass('test-class');
75
+ expect(element).toHaveAttribute('data-router-disabled', 'true');
76
+ });
25
77
  });
26
78
  });
@@ -5,9 +5,17 @@ import { Route } from 'react-router-dom';
5
5
  // Basically a workaround for the fact that react-router's withRouter cannot forward ref's through
6
6
  // functional components. Use this instead to gain the benefits of withRouter but also ref forwarding
7
7
  export default function withRouterAndRef(Wrapped: React.ComponentType<any>) {
8
- const WithRouterAndRef = React.forwardRef<Object, React.Ref<any>>((props, ref) => (
9
- <Route>{routeProps => <Wrapped ref={ref} {...routeProps} {...props} />}</Route>
10
- ));
8
+ const WithRouterAndRef = React.forwardRef<Object, React.Ref<any>>((props, ref) => {
9
+ const { routerDisabled } = props;
10
+
11
+ // If router is disabled, return component directly without Route wrapper
12
+ if (routerDisabled) {
13
+ return <Wrapped ref={ref} {...props} />;
14
+ }
15
+
16
+ // Default behavior: wrap with Route to get router props
17
+ return <Route>{routeProps => <Wrapped ref={ref} {...routeProps} {...props} />}</Route>;
18
+ });
11
19
  const name = Wrapped.displayName || Wrapped.name || 'Component';
12
20
  WithRouterAndRef.displayName = `withRouterAndRef(${name})`;
13
21
  return WithRouterAndRef;
@@ -5,6 +5,7 @@ import ContentExplorer from '../../ContentExplorer';
5
5
  import { mockEmptyRootFolder, mockRootFolder } from '../../../common/__mocks__/mockRootFolder';
6
6
  import mockSubfolder from '../../../common/__mocks__/mockSubfolder';
7
7
  import mockRecentItems from '../../../common/__mocks__/mockRecentItems';
8
+ import { mockUserRequest } from '../../../common/__mocks__/mockRequests';
8
9
 
9
10
  import { DEFAULT_HOSTNAME_API } from '../../../../constants';
10
11
 
@@ -227,10 +228,38 @@ export const closeCreateFolderDialog = {
227
228
  // },
228
229
  // };
229
230
 
231
+ const defaultHandlers = [
232
+ http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/69083462919`, () => {
233
+ return HttpResponse.json(mockRootFolder);
234
+ }),
235
+ http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/73426618530`, () => {
236
+ return HttpResponse.json(mockSubfolder);
237
+ }),
238
+ http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/74729718131`, () => {
239
+ return HttpResponse.json(mockEmptyRootFolder);
240
+ }),
241
+ http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/191354690948`, () => {
242
+ return new HttpResponse('Internal Server Error', { status: 500 });
243
+ }),
244
+ http.get(`${DEFAULT_HOSTNAME_API}/2.0/recent_items`, () => {
245
+ return HttpResponse.json(mockRecentItems);
246
+ }),
247
+ ];
248
+
230
249
  export const emptyState = {
231
250
  args: {
232
251
  rootFolderId: '74729718131',
233
252
  },
253
+ parameters: {
254
+ msw: {
255
+ handlers: [
256
+ ...defaultHandlers,
257
+ http.get(mockUserRequest.url, () => {
258
+ return HttpResponse.json(mockUserRequest.response);
259
+ }),
260
+ ],
261
+ },
262
+ },
234
263
  play: async ({ canvasElement }) => {
235
264
  const canvas = within(canvasElement);
236
265
  await waitFor(() => {
@@ -271,23 +300,7 @@ export default {
271
300
  },
272
301
  parameters: {
273
302
  msw: {
274
- handlers: [
275
- http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/69083462919`, () => {
276
- return HttpResponse.json(mockRootFolder);
277
- }),
278
- http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/73426618530`, () => {
279
- return HttpResponse.json(mockSubfolder);
280
- }),
281
- http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/74729718131`, () => {
282
- return HttpResponse.json(mockEmptyRootFolder);
283
- }),
284
- http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/191354690948`, () => {
285
- return new HttpResponse('Internal Server Error', { status: 500 });
286
- }),
287
- http.get(`${DEFAULT_HOSTNAME_API}/2.0/recent_items`, () => {
288
- return HttpResponse.json(mockRecentItems);
289
- }),
290
- ],
303
+ handlers: defaultHandlers,
291
304
  },
292
305
  },
293
306
  };
@@ -349,6 +349,7 @@ class ContentSidebar extends React.Component<Props, State> {
349
349
  defaultView,
350
350
  detailsSidebarProps,
351
351
  docGenSidebarProps,
352
+ features,
352
353
  fileId,
353
354
  getPreview,
354
355
  getViewer,
@@ -382,7 +383,7 @@ class ContentSidebar extends React.Component<Props, State> {
382
383
  return (
383
384
  <Internationalize language={language} messages={messages}>
384
385
  <APIContext.Provider value={(this.api: any)}>
385
- <NavRouter history={history} initialEntries={[initialPath]}>
386
+ <NavRouter history={history} initialEntries={[initialPath]} features={features}>
386
387
  <TooltipProvider>
387
388
  <Sidebar
388
389
  activitySidebarProps={activitySidebarProps}
@@ -8,23 +8,46 @@ import * as React from 'react';
8
8
  import { withRouter, type RouterHistory } from 'react-router-dom';
9
9
  import SidebarToggleButton from '../../components/sidebar-toggle-button/SidebarToggleButton';
10
10
  import { SIDEBAR_NAV_TARGETS } from '../common/interactionTargets';
11
+ import type { InternalSidebarNavigation, InternalSidebarNavigationHandler } from '../common/types/SidebarNavigation';
11
12
 
12
13
  type Props = {
13
- history: RouterHistory,
14
+ history?: RouterHistory,
15
+ internalSidebarNavigation?: InternalSidebarNavigation,
16
+ internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
14
17
  isOpen?: boolean,
18
+ routerDisabled?: boolean,
15
19
  };
16
20
 
17
- const SidebarToggle = ({ history, isOpen }: Props) => {
21
+ const SidebarToggle = ({
22
+ history,
23
+ internalSidebarNavigation,
24
+ internalSidebarNavigationHandler,
25
+ isOpen,
26
+ routerDisabled = false,
27
+ }: Props) => {
28
+ const handleToggleClick = event => {
29
+ event.preventDefault();
30
+
31
+ if (routerDisabled) {
32
+ // Use internal navigation handler when router is disabled
33
+ if (internalSidebarNavigationHandler && internalSidebarNavigation) {
34
+ internalSidebarNavigationHandler({
35
+ ...internalSidebarNavigation,
36
+ open: !isOpen,
37
+ }, true); // Always use replace for toggle
38
+ }
39
+ } else if (history) {
40
+ history.replace({ state: { open: !isOpen } });
41
+ }
42
+ };
43
+
18
44
  return (
19
45
  <SidebarToggleButton
20
46
  data-resin-target={SIDEBAR_NAV_TARGETS.TOGGLE}
21
47
  data-testid="sidebartoggle"
22
48
  // $FlowFixMe
23
49
  isOpen={isOpen}
24
- onClick={event => {
25
- event.preventDefault();
26
- history.replace({ state: { open: !isOpen } });
27
- }}
50
+ onClick={handleToggleClick}
28
51
  />
29
52
  );
30
53
  };
@@ -1,23 +1,87 @@
1
1
  import * as React from 'react';
2
- import { shallow } from 'enzyme/build';
2
+ import { render, screen, userEvent } from '../../../test-utils/testing-library';
3
3
  import { SidebarToggleComponent as SidebarToggle } from '../SidebarToggle';
4
4
 
5
5
  describe('elements/content-sidebar/SidebarToggle', () => {
6
6
  const historyMock = { replace: jest.fn() };
7
- const getWrapper = (props = {}) => shallow(<SidebarToggle history={historyMock} {...props} />);
7
+
8
+ beforeEach(() => {
9
+ jest.clearAllMocks();
10
+ });
11
+
12
+ const renderSidebarToggle = (props = {}) => {
13
+ return render(<SidebarToggle history={historyMock} {...props} />);
14
+ };
8
15
 
9
16
  test.each`
10
- isOpen | location
17
+ isOpen | expectedState
11
18
  ${true} | ${{ state: { open: false } }}
12
19
  ${false} | ${{ state: { open: true } }}
13
- `('should render and handle clicks correctly when isOpen is $isOpen', ({ isOpen, location }) => {
14
- const event = { preventDefault: jest.fn() };
15
- const wrapper = getWrapper({ isOpen });
20
+ `('should render and handle clicks correctly when isOpen is $isOpen', async ({ isOpen, expectedState }) => {
21
+ const user = userEvent();
22
+ renderSidebarToggle({ isOpen });
23
+
24
+ const toggleButton = screen.getByTestId('sidebartoggle');
25
+ expect(toggleButton).toBeInTheDocument();
26
+
27
+ await user.click(toggleButton);
28
+
29
+ expect(historyMock.replace).toHaveBeenCalledWith(expectedState);
30
+ });
31
+ });
16
32
 
17
- wrapper.simulate('click', event);
33
+ describe('elements/content-sidebar/SidebarToggle - Router Disabled', () => {
34
+ const mockInternalSidebarNavigationHandler = jest.fn();
35
+ const defaultProps = {
36
+ routerDisabled: true,
37
+ internalSidebarNavigation: { sidebar: 'activity' },
38
+ internalSidebarNavigationHandler: mockInternalSidebarNavigationHandler,
39
+ };
18
40
 
19
- expect(event.preventDefault).toHaveBeenCalled();
20
- expect(historyMock.replace).toHaveBeenCalledWith(location);
21
- expect(wrapper).toMatchSnapshot();
41
+ beforeEach(() => {
42
+ jest.clearAllMocks();
22
43
  });
44
+
45
+ const renderSidebarToggle = (props = {}) => {
46
+ return render(<SidebarToggle {...defaultProps} {...props} />);
47
+ };
48
+
49
+ test.each`
50
+ isOpen | expectedNavigation
51
+ ${true} | ${{ sidebar: 'activity', open: false }}
52
+ ${false} | ${{ sidebar: 'activity', open: true }}
53
+ `('should handle toggle clicks correctly when isOpen is $isOpen', async ({ isOpen, expectedNavigation }) => {
54
+ const user = userEvent();
55
+ renderSidebarToggle({ isOpen });
56
+
57
+ const toggleButton = screen.getByTestId('sidebartoggle');
58
+ expect(toggleButton).toBeInTheDocument();
59
+ await user.click(toggleButton);
60
+
61
+ expect(mockInternalSidebarNavigationHandler).toHaveBeenCalledWith(expectedNavigation, true);
62
+ });
63
+
64
+ test('should handle complex navigation state correctly', async () => {
65
+ const user = userEvent();
66
+ const complexNavigation = {
67
+ sidebar: 'activity',
68
+ versionId: '123',
69
+ activeFeedEntryType: 'comments',
70
+ activeFeedEntryId: '456',
71
+ };
72
+
73
+ renderSidebarToggle({
74
+ isOpen: true,
75
+ internalSidebarNavigation: complexNavigation,
76
+ });
77
+
78
+ const toggleButton = screen.getByTestId('sidebartoggle');
79
+ await user.click(toggleButton);
80
+
81
+ expect(mockInternalSidebarNavigationHandler).toHaveBeenCalledWith({
82
+ ...complexNavigation,
83
+ open: false,
84
+ }, true);
85
+ });
86
+
23
87
  });
@@ -344,6 +344,19 @@ export const SwitchEditingTemplateInstances: StoryObj<typeof MetadataSidebarRede
344
344
  fileId: '416047501580',
345
345
  metadataSidebarProps: defaultMetadataSidebarProps,
346
346
  },
347
+ parameters: {
348
+ msw: {
349
+ handlers: [
350
+ ...defaultMockHandlers,
351
+ http.get(`/2.0/files/416047501580`, () => {
352
+ return HttpResponse.json(mockFileRequest.response);
353
+ }),
354
+ http.get(`/2.0/files/416047501580/metadata`, () => {
355
+ return HttpResponse.json(mockMetadataInstances.response);
356
+ }),
357
+ ],
358
+ },
359
+ },
347
360
  play: async ({ canvasElement }) => {
348
361
  const canvas = within(canvasElement);
349
362
  // open and edit a new template
@@ -543,7 +556,7 @@ export const SuggestionForNewlyCreatedTemplateInstance: StoryObj<typeof Metadata
543
556
  const autofillButton = await canvas.findByRole('button', { name: 'Autofill' });
544
557
  userEvent.click(autofillButton);
545
558
 
546
- const suggestion = await canvas.findByText('4/1/2024');
559
+ const suggestion = await canvas.findByText('4/1/2024', {}, { timeout: 5000 });
547
560
  expect(suggestion).toBeInTheDocument();
548
561
  },
549
562
  };
@@ -20,6 +20,8 @@ type Props = FlyoutProps & {
20
20
  header?: React.Element<any>,
21
21
  /** Optional function to get the scrollRef in parent components */
22
22
  scrollRefFn?: any => any,
23
+ /** Are OverlayHeader actions enabled */
24
+ isOverlayHeaderActionEnabled?: boolean,
23
25
  };
24
26
 
25
27
  class HeaderFlyout extends React.Component<Props> {
@@ -30,7 +32,16 @@ class HeaderFlyout extends React.Component<Props> {
30
32
  };
31
33
 
32
34
  render() {
33
- const { header, footer, flyoutButton, children, scrollRefFn, className, ...rest } = this.props;
35
+ const {
36
+ header,
37
+ footer,
38
+ flyoutButton,
39
+ children,
40
+ scrollRefFn,
41
+ className,
42
+ isOverlayHeaderActionEnabled = false,
43
+ ...rest
44
+ } = this.props;
34
45
 
35
46
  return (
36
47
  <Flyout
@@ -42,7 +53,9 @@ class HeaderFlyout extends React.Component<Props> {
42
53
  >
43
54
  {flyoutButton}
44
55
  <Overlay className="header-flyout-overlay">
45
- <OverlayHeader>{header && <h4 className="header-flyout-title">{header}</h4>}</OverlayHeader>
56
+ <OverlayHeader isOverlayHeaderActionEnabled={isOverlayHeaderActionEnabled}>
57
+ {header && <h4 className="header-flyout-title">{header}</h4>}
58
+ </OverlayHeader>
46
59
  <div className="header-flyout-list-container">
47
60
  <div
48
61
  className={classNames('flyout-list-container-body', {
@@ -21,7 +21,9 @@ exports[`components/core/header/components/HeaderFlyout render() should include
21
21
  <Overlay
22
22
  className="header-flyout-overlay"
23
23
  >
24
- <OverlayHeader>
24
+ <OverlayHeader
25
+ isOverlayHeaderActionEnabled={false}
26
+ >
25
27
  <h4
26
28
  className="header-flyout-title"
27
29
  >
@@ -78,7 +80,9 @@ exports[`components/core/header/components/HeaderFlyout render() should render d
78
80
  <Overlay
79
81
  className="header-flyout-overlay"
80
82
  >
81
- <OverlayHeader />
83
+ <OverlayHeader
84
+ isOverlayHeaderActionEnabled={false}
85
+ />
82
86
  <div
83
87
  className="header-flyout-list-container"
84
88
  >
@@ -123,7 +127,9 @@ exports[`components/core/header/components/HeaderFlyout render() should render t
123
127
  <Overlay
124
128
  className="header-flyout-overlay"
125
129
  >
126
- <OverlayHeader />
130
+ <OverlayHeader
131
+ isOverlayHeaderActionEnabled={false}
132
+ />
127
133
  <div
128
134
  className="header-flyout-list-container"
129
135
  >