Skip to content

Commit f969170

Browse files
feat(router): withRouterIfEnabled (#4221)
* feat(router): withRouterIfEnabled * feat(router): withRouterIfEnabled - fixed tests made sure history is treated as optional in affected components * feat(router): withRouterIfEnabled - fixes * feat(router): withRouterIfEnabled - fixes * feat(router): withRouterIfEnabled - fixes
1 parent 90ee8fc commit f969170

File tree

7 files changed

+95
-12
lines changed

7 files changed

+95
-12
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// @flow
2+
import * as React from 'react';
3+
import { MemoryRouter } from 'react-router-dom';
4+
import { render } from '../../../../test-utils/testing-library';
5+
import withRouterIfEnabled from '../withRouterIfEnabled';
6+
7+
const TestComponent = (props: any) => {
8+
const { history, location, match, routerDisabled } = props;
9+
return (
10+
<div
11+
data-testid="test-component"
12+
data-router-disabled={routerDisabled ? 'true' : undefined}
13+
data-has-history={history ? 'true' : undefined}
14+
data-has-location={location ? 'true' : undefined}
15+
data-has-match={match ? 'true' : undefined}
16+
/>
17+
);
18+
};
19+
TestComponent.displayName = 'TestComponent';
20+
21+
const WithRouterIfEnabled = withRouterIfEnabled(TestComponent);
22+
23+
test('injects router props when wrapped in a Router', () => {
24+
const { getByTestId } = render(
25+
<MemoryRouter initialEntries={[{ pathname: '/foo' }]}>
26+
<WithRouterIfEnabled />
27+
</MemoryRouter>,
28+
);
29+
30+
const component = getByTestId('test-component');
31+
expect(component).toHaveAttribute('data-has-history', 'true');
32+
expect(component).toHaveAttribute('data-has-location', 'true');
33+
expect(component).toHaveAttribute('data-has-match', 'true');
34+
expect(component).not.toHaveAttribute('data-router-disabled');
35+
});
36+
37+
test('renders without Router and without router props (routerDisabled prop)', () => {
38+
const { getByTestId } = render(<WithRouterIfEnabled routerDisabled />);
39+
const component = getByTestId('test-component');
40+
expect(component).not.toHaveAttribute('data-has-history');
41+
expect(component).not.toHaveAttribute('data-has-location');
42+
expect(component).not.toHaveAttribute('data-has-match');
43+
expect(component).toHaveAttribute('data-router-disabled', 'true');
44+
});
45+
46+
test('renders without Router and without router props (feature flag)', () => {
47+
const features = { routerDisabled: { value: true } };
48+
const { getByTestId } = render(<WithRouterIfEnabled features={features} />);
49+
50+
const component = getByTestId('test-component');
51+
expect(component).not.toHaveAttribute('data-has-history');
52+
expect(component).not.toHaveAttribute('data-has-location');
53+
expect(component).not.toHaveAttribute('data-has-match');
54+
});
55+
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
// eslint-disable-next-line import/prefer-default-export
1+
// @flow
22
export { default as withRouterAndRef } from './withRouterAndRef';
3+
export { default as withRouterIfEnabled } from './withRouterIfEnabled';
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// @flow
2+
import * as React from 'react';
3+
import { withRouter } from 'react-router-dom';
4+
import { isFeatureEnabled } from '../feature-checking';
5+
6+
export default function withRouterIfEnabled(Wrapped: React.ComponentType<any>) {
7+
8+
const WrappedWithRouter = withRouter(Wrapped);
9+
10+
const WithRouterIfEnabled = (props: any) => {
11+
const routerDisabled =
12+
props?.routerDisabled === true || isFeatureEnabled(props?.features, 'routerDisabled.value');
13+
14+
const Component = routerDisabled ? Wrapped : WrappedWithRouter;
15+
16+
return <Component {...props} />;
17+
};
18+
19+
const name = Wrapped.displayName || Wrapped.name || 'Component';
20+
WithRouterIfEnabled.displayName = `withRouterIfEnabled(${name})`;
21+
22+
return WithRouterIfEnabled;
23+
}
24+

src/elements/content-sidebar/AddTaskButton.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @flow
22
import * as React from 'react';
3-
import { withRouter, type RouterHistory } from 'react-router-dom';
3+
import { type RouterHistory } from 'react-router-dom';
4+
import { withRouterIfEnabled } from '../common/routing';
45

56
import AddTaskMenu from './AddTaskMenu';
67
import TaskModal from './TaskModal';
@@ -11,7 +12,7 @@ import type { ElementsXhrError } from '../../common/types/api';
1112
import type { InternalSidebarNavigation, InternalSidebarNavigationHandler } from '../common/types/SidebarNavigation';
1213

1314
type Props = {|
14-
history: RouterHistory,
15+
history?: RouterHistory,
1516
internalSidebarNavigation?: InternalSidebarNavigation,
1617
internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
1718
isDisabled: boolean,
@@ -54,7 +55,7 @@ class AddTaskButton extends React.Component<Props, State> {
5455
},
5556
true,
5657
);
57-
} else {
58+
} else if (history) {
5859
history.replace({ state: { open: true } });
5960
}
6061

