mirror of
https://github.com/apache/superset.git
synced 2026-04-20 08:34:37 +00:00
refactor(Menu): Upgrade Menu Component to Ant Design 5 (#31699)
Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
This commit is contained in:
@@ -17,28 +17,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { KeyboardEvent, ReactElement } from 'react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
import { FeatureFlag, VizType } from '@superset-ui/core';
|
||||
import mockState from 'spec/fixtures/mockState';
|
||||
import { Menu } from 'src/components/Menu';
|
||||
import SliceHeaderControls from '.';
|
||||
import { SliceHeaderControlsProps } from './types';
|
||||
import { handleDropdownNavigation } from './utils';
|
||||
import SliceHeaderControls, { SliceHeaderControlsProps } from '.';
|
||||
|
||||
jest.mock('src/components/Dropdown', () => {
|
||||
const original = jest.requireActual('src/components/Dropdown');
|
||||
return {
|
||||
...original,
|
||||
NoAnimationDropdown: (props: any) => (
|
||||
<div data-test="NoAnimationDropdown" className="ant-dropdown">
|
||||
{props.overlay}
|
||||
{props.children}
|
||||
</div>
|
||||
),
|
||||
};
|
||||
});
|
||||
const SLICE_ID = 371;
|
||||
|
||||
const createProps = (viz_type = VizType.Sunburst) =>
|
||||
({
|
||||
@@ -54,7 +39,7 @@ const createProps = (viz_type = VizType.Sunburst) =>
|
||||
toggleExpandSlice: jest.fn(),
|
||||
logEvent: jest.fn(),
|
||||
slice: {
|
||||
slice_id: 371,
|
||||
slice_id: SLICE_ID,
|
||||
slice_url: '/explore/?form_data=%7B%22slice_id%22%3A%20371%7D',
|
||||
slice_name: 'Vaccine Candidates per Country & Stage',
|
||||
slice_description: 'Table of vaccine candidates for 100 countries',
|
||||
@@ -73,7 +58,7 @@ const createProps = (viz_type = VizType.Sunburst) =>
|
||||
secondary_metric: 'metrics',
|
||||
},
|
||||
row_limit: 10000,
|
||||
slice_id: 371,
|
||||
slice_id: SLICE_ID,
|
||||
time_range: 'No filter',
|
||||
url_params: {},
|
||||
viz_type,
|
||||
@@ -104,6 +89,7 @@ const createProps = (viz_type = VizType.Sunburst) =>
|
||||
viz_type: VizType.Sunburst,
|
||||
},
|
||||
exploreUrl: '/explore',
|
||||
defaultOpen: true,
|
||||
}) as SliceHeaderControlsProps;
|
||||
|
||||
const renderWrapper = (
|
||||
@@ -131,7 +117,7 @@ test('Should render', () => {
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'More Options' }),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByTestId('NoAnimationDropdown')).toBeInTheDocument();
|
||||
expect(screen.getByTestId(`slice_${SLICE_ID}-menu`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Should render default props', () => {
|
||||
@@ -157,27 +143,17 @@ test('Should render default props', () => {
|
||||
delete props.isExpanded;
|
||||
|
||||
renderWrapper(props);
|
||||
expect(
|
||||
screen.getByRole('menuitem', { name: 'Enter fullscreen' }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('menuitem', { name: /Force refresh/ }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('menuitem', { name: 'Show chart description' }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('menuitem', { name: 'Edit chart' }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('menuitem', { name: 'Download' }),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByRole('menuitem', { name: 'Share' })).toBeInTheDocument();
|
||||
expect(screen.getByText('Enter fullscreen')).toBeInTheDocument();
|
||||
expect(screen.getByText('Force refresh')).toBeInTheDocument();
|
||||
expect(screen.getByText('Show chart description')).toBeInTheDocument();
|
||||
expect(screen.getByText('Edit chart')).toBeInTheDocument();
|
||||
expect(screen.getByText('Download')).toBeInTheDocument();
|
||||
expect(screen.getByText('Share')).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'More Options' }),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByTestId('NoAnimationDropdown')).toBeInTheDocument();
|
||||
expect(screen.getByTestId(`slice_${SLICE_ID}-menu`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Should "export to CSV"', async () => {
|
||||
@@ -449,168 +425,3 @@ test('Should not show the "Edit chart" button', () => {
|
||||
});
|
||||
expect(screen.queryByText('Edit chart')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('handleDropdownNavigation', () => {
|
||||
const mockToggleDropdown = jest.fn();
|
||||
const mockSetSelectedKeys = jest.fn();
|
||||
const mockSetOpenKeys = jest.fn();
|
||||
|
||||
const menu = (
|
||||
<Menu selectedKeys={['item1']}>
|
||||
<Menu.Item key="item1">Item 1</Menu.Item>
|
||||
<Menu.Item key="item2">Item 2</Menu.Item>
|
||||
<Menu.Item key="item3">Item 3</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should continue with system tab navigation if dropdown is closed and tab key is pressed', () => {
|
||||
const event = {
|
||||
key: 'Tab',
|
||||
preventDefault: jest.fn(),
|
||||
} as unknown as KeyboardEvent<HTMLDivElement>;
|
||||
|
||||
handleDropdownNavigation(
|
||||
event,
|
||||
false,
|
||||
<div />,
|
||||
mockToggleDropdown,
|
||||
mockSetSelectedKeys,
|
||||
mockSetOpenKeys,
|
||||
);
|
||||
expect(mockToggleDropdown).not.toHaveBeenCalled();
|
||||
expect(mockSetSelectedKeys).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should prevent default behavior and toggle dropdown if dropdown
|
||||
is closed and action key is pressed`, () => {
|
||||
const event = {
|
||||
key: 'Enter',
|
||||
preventDefault: jest.fn(),
|
||||
} as unknown as KeyboardEvent<HTMLDivElement>;
|
||||
|
||||
handleDropdownNavigation(
|
||||
event,
|
||||
false,
|
||||
<div />,
|
||||
mockToggleDropdown,
|
||||
mockSetSelectedKeys,
|
||||
mockSetOpenKeys,
|
||||
);
|
||||
expect(mockToggleDropdown).toHaveBeenCalled();
|
||||
expect(mockSetSelectedKeys).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should trigger menu item click,
|
||||
clear selected keys, close dropdown, and focus on menu trigger
|
||||
if action key is pressed and menu item is selected`, () => {
|
||||
const event = {
|
||||
key: 'Enter',
|
||||
preventDefault: jest.fn(),
|
||||
currentTarget: { focus: jest.fn() },
|
||||
} as unknown as KeyboardEvent<HTMLDivElement>;
|
||||
|
||||
handleDropdownNavigation(
|
||||
event,
|
||||
true,
|
||||
menu,
|
||||
mockToggleDropdown,
|
||||
mockSetSelectedKeys,
|
||||
mockSetOpenKeys,
|
||||
);
|
||||
expect(mockToggleDropdown).toHaveBeenCalled();
|
||||
expect(mockSetSelectedKeys).toHaveBeenCalledWith([]);
|
||||
expect(event.currentTarget.focus).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should select the next menu item if down arrow key is pressed', () => {
|
||||
const event = {
|
||||
key: 'ArrowDown',
|
||||
preventDefault: jest.fn(),
|
||||
} as unknown as KeyboardEvent<HTMLDivElement>;
|
||||
|
||||
handleDropdownNavigation(
|
||||
event,
|
||||
true,
|
||||
menu,
|
||||
mockToggleDropdown,
|
||||
mockSetSelectedKeys,
|
||||
mockSetOpenKeys,
|
||||
);
|
||||
expect(mockSetSelectedKeys).toHaveBeenCalledWith(['item2']);
|
||||
});
|
||||
|
||||
test('should select the previous menu item if up arrow key is pressed', () => {
|
||||
const event = {
|
||||
key: 'ArrowUp',
|
||||
preventDefault: jest.fn(),
|
||||
} as unknown as KeyboardEvent<HTMLDivElement>;
|
||||
|
||||
handleDropdownNavigation(
|
||||
event,
|
||||
true,
|
||||
menu,
|
||||
mockToggleDropdown,
|
||||
mockSetSelectedKeys,
|
||||
mockSetOpenKeys,
|
||||
);
|
||||
expect(mockSetSelectedKeys).toHaveBeenCalledWith(['item1']);
|
||||
});
|
||||
|
||||
test('should close dropdown menu if escape key is pressed', () => {
|
||||
const event = {
|
||||
key: 'Escape',
|
||||
preventDefault: jest.fn(),
|
||||
} as unknown as KeyboardEvent<HTMLDivElement>;
|
||||
|
||||
handleDropdownNavigation(
|
||||
event,
|
||||
true,
|
||||
<div />,
|
||||
mockToggleDropdown,
|
||||
mockSetSelectedKeys,
|
||||
mockSetOpenKeys,
|
||||
);
|
||||
expect(mockToggleDropdown).toHaveBeenCalled();
|
||||
expect(mockSetSelectedKeys).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should do nothing if an unsupported key is pressed', () => {
|
||||
const event = {
|
||||
key: 'Shift',
|
||||
preventDefault: jest.fn(),
|
||||
} as unknown as KeyboardEvent<HTMLDivElement>;
|
||||
|
||||
handleDropdownNavigation(
|
||||
event,
|
||||
true,
|
||||
<div />,
|
||||
mockToggleDropdown,
|
||||
mockSetSelectedKeys,
|
||||
mockSetOpenKeys,
|
||||
);
|
||||
expect(mockToggleDropdown).not.toHaveBeenCalled();
|
||||
expect(mockSetSelectedKeys).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should find a child element with a key', () => {
|
||||
const item = {
|
||||
props: {
|
||||
children: [
|
||||
<div key="1">Child 1</div>,
|
||||
<div key="2">Child 2</div>,
|
||||
<div key="3">Child 3</div>,
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const childWithKey = item?.props?.children?.find(
|
||||
(child: ReactElement) => child?.key,
|
||||
);
|
||||
|
||||
expect(childWithKey).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user