Remove Navigation.UserMenu

This commit is contained in:
Andrew Musgrave
2019-05-29 17:38:23 -04:00
parent 3b3b1337e1
commit 298e6122a4
27 changed files with 86 additions and 734 deletions

View File

@@ -10,7 +10,6 @@ import EventListener from '../EventListener';
import {withAppProvider, WithAppProviderProps} from '../AppProvider';
import Backdrop from '../Backdrop';
import TrapFocus from '../TrapFocus';
import {UserMenuProvider} from '../TopBar';
import {dataPolarisTopBar, layer} from '../shared';
import {setRootProperty} from '../../utilities/setRootProperty';
import {ContextualSaveBarProps, ToastID, ToastPropsWithID} from './types';
@@ -239,10 +238,8 @@ export class Frame extends React.PureComponent<CombinedProps, State> {
{...navigationAttributes}
>
{skipMarkup}
<UserMenuProvider mobileView={mobileView || false}>
{topBarMarkup}
{navigationMarkup}
</UserMenuProvider>
{topBarMarkup}
{navigationMarkup}
{contextualSaveBarMarkup}
{loadingMarkup}
{navigationOverlayMarkup}

View File

@@ -93,15 +93,6 @@ class FrameExample extends React.Component {
},
];
const navigationUserMenuMarkup = (
<Navigation.UserMenu
actions={userMenuActions}
name="Dharma"
detail={storeName}
avatarInitials="D"
/>
);
const contextualSaveBarMarkup = isDirty ? (
<ContextualSaveBar
message="Unsaved changes"
@@ -157,7 +148,7 @@ class FrameExample extends React.Component {
);
const navigationMarkup = (
<Navigation location="/" userMenu={navigationUserMenuMarkup}>
<Navigation location="/">
<Navigation.Section
items={[
{

View File

@@ -13,8 +13,6 @@ import {
ContextualSaveBar as FrameContextualSavebar,
Loading as FrameLoading,
} from '../components';
import TopBar, {UserMenuProvider} from '../../TopBar';
import Navigation from '../../Navigation';
window.matchMedia =
window.matchMedia ||
@@ -218,26 +216,4 @@ describe('<Frame />', () => {
);
expect(frame.find(FrameLoading).exists()).toBe(true);
});
describe('<UserMenuProvider />', () => {
it('renders', () => {
const frame = mountWithAppProvider(<Frame />);
expect(frame.find(UserMenuProvider).exists()).toBe(true);
});
it('receives a mobileView boolean', () => {
const frame = mountWithAppProvider(<Frame />);
expect(frame.find(UserMenuProvider).prop('mobileView')).toBe(false);
});
it('receives the given top bar and navigation as its children', () => {
const topBar = <TopBar />;
const navigation = <Navigation location="" />;
const frame = mountWithAppProvider(
<Frame topBar={topBar} navigation={navigation} />,
);
expect(frame.find(UserMenuProvider).contains(topBar)).toBe(true);
expect(frame.find(UserMenuProvider).contains(navigation)).toBe(true);
});
});
});

View File

@@ -4,7 +4,7 @@ import Scrollable from '../Scrollable';
import WithinContentContext from '../WithinContentContext';
import NavigationContext from './context';
import {UserMenu, Section, Item} from './components';
import {Section, Item} from './components';
import {SectionType} from './types';
import styles from './Navigation.scss';
@@ -13,36 +13,16 @@ export interface Props {
location: string;
sections?: SectionType[];
children?: React.ReactNode;
/** @deprecated Pass a user menu into <TopBar /> instead. */
userMenu?: React.ReactNode;
contextControl?: React.ReactNode;
onDismiss?(): void;
}
export default class Navigation extends React.Component<Props, never> {
static Item = Item;
static UserMenu = UserMenu;
static Section = Section;
constructor(props: Props) {
super(props);
if (props.userMenu) {
// eslint-disable-next-line no-console
console.warn(
'Deprecation: the `userMenu` prop is deprecated and will be removed in the next major version. Pass a user menu into <TopBar /> instead.',
);
}
}
render() {
const {
children,
userMenu,
contextControl,
location,
onDismiss,
} = this.props;
const {children, contextControl, location, onDismiss} = this.props;
const contextControlMarkup = contextControl && (
<div className={styles.ContextControl}>{contextControl}</div>
@@ -58,7 +38,6 @@ export default class Navigation extends React.Component<Props, never> {
<WithinContentContext.Provider value={{withinContentContainer: true}}>
<nav className={styles.Navigation}>
{contextControlMarkup}
<div className={styles.UserMenu}>{userMenu}</div>
<Scrollable className={styles.PrimaryNavigation}>
{children}
</Scrollable>

View File

@@ -165,18 +165,6 @@ Action allows a complementary icon-only action to render next to the section tit
---
<a name="subcomponent-usermenu"></a>
## Navigation user menu
The user menu component displays the current users avatar and name, and actions that are related to the current logged in user. The menu is displayed at the top of the navigation sidebar at small screen sizes. The user menu can display any messages that the current user has available to read.
### Deprecation rationale
As of release 3.6.0 `Navigation.UserMenu` is deprecated in favor of [`TopBar.UserMenu`](https://polaris.shopify.com/components/structure/top-bar#top-bar-menu) which will stay visible on mobile.
---
## Examples
### Basic navigation

View File

@@ -1,70 +0,0 @@
import React from 'react';
import {UserMenuModifier} from '../../../TopBar';
import {IconableAction} from '../../../../types';
import {Props as MessageProps} from '../Message';
import {Props as AvatarProps} from '../../../Avatar';
interface UserActionSection {
id: string;
items: IconableAction[];
}
export interface Props {
name?: string;
detail?: string;
actions?: UserActionSection[];
message?: MessageProps;
avatarInitials: AvatarProps['initials'];
avatarSource?: AvatarProps['source'];
}
interface State {
open: boolean;
}
/** @deprecated Use <TopBar.UserMenu /> instead. */
class UserMenu extends React.Component<Props, State> {
state: State = {
open: false,
};
constructor(props: Props) {
super(props);
// eslint-disable-next-line no-console
console.warn(
'Deprecation: <Navigation.UserMenu /> is deprecated and will be removed in the next major version. Use <TopBar.UserMenu /> instead.',
);
}
render() {
const {
name,
detail,
actions,
message,
avatarInitials,
avatarSource,
} = this.props;
const {open} = this.state;
const userMenuProps = {
actions: actions || [],
message,
name: name || '',
detail,
initials: avatarInitials,
avatar: avatarSource,
onToggle: this.handleToggle,
open,
};
return <UserMenuModifier userMenuProps={userMenuProps} />;
}
private handleToggle = () => {
const {open} = this.state;
this.setState({open: !open});
};
}
export default UserMenu;

View File

@@ -1,5 +0,0 @@
import UserMenu from './UserMenu';
export {Props} from './UserMenu';
export default UserMenu;

View File

@@ -1,104 +0,0 @@
import React from 'react';
import {mountWithAppProvider, trigger} from 'test-utilities';
import {UserMenuModifier} from '../../../../TopBar';
import UserMenu, {Props as UserMenuProps} from '../UserMenu';
describe('<UserMenu />', () => {
const mockProps = {
avatarInitials: '',
avatarSource: '',
};
describe('avatarInitials', () => {
it('gets passed into the modifier', () => {
const avatarInitials = 'JD';
const userMenu = mountWithAppProvider(
<UserMenu {...mockProps} avatarInitials={avatarInitials} />,
);
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({initials: avatarInitials}));
});
});
describe('avatarSource', () => {
it('gets passed into the modifier', () => {
const avatarSource = '';
const userMenu = mountWithAppProvider(
<UserMenu {...mockProps} avatarSource={avatarSource} />,
);
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({avatar: avatarSource}));
});
});
describe('message', () => {
it('gets passed into the modifier', () => {
const message = {} as UserMenuProps['message'];
const userMenu = mountWithAppProvider(
<UserMenu {...mockProps} message={message} />,
);
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({message}));
});
});
describe('actions', () => {
it('gets passed into the modifier', () => {
const actions = [] as UserMenuProps['actions'];
const userMenu = mountWithAppProvider(
<UserMenu {...mockProps} actions={actions} />,
);
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({actions}));
});
});
describe('detail', () => {
it('gets passed into the modifier', () => {
const detail = 'Little Victories CA';
const userMenu = mountWithAppProvider(
<UserMenu {...mockProps} detail={detail} />,
);
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({detail}));
});
});
describe('name', () => {
it('gets passed into the modifier', () => {
const name = 'John Doe';
const userMenu = mountWithAppProvider(
<UserMenu {...mockProps} name={name} />,
);
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({name}));
});
});
describe('<UserMenuModifier />', () => {
it('passes in an open prop which is false by default', () => {
const userMenu = mountWithAppProvider(<UserMenu {...mockProps} />);
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({open: false}));
});
it('toggles the open prop when the user menu is toggled', () => {
const userMenu = mountWithAppProvider(<UserMenu {...mockProps} />);
trigger(userMenu.find(UserMenuModifier), 'userMenuProps.onToggle');
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({open: true}));
trigger(userMenu.find(UserMenuModifier), 'userMenuProps.onToggle');
expect(
userMenu.find(UserMenuModifier).prop('userMenuProps'),
).toStrictEqual(expect.objectContaining({open: false}));
});
});
});