@@ -103,4 +104,4 @@ class AddTaskButton extends React.Component<Props, State> {
103104
}
104105

105106
export { AddTaskButton as AddTaskButtonComponent };
106-
export default withRouter(AddTaskButton);
107+
export default withRouterIfEnabled(AddTaskButton);

src/elements/content-sidebar/SidebarToggle.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
*/
66

77
import * as React from 'react';
8-
import { withRouter, type RouterHistory } from 'react-router-dom';
8+
import { type RouterHistory } from 'react-router-dom';
9+
import { withRouterIfEnabled } from '../common/routing';
910
import SidebarToggleButton from '../../components/sidebar-toggle-button/SidebarToggleButton';
1011
import { SIDEBAR_NAV_TARGETS } from '../common/interactionTargets';
1112
import type { InternalSidebarNavigation, InternalSidebarNavigationHandler } from '../common/types/SidebarNavigation';
@@ -53,4 +54,4 @@ const SidebarToggle = ({
5354
};
5455

5556
export { SidebarToggle as SidebarToggleComponent };
56-
export default withRouter(SidebarToggle);
57+
export default withRouterIfEnabled(SidebarToggle);

src/elements/content-sidebar/__tests__/__snapshots__/ActivitySidebar.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ exports[`elements/content-sidebar/ActivitySidebar render() should render the act
44
<SidebarContent
55
actions={
66
<React.Fragment>
7-
<withRouter(AddTaskButton)
7+
<withRouterIfEnabled(AddTaskButton)
88
isDisabled={false}
99
onTaskModalClose={[Function]}
1010
taskFormProps={

src/elements/content-sidebar/versions/VersionsSidebarContainer.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import flow from 'lodash/flow';
99
import getProp from 'lodash/get';
1010
import merge from 'lodash/merge';
1111
import noop from 'lodash/noop';
12-
import { generatePath, withRouter } from 'react-router-dom';
12+
import { generatePath } from 'react-router-dom';
1313
import type { Match, RouterHistory } from 'react-router-dom';
1414
import type { MessageDescriptor } from 'react-intl';
1515
import { withFeatureConsumer, isFeatureEnabled } from '../../common/feature-checking';
@@ -21,6 +21,7 @@ import StaticVersionsSidebar from './StaticVersionSidebar';
2121
import VersionsSidebar from './VersionsSidebar';
2222
import VersionsSidebarAPI from './VersionsSidebarAPI';
2323
import { withAPIContext } from '../../common/api-context';
24+
import { withRouterIfEnabled } from '../../common/routing';
2425
import type { FeatureConfig } from '../../common/feature-checking';
2526
import type { VersionActionCallback, VersionChangeCallback, SidebarLoadCallback } from './flowTypes';
2627
import type { BoxItemVersion, BoxItem, FileVersions } from '../../../common/types/core';
@@ -36,7 +37,7 @@ type Props = {
3637
features: FeatureConfig,
3738
fileId: string,
3839
hasSidebarInitialized?: boolean,
39-
history: RouterHistory,
40+
history?: RouterHistory,
4041
internalSidebarNavigation?: InternalSidebarNavigation,
4142
internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
4243
match: Match,
@@ -283,7 +284,7 @@ class VersionsSidebarContainer extends React.Component<Props, State> {
283284
delete navigationUpdate.versionId;
284285
}
285286
internalSidebarNavigationHandler(navigationUpdate);
286-
} else {
287+
} else if (history) {
287288
history.push(generatePath(match.path, { ...match.params, versionId }));
288289
}
289290
};
@@ -349,4 +350,4 @@ class VersionsSidebarContainer extends React.Component<Props, State> {
349350

350351
export type VersionsSidebarProps = Props;
351352
export { VersionsSidebarContainer as VersionsSidebarContainerComponent };
352-
export default flow([withRouter, withAPIContext, withFeatureConsumer])(VersionsSidebarContainer);
353+
export default flow([withRouterIfEnabled, withAPIContext, withFeatureConsumer])(VersionsSidebarContainer);

0 commit comments

Comments
 (0)