diff --git a/packages/core/upload/admin/src/hooks/__mocks__/useBulkRemove.js b/packages/core/upload/admin/src/hooks/__mocks__/useBulkRemove.js
new file mode 100644
index 0000000000..fc04e96a43
--- /dev/null
+++ b/packages/core/upload/admin/src/hooks/__mocks__/useBulkRemove.js
@@ -0,0 +1,5 @@
+export const useBulkRemove = jest.fn().mockReturnValue({
+ isLoading: false,
+ error: null,
+ remove: jest.fn(),
+});
diff --git a/packages/core/upload/admin/src/pages/App/tests/BulkActions.test.js b/packages/core/upload/admin/src/pages/App/tests/BulkActions.test.js
index f91d8f2457..cc3134534e 100644
--- a/packages/core/upload/admin/src/pages/App/tests/BulkActions.test.js
+++ b/packages/core/upload/admin/src/pages/App/tests/BulkActions.test.js
@@ -7,6 +7,8 @@ import { IntlProvider } from 'react-intl';
import { BulkActions } from '../components/BulkActions';
+jest.mock('../../../hooks/useBulkRemove');
+
jest.mock('@strapi/helper-plugin', () => ({
...jest.requireActual('@strapi/helper-plugin'),
useNotification: jest.fn(),
@@ -41,7 +43,7 @@ const setup = (
);
};
-describe('Header', () => {
+describe('BulkActions', () => {
afterEach(() => {
jest.clearAllMocks();
});
diff --git a/packages/core/upload/admin/src/pages/App/tests/BulkDeleteButton.test.js b/packages/core/upload/admin/src/pages/App/tests/BulkDeleteButton.test.js
new file mode 100644
index 0000000000..499d7b1d42
--- /dev/null
+++ b/packages/core/upload/admin/src/pages/App/tests/BulkDeleteButton.test.js
@@ -0,0 +1,79 @@
+import React from 'react';
+import { ThemeProvider, lightTheme } from '@strapi/design-system';
+import { QueryClientProvider, QueryClient } from 'react-query';
+import { render, fireEvent, waitFor, act } from '@testing-library/react';
+import { MemoryRouter } from 'react-router-dom';
+import { IntlProvider } from 'react-intl';
+
+import { BulkDeleteButton } from '../components/BulkDeleteButton';
+import { useBulkRemove } from '../../../hooks/useBulkRemove';
+
+jest.mock('../../../hooks/useBulkRemove');
+
+const setup = (
+ props = {
+ selected: [],
+ onSuccess: jest.fn(),
+ }
+) => {
+ const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ retry: false,
+ refetchOnWindowFocus: false,
+ },
+ },
+ });
+
+ return render(
+
+
+
+
+
+
+
+
+
+ );
+};
+
+describe('BulkDeleteButton', () => {
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ test('renders', () => {
+ const { container } = setup();
+
+ expect(container).toMatchSnapshot();
+ });
+
+ test('opens confirm dialog before the API call', () => {
+ const onSuccessSpy = jest.fn();
+ const { getByText } = setup({
+ onSuccess: onSuccessSpy,
+ selected: [{ type: 'asset' }],
+ });
+ const removeSpy = jest.fn().mockResolvedValueOnce({});
+
+ useBulkRemove.mockReturnValueOnce({
+ isLoading: false,
+ error: null,
+ remove: removeSpy,
+ });
+
+ act(() => {
+ fireEvent.click(getByText('Delete'));
+ });
+
+ expect(getByText('Are you sure you want to delete this?')).toBeInTheDocument();
+
+ act(() => {
+ fireEvent.click(getByText('Confirm'));
+ });
+
+ expect(removeSpy).toBeCalledWith([{ type: 'asset' }]);
+ waitFor(() => expect(onSuccessSpy).toBeCalledTimes(1));
+ });
+});
diff --git a/packages/core/upload/admin/src/pages/App/tests/__snapshots__/BulkActions.test.js.snap b/packages/core/upload/admin/src/pages/App/tests/__snapshots__/BulkActions.test.js.snap
index 8be5d0cd07..d70725e8dd 100644
--- a/packages/core/upload/admin/src/pages/App/tests/__snapshots__/BulkActions.test.js.snap
+++ b/packages/core/upload/admin/src/pages/App/tests/__snapshots__/BulkActions.test.js.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Header renders 1`] = `
+exports[`BulkActions renders 1`] = `
.c12 {
border: 0;
-webkit-clip: rect(0 0 0 0);
diff --git a/packages/core/upload/admin/src/pages/App/tests/__snapshots__/BulkDeleteButton.test.js.snap b/packages/core/upload/admin/src/pages/App/tests/__snapshots__/BulkDeleteButton.test.js.snap
new file mode 100644
index 0000000000..7ffbd2abd5
--- /dev/null
+++ b/packages/core/upload/admin/src/pages/App/tests/__snapshots__/BulkDeleteButton.test.js.snap
@@ -0,0 +1,223 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`BulkDeleteButton renders 1`] = `
+.c7 {
+ border: 0;
+ -webkit-clip: rect(0 0 0 0);
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+
+.c6 {
+ font-weight: 600;
+ color: #32324d;
+ font-size: 0.75rem;
+ line-height: 1.33;
+}
+
+.c3 {
+ padding-right: 8px;
+}
+
+.c0 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ cursor: pointer;
+ padding: 8px;
+ border-radius: 4px;
+ background: #ffffff;
+ border: 1px solid #dcdce4;
+ position: relative;
+ outline: none;
+}
+
+.c0 svg {
+ height: 12px;
+ width: 12px;
+}
+
+.c0 svg > g,
+.c0 svg path {
+ fill: #ffffff;
+}
+
+.c0[aria-disabled='true'] {
+ pointer-events: none;
+}
+
+.c0:after {
+ -webkit-transition-property: all;
+ transition-property: all;
+ -webkit-transition-duration: 0.2s;
+ transition-duration: 0.2s;
+ border-radius: 8px;
+ content: '';
+ position: absolute;
+ top: -4px;
+ bottom: -4px;
+ left: -4px;
+ right: -4px;
+ border: 2px solid transparent;
+}
+
+.c0:focus-visible {
+ outline: none;
+}
+
+.c0:focus-visible:after {
+ border-radius: 8px;
+ content: '';
+ position: absolute;
+ top: -5px;
+ bottom: -5px;
+ left: -5px;
+ right: -5px;
+ border: 2px solid #4945ff;
+}
+
+.c4 {
+ height: 100%;
+}
+
+.c1 {
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ padding: 8px 16px;
+ background: #4945ff;
+ border: 1px solid #4945ff;
+ border: 1px solid #f5c0b8;
+ background: #fcecea;
+}
+
+.c1 .c2 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+}
+
+.c1 .c5 {
+ color: #ffffff;
+}
+
+.c1[aria-disabled='true'] {
+ border: 1px solid #dcdce4;
+ background: #eaeaef;
+}
+
+.c1[aria-disabled='true'] .c5 {
+ color: #666687;
+}
+
+.c1[aria-disabled='true'] svg > g,
+.c1[aria-disabled='true'] svg path {
+ fill: #666687;
+}
+
+.c1[aria-disabled='true']:active {
+ border: 1px solid #dcdce4;
+ background: #eaeaef;
+}
+
+.c1[aria-disabled='true']:active .c5 {
+ color: #666687;
+}
+
+.c1[aria-disabled='true']:active svg > g,
+.c1[aria-disabled='true']:active svg path {
+ fill: #666687;
+}
+
+.c1:hover {
+ background-color: #ffffff;
+}
+
+.c1:active {
+ background-color: #ffffff;
+ border: 1px solid #d02b20;
+}
+
+.c1:active .c5 {
+ color: #d02b20;
+}
+
+.c1:active svg > g,
+.c1:active svg path {
+ fill: #d02b20;
+}
+
+.c1 .c5 {
+ color: #b72b1a;
+}
+
+.c1 svg > g,
+.c1 svg path {
+ fill: #b72b1a;
+}
+
+
+`;