Skip to content

Commit a73a97d

Browse files
committed
feat(metadata-view): bulk custom actions
Refactor to use RTL
1 parent 1419ef0 commit a73a97d

4 files changed

Lines changed: 153 additions & 52 deletions

File tree

src/elements/common/sub-header/SubHeaderRight.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const SubHeaderRight = ({
7171
const showAdd: boolean = (!!canUpload || !!canCreateNewFolder) && isFolder;
7272
const isMetadataView: boolean = view === VIEW_METADATA;
7373
const hasSelectedItems: boolean = !!(selectedItemIds && (selectedItemIds === 'all' || selectedItemIds.size > 0));
74+
7475
return (
7576
<div className="be-sub-header-right">
7677
{!isMetadataView && (

src/elements/common/sub-header/__tests__/SubHeaderRight.test.tsx

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as React from 'react';
2-
import { render, screen } from '../../../../test-utils/testing-library';
2+
import { render, screen, userEvent } from '../../../../test-utils/testing-library';
33
import SubHeaderRight, { SubHeaderRightProps } from '../SubHeaderRight';
4-
import { VIEW_FOLDER, VIEW_MODE_GRID } from '../../../../constants';
4+
import { VIEW_FOLDER, VIEW_METADATA, VIEW_MODE_GRID } from '../../../../constants';
5+
import { FeatureProvider } from '../../feature-checking';
56

67
describe('elements/common/sub-header/SubHeaderRight', () => {
78
const defaultProps = {
@@ -21,8 +22,12 @@ describe('elements/common/sub-header/SubHeaderRight', () => {
2122
viewMode: VIEW_MODE_GRID,
2223
};
2324

24-
const renderComponent = (props: Partial<SubHeaderRightProps> = {}) =>
25-
render(<SubHeaderRight {...defaultProps} {...props} />);
25+
const renderComponent = (props: Partial<SubHeaderRightProps> = {}, features = {}) =>
26+
render(
27+
<FeatureProvider features={features}>
28+
<SubHeaderRight {...defaultProps} {...props} />
29+
</FeatureProvider>,
30+
);
2631

2732
test('should render GridViewSlider when there are items and viewMode is grid', () => {
2833
renderComponent({
@@ -82,4 +87,95 @@ describe('elements/common/sub-header/SubHeaderRight', () => {
8287
renderComponent(defaultProps);
8388
expect(screen.queryByRole('button', { name: 'Add' })).not.toBeInTheDocument();
8489
});
90+
91+
describe('metadataViewV2', () => {
92+
const metadataViewV2Props = {
93+
...defaultProps,
94+
selectedItemIds: 'all' as const,
95+
bulkItemActions: [
96+
{
97+
label: 'Download',
98+
onClick: jest.fn(),
99+
},
100+
],
101+
view: VIEW_METADATA,
102+
onMetadataSidePanelToggle: jest.fn(),
103+
};
104+
105+
test.each([
106+
{
107+
selectedItemIds: 'all' as const,
108+
},
109+
{
110+
selectedItemIds: new Set(['1', '2']),
111+
},
112+
])('should render bulkItemActionMenu when selectedItemIds is $selectedItemIds', async ({ selectedItemIds }) => {
113+
const features = {
114+
contentExplorer: {
115+
metadataViewV2: true, // enable the feature flag
116+
},
117+
};
118+
119+
renderComponent(
120+
{
121+
...metadataViewV2Props,
122+
selectedItemIds,
123+
},
124+
features,
125+
);
126+
127+
expect(screen.getByRole('button', { name: 'Bulk actions' })).toBeInTheDocument();
128+
});
129+
130+
test('should call onClick when a bulk item action is clicked', async () => {
131+
const mockOnClick = jest.fn();
132+
const user = userEvent();
133+
const features = {
134+
contentExplorer: {
135+
metadataViewV2: true, // enable the feature flag
136+
},
137+
};
138+
139+
renderComponent(
140+
{
141+
...metadataViewV2Props,
142+
bulkItemActions: [
143+
{
144+
label: 'Download',
145+
onClick: mockOnClick,
146+
},
147+
],
148+
},
149+
features,
150+
);
151+
152+
const ellipsisButton = screen.getByRole('button', { name: 'Bulk actions' });
153+
154+
await user.click(ellipsisButton);
155+
156+
const downloadAction = screen.getByRole('menuitem', { name: 'Download' });
157+
await user.click(downloadAction);
158+
159+
const expectedOnClickArgument = 'all';
160+
expect(mockOnClick).toHaveBeenCalledWith(expectedOnClickArgument);
161+
});
162+
163+
test('should not render metadata button when metadataViewV2 feature is disabled', async () => {
164+
const features = {
165+
contentExplorer: {
166+
metadataViewV2: false, // Disable the feature flag
167+
},
168+
};
169+
170+
renderComponent(
171+
{
172+
...metadataViewV2Props,
173+
},
174+
features,
175+
);
176+
177+
expect(screen.queryByRole('button', { name: 'Bulk actions' })).not.toBeInTheDocument();
178+
expect(screen.queryByRole('button', { name: 'Metadata' })).not.toBeInTheDocument();
179+
});
180+
});
85181
});

src/elements/content-explorer/__tests__/ContentExplorer.test.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,58 @@ describe('elements/content-explorer/ContentExplorer', () => {
505505

506506
expect(screen.getByRole('button', { name: 'Metadata' })).toBeInTheDocument();
507507
});
508+
509+
test('should call onClick when bulk item action is clicked', async () => {
510+
const mockOnClick = jest.fn();
511+
const metadataViewV2WithBulkItemActions = {
512+
...metadataViewV2ElementProps,
513+
bulkItemActions: [
514+
{
515+
label: 'Download',
516+
onClick: mockOnClick,
517+
},
518+
],
519+
};
520+
521+
renderComponent(metadataViewV2WithBulkItemActions);
522+
523+
await waitFor(() => {
524+
expect(screen.getByTestId('content-explorer')).toBeInTheDocument();
525+
});
526+
527+
await waitFor(() => {
528+
expect(screen.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();
529+
});
530+
531+
const firstRow = screen.getByRole('row', { name: /Child 2/i });
532+
const checkbox = within(firstRow).getByRole('checkbox');
533+
await userEvent.click(checkbox);
534+
535+
await waitFor(() => {
536+
expect(screen.getByRole('button', { name: 'Bulk actions' })).toBeInTheDocument();
537+
});
538+
539+
const ellipsisButton = screen.getByRole('button', { name: 'Bulk actions' });
540+
await userEvent.click(ellipsisButton);
541+
542+
await waitFor(() => {
543+
expect(screen.getByRole('menuitem', { name: 'Download' })).toBeInTheDocument();
544+
});
545+
546+
const downloadAction = screen.getByRole('menuitem', { name: 'Download' });
547+
await userEvent.click(downloadAction);
548+
549+
const expectedOnClickArgument = new Set(['1188890835']);
550+
await waitFor(() => {
551+
expect(mockOnClick).toHaveBeenCalled();
552+
553+
// Array conversion from sets to avoid set comparison issues in Jest
554+
const argsForFirstMockCall = mockOnClick.mock.calls[0];
555+
const firstArgToMockOnClick = argsForFirstMockCall[0];
556+
557+
expect(Array.from(firstArgToMockOnClick)).toEqual(Array.from(expectedOnClickArgument));
558+
});
559+
});
508560
});
509561
});
510562

src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -205,23 +205,6 @@ export const sidePanelOpenWithSingleItemSelected: Story = {
205205
},
206206
};
207207

208-
export const metadataViewV2WithBulkItemActionMenuShowsEllipsis: Story = {
209-
args: metadataViewV2WithBulkItemActions,
210-
play: async ({ canvas }) => {
211-
await waitFor(() => {
212-
expect(canvas.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();
213-
});
214-
215-
const firstRow = canvas.getByRole('row', { name: /Child 2/i });
216-
const checkbox = within(firstRow).getByRole('checkbox');
217-
userEvent.click(checkbox);
218-
219-
await waitFor(() => {
220-
expect(canvas.getByRole('button', { name: 'Bulk actions' })).toBeInTheDocument();
221-
});
222-
},
223-
};
224-
225208
export const metadataViewV2WithBulkItemActionMenuShowsItemActionMenu: Story = {
226209
args: metadataViewV2WithBulkItemActions,
227210
play: async ({ canvas }) => {
@@ -247,37 +230,6 @@ export const metadataViewV2WithBulkItemActionMenuShowsItemActionMenu: Story = {
247230
},
248231
};
249232

250-
export const metadataViewV2WithBulkItemActionMenuCallsOnClick: Story = {
251-
args: metadataViewV2WithBulkItemActions,
252-
play: async ({ canvas, args }) => {
253-
await waitFor(() => {
254-
expect(canvas.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();
255-
});
256-
257-
const firstRow = canvas.getByRole('row', { name: /Child 2/i });
258-
const checkbox = within(firstRow).getByRole('checkbox');
259-
userEvent.click(checkbox);
260-
261-
await waitFor(() => {
262-
expect(canvas.getByRole('button', { name: 'Bulk actions' })).toBeInTheDocument();
263-
});
264-
265-
const ellipsisButton = canvas.getByRole('button', { name: 'Bulk actions' });
266-
267-
userEvent.click(ellipsisButton);
268-
269-
await waitFor(() => {
270-
expect(screen.getByRole('menuitem', { name: 'Download' })).toBeInTheDocument();
271-
});
272-
const downloadAction = screen.getByRole('menuitem', { name: 'Download' });
273-
userEvent.click(downloadAction);
274-
275-
await waitFor(() => {
276-
expect(args.bulkItemActions[0].onClick).toHaveBeenCalled();
277-
});
278-
},
279-
};
280-
281233
const meta: Meta<typeof ContentExplorer> = {
282234
title: 'Elements/ContentExplorer/tests/MetadataView/visual',
283235
component: ContentExplorer,

0 commit comments

Comments
 (0)