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.
- package/dist/explorer.js +1 -1
- package/dist/preview.js +1 -1
- package/dist/sidebar.js +1 -1
- package/es/components/flyout/OverlayHeader.js +6 -3
- package/es/components/flyout/OverlayHeader.js.map +1 -1
- package/es/elements/common/nav-router/NavRouter.js +7 -3
- package/es/elements/common/nav-router/NavRouter.js.flow +10 -1
- package/es/elements/common/nav-router/NavRouter.js.map +1 -1
- package/es/elements/common/nav-router/types.js.map +1 -1
- package/es/elements/common/nav-router/withNavRouter.js +10 -1
- package/es/elements/common/nav-router/withNavRouter.js.flow +5 -0
- package/es/elements/common/nav-router/withNavRouter.js.map +1 -1
- package/es/elements/common/routing/withRouterAndRef.js +17 -3
- package/es/elements/common/routing/withRouterAndRef.js.flow +11 -3
- package/es/elements/common/routing/withRouterAndRef.js.map +1 -1
- package/es/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js +22 -13
- package/es/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js.flow +30 -17
- package/es/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js.map +1 -1
- package/es/elements/content-sidebar/ContentSidebar.js +3 -1
- package/es/elements/content-sidebar/ContentSidebar.js.flow +2 -1
- package/es/elements/content-sidebar/ContentSidebar.js.map +1 -1
- package/es/elements/content-sidebar/SidebarToggle.js +27 -9
- package/es/elements/content-sidebar/SidebarToggle.js.flow +29 -6
- package/es/elements/content-sidebar/SidebarToggle.js.map +1 -1
- package/es/elements/content-sidebar/stories/tests/MetadataSidebarRedesign-visual.stories.js +12 -1
- package/es/elements/content-sidebar/stories/tests/MetadataSidebarRedesign-visual.stories.js.map +1 -1
- package/es/features/header-flyout/HeaderFlyout.js +6 -3
- package/es/features/header-flyout/HeaderFlyout.js.flow +15 -2
- package/es/features/header-flyout/HeaderFlyout.js.map +1 -1
- package/es/src/components/flyout/OverlayHeader.d.ts +3 -1
- package/es/src/elements/common/nav-router/NavRouter.d.ts +3 -1
- package/es/src/elements/common/nav-router/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/flyout/OverlayHeader.tsx +7 -3
- package/src/components/flyout/__tests__/OverlayHeader.test.js +25 -0
- package/src/elements/common/nav-router/NavRouter.js.flow +10 -1
- package/src/elements/common/nav-router/NavRouter.tsx +9 -3
- package/src/elements/common/nav-router/__tests__/withNavRouter.test.tsx +34 -20
- package/src/elements/common/nav-router/types.ts +2 -0
- package/src/elements/common/nav-router/withNavRouter.js.flow +5 -0
- package/src/elements/common/nav-router/withNavRouter.tsx +9 -1
- package/src/elements/common/routing/__tests__/withRouterAndRef.test.js +64 -12
- package/src/elements/common/routing/withRouterAndRef.js +11 -3
- package/src/elements/content-explorer/stories/tests/ContentExplorer-visual.stories.js +30 -17
- package/src/elements/content-sidebar/ContentSidebar.js +2 -1
- package/src/elements/content-sidebar/SidebarToggle.js +29 -6
- package/src/elements/content-sidebar/__tests__/SidebarToggle.test.js +74 -10
- package/src/elements/content-sidebar/stories/tests/MetadataSidebarRedesign-visual.stories.tsx +14 -1
- package/src/features/header-flyout/HeaderFlyout.js +15 -2
- package/src/features/header-flyout/__tests__/__snapshots__/HeaderFlyout.test.js.snap +9 -3
- 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 {
|
|
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
|
|
18
|
+
const renderComponent = (props?: Props & WithNavRouterProps) =>
|
|
19
|
+
render(<WrappedComponent {...props} />);
|
|
17
20
|
|
|
18
21
|
test('should wrap component with NavRouter', () => {
|
|
19
|
-
const
|
|
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
|
-
|
|
22
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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
|
});
|
|
@@ -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 {
|
|
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) =>
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
|
14
|
+
history?: RouterHistory,
|
|
15
|
+
internalSidebarNavigation?: InternalSidebarNavigation,
|
|
16
|
+
internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
|
|
14
17
|
isOpen?: boolean,
|
|
18
|
+
routerDisabled?: boolean,
|
|
15
19
|
};
|
|
16
20
|
|
|
17
|
-
const SidebarToggle = ({
|
|
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={
|
|
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 {
|
|
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
|
-
|
|
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 |
|
|
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,
|
|
14
|
-
const
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
20
|
-
|
|
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
|
});
|
package/src/elements/content-sidebar/stories/tests/MetadataSidebarRedesign-visual.stories.tsx
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
>
|