View File

@@ -1,4 +1,3 @@
export {default as Section, Props as SectionProps} from './Section';
export {default as Item, Props as ItemProps} from './Item';
export {default as Message, Props as MessageProps} from './Message';
export {default as UserMenu, Props as UserMenuProps} from './UserMenu';

View File

@@ -2,7 +2,6 @@ import React from 'react';
import {mountWithAppProvider} from 'test-utilities';
import Navigation from '../Navigation';
import NavigationContext from '../context';
import {UserMenu} from '../components';
import WithinContentContext from '../../WithinContentContext';
describe('<Navigation />', () => {
@@ -58,16 +57,6 @@ describe('<Navigation />', () => {
});
});
describe('userMenu', () => {
it('renders the given user menu', () => {
const userMenu = <UserMenu avatarInitials="" />;
const navigation = mountWithAppProvider(
<Navigation location="/" userMenu={userMenu} />,
);
expect(navigation.contains(userMenu)).toBeTruthy();
});
});
describe('contextControl', () => {
it('doesnt render by default', () => {
const contextControl = <div />;

View File

@@ -1,21 +1,68 @@
import React from 'react';
import withContext from '../../../WithContext';
import {WithContextTypes} from '../../../../types';
import {Consumer as UserMenuConsumer, UserMenuContextTypes} from './context';
import {UserMenu as UserMenuComponent, UserMenuProps} from './components';
import {IconableAction} from '../../../../types';
import Avatar, {Props as AvatarProps} from '../../../Avatar';
import MessageIndicator from '../../../MessageIndicator';
import Menu, {MessageProps} from '../Menu';
type ComposedProps = UserMenuProps & WithContextTypes<UserMenuContextTypes>;
import styles from './UserMenu.scss';
function UserMenu({
context: {mobileUserMenuProps, mobileView},
...userMenuProps
}: ComposedProps) {
if (mobileUserMenuProps && mobileView) {
return <UserMenuComponent {...mobileUserMenuProps} />;
}
return <UserMenuComponent {...userMenuProps} />;
export interface Props {
/** An array of action objects that are rendered inside of a popover triggered by this menu */
actions: {items: IconableAction[]}[];
/** Accepts a message that facilitates direct, urgent communication with the merchant through the user menu */
message?: MessageProps;
/** A string detailing the merchants full name to be displayed in the user menu */
name: string;
/** A string allowing further details on the merchants name displayed in the user menu */
detail?: string;
/** The merchants initials, rendered in place of an avatar image when not provided */
initials: AvatarProps['initials'];
/** An avatar image representing the merchant */
avatar?: AvatarProps['source'];
/** A boolean property indicating whether the user menu is currently open */
open: boolean;
/** A callback function to handle opening and closing the user menu */
onToggle(): void;
}
export default withContext<UserMenuProps, {}, UserMenuContextTypes>(
UserMenuConsumer,
)(UserMenu);
function UserMenu({
name,
detail,
avatar,
initials,
actions,
message,
onToggle,
open,
}: Props) {
const showIndicator = Boolean(message);
const activatorContentMarkup = (
<React.Fragment>
<MessageIndicator active={showIndicator}>
<Avatar
size="small"
source={avatar}
initials={initials && initials.replace(' ', '')}
/>
</MessageIndicator>
<span className={styles.Details}>
<p className={styles.Name}>{name}</p>
<p className={styles.Detail}>{detail}</p>
</span>
</React.Fragment>
);
return (
<Menu
activatorContent={activatorContentMarkup}
open={open}
onOpen={onToggle}
onClose={onToggle}
actions={actions}
message={message}
/>
);
}
export default UserMenu;

View File

@@ -1,67 +0,0 @@
import React from 'react';
import {IconableAction} from '../../../../../../types';
import Avatar, {Props as AvatarProps} from '../../../../../Avatar';
import MessageIndicator from '../../../../../MessageIndicator';
import Menu, {MessageProps} from '../../../Menu';
import styles from './UserMenu.scss';
export interface Props {
/** An array of action objects that are rendered inside of a popover triggered by this menu */
actions: {items: IconableAction[]}[];
/** Accepts a message that facilitates direct, urgent communication with the merchant through the user menu */
message?: MessageProps;
/** A string detailing the merchants full name to be displayed in the user menu */
name: string;
/** A string allowing further details on the merchants name displayed in the user menu */
detail?: string;
/** The merchants initials, rendered in place of an avatar image when not provided */
initials: AvatarProps['initials'];
/** An avatar image representing the merchant */
avatar?: AvatarProps['source'];
/** A boolean property indicating whether the user menu is currently open */
open: boolean;
/** A callback function to handle opening and closing the user menu */
onToggle(): void;
}
function UserMenu({
name,
detail,
avatar,
initials,
actions,
message,
onToggle,
open,
}: Props) {
const showIndicator = Boolean(message);
const activatorContentMarkup = (
<React.Fragment>
<MessageIndicator active={showIndicator}>
<Avatar
size="small"
source={avatar}
initials={initials && initials.replace(' ', '')}
/>
</MessageIndicator>
<span className={styles.Details}>
<p className={styles.Name}>{name}</p>
<p className={styles.Detail}>{detail}</p>
</span>
</React.Fragment>
);
return (
<Menu
activatorContent={activatorContentMarkup}
open={open}
onOpen={onToggle}
onClose={onToggle}
actions={actions}
message={message}
/>
);
}
export default UserMenu;

View File

@@ -1 +0,0 @@
export {default, Props} from './UserMenu';

View File

@@ -1,76 +0,0 @@
import React from 'react';
import {NotificationMajorMonotone} from '@shopify/polaris-icons';
import {ReactWrapper} from 'enzyme';
import {mountWithAppProvider} from 'test-utilities';
import Menu from '../../../../Menu';
import UserMenu from '../UserMenu';
const actions = [{items: [{icon: NotificationMajorMonotone, onAction: noop}]}];
const message = {
title: 'test message',
description: 'test description',
link: {to: '/', content: 'Home'},
action: {
onClick: noop,
content: 'New',
},
badge: {
content: 'flashy new home card',
status: 'new' as 'new',
},
};
const userProps = {
actions,
name: 'Andrew Musgrave',
detail: 'FED',
initials: 'am',
open: true,
onToggle: noop,
message,
};
describe('<UserMenu />', () => {
it('mounts', () => {
const user = mountWithAppProvider(<UserMenu {...userProps} />);
expect(user).toBeTruthy();
});
it('constructs activatorContent and passes it down to menu', () => {
const user = mountWithAppProvider(<UserMenu {...userProps} />);
expect(returnMenuProp(user, 'activatorContent')).toBeTruthy();
});
it('passes the open prop down to menu', () => {
const user = mountWithAppProvider(<UserMenu {...userProps} />);
expect(returnMenuProp(user, 'open')).toBe(true);
});
it('passes the actions prop down to menu', () => {
const user = mountWithAppProvider(<UserMenu {...userProps} />);
expect(returnMenuProp(user, 'actions')).toBe(actions);
});
it('passes the message prop down to menu', () => {
const user = mountWithAppProvider(<UserMenu {...userProps} />);
expect(returnMenuProp(user, 'message')).toBe(message);
});
describe('onToggle', () => {
it('passes the onToggle prop down to menu as onOpen', () => {
const user = mountWithAppProvider(<UserMenu {...userProps} />);
expect(returnMenuProp(user, 'onOpen')).toBe(noop);
});
it('passes the onToggle prop down to menu as onClose', () => {
const user = mountWithAppProvider(<UserMenu {...userProps} />);
expect(returnMenuProp(user, 'onClose')).toBe(noop);
});
});
});
function noop() {}
function returnMenuProp(wrapper: ReactWrapper, prop: string) {
return wrapper.find(Menu).prop(prop);
}

View File

@@ -1 +0,0 @@
export {default as UserMenu, Props as UserMenuProps} from './UserMenu';

View File

@@ -1,6 +0,0 @@
// Variable prefixed with underscore to prevent unused variable error.
// More info here: https://github.com/Shopify/polaris-react/pull/938
import * as _React from 'react';
import UserMenuContext from './context';
export default UserMenuContext.Consumer;

View File

@@ -1,32 +0,0 @@
import React from 'react';
import withContext from '../../../../WithContext';
import {WithContextTypes} from '../../../../../types';
import {UserMenuProps} from '../components';
import Consumer from './Consumer';
import {UserMenuContextTypes} from './context';
interface Props {
userMenuProps: UserMenuProps;
}
type ComposedProps = Props & WithContextTypes<UserMenuContextTypes>;
class Modifier extends React.Component<ComposedProps, {}> {
static getDerivedStateFromProps({
context: {setMobileUserMenuProps},
userMenuProps,
}: ComposedProps) {
if (setMobileUserMenuProps) {
setMobileUserMenuProps(userMenuProps);
}
return null;
}
state: {} = {};
render() {
return null;
}
}
export default withContext<Props, {}, UserMenuContextTypes>(Consumer)(Modifier);

View File

@@ -1,54 +0,0 @@
import React from 'react';
import isEqual from 'lodash/isEqual';
import {UserMenuProps} from '../components';
import UserMenuContext, {UserMenuContextTypes} from './context';
interface Props {
mobileView: boolean;
children: React.ReactNode;
}
class Provider extends React.Component<Props, UserMenuContextTypes> {
static getDerivedStateFromProps(
{mobileView: nextMobileView}: Props,
{mobileView}: UserMenuContextTypes,
) {
if (nextMobileView !== mobileView) {
return {mobileView: nextMobileView};
}
return null;
}
constructor(props: Props) {
super(props);
this.setMobileUserMenuProps = this.setMobileUserMenuProps.bind(this);
this.state = {
// eslint-disable-next-line react/no-unused-state
mobileView: props.mobileView,
mobileUserMenuProps: undefined,
// eslint-disable-next-line react/no-unused-state
setMobileUserMenuProps: this.setMobileUserMenuProps,
};
}
render() {
const {state} = this;
const {children} = this.props;
return (
<UserMenuContext.Provider value={state}>
{children}
</UserMenuContext.Provider>
);
}
private setMobileUserMenuProps(mobileUserMenuProps: UserMenuProps) {
const {mobileUserMenuProps: prevMobileUserMenuProps} = this.state;
if (isEqual(mobileUserMenuProps, prevMobileUserMenuProps)) {
return;
}
this.setState({mobileUserMenuProps});
}
}
export default Provider;

View File

@@ -1,10 +0,0 @@
import React from 'react';
import {UserMenuProps} from '../components';
export interface UserMenuContextTypes {
mobileView?: boolean;
mobileUserMenuProps?: UserMenuProps;
setMobileUserMenuProps?(props: UserMenuProps): void;
}
export default React.createContext<UserMenuContextTypes>({});

View File

@@ -1,4 +0,0 @@
export {default as Provider} from './Provider';
export {default as Consumer} from './Consumer';
export {default as Modifier} from './Modifier';
export {default as UserMenuContext, UserMenuContextTypes} from './context';

View File

@@ -1,34 +0,0 @@
import React from 'react';
import {ViewMinor} from '@shopify/polaris-icons';
import {mountWithAppProvider} from 'test-utilities';
import {UserMenuProps} from '../../components';
import UserMenuContext from '../context';
import Modifier from '../Modifier';
describe('<Modifier />', () => {
const userMenuProps: UserMenuProps = {
actions: [{items: [{icon: ViewMinor}]}],
name: '',
initials: '',
open: false,
onToggle: noop,
};
describe('userMenuProps', () => {
it('sets the mobile user menu props', () => {
const setMobileUserMenuPropsSpy = jest.fn();
mountWithAppProvider(
<UserMenuContext.Provider
value={{
setMobileUserMenuProps: setMobileUserMenuPropsSpy,
}}
>
<Modifier userMenuProps={userMenuProps} />
</UserMenuContext.Provider>,
);
expect(setMobileUserMenuPropsSpy).toHaveBeenCalledWith(userMenuProps);
});
});
});
function noop() {}

View File

@@ -1,78 +0,0 @@
import React from 'react';
import {mountWithAppProvider, trigger} from 'test-utilities';
import UserMenuContext from '../context';
import Provider from '../Provider';
jest.mock('../context', () => ({
Provider: ({children}: {children: React.ReactNode}) => children,
}));
describe('<Provider />', () => {
const mockProps = {
mobileView: false,
children: null,
};
describe('mobileView', () => {
it('gets passed into the context provider', () => {
const mobileView = true;
const provider = mountWithAppProvider(
<Provider {...mockProps} mobileView={mobileView} />,
);
expect(
provider.find(UserMenuContext.Provider).prop('value'),
).toStrictEqual(
expect.objectContaining({
mobileView,
}),
);
});
it('updates the context provider when it changes', () => {
const mobileView = true;
const newMobileView = false;
const provider = mountWithAppProvider(
<Provider {...mockProps} mobileView={mobileView} />,
);
provider.setProps({mobileView: newMobileView});
expect(
provider.find(UserMenuContext.Provider).prop('value'),
).toStrictEqual(
expect.objectContaining({
mobileView: newMobileView,
}),
);
});
});
describe('children', () => {
it('get passed into the context provider', () => {
const children = <div />;
const provider = mountWithAppProvider(
<Provider {...mockProps}>{children}</Provider>,
);
expect(
provider.find(UserMenuContext.Provider).contains(children),
).toBeTruthy();
});
});
describe('<UserMenuContext.Provider />', () => {
it('receives updated menu props when setMobileUserMenuProps is called', () => {
const newUserMenuProps = {initials: 'JD'};
const provider = mountWithAppProvider(<Provider {...mockProps} />);
trigger(
provider.find(UserMenuContext.Provider),
'value.setMobileUserMenuProps',
newUserMenuProps,
);
expect(
provider.find(UserMenuContext.Provider).prop('value'),
).toStrictEqual(
expect.objectContaining({
mobileUserMenuProps: newUserMenuProps,
}),
);
});
});
});

View File

@@ -1,5 +1,4 @@
import UserMenu from './UserMenu';
export {UserMenuProps as Props} from './components';
export {Provider, Modifier} from './context';
export {Props} from './UserMenu';
export default UserMenu;

View File

@@ -1,85 +1,25 @@
import React from 'react';
import {ViewMinor} from '@shopify/polaris-icons';
import {mountWithAppProvider} from 'test-utilities';
import {UserMenuContext} from '../context';
import {UserMenu as UserMenuComponent, UserMenuProps} from '../components';
import UserMenu from '../UserMenu';
import UserMenu, {Props} from '../UserMenu';
describe('<UserMenu />', () => {
describe('<UserMenuConsumer />', () => {
const userMenuProps: UserMenuProps = {
actions: [{items: [{icon: ViewMinor}]}],
name: '',
initials: '',
open: false,
onToggle: noop,
};
const userMenuProps: Props = {
actions: [{items: [{icon: ViewMinor}]}],
name: '',
initials: '',
open: false,
onToggle: noop,
};
it('renders with the given props', () => {
const userMenu = mountWithAppProvider(
<UserMenuContext.Provider
value={{
mobileView: false,
mobileUserMenuProps: undefined,
}}
>
<UserMenu {...userMenuProps} />
</UserMenuContext.Provider>,
);
expect(userMenu.find(UserMenuComponent).props()).toStrictEqual(
userMenuProps,
);
});
it('renders with the given props', () => {
const userMenu = mountWithAppProvider(<UserMenu {...userMenuProps} />);
expect(userMenu.find(UserMenu).props()).toStrictEqual(userMenuProps);
});
it('renders with the given props when in mobile view but no mobile props are available', () => {
const userMenu = mountWithAppProvider(
<UserMenuContext.Provider
value={{
mobileView: true,
mobileUserMenuProps: undefined,
}}
>
<UserMenu {...userMenuProps} />
</UserMenuContext.Provider>,
);
expect(userMenu.find(UserMenuComponent).props()).toStrictEqual(
userMenuProps,
);
});
it('renders with the given props when mobile props are available but not in mobile view', () => {
const mobileUserMenuProps = {...userMenuProps, initials: 'JD'};
const userMenu = mountWithAppProvider(
<UserMenuContext.Provider
value={{
mobileView: false,
mobileUserMenuProps,
}}
>
<UserMenu {...userMenuProps} />
</UserMenuContext.Provider>,
);
expect(userMenu.find(UserMenuComponent).props()).toStrictEqual(
userMenuProps,
);
});
it('renders with the mobile props when available and in mobile view', () => {
const mobileUserMenuProps = {...userMenuProps, initials: 'JD'};
const userMenu = mountWithAppProvider(
<UserMenuContext.Provider
value={{
mobileView: true,
mobileUserMenuProps,
}}
>
<UserMenu {...userMenuProps} />
</UserMenuContext.Provider>,
);
expect(userMenu.find(UserMenuComponent).props()).toStrictEqual(
mobileUserMenuProps,
);
});
it('renders with the given props when in mobile view but no mobile props are available', () => {
const userMenu = mountWithAppProvider(<UserMenu {...userMenuProps} />);
expect(userMenu.find(UserMenu).props()).toStrictEqual(userMenuProps);
});
});

View File

@@ -1,10 +1,5 @@
export {default as Search, Props as SearchProps} from './Search';
export {default as SearchField, Props as SearchFieldProps} from './SearchField';
export {
default as UserMenu,
Props as UserProps,
Provider as UserMenuProvider,
Modifier as UserMenuModifier,
} from './UserMenu';
export {default as UserMenu, Props as UserProps} from './UserMenu';
export {default as Menu, Props as MenuProps} from './Menu';
export {MessageProps} from './Menu/components';

View File

@@ -1,11 +1,5 @@
import TopBar from './TopBar';
export {Props} from './TopBar';
export {
UserProps,
SearchFieldProps,
MessageProps,
UserMenuModifier,
UserMenuProvider,
} from './components';
export {UserProps, SearchFieldProps, MessageProps} from './components';
export default TopBar;