From ddcbafe9d95cdf6c68a607bc6dc3da2ca44a65f2 Mon Sep 17 00:00:00 2001
From: Josh <37798644+joshuaellis@users.noreply.github.com>
Date: Wed, 4 Oct 2023 16:03:02 +0100
Subject: [PATCH] tests(upload): fix error logs in upload tests (#18261)
* chore: add test utils
* test(upload): fix useModalQueryParams
* test(upload): fix TableRows
* test(upload): fix useConfig test
* test(upload): fix useFolder tests
* test(upload): fix useFolders test
* test(upload): fix SettingsPage tests
* test(upload): fix UploadAssetDialog tests
* test(upload): fix CarouselAssets tests
---
.../Carousel/tests/CarouselAssets.test.js | 77 +-
.../src/components/TableList/TableRows.js | 2 +-
.../TableList/tests/TableRows.test.js | 93 +-
.../UploadAssetDialog/UploadAssetDialog.js | 3 +-
.../tests/UploadAssetDialog.test.js | 169 +-
.../UploadAssetDialog.test.js.snap | 1402 -----------------
.../UploadAssetDialog/tests/server.js | 18 -
.../admin/src/hooks/tests/useConfig.test.js | 204 +--
.../admin/src/hooks/tests/useFolder.test.js | 121 +-
.../admin/src/hooks/tests/useFolders.test.js | 269 ++--
.../hooks/tests/useModalQueryParams.test.js | 134 +-
.../core/upload/admin/src/hooks/useConfig.js | 30 +-
.../core/upload/admin/src/hooks/useFolder.js | 60 +-
.../core/upload/admin/src/hooks/useFolders.js | 47 +-
.../admin/src/pages/SettingsPage/index.js | 97 +-
.../admin/src/pages/SettingsPage/reducer.js | 20 -
.../pages/SettingsPage/tests/index.test.js | 876 +---------
.../pages/SettingsPage/tests/reducer.test.js | 50 +-
.../pages/SettingsPage/tests/utils/server.js | 17 -
.../src/utils/tests/downloadFile.test.js | 24 +-
packages/core/upload/admin/tests/server.js | 192 +++
packages/core/upload/admin/tests/setup.js | 13 +
packages/core/upload/admin/tests/utils.jsx | 97 ++
packages/core/upload/jest.config.front.js | 4 +
packages/core/upload/jsconfig.json | 8 +
25 files changed, 790 insertions(+), 3237 deletions(-)
delete mode 100644 packages/core/upload/admin/src/components/UploadAssetDialog/tests/__snapshots__/UploadAssetDialog.test.js.snap
delete mode 100644 packages/core/upload/admin/src/components/UploadAssetDialog/tests/server.js
delete mode 100644 packages/core/upload/admin/src/pages/SettingsPage/tests/utils/server.js
create mode 100644 packages/core/upload/admin/tests/server.js
create mode 100644 packages/core/upload/admin/tests/setup.js
create mode 100644 packages/core/upload/admin/tests/utils.jsx
create mode 100644 packages/core/upload/jsconfig.json
diff --git a/packages/core/upload/admin/src/components/MediaLibraryInput/Carousel/tests/CarouselAssets.test.js b/packages/core/upload/admin/src/components/MediaLibraryInput/Carousel/tests/CarouselAssets.test.js
index 2d5cda7fcd..0e912dd081 100644
--- a/packages/core/upload/admin/src/components/MediaLibraryInput/Carousel/tests/CarouselAssets.test.js
+++ b/packages/core/upload/admin/src/components/MediaLibraryInput/Carousel/tests/CarouselAssets.test.js
@@ -1,19 +1,9 @@
import React from 'react';
-import { lightTheme, ThemeProvider } from '@strapi/design-system';
-import { fireEvent, render } from '@testing-library/react';
-import { IntlProvider } from 'react-intl';
-import { QueryClient, QueryClientProvider } from 'react-query';
+import { render, waitFor } from '@tests/utils';
import { CarouselAssets } from '../CarouselAssets';
-jest.mock('@strapi/helper-plugin', () => ({
- ...jest.requireActual('@strapi/helper-plugin'),
- useNotification: jest.fn(() => ({
- toggleNotification: jest.fn(),
- })),
-}));
-
const ASSET_FIXTURES = [
{
alternativeText: 'alternative text',
@@ -33,38 +23,21 @@ const ASSET_FIXTURES = [
},
];
-const client = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
-});
-
-const ComponentFixture = (props) => {
- return (
-
-
-
-
-
-
-
+const setup = (props) =>
+ render(
+
);
-};
-
-const setup = (props) => render();
describe('MediaLibraryInput | Carousel | CarouselAssets', () => {
it('should render empty carousel', () => {
@@ -90,30 +63,32 @@ describe('MediaLibraryInput | Carousel | CarouselAssets', () => {
expect(getByRole('button', { name: 'edit' })).toBeInTheDocument();
});
- it('should call onAddAsset', () => {
+ it('should call onAddAsset', async () => {
const onAddAssetSpy = jest.fn();
- const { getByRole } = setup({ onAddAsset: onAddAssetSpy });
+ const { getByRole, user } = setup({ onAddAsset: onAddAssetSpy });
- fireEvent.click(getByRole('button', { name: 'Add' }));
+ await user.click(getByRole('button', { name: 'Add' }));
expect(onAddAssetSpy).toHaveBeenCalledTimes(1);
});
- it('should call onDeleteAsset', () => {
+ it('should call onDeleteAsset', async () => {
const onDeleteAssetSpy = jest.fn();
- const { getByRole } = setup({ onDeleteAsset: onDeleteAssetSpy });
+ const { getByRole, user } = setup({ onDeleteAsset: onDeleteAssetSpy });
- fireEvent.click(getByRole('button', { name: 'Delete' }));
+ await user.click(getByRole('button', { name: 'Delete' }));
expect(onDeleteAssetSpy).toHaveBeenCalledTimes(1);
});
- it('should open edit view', () => {
- const { getByRole, getByText } = setup();
+ it('should open edit view', async () => {
+ const { getByRole, getByText, user, queryByText } = setup();
- fireEvent.click(getByRole('button', { name: 'edit' }));
+ await user.click(getByRole('button', { name: 'edit' }));
expect(getByText('Details')).toBeInTheDocument();
+
+ await waitFor(() => expect(queryByText('Content is loading.')).not.toBeInTheDocument());
});
it('should render the localized label', () => {
diff --git a/packages/core/upload/admin/src/components/TableList/TableRows.js b/packages/core/upload/admin/src/components/TableList/TableRows.js
index 9503da454b..29db193c57 100644
--- a/packages/core/upload/admin/src/components/TableList/TableRows.js
+++ b/packages/core/upload/admin/src/components/TableList/TableRows.js
@@ -46,7 +46,7 @@ export const TableRows = ({
fn: () => handleRowClickFn(element, contentType, id, path),
})}
>
-
+ | e.stopPropagation()}>
({
- ...jest.requireActual('@strapi/helper-plugin'),
- useQueryParams: jest.fn(() => [{ query: {} }]),
-}));
-
const ASSET_FIXTURE = {
alternativeText: 'alternative text',
createdAt: '2021-10-01T08:04:56.326Z',
@@ -32,7 +25,7 @@ const ASSET_FIXTURE = {
const FOLDER_FIXTURE = {
createdAt: '2022-11-17T10:40:06.022Z',
- id: 1,
+ id: 2,
name: 'folder 1',
type: 'folder',
updatedAt: '2022-11-17T10:40:06.022Z',
@@ -47,26 +40,12 @@ const PROPS_FIXTURE = {
selected: [],
};
-const ComponentFixture = (props) => {
- const customProps = {
- ...PROPS_FIXTURE,
- ...props,
- };
-
- return (
-
-
-
-
-
-
-
- );
-};
-
-const setup = (props) => render();
+const setup = (props) =>
+ render(, {
+ renderOptions: {
+ wrapper: ({ children }) => {children},
+ },
+ });
describe('TableList | TableRows', () => {
describe('rendering assets', () => {
@@ -85,7 +64,10 @@ describe('TableList | TableRows', () => {
const onSelectOneSpy = jest.fn();
const { getByRole } = setup({ onSelectOne: onSelectOneSpy });
- fireEvent.click(getByRole('checkbox', { name: 'Select michka asset', hidden: true }));
+ /**
+ * using UserEvent never triggers the onChange event.
+ */
+ fireEvent.click(getByRole('checkbox', { name: 'Select michka asset' }));
expect(onSelectOneSpy).toHaveBeenCalledTimes(1);
});
@@ -93,34 +75,32 @@ describe('TableList | TableRows', () => {
it('should reflect non selected assets state', () => {
const { getByRole } = setup();
- expect(
- getByRole('checkbox', { name: 'Select michka asset', hidden: true })
- ).not.toBeChecked();
+ expect(getByRole('checkbox', { name: 'Select michka asset' })).not.toBeChecked();
});
it('should reflect selected assets state', () => {
const { getByRole } = setup({ selected: [{ id: 1, type: 'asset' }] });
- expect(getByRole('checkbox', { name: 'Select michka asset', hidden: true })).toBeChecked();
+ expect(getByRole('checkbox', { name: 'Select michka asset' })).toBeChecked();
});
it('should disable select asset checkbox when users do not have the permission to update', () => {
const { getByRole } = setup({ canUpdate: false });
- expect(getByRole('checkbox', { name: 'Select michka asset', hidden: true })).toBeDisabled();
+ expect(getByRole('checkbox', { name: 'Select michka asset' })).toBeDisabled();
});
it('should disable select asset checkbox when users if the file type is not allowed', () => {
const { getByRole } = setup({ allowedTypes: [] });
- expect(getByRole('checkbox', { name: 'Select michka asset', hidden: true })).toBeDisabled();
+ expect(getByRole('checkbox', { name: 'Select michka asset' })).toBeDisabled();
});
- it('should call onEditAsset callback', () => {
+ it('should call onEditAsset callback', async () => {
const onEditAssetSpy = jest.fn();
- const { getByRole } = setup({ onEditAsset: onEditAssetSpy });
+ const { getByRole, user } = setup({ onEditAsset: onEditAssetSpy });
- fireEvent.click(getByRole('button', { name: 'Edit', hidden: true }));
+ await user.click(getByRole('button', { name: 'Edit', hidden: true }));
expect(onEditAssetSpy).toHaveBeenCalledTimes(1);
});
@@ -135,14 +115,14 @@ describe('TableList | TableRows', () => {
expect(getByText('folder 1')).toBeInTheDocument();
});
- it('should call onEditFolder callback', () => {
+ it('should call onEditFolder callback', async () => {
const onEditFolderSpy = jest.fn();
- const { getByRole } = setup({
+ const { getByRole, user } = setup({
rows: [FOLDER_FIXTURE],
onEditFolder: onEditFolderSpy,
});
- fireEvent.click(getByRole('button', { name: 'Edit', hidden: true }));
+ await user.click(getByRole('button', { name: 'Edit', hidden: true }));
expect(onEditFolderSpy).toHaveBeenCalledTimes(1);
});
@@ -159,13 +139,16 @@ describe('TableList | TableRows', () => {
expect(getByRole('button', { name: 'Access folder', hidden: true })).toBeInTheDocument();
});
- it('should call onChangeFolder when clicking on folder navigation button', () => {
+ it('should call onChangeFolder when clicking on folder navigation button', async () => {
const onChangeFolderSpy = jest.fn();
- const { getByRole } = setup({ rows: [FOLDER_FIXTURE], onChangeFolder: onChangeFolderSpy });
+ const { getByRole, user } = setup({
+ rows: [FOLDER_FIXTURE],
+ onChangeFolder: onChangeFolderSpy,
+ });
- fireEvent.click(getByRole('button', { name: 'Access folder', hidden: true }));
+ await user.click(getByRole('button', { name: 'Access folder', hidden: true }));
- expect(onChangeFolderSpy).toHaveBeenCalledWith(1);
+ expect(onChangeFolderSpy).toHaveBeenCalledWith(2);
});
it('should reflect non selected folder state', () => {
@@ -179,7 +162,7 @@ describe('TableList | TableRows', () => {
it('should reflect selected folder state', () => {
const { getByRole } = setup({
rows: [FOLDER_FIXTURE],
- selected: [{ id: 1, type: 'folder' }],
+ selected: [{ id: 2, type: 'folder' }],
});
expect(getByRole('checkbox', { name: 'Select folder 1 folder', hidden: true })).toBeChecked();
@@ -208,17 +191,15 @@ describe('TableList | TableRows', () => {
});
});
- describe.only('rendering folder & asset with the same id', () => {
+ describe('rendering folder & asset with the same id', () => {
it('should reflect selected only folder state', () => {
const { getByRole } = setup({
rows: [FOLDER_FIXTURE, ASSET_FIXTURE],
- selected: [{ id: 1, type: 'folder' }],
+ selected: [{ id: 2, type: 'folder' }],
});
expect(getByRole('checkbox', { name: 'Select folder 1 folder', hidden: true })).toBeChecked();
- expect(
- getByRole('checkbox', { name: 'Select michka asset', hidden: true })
- ).not.toBeChecked();
+ expect(getByRole('checkbox', { name: 'Select michka asset' })).not.toBeChecked();
});
it('should reflect selected only asset state', () => {
@@ -230,7 +211,7 @@ describe('TableList | TableRows', () => {
expect(
getByRole('checkbox', { name: 'Select folder 1 folder', hidden: true })
).not.toBeChecked();
- expect(getByRole('checkbox', { name: 'Select michka asset', hidden: true })).toBeChecked();
+ expect(getByRole('checkbox', { name: 'Select michka asset' })).toBeChecked();
});
it('should reflect selected both asset & folder state', () => {
@@ -238,12 +219,12 @@ describe('TableList | TableRows', () => {
rows: [FOLDER_FIXTURE, ASSET_FIXTURE],
selected: [
{ id: 1, type: 'asset' },
- { id: 1, type: 'folder' },
+ { id: 2, type: 'folder' },
],
});
expect(getByRole('checkbox', { name: 'Select folder 1 folder', hidden: true })).toBeChecked();
- expect(getByRole('checkbox', { name: 'Select michka asset', hidden: true })).toBeChecked();
+ expect(getByRole('checkbox', { name: 'Select michka asset' })).toBeChecked();
});
});
});
diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/UploadAssetDialog.js b/packages/core/upload/admin/src/components/UploadAssetDialog/UploadAssetDialog.js
index 030369e122..f91f11d499 100644
--- a/packages/core/upload/admin/src/components/UploadAssetDialog/UploadAssetDialog.js
+++ b/packages/core/upload/admin/src/components/UploadAssetDialog/UploadAssetDialog.js
@@ -134,6 +134,7 @@ UploadAssetDialog.defaultProps = {
addUploadedFiles: undefined,
folderId: null,
initialAssetsToAdd: undefined,
+ onClose() {},
trackedLocation: undefined,
validateAssetsTypes: undefined,
};
@@ -142,7 +143,7 @@ UploadAssetDialog.propTypes = {
addUploadedFiles: PropTypes.func,
folderId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
initialAssetsToAdd: PropTypes.arrayOf(AssetDefinition),
- onClose: PropTypes.func.isRequired,
+ onClose: PropTypes.func,
trackedLocation: PropTypes.string,
validateAssetsTypes: PropTypes.func,
};
diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/tests/UploadAssetDialog.test.js b/packages/core/upload/admin/src/components/UploadAssetDialog/tests/UploadAssetDialog.test.js
index 1890466229..c4c59ef332 100644
--- a/packages/core/upload/admin/src/components/UploadAssetDialog/tests/UploadAssetDialog.test.js
+++ b/packages/core/upload/admin/src/components/UploadAssetDialog/tests/UploadAssetDialog.test.js
@@ -1,81 +1,41 @@
+/* eslint-disable no-await-in-loop */
import React from 'react';
-import { lightTheme, ThemeProvider } from '@strapi/design-system';
-import { TrackingProvider } from '@strapi/helper-plugin';
-import { fireEvent, render as renderTL, screen, waitFor, within } from '@testing-library/react';
-import { QueryClient, QueryClientProvider } from 'react-query';
+import { within } from '@testing-library/react';
+import { fireEvent, render, screen, waitFor } from '@tests/utils';
-import en from '../../../translations/en.json';
import { UploadAssetDialog } from '../UploadAssetDialog';
-import { server } from './server';
-
-jest.mock('../../../utils/getTrad', () => (x) => x);
-
-jest.mock('react-intl', () => ({
- useIntl: () => ({ formatMessage: jest.fn(({ id }) => en[id] || id) }),
-}));
-
-const queryClient = new QueryClient({
- defaultOptions: {
- queries: {
- refetchOnWindowFocus: false,
- },
- },
-});
-
-const render = (props = { onClose() {} }) =>
- renderTL(
-
-
-
-
-
-
- ,
- { container: document.getElementById('app') }
- );
-
describe('UploadAssetDialog', () => {
let confirmSpy;
+
beforeAll(() => {
confirmSpy = jest.spyOn(window, 'confirm');
confirmSpy.mockImplementation(jest.fn(() => true));
- server.listen();
});
- afterEach(() => server.resetHandlers());
+
afterAll(() => {
confirmSpy.mockRestore();
- server.close();
});
describe('from computer', () => {
- it('snapshots the component', () => {
- render();
-
- expect(document.body).toMatchSnapshot();
- });
-
- it('closes the dialog when clicking on cancel on the add asset step', () => {
+ it('closes the dialog when clicking on cancel on the add asset step', async () => {
const onCloseSpy = jest.fn();
- render({ onClose: onCloseSpy, onSuccess() {} });
+ const { user, getByRole } = render();
- fireEvent.click(screen.getByText('app.components.Button.cancel'));
+ await user.click(getByRole('button', { name: 'cancel' }));
expect(onCloseSpy).toBeCalled();
});
- it('open confirm box when clicking on cancel on the pending asset step', () => {
+ it('open confirm box when clicking on cancel on the pending asset step', async () => {
const file = new File(['Some stuff'], 'test.png', { type: 'image/png' });
- const onCloseSpy = jest.fn();
- render({ onClose: onCloseSpy, onSuccess() {} });
+ const { user, getByRole } = render();
- const fileList = [file];
- fileList.item = (i) => fileList[i];
+ await user.upload(document.querySelector('[type="file"]'), file);
- fireEvent.change(document.querySelector('[type="file"]'), { target: { files: fileList } });
- fireEvent.click(screen.getByText('app.components.Button.cancel'));
+ await user.click(getByRole('button', { name: 'cancel' }));
expect(window.confirm).toBeCalled();
});
@@ -86,53 +46,30 @@ describe('UploadAssetDialog', () => {
['pdf', 'application/pdf', 'Doc', 1],
['unknown', 'unknown', 'Doc', 1],
].forEach(([ext, mime, assetType, number]) => {
- it(`shows ${number} valid ${mime} file`, () => {
- const onCloseSpy = jest.fn();
-
- // see https://github.com/testing-library/react-testing-library/issues/470
- Object.defineProperty(HTMLMediaElement.prototype, 'muted', {
- set() {},
- });
-
+ it(`shows ${number} valid ${mime} file`, async () => {
const file = new File(['Some stuff'], `test.${ext}`, { type: mime });
- const fileList = [file];
- fileList.item = (i) => fileList[i];
+ const { user, getByText, getAllByText } = render();
- render({ onClose: onCloseSpy, onSuccess() {} });
+ await user.upload(document.querySelector('[type="file"]'), file);
- fireEvent.change(document.querySelector('[type="file"]'), {
- target: { files: fileList },
- });
-
- expect(screen.getAllByText(`Add new assets`).length).toBe(2);
+ expect(getByText('1 asset ready to upload')).toBeInTheDocument();
expect(
- screen.getByText(
- '{number, plural, =0 {No asset} one {1 asset} other {# assets}} ready to upload'
- )
+ getByText('Manage the assets before adding them to the Media Library')
).toBeInTheDocument();
- expect(
- screen.getByText('Manage the assets before adding them to the Media Library')
- ).toBeInTheDocument();
- expect(screen.getAllByText(`test.${ext}`).length).toBe(number);
- expect(screen.getByText(ext)).toBeInTheDocument();
- expect(screen.getByText(assetType)).toBeInTheDocument();
+
+ expect(getAllByText(`test.${ext}`).length).toBe(number);
+ expect(getByText(ext)).toBeInTheDocument();
+ expect(getByText(assetType)).toBeInTheDocument();
});
});
});
describe('from url', () => {
- it('snapshots the component', () => {
- render();
-
- fireEvent.click(screen.getByText('From url'));
-
- expect(document.body).toMatchSnapshot();
- });
-
it('shows an error message when the asset does not exist', async () => {
- render();
- fireEvent.click(screen.getByText('From url'));
+ const { user, getByRole } = render();
+
+ await user.click(getByRole('tab', { name: 'From URL' }));
const urls = [
'http://localhost:5000/an-image.png',
@@ -140,27 +77,48 @@ describe('UploadAssetDialog', () => {
'http://localhost:5000/a-video.mp4',
'http://localhost:5000/not-working-like-cors.lutin',
'http://localhost:1234/some-where-not-existing.jpg',
- ].join('\n');
+ ];
- fireEvent.change(screen.getByLabelText('URL'), { target: { value: urls } });
- fireEvent.click(screen.getByText('Next'));
+ // eslint-disable-next-line no-restricted-syntax
+ for (const url of urls) {
+ await user.type(getByRole('textbox', 'URL'), url);
- await waitFor(() => expect(screen.getByText('Failed to fetch')).toBeInTheDocument());
+ await user.type(getByRole('textbox', 'URL'), '[Enter]');
+ }
+
+ /**
+ * userEvent does not submit forms.
+ */
+ fireEvent.click(getByRole('button', { name: 'Next' }));
+
+ await waitFor(() => expect(screen.getByText('An error occured')).toBeInTheDocument());
});
it('snapshots the component with 4 URLs: 3 valid and one in failure', async () => {
- render();
- fireEvent.click(screen.getByText('From url'));
+ const { user, getByText, getByRole } = render();
+
+ await user.click(getByRole('tab', { name: 'From URL' }));
const urls = [
'http://localhost:5000/an-image.png',
'http://localhost:5000/a-pdf.pdf',
'http://localhost:5000/a-video.mp4',
'http://localhost:5000/not-working-like-cors.lutin',
- ].join('\n');
+ ];
- fireEvent.change(screen.getByLabelText('URL'), { target: { value: urls } });
- fireEvent.click(screen.getByText('Next'));
+ // eslint-disable-next-line no-restricted-syntax
+ for (const url of urls) {
+ await user.type(getByRole('textbox', 'URL'), url);
+
+ if (urls.indexOf(url) < urls.length - 1) {
+ await user.type(getByRole('textbox', 'URL'), '[Enter]');
+ }
+ }
+
+ /**
+ * userEvent does not submit forms.
+ */
+ fireEvent.click(getByRole('button', { name: 'Next' }));
const assets = [
{
@@ -201,25 +159,14 @@ describe('UploadAssetDialog', () => {
},
];
- await waitFor(() =>
- expect(
- screen.getByText(
- '{number, plural, =0 {No asset} one {1 asset} other {# assets}} ready to upload'
- )
- ).toBeInTheDocument()
- );
- expect(screen.getAllByText(`Add new assets`).length).toBe(2);
- expect(
- screen.getByText('Manage the assets before adding them to the Media Library')
- ).toBeInTheDocument();
+ await waitFor(() => expect(getByText('4 assets ready to upload')).toBeInTheDocument());
assets.forEach((asset) => {
- const dialog = within(screen.getByRole('dialog'));
- const card = within(dialog.getAllByLabelText(asset.name)[0]);
+ const card = within(screen.getByRole('dialog')).getAllByLabelText(asset.name)[0];
- expect(card.getByText(asset.ext)).toBeInTheDocument();
+ expect(within(card).getByText(asset.ext)).toBeInTheDocument();
expect(
- card.getByText(asset.type.charAt(0).toUpperCase() + asset.type.slice(1))
+ within(card).getByText(`${asset.type.charAt(0).toUpperCase()}${asset.type.slice(1)}`)
).toBeInTheDocument();
});
});
diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/tests/__snapshots__/UploadAssetDialog.test.js.snap b/packages/core/upload/admin/src/components/UploadAssetDialog/tests/__snapshots__/UploadAssetDialog.test.js.snap
deleted file mode 100644
index 67e4c9a4b9..0000000000
--- a/packages/core/upload/admin/src/components/UploadAssetDialog/tests/__snapshots__/UploadAssetDialog.test.js.snap
+++ /dev/null
@@ -1,1402 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`UploadAssetDialog from computer snapshots the component 1`] = `
-.c0 {
- 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;
-}
-
-.c9 {
- font-size: 0.875rem;
- line-height: 1.43;
- font-weight: 600;
- color: #32324d;
-}
-
-.c17 {
- font-weight: 600;
- font-size: 0.6875rem;
- line-height: 1.45;
- text-transform: uppercase;
- color: #4945ff;
-}
-
-.c19 {
- font-weight: 600;
- font-size: 0.6875rem;
- line-height: 1.45;
- text-transform: uppercase;
- color: #666687;
-}
-
-.c29 {
- font-weight: 500;
- font-size: 1rem;
- line-height: 1.25;
- color: #666687;
-}
-
-.c36 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #ffffff;
-}
-
-.c1 {
- padding-right: 40px;
- padding-left: 40px;
- position: fixed;
- z-index: 4;
-}
-
-.c4 {
- background: #ffffff;
- border-radius: 4px;
- box-shadow: 0px 2px 15px rgba(33,33,52,0.1);
- width: 51.875rem;
-}
-
-.c5 {
- background: #f6f6f9;
- padding-top: 16px;
- padding-right: 20px;
- padding-bottom: 16px;
- padding-left: 20px;
-}
-
-.c10 {
- background: #ffffff;
- padding: 8px;
- border-radius: 4px;
- border-color: #dcdce4;
- border: 1px solid #dcdce4;
- cursor: pointer;
-}
-
-.c13 {
- padding-top: 24px;
- padding-right: 40px;
- padding-left: 40px;
-}
-
-.c15 {
- padding: 16px;
-}
-
-.c20 {
- background: #eaeaef;
-}
-
-.c22 {
- padding-top: 24px;
- padding-right: 40px;
- padding-bottom: 24px;
- padding-left: 40px;
-}
-
-.c23 {
- background: #f6f6f9;
- padding-top: 64px;
- padding-bottom: 64px;
- border-radius: 4px;
- border-color: #c0c0cf;
- border: 1px solid #c0c0cf;
- position: relative;
-}
-
-.c28 {
- padding-top: 12px;
- padding-bottom: 20px;
-}
-
-.c30 {
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- z-index: 1;
- width: 100%;
-}
-
-.c32 {
- position: relative;
-}
-
-.c33 {
- background: #4945ff;
- padding: 8px;
- padding-right: 16px;
- padding-left: 16px;
- border-radius: 4px;
- border-color: #4945ff;
- border: 1px solid #4945ff;
- cursor: pointer;
-}
-
-.c2 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c7 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
- justify-content: space-between;
-}
-
-.c25 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
-}
-
-.c34 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- gap: 8px;
-}
-
-.c11 {
- position: relative;
- outline: none;
-}
-
-.c11 > svg {
- height: 12px;
- width: 12px;
-}
-
-.c11 > svg > g,
-.c11 > svg path {
- fill: #ffffff;
-}
-
-.c11[aria-disabled='true'] {
- pointer-events: none;
-}
-
-.c11: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;
-}
-
-.c11:focus-visible {
- outline: none;
-}
-
-.c11:focus-visible:after {
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -5px;
- bottom: -5px;
- left: -5px;
- right: -5px;
- border: 2px solid #4945ff;
-}
-
-.c35 {
- height: 2rem;
-}
-
-.c35 svg {
- height: 0.75rem;
- width: auto;
-}
-
-.c35[aria-disabled='true'] {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c35[aria-disabled='true'] .c8 {
- color: #666687;
-}
-
-.c35[aria-disabled='true'] svg > g,
-.c35[aria-disabled='true'] svg path {
- fill: #666687;
-}
-
-.c35[aria-disabled='true']:active {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c35[aria-disabled='true']:active .c8 {
- color: #666687;
-}
-
-.c35[aria-disabled='true']:active svg > g,
-.c35[aria-disabled='true']:active svg path {
- fill: #666687;
-}
-
-.c35:hover {
- border: 1px solid #7b79ff;
- background: #7b79ff;
-}
-
-.c35:active {
- border: 1px solid #4945ff;
- background: #4945ff;
-}
-
-.c35 svg > g,
-.c35 svg path {
- fill: #ffffff;
-}
-
-.c38 {
- height: 2rem;
- border: 1px solid #dcdce4;
- background: #ffffff;
-}
-
-.c38 svg {
- height: 0.75rem;
- width: auto;
-}
-
-.c38[aria-disabled='true'] {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c38[aria-disabled='true'] .c8 {
- color: #666687;
-}
-
-.c38[aria-disabled='true'] svg > g,
-.c38[aria-disabled='true'] svg path {
- fill: #666687;
-}
-
-.c38[aria-disabled='true']:active {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c38[aria-disabled='true']:active .c8 {
- color: #666687;
-}
-
-.c38[aria-disabled='true']:active svg > g,
-.c38[aria-disabled='true']:active svg path {
- fill: #666687;
-}
-
-.c38:hover {
- background-color: #f6f6f9;
-}
-
-.c38:active {
- background-color: #eaeaef;
-}
-
-.c38 .c8 {
- color: #32324d;
-}
-
-.c38 svg > g,
-.c38 svg path {
- fill: #32324d;
-}
-
-.c21 {
- height: 1px;
- border: none;
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0;
- margin: 0;
-}
-
-.c12 {
- border-color: #dcdce4;
- height: 2rem;
- width: 2rem;
-}
-
-.c12 svg g,
-.c12 svg path {
- fill: #8e8ea9;
-}
-
-.c12:hover svg g,
-.c12:focus svg g,
-.c12:hover svg path,
-.c12:focus svg path {
- fill: #666687;
-}
-
-.c12[aria-disabled='true'] svg path {
- fill: #666687;
-}
-
-.c3 {
- background: #32324d1F;
- inset: 0;
-}
-
-.c6 {
- border-radius: 4px 4px 0 0;
- border-bottom: 1px solid #eaeaef;
-}
-
-.c37 {
- border-radius: 0 0 4px 4px;
- border-top: 1px solid #eaeaef;
-}
-
-.c16 {
- border-bottom: 2px solid #4945ff;
-}
-
-.c18 {
- border-bottom: 2px solid transparent;
-}
-
-.c14[aria-disabled='true'] {
- cursor: not-allowed;
-}
-
-.c26 {
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
-}
-
-.c27 {
- font-size: 3.75rem;
-}
-
-.c27 svg path {
- fill: #4945ff;
-}
-
-.c24 {
- border-style: dashed;
-}
-
-.c31 {
- opacity: 0;
- cursor: pointer;
-}
-
-
-
-
-
-
-
-
-
-
-
- Add new assets
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`UploadAssetDialog from url snapshots the component 1`] = `
-.c0 {
- 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;
-}
-
-.c9 {
- font-size: 0.875rem;
- line-height: 1.43;
- font-weight: 600;
- color: #32324d;
-}
-
-.c19 {
- font-weight: 600;
- font-size: 0.6875rem;
- line-height: 1.45;
- text-transform: uppercase;
- color: #4945ff;
-}
-
-.c17 {
- font-weight: 600;
- font-size: 0.6875rem;
- line-height: 1.45;
- text-transform: uppercase;
- color: #666687;
-}
-
-.c35 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #ffffff;
-}
-
-.c24 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #32324d;
-}
-
-.c30 {
- font-size: 0.75rem;
- line-height: 1.33;
- color: #666687;
-}
-
-.c1 {
- padding-right: 40px;
- padding-left: 40px;
- position: fixed;
- z-index: 4;
-}
-
-.c4 {
- background: #ffffff;
- border-radius: 4px;
- box-shadow: 0px 2px 15px rgba(33,33,52,0.1);
- width: 51.875rem;
-}
-
-.c5 {
- background: #f6f6f9;
- padding-top: 16px;
- padding-right: 20px;
- padding-bottom: 16px;
- padding-left: 20px;
-}
-
-.c10 {
- background: #ffffff;
- padding: 8px;
- border-radius: 4px;
- border-color: #dcdce4;
- border: 1px solid #dcdce4;
- cursor: pointer;
-}
-
-.c13 {
- padding-top: 24px;
- padding-right: 40px;
- padding-left: 40px;
-}
-
-.c15 {
- padding: 16px;
-}
-
-.c20 {
- background: #eaeaef;
-}
-
-.c22 {
- padding-top: 24px;
- padding-right: 40px;
- padding-bottom: 24px;
- padding-left: 40px;
-}
-
-.c33 {
- background: #4945ff;
- padding: 8px;
- padding-right: 16px;
- padding-left: 16px;
- border-radius: 4px;
- border-color: #4945ff;
- border: 1px solid #4945ff;
- cursor: pointer;
-}
-
-.c26 {
- border-radius: 4px;
- border-color: #dcdce4;
- border: 1px solid #dcdce4;
-}
-
-.c28 {
- font-size: 0.875rem;
- background: #ffffff;
- color: #32324d;
- padding: 16px;
- border-radius: 4px;
- width: 100%;
- height: 6.5625rem;
- line-height: 1.43;
-}
-
-.c2 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
-}
-
-.c7 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
- justify-content: space-between;
-}
-
-.c32 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- gap: 8px;
-}
-
-.c23 {
- -webkit-align-items: stretch;
- -webkit-box-align: stretch;
- -ms-flex-align: stretch;
- align-items: stretch;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- gap: 4px;
-}
-
-.c11 {
- position: relative;
- outline: none;
-}
-
-.c11 > svg {
- height: 12px;
- width: 12px;
-}
-
-.c11 > svg > g,
-.c11 > svg path {
- fill: #ffffff;
-}
-
-.c11[aria-disabled='true'] {
- pointer-events: none;
-}
-
-.c11: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;
-}
-
-.c11:focus-visible {
- outline: none;
-}
-
-.c11:focus-visible:after {
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -5px;
- bottom: -5px;
- left: -5px;
- right: -5px;
- border: 2px solid #4945ff;
-}
-
-.c36 {
- height: 2rem;
-}
-
-.c36 svg {
- height: 0.75rem;
- width: auto;
-}
-
-.c36[aria-disabled='true'] {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c36[aria-disabled='true'] .c8 {
- color: #666687;
-}
-
-.c36[aria-disabled='true'] svg > g,
-.c36[aria-disabled='true'] svg path {
- fill: #666687;
-}
-
-.c36[aria-disabled='true']:active {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c36[aria-disabled='true']:active .c8 {
- color: #666687;
-}
-
-.c36[aria-disabled='true']:active svg > g,
-.c36[aria-disabled='true']:active svg path {
- fill: #666687;
-}
-
-.c36:hover {
- border: 1px solid #7b79ff;
- background: #7b79ff;
-}
-
-.c36:active {
- border: 1px solid #4945ff;
- background: #4945ff;
-}
-
-.c36 svg > g,
-.c36 svg path {
- fill: #ffffff;
-}
-
-.c34 {
- height: 2rem;
- border: 1px solid #dcdce4;
- background: #ffffff;
-}
-
-.c34 svg {
- height: 0.75rem;
- width: auto;
-}
-
-.c34[aria-disabled='true'] {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c34[aria-disabled='true'] .c8 {
- color: #666687;
-}
-
-.c34[aria-disabled='true'] svg > g,
-.c34[aria-disabled='true'] svg path {
- fill: #666687;
-}
-
-.c34[aria-disabled='true']:active {
- border: 1px solid #dcdce4;
- background: #eaeaef;
-}
-
-.c34[aria-disabled='true']:active .c8 {
- color: #666687;
-}
-
-.c34[aria-disabled='true']:active svg > g,
-.c34[aria-disabled='true']:active svg path {
- fill: #666687;
-}
-
-.c34:hover {
- background-color: #f6f6f9;
-}
-
-.c34:active {
- background-color: #eaeaef;
-}
-
-.c34 .c8 {
- color: #32324d;
-}
-
-.c34 svg > g,
-.c34 svg path {
- fill: #32324d;
-}
-
-.c25 {
- 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;
-}
-
-.c21 {
- height: 1px;
- border: none;
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0;
- margin: 0;
-}
-
-.c12 {
- border-color: #dcdce4;
- height: 2rem;
- width: 2rem;
-}
-
-.c12 svg g,
-.c12 svg path {
- fill: #8e8ea9;
-}
-
-.c12:hover svg g,
-.c12:focus svg g,
-.c12:hover svg path,
-.c12:focus svg path {
- fill: #666687;
-}
-
-.c12[aria-disabled='true'] svg path {
- fill: #666687;
-}
-
-.c3 {
- background: #32324d1F;
- inset: 0;
-}
-
-.c6 {
- border-radius: 4px 4px 0 0;
- border-bottom: 1px solid #eaeaef;
-}
-
-.c31 {
- border-radius: 0 0 4px 4px;
- border-top: 1px solid #eaeaef;
-}
-
-.c18 {
- border-bottom: 2px solid #4945ff;
-}
-
-.c16 {
- border-bottom: 2px solid transparent;
-}
-
-.c14[aria-disabled='true'] {
- cursor: not-allowed;
-}
-
-.c27 {
- outline: none;
- box-shadow: 0;
- -webkit-transition-property: border-color,box-shadow,fill;
- transition-property: border-color,box-shadow,fill;
- -webkit-transition-duration: 0.2s;
- transition-duration: 0.2s;
-}
-
-.c27:focus-within {
- border: 1px solid #4945ff;
- box-shadow: #4945ff 0px 0px 0px 2px;
-}
-
-.c29 {
- border: none;
- resize: none;
-}
-
-.c29::-webkit-input-placeholder {
- color: #8e8ea9;
- font-size: 0.875rem;
- color: #8e8ea9;
- opacity: 1;
-}
-
-.c29::-moz-placeholder {
- color: #8e8ea9;
- font-size: 0.875rem;
- color: #8e8ea9;
- opacity: 1;
-}
-
-.c29:-ms-input-placeholder {
- color: #8e8ea9;
- font-size: 0.875rem;
- color: #8e8ea9;
- opacity: 1;
-}
-
-.c29::placeholder {
- color: #8e8ea9;
- font-size: 0.875rem;
- color: #8e8ea9;
- opacity: 1;
-}
-
-.c29:focus-within {
- outline: none;
-}
-
-
-
-
-
-
-
-
-
-
-
- Add new assets
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/tests/server.js b/packages/core/upload/admin/src/components/UploadAssetDialog/tests/server.js
deleted file mode 100644
index f3c2e06bb3..0000000000
--- a/packages/core/upload/admin/src/components/UploadAssetDialog/tests/server.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// mocking window.fetch since msw is not able to give back the res.url param
-
-import { rest } from 'msw';
-import { setupServer } from 'msw/node';
-
-export const server = setupServer(
- rest.get('*/an-image.png', (req, res, ctx) =>
- res(ctx.set('Content-Type', 'image/png'), ctx.body())
- ),
- rest.get('*/a-pdf.pdf', (req, res, ctx) =>
- res(ctx.set('Content-Type', 'application/pdf'), ctx.body())
- ),
- rest.get('*/a-video.mp4', (req, res, ctx) =>
- res(ctx.set('Content-Type', 'video/mp4'), ctx.body())
- ),
- rest.get('*/not-working-like-cors.lutin', (req, res, ctx) => res(ctx.json({}))),
- rest.get('*/some-where-not-existing.jpg', (req, res) => res.networkError('Failed to fetch'))
-);
diff --git a/packages/core/upload/admin/src/hooks/tests/useConfig.test.js b/packages/core/upload/admin/src/hooks/tests/useConfig.test.js
index feda81ee0c..8b68c4217d 100644
--- a/packages/core/upload/admin/src/hooks/tests/useConfig.test.js
+++ b/packages/core/upload/admin/src/hooks/tests/useConfig.test.js
@@ -1,183 +1,73 @@
-import React from 'react';
+import { act, renderHook, waitFor, screen, server } from '@tests/utils';
+import { rest } from 'msw';
-import { lightTheme, ThemeProvider } from '@strapi/design-system';
-import { NotificationsProvider, useFetchClient, useNotification } from '@strapi/helper-plugin';
-import { act, renderHook, waitFor } from '@testing-library/react';
-import { IntlProvider } from 'react-intl';
-import { QueryClient, QueryClientProvider, useQueryClient } from 'react-query';
-import { BrowserRouter as Router, Route } from 'react-router-dom';
-
-import { pageSizes, sortOptions } from '../../constants';
-import pluginId from '../../pluginId';
import { useConfig } from '../useConfig';
-const mockGetResponse = {
- data: {
- data: {
- pageSize: pageSizes[0],
- sort: sortOptions[0].value,
- },
- },
-};
-
-const notificationStatusMock = jest.fn();
-
-jest.mock('@strapi/helper-plugin', () => ({
- ...jest.requireActual('@strapi/helper-plugin'),
- useNotification: () => notificationStatusMock,
- useFetchClient: jest.fn().mockReturnValue({
- put: jest.fn().mockResolvedValue({ data: { data: {} } }),
- get: jest.fn(),
- }),
-}));
-
-const refetchQueriesMock = jest.fn();
-
-jest.mock('react-query', () => ({
- ...jest.requireActual('react-query'),
- useQueryClient: () => ({
- refetchQueries: refetchQueriesMock,
- }),
-}));
-
-const client = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
-});
-
-// eslint-disable-next-line react/prop-types
-function ComponentFixture({ children }) {
- return (
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
- );
-}
-
-function setup(...args) {
- return new Promise((resolve) => {
- act(() => {
- resolve(renderHook(() => useConfig(...args), { wrapper: ComponentFixture }));
- });
- });
-}
-
describe('useConfig', () => {
- beforeEach(() => {
- jest.clearAllMocks();
- });
-
describe('query', () => {
test('does call the get endpoint', async () => {
- const { get } = useFetchClient();
- get.mockReturnValueOnce(mockGetResponse);
-
- const { result } = await setup();
- expect(get).toHaveBeenCalledWith(`/${pluginId}/configuration`);
+ const { result } = renderHook(() => useConfig());
await waitFor(() => expect(result.current.config.isLoading).toBe(false));
- expect(result.current.config.data).toEqual(mockGetResponse.data.data);
+
+ expect(result.current.config.data).toMatchInlineSnapshot(`
+ {
+ "pageSize": 20,
+ "sort": "updatedAt:DESC",
+ }
+ `);
});
test('should still return an object even if the server returns a falsey value', async () => {
- const { get } = useFetchClient();
- get.mockReturnValueOnce({
- data: {
- data: null,
- },
- });
-
- const { result } = await setup();
-
- await waitFor(() => expect(result.current.config.data).toEqual({}));
- });
-
- test('calls toggleNotification in case of error', async () => {
- const { get } = useFetchClient();
- const originalConsoleError = console.error;
- console.error = jest.fn();
-
- get.mockRejectedValueOnce(new Error('Jest mock error'));
- const toggleNotification = useNotification();
- await setup({});
-
- await waitFor(() =>
- expect(toggleNotification).toBeCalledWith({
- type: 'warning',
- message: { id: 'notification.error' },
+ server.use(
+ rest.get('/upload/configuration', (req, res, ctx) => {
+ return res(
+ ctx.json({
+ data: null,
+ })
+ );
})
);
+ const { result } = renderHook(() => useConfig());
+
+ await waitFor(() => expect(result.current.config.data).toEqual({}));
+
+ server.restoreHandlers();
+ });
+
+ test('calls toggleNotification in case of error', async () => {
+ const originalConsoleError = console.error;
+ console.error = jest.fn();
+ server.use(
+ rest.get('/upload/configuration', (req, res, ctx) => {
+ return res(ctx.status(500));
+ })
+ );
+
+ renderHook(() => useConfig());
+
+ await waitFor(() => expect(screen.getByText('notification.error')).toBeInTheDocument());
+
console.error = originalConsoleError;
+ server.restoreHandlers();
});
});
describe('mutation', () => {
test('does call the proper mutation endpoint', async () => {
- const { put } = useFetchClient();
- const queryClient = useQueryClient();
+ const { result } = renderHook(() => useConfig());
- let setupResult;
- await act(async () => {
- setupResult = await setup();
- });
-
- const {
- result: {
- current: { mutateConfig },
- },
- } = setupResult;
-
- const mutateWith = {};
- await act(async () => {
- await mutateConfig.mutateAsync(mutateWith);
- });
-
- expect(put).toHaveBeenCalledWith(`/${pluginId}/configuration`, mutateWith);
- expect(queryClient.refetchQueries).toHaveBeenCalledWith(['upload', 'configuration'], {
- active: true,
- });
- });
-
- test('does handle errors', async () => {
- const { put } = useFetchClient();
- const originalConsoleError = console.error;
- console.error = jest.fn();
-
- const toggleNotification = useNotification();
- put.mockRejectedValueOnce(new Error('Jest mock error'));
-
- const {
- result: { current },
- } = await setup();
- const { mutateConfig } = current;
-
- const mutateWith = {};
- try {
- await act(async () => {
- await mutateConfig.mutateAsync(mutateWith);
+ act(() => {
+ result.current.mutateConfig.mutateAsync({
+ pageSize: 100,
+ sort: 'name:DESC',
});
- } catch {
- expect(toggleNotification).toBeCalledWith({
- type: 'warning',
- message: { id: 'notification.error' },
- });
- }
+ });
- console.error = originalConsoleError;
+ expect(result.current.config.isLoading).toBe(true);
+
+ await waitFor(() => expect(result.current.config.isLoading).toBe(false));
});
});
});
diff --git a/packages/core/upload/admin/src/hooks/tests/useFolder.test.js b/packages/core/upload/admin/src/hooks/tests/useFolder.test.js
index 1d61faca10..e30518e655 100644
--- a/packages/core/upload/admin/src/hooks/tests/useFolder.test.js
+++ b/packages/core/upload/admin/src/hooks/tests/useFolder.test.js
@@ -1,123 +1,58 @@
-import React from 'react';
-
-import { lightTheme, ThemeProvider, useNotifyAT } from '@strapi/design-system';
-import { NotificationsProvider, useFetchClient, useNotification } from '@strapi/helper-plugin';
-import { act, renderHook, waitFor } from '@testing-library/react';
-import { IntlProvider } from 'react-intl';
-import { QueryClient, QueryClientProvider } from 'react-query';
-import { BrowserRouter as Router, Route } from 'react-router-dom';
+import { renderHook, screen, server, waitFor } from '@tests/utils';
+import { rest } from 'msw';
import { useFolder } from '../useFolder';
-const notifyStatusMock = jest.fn();
-
-jest.mock('@strapi/design-system', () => ({
- ...jest.requireActual('@strapi/design-system'),
- useNotifyAT: () => ({
- notifyStatus: notifyStatusMock,
- }),
-}));
-
-const notificationStatusMock = jest.fn();
-
-jest.mock('@strapi/helper-plugin', () => ({
- ...jest.requireActual('@strapi/helper-plugin'),
- useNotification: () => notificationStatusMock,
- useFetchClient: jest.fn().mockReturnValue({
- get: jest.fn().mockResolvedValue({
- data: {
- id: 1,
- },
- }),
- }),
-}));
-
-const client = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
-});
-
-// eslint-disable-next-line react/prop-types
-function ComponentFixture({ children }) {
- return (
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
- );
-}
-
-function setup(...args) {
- return new Promise((resolve) => {
- act(() => {
- resolve(renderHook(() => useFolder(...args), { wrapper: ComponentFixture }));
- });
- });
-}
-
describe('useFolder', () => {
afterEach(() => {
jest.clearAllMocks();
});
test('fetches data from the right URL if no query param was set', async () => {
- const { get } = useFetchClient();
- const { result } = await setup(1, {});
+ const { result } = renderHook(() => useFolder(1));
- await waitFor(() => result.current.isSuccess);
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
- await waitFor(() =>
- expect(get).toBeCalledWith('/upload/folders/1', {
- params: {
- populate: {
- parent: {
- populate: {
- parent: '*',
- },
- },
- },
+ expect(result.current.data).toMatchInlineSnapshot(`
+ {
+ "children": {
+ "count": 2,
},
- })
- );
+ "createdAt": "2023-06-26T12:48:54.054Z",
+ "files": {
+ "count": 0,
+ },
+ "id": 1,
+ "name": "test",
+ "parent": null,
+ "path": "/1",
+ "pathId": 1,
+ "updatedAt": "2023-06-26T12:48:54.054Z",
+ }
+ `);
});
test('it does not fetch, if enabled is set to false', async () => {
- const { get } = useFetchClient();
- const { result } = await setup(1, { enabled: false });
+ const { result } = renderHook(() => useFolder(1, { enabled: false }));
- await waitFor(() => result.current.isSuccess);
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
- expect(get).toBeCalledTimes(0);
+ expect(result.current.data).toBe(undefined);
});
test('calls toggleNotification in case of error', async () => {
- const { get } = useFetchClient();
const originalConsoleError = console.error;
console.error = jest.fn();
- get.mockRejectedValueOnce(new Error('Jest mock error'));
+ server.use(rest.get('/upload/folders/:id', (req, res, ctx) => res(ctx.status(500))));
- const { notifyStatus } = useNotifyAT();
- const toggleNotification = useNotification();
- const { result } = await setup(1, {});
+ const { result } = renderHook(() => useFolder(1));
- await waitFor(() => !result.current.isLoading);
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
- expect(toggleNotification).toBeCalled();
- expect(notifyStatus).not.toBeCalled();
+ expect(screen.getByText('Not found')).toBeInTheDocument();
console.error = originalConsoleError;
+ server.restoreHandlers();
});
});
diff --git a/packages/core/upload/admin/src/hooks/tests/useFolders.test.js b/packages/core/upload/admin/src/hooks/tests/useFolders.test.js
index 1829cfcfd0..0de4694b95 100644
--- a/packages/core/upload/admin/src/hooks/tests/useFolders.test.js
+++ b/packages/core/upload/admin/src/hooks/tests/useFolders.test.js
@@ -1,223 +1,138 @@
-import React from 'react';
-
-import { lightTheme, ThemeProvider, useNotifyAT } from '@strapi/design-system';
-import { NotificationsProvider, useFetchClient, useNotification } from '@strapi/helper-plugin';
-import { act, renderHook, waitFor } from '@testing-library/react';
-import { IntlProvider } from 'react-intl';
-import { QueryClient, QueryClientProvider } from 'react-query';
-import { BrowserRouter as Router, Route } from 'react-router-dom';
+import { renderHook, waitFor, screen, server } from '@tests/utils';
+import { rest } from 'msw';
import { useFolders } from '../useFolders';
-const notifyStatusMock = jest.fn();
-
-jest.mock('@strapi/design-system', () => ({
- ...jest.requireActual('@strapi/design-system'),
- useNotifyAT: () => ({
- notifyStatus: notifyStatusMock,
- }),
-}));
-
-const notificationStatusMock = jest.fn();
-
-jest.mock('@strapi/helper-plugin', () => ({
- ...jest.requireActual('@strapi/helper-plugin'),
- useNotification: () => notificationStatusMock,
- useFetchClient: jest.fn().mockReturnValue({
- get: jest.fn().mockResolvedValue({
- data: {
- id: 1,
- },
- }),
- }),
-}));
-
-const client = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
-});
-
-// eslint-disable-next-line react/prop-types
-function ComponentFixture({ children }) {
- return (
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
- );
-}
-
-function setup(...args) {
- return new Promise((resolve) => {
- act(() => {
- resolve(renderHook(() => useFolders(...args), { wrapper: ComponentFixture }));
- });
- });
-}
-
describe('useFolders', () => {
afterEach(() => {
jest.clearAllMocks();
});
test('fetches data from the right URL if no query param was set', async () => {
- const { get } = useFetchClient();
- const { result } = await setup({});
+ const { result } = renderHook(() => useFolders());
- await waitFor(() => result.current.isSuccess);
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
- const expected = {
- pagination: {
- pageSize: -1,
- },
- filters: {
- $and: [
- {
- parent: {
- id: {
- $null: true,
- },
- },
+ expect(result.current.data).toMatchInlineSnapshot(`
+ [
+ {
+ "children": {
+ "count": 2,
},
- ],
- },
- };
-
- await waitFor(() =>
- expect(get).toBeCalledWith(`/upload/folders`, {
- params: expected,
- })
- );
+ "createdAt": "2023-06-26T12:48:54.054Z",
+ "files": {
+ "count": 0,
+ },
+ "id": 1,
+ "name": "test",
+ "path": "/1",
+ "pathId": 1,
+ "updatedAt": "2023-06-26T12:48:54.054Z",
+ },
+ ]
+ `);
});
test('does not use parent filter in params if _q', async () => {
- const { get } = useFetchClient();
+ const { result } = renderHook(() =>
+ useFolders({
+ query: { folder: 5, _q: 'something', filters: { $and: [{ something: 'true' }] } },
+ })
+ );
- await setup({
- query: { folder: 5, _q: 'something', filters: { $and: [{ something: 'true' }] } },
- });
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
- const expected = {
- filters: {
- $and: [
- {
- something: 'true',
+ expect(result.current.data).toMatchInlineSnapshot(`
+ [
+ {
+ "children": {
+ "count": 2,
},
- ],
- },
- pagination: {
- pageSize: -1,
- },
- _q: 'something',
- };
+ "createdAt": "2023-06-26T12:48:54.054Z",
+ "files": {
+ "count": 0,
+ },
+ "id": 1,
+ "name": "something",
+ "path": "/1",
+ "pathId": 1,
+ "updatedAt": "2023-06-26T12:48:54.054Z",
+ },
+ ]
+ `);
- expect(get).toBeCalledWith(`/upload/folders`, {
- params: expected,
- });
+ expect(result.current.data[0].name).toBe('something');
});
test('fetches data from the right URL if a query param was set', async () => {
- const { get } = useFetchClient();
- const { result } = await setup({ query: { folder: 1 } });
+ const { result } = renderHook(() => useFolders({ query: { folder: 1 } }));
- await waitFor(() => result.current.isSuccess);
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
- const expected = {
- pagination: {
- pageSize: -1,
- },
- filters: {
- $and: [
- {
- parent: {
- id: 1,
- },
+ expect(result.current.data).toMatchInlineSnapshot(`
+ [
+ {
+ "children": {
+ "count": 0,
},
- ],
- },
- };
-
- expect(get).toBeCalledWith(`/upload/folders`, {
- params: expected,
- });
- });
-
- test('allows to merge filter query params using filters.$and', async () => {
- const { get } = useFetchClient();
- await setup({
- query: { folder: 5, filters: { $and: [{ something: 'true' }] } },
- });
-
- const expected = {
- filters: {
- $and: [
- {
- something: 'true',
+ "createdAt": "2023-06-26T12:49:31.354Z",
+ "files": {
+ "count": 3,
},
- {
- parent: {
- id: 5,
- },
+ "id": 3,
+ "name": "2022",
+ "path": "/1/3",
+ "pathId": 3,
+ "updatedAt": "2023-06-26T12:49:31.354Z",
+ },
+ {
+ "children": {
+ "count": 0,
},
- ],
- },
- pagination: {
- pageSize: -1,
- },
- };
+ "createdAt": "2023-06-26T12:49:08.466Z",
+ "files": {
+ "count": 3,
+ },
+ "id": 2,
+ "name": "2023",
+ "path": "/1/2",
+ "pathId": 2,
+ "updatedAt": "2023-06-26T12:49:08.466Z",
+ },
+ ]
+ `);
- expect(get).toBeCalledWith(`/upload/folders`, {
- params: expected,
+ result.current.data.forEach((folder) => {
+ /**
+ * We're passing a "current folder" in the query, which means
+ * any folders returned should include the current folder's ID
+ * in it's path because this get's the children of current.
+ */
+ expect(folder.path.includes('1')).toBe(true);
});
});
test('it does not fetch, if enabled is set to false', async () => {
- const { get } = useFetchClient();
- const { result } = await setup({ enabled: false });
+ const { result } = renderHook(() => useFolders({ enabled: false }));
- await waitFor(() => result.current.isSuccess);
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
- expect(get).toBeCalledTimes(0);
- });
-
- test('calls notifyStatus in case of success', async () => {
- const { notifyStatus } = useNotifyAT();
- const toggleNotification = useNotification();
- await setup({});
-
- await waitFor(() => {
- expect(notifyStatus).toBeCalledWith('The folders have finished loading.');
- });
-
- expect(toggleNotification).toBeCalledTimes(0);
+ expect(result.current.data).toBe(undefined);
});
test('calls toggleNotification in case of error', async () => {
- const { get } = useFetchClient();
const originalConsoleError = console.error;
console.error = jest.fn();
- get.mockRejectedValueOnce(new Error('Jest mock error'));
+ server.use(rest.get('/upload/folders', (req, res, ctx) => res(ctx.status(500))));
- const { notifyStatus } = useNotifyAT();
- const toggleNotification = useNotification();
- await setup({});
+ const { result } = renderHook(() => useFolders());
- await waitFor(() => expect(toggleNotification).toBeCalled());
- await waitFor(() => expect(notifyStatus).not.toBeCalled());
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
+
+ await waitFor(() => expect(screen.getByText('notification.error')).toBeInTheDocument());
console.error = originalConsoleError;
+ server.restoreHandlers();
});
});
diff --git a/packages/core/upload/admin/src/hooks/tests/useModalQueryParams.test.js b/packages/core/upload/admin/src/hooks/tests/useModalQueryParams.test.js
index 3e7408f86b..3f6b66bb05 100644
--- a/packages/core/upload/admin/src/hooks/tests/useModalQueryParams.test.js
+++ b/packages/core/upload/admin/src/hooks/tests/useModalQueryParams.test.js
@@ -1,45 +1,7 @@
-import React from 'react';
-
-import { lightTheme, ThemeProvider } from '@strapi/design-system';
-import { NotificationsProvider } from '@strapi/helper-plugin';
-import { act, renderHook } from '@testing-library/react';
-import { IntlProvider } from 'react-intl';
-import { QueryClient, QueryClientProvider } from 'react-query';
-import { MemoryRouter } from 'react-router-dom';
+import { act, renderHook, waitFor } from '@tests/utils';
import useModalQueryParams from '../useModalQueryParams';
-/**
- * TODO: we should set up MSW for these tests
- */
-function setup(...args) {
- return renderHook(() => useModalQueryParams(...args), {
- wrapper({ children }) {
- const client = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
- });
-
- return (
-
-
-
-
-
- {children}
-
-
-
-
-
- );
- },
- });
-}
-
const FIXTURE_QUERY = {
page: 1,
sort: 'updatedAt:DESC',
@@ -54,17 +16,15 @@ describe('useModalQueryParams', () => {
jest.clearAllMocks();
});
- test('setup proper defaults', () => {
- const {
- result: {
- current: [{ queryObject, rawQuery }, callbacks],
- },
- } = setup();
+ test('setup proper defaults', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
- expect(queryObject).toStrictEqual(FIXTURE_QUERY);
- expect(rawQuery).toBe('page=1&sort=updatedAt:DESC&pageSize=10');
+ expect(result.current[0].queryObject).toStrictEqual(FIXTURE_QUERY);
+ expect(result.current[0].rawQuery).toMatchInlineSnapshot(
+ `"page=1&sort=updatedAt:DESC&pageSize=10"`
+ );
- expect(callbacks).toStrictEqual({
+ expect(result.current[1]).toStrictEqual({
onChangeFilters: expect.any(Function),
onChangeFolder: expect.any(Function),
onChangePage: expect.any(Function),
@@ -72,29 +32,25 @@ describe('useModalQueryParams', () => {
onChangeSort: expect.any(Function),
onChangeSearch: expect.any(Function),
});
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
});
- test('set initial state', () => {
- const {
- result: { current },
- } = setup();
+ test('handles initial state', async () => {
+ const { result } = renderHook(() => useModalQueryParams({ state: true }));
- expect(current[0].queryObject).toStrictEqual(FIXTURE_QUERY);
- });
-
- test('handles initial state', () => {
- const {
- result: { current },
- } = setup({ state: true });
-
- expect(current[0].queryObject).toStrictEqual({
+ expect(result.current[0].queryObject).toStrictEqual({
...FIXTURE_QUERY,
state: true,
});
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
});
- test('onChangeFilters', () => {
- const { result } = setup();
+ test('onChangeFilters', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangeFilters([{ some: 'thing' }]);
@@ -102,6 +58,7 @@ describe('useModalQueryParams', () => {
expect(result.current[0].queryObject).toStrictEqual({
...FIXTURE_QUERY,
+ pageSize: 20,
filters: {
...FIXTURE_QUERY.filters,
$and: [
@@ -113,8 +70,10 @@ describe('useModalQueryParams', () => {
});
});
- test('onChangeFolder', () => {
- const { result } = setup();
+ test('onChangeFolder', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangeFolder({ id: 1 }, '/1');
@@ -122,6 +81,7 @@ describe('useModalQueryParams', () => {
expect(result.current[0].queryObject).toStrictEqual({
...FIXTURE_QUERY,
+ pageSize: 20,
folder: {
id: 1,
},
@@ -129,8 +89,10 @@ describe('useModalQueryParams', () => {
});
});
- test('onChangePage', () => {
- const { result } = setup();
+ test('onChangePage', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangePage({ id: 1 });
@@ -138,14 +100,17 @@ describe('useModalQueryParams', () => {
expect(result.current[0].queryObject).toStrictEqual({
...FIXTURE_QUERY,
+ pageSize: 20,
page: {
id: 1,
},
});
});
- test('onChangePageSize', () => {
- const { result } = setup();
+ test('onChangePageSize', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangePageSize(5);
@@ -157,8 +122,10 @@ describe('useModalQueryParams', () => {
});
});
- test('onChangePageSize - converts string to numbers', () => {
- const { result } = setup();
+ test('onChangePageSize - converts string to numbers', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangePageSize('5');
@@ -170,8 +137,10 @@ describe('useModalQueryParams', () => {
});
});
- test('onChangeSort', () => {
- const { result } = setup();
+ test('onChangeSort', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangeSort('something:else');
@@ -179,12 +148,15 @@ describe('useModalQueryParams', () => {
expect(result.current[0].queryObject).toStrictEqual({
...FIXTURE_QUERY,
+ pageSize: 20,
sort: 'something:else',
});
});
- test('onChangeSearch', () => {
- const { result } = setup();
+ test('onChangeSearch', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangeSearch('something');
@@ -192,12 +164,15 @@ describe('useModalQueryParams', () => {
expect(result.current[0].queryObject).toStrictEqual({
...FIXTURE_QUERY,
+ pageSize: 20,
_q: 'something',
});
});
- test('onChangeSearch - empty string resets all values and removes _q and page', () => {
- const { result } = setup();
+ test('onChangeSearch - empty string resets all values and removes _q and page', async () => {
+ const { result } = renderHook(() => useModalQueryParams());
+
+ await waitFor(() => expect(result.current[0].queryObject.pageSize).toBe(20));
act(() => {
result.current[1].onChangePage({ id: 1 });
@@ -211,6 +186,9 @@ describe('useModalQueryParams', () => {
result.current[1].onChangeSearch('');
});
- expect(result.current[0].queryObject).toStrictEqual(FIXTURE_QUERY);
+ expect(result.current[0].queryObject).toStrictEqual({
+ ...FIXTURE_QUERY,
+ pageSize: 20,
+ });
});
});
diff --git a/packages/core/upload/admin/src/hooks/useConfig.js b/packages/core/upload/admin/src/hooks/useConfig.js
index 858e762b83..2b4f7ded68 100644
--- a/packages/core/upload/admin/src/hooks/useConfig.js
+++ b/packages/core/upload/admin/src/hooks/useConfig.js
@@ -1,5 +1,5 @@
import { useFetchClient, useNotification, useTracking } from '@strapi/helper-plugin';
-import { useMutation, useQuery, useQueryClient } from 'react-query';
+import { useMutation, useQuery } from 'react-query';
import pluginId from '../pluginId';
@@ -7,7 +7,6 @@ const endpoint = `/${pluginId}/configuration`;
const queryKey = [pluginId, 'configuration'];
export const useConfig = () => {
- const queryClient = useQueryClient();
const { trackUsage } = useTracking();
const toggleNotification = useNotification();
const { get, put } = useFetchClient();
@@ -33,18 +32,23 @@ export const useConfig = () => {
}
);
- const putMutation = useMutation(async (body) => put(endpoint, body), {
- onSuccess() {
- trackUsage('didEditMediaLibraryConfig');
- queryClient.refetchQueries(queryKey, { active: true });
+ const putMutation = useMutation(
+ async (body) => {
+ await put(endpoint, body);
},
- onError() {
- return toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
- },
- });
+ {
+ onSuccess() {
+ trackUsage('didEditMediaLibraryConfig');
+ config.refetch();
+ },
+ onError() {
+ return toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+ },
+ }
+ );
return {
config,
diff --git a/packages/core/upload/admin/src/hooks/useFolder.js b/packages/core/upload/admin/src/hooks/useFolder.js
index f9b27b3832..288dd75015 100644
--- a/packages/core/upload/admin/src/hooks/useFolder.js
+++ b/packages/core/upload/admin/src/hooks/useFolder.js
@@ -4,45 +4,45 @@ import { useQuery } from 'react-query';
import pluginId from '../pluginId';
import { getTrad } from '../utils';
-export const useFolder = (id, { enabled = true }) => {
+export const useFolder = (id, { enabled = true } = {}) => {
const toggleNotification = useNotification();
const { get } = useFetchClient();
- const fetchFolder = async () => {
- try {
- const params = {
- populate: {
- parent: {
- populate: {
- parent: '*',
+ const { data, error, isLoading } = useQuery(
+ [pluginId, 'folder', id],
+ async () => {
+ const {
+ data: { data },
+ } = await get(`/upload/folders/${id}`, {
+ params: {
+ populate: {
+ parent: {
+ populate: {
+ parent: '*',
+ },
},
},
},
- };
- const {
- data: { data },
- } = await get(`/upload/folders/${id}`, { params });
-
- return data;
- } catch (err) {
- toggleNotification({
- type: 'warning',
- message: {
- id: getTrad('notification.warning.404'),
- defaultMessage: 'Not found',
- },
});
- throw err;
+ return data;
+ },
+ {
+ retry: false,
+ enabled,
+ staleTime: 0,
+ cacheTime: 0,
+ onError() {
+ toggleNotification({
+ type: 'warning',
+ message: {
+ id: getTrad('notification.warning.404'),
+ defaultMessage: 'Not found',
+ },
+ });
+ },
}
- };
-
- const { data, error, isLoading } = useQuery([pluginId, 'folder', id], fetchFolder, {
- retry: false,
- enabled,
- staleTime: 0,
- cacheTime: 0,
- });
+ );
return { data, error, isLoading };
};
diff --git a/packages/core/upload/admin/src/hooks/useFolders.js b/packages/core/upload/admin/src/hooks/useFolders.js
index 10e5d7e81c..3658e42601 100644
--- a/packages/core/upload/admin/src/hooks/useFolders.js
+++ b/packages/core/upload/admin/src/hooks/useFolders.js
@@ -1,3 +1,5 @@
+import * as React from 'react';
+
import { useNotifyAT } from '@strapi/design-system';
import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import { stringify } from 'qs';
@@ -6,7 +8,7 @@ import { useQuery } from 'react-query';
import pluginId from '../pluginId';
-export const useFolders = ({ enabled = true, query = {} }) => {
+export const useFolders = ({ enabled = true, query = {} } = {}) => {
const { formatMessage } = useIntl();
const toggleNotification = useNotification();
const { notifyStatus } = useNotifyAT();
@@ -44,39 +46,38 @@ export const useFolders = ({ enabled = true, query = {} }) => {
};
}
- const fetchFolders = async () => {
- try {
+ const { data, error, isLoading } = useQuery(
+ [pluginId, 'folders', stringify(params)],
+ async () => {
const {
data: { data },
} = await get('/upload/folders', { params });
+ return data;
+ },
+ {
+ enabled,
+ staleTime: 0,
+ cacheTime: 0,
+ onError() {
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+ },
+ }
+ );
+
+ React.useEffect(() => {
+ if (data) {
notifyStatus(
formatMessage({
id: 'list.asset.at.finished',
defaultMessage: 'The folders have finished loading.',
})
);
-
- return data;
- } catch (err) {
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
-
- throw err;
}
- };
-
- const { data, error, isLoading } = useQuery(
- [pluginId, 'folders', stringify(params)],
- fetchFolders,
- {
- enabled,
- staleTime: 0,
- cacheTime: 0,
- }
- );
+ }, [data, formatMessage, notifyStatus]);
return { data, error, isLoading };
};
diff --git a/packages/core/upload/admin/src/pages/SettingsPage/index.js b/packages/core/upload/admin/src/pages/SettingsPage/index.js
index ecb7cfdbf2..94c300a358 100644
--- a/packages/core/upload/admin/src/pages/SettingsPage/index.js
+++ b/packages/core/upload/admin/src/pages/SettingsPage/index.js
@@ -1,4 +1,4 @@
-import React, { useEffect, useReducer, useRef } from 'react';
+import React, { useReducer } from 'react';
import {
Box,
@@ -22,10 +22,10 @@ import {
useOverlayBlocker,
} from '@strapi/helper-plugin';
import { Check } from '@strapi/icons';
-import axios from 'axios';
import isEqual from 'lodash/isEqual';
import { Helmet } from 'react-helmet';
import { useIntl } from 'react-intl';
+import { useMutation, useQuery } from 'react-query';
import { PERMISSIONS } from '../../constants';
import { getTrad } from '../../utils';
@@ -38,50 +38,50 @@ export const SettingsPage = () => {
const { lockApp, unlockApp } = useOverlayBlocker();
const toggleNotification = useNotification();
const { get, put } = useFetchClient();
+
useFocusWhenNavigate();
- const [{ initialData, isLoading, isSubmiting, modifiedData }, dispatch] = useReducer(
- reducer,
- initialState,
- init
- );
+ const [{ initialData, modifiedData }, dispatch] = useReducer(reducer, initialState, init);
- const isMounted = useRef(true);
+ const { data, isLoading, refetch } = useQuery({
+ queryKey: ['upload', 'settings'],
+ async queryFn() {
+ const {
+ data: { data },
+ } = await get('/upload/settings');
- useEffect(() => {
- const CancelToken = axios.CancelToken;
- const source = CancelToken.source();
+ return data;
+ },
+ });
- const getData = async () => {
- try {
- const {
- data: { data },
- } = await get('/upload/settings', {
- cancelToken: source.token,
- });
-
- dispatch({
- type: 'GET_DATA_SUCCEEDED',
- data,
- });
- } catch (err) {
- console.error(err);
- }
- };
-
- if (isMounted.current) {
- getData();
+ React.useEffect(() => {
+ if (data) {
+ dispatch({
+ type: 'GET_DATA_SUCCEEDED',
+ data,
+ });
}
-
- return () => {
- source.cancel('Operation canceled by the user.');
- isMounted.current = false;
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ }, [data]);
const isSaveButtonDisabled = isEqual(initialData, modifiedData);
+ const { mutateAsync, isLoading: isSubmiting } = useMutation({
+ async mutationFn(body) {
+ return put('/upload/settings', body);
+ },
+ onSuccess() {
+ refetch();
+
+ toggleNotification({
+ type: 'success',
+ message: { id: 'notification.form.success.fields' },
+ });
+ },
+ onError(err) {
+ console.error(err);
+ },
+ });
+
const handleSubmit = async (e) => {
e.preventDefault();
@@ -91,24 +91,7 @@ export const SettingsPage = () => {
lockApp();
- dispatch({ type: 'ON_SUBMIT' });
-
- try {
- await put('/upload/settings', modifiedData);
-
- dispatch({
- type: 'SUBMIT_SUCCEEDED',
- });
-
- toggleNotification({
- type: 'success',
- message: { id: 'notification.form.success.fields' },
- });
- } catch (err) {
- console.error(err);
-
- dispatch({ type: 'ON_SUBMIT_ERROR' });
- }
+ await mutateAsync(modifiedData);
unlockApp();
};
@@ -138,7 +121,6 @@ export const SettingsPage = () => {
primaryAction={
}
@@ -175,7 +157,6 @@ export const SettingsPage = () => {
{
{
// eslint-disable-next-line consistent-return
produce(state, (drafState) => {
switch (action.type) {
- case 'CANCEL_CHANGES': {
- drafState.modifiedData = state.initialData;
- break;
- }
case 'GET_DATA_SUCCEEDED': {
- drafState.isLoading = false;
drafState.initialData = action.data;
drafState.modifiedData = action.data;
break;
@@ -36,19 +29,6 @@ const reducer = (state, action) =>
set(drafState, ['modifiedData', ...action.keys.split('.')], action.value);
break;
}
- case 'ON_SUBMIT': {
- drafState.isSubmiting = true;
- break;
- }
- case 'SUBMIT_SUCCEEDED': {
- drafState.initialData = state.modifiedData;
- drafState.isSubmiting = false;
- break;
- }
- case 'ON_SUBMIT_ERROR': {
- drafState.isSubmiting = false;
- break;
- }
default:
return state;
}
diff --git a/packages/core/upload/admin/src/pages/SettingsPage/tests/index.test.js b/packages/core/upload/admin/src/pages/SettingsPage/tests/index.test.js
index 5d8c71131b..72ce9fef93 100644
--- a/packages/core/upload/admin/src/pages/SettingsPage/tests/index.test.js
+++ b/packages/core/upload/admin/src/pages/SettingsPage/tests/index.test.js
@@ -1,874 +1,34 @@
-/**
- *
- * Tests for SettingsPage
- *
- */
-
import React from 'react';
-import { lightTheme, ThemeProvider } from '@strapi/design-system';
-import { render, waitFor } from '@testing-library/react';
-import { IntlProvider } from 'react-intl';
+import { render, waitFor } from '@tests/utils';
import { SettingsPage } from '../index';
-import server from './utils/server';
+describe('SettingsPage', () => {
+ it('renders', async () => {
+ const { getByRole, queryByText } = render();
-jest.mock('@strapi/helper-plugin', () => ({
- ...jest.requireActual('@strapi/helper-plugin'),
- useNotification: jest.fn(),
- useOverlayBlocker: () => ({ lockApp: jest.fn(), unlockApp: jest.fn() }),
- useFocusWhenNavigate: jest.fn(),
-}));
+ await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
-const App = (
-
-
-
-
-
-);
+ expect(getByRole('heading', { name: 'Media Library' })).toBeInTheDocument();
+ expect(getByRole('heading', { name: 'Asset management' })).toBeInTheDocument();
-describe('Upload | SettingsPage', () => {
- beforeAll(() => server.listen());
+ expect(getByRole('button', { name: 'Save' })).toBeInTheDocument();
- beforeEach(() => {
- jest.clearAllMocks();
- });
-
- afterEach(() => server.resetHandlers());
-
- afterAll(() => server.close());
-
- it('renders and matches the snapshot', async () => {
- const { container, getByText } = render(App);
-
- await waitFor(() =>
- expect(
- getByText(
- 'Enabling this option will automatically rotate the image according to EXIF orientation tag.'
- )
- ).toBeInTheDocument()
- );
-
- expect(container).toMatchInlineSnapshot(`
- .c41 {
- 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;
- font-size: 2rem;
- line-height: 1.25;
- color: #32324d;
- }
-
- .c11 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #ffffff;
- }
-
- .c12 {
- font-size: 1rem;
- line-height: 1.5;
- color: #666687;
- }
-
- .c20 {
- font-weight: 500;
- font-size: 1rem;
- line-height: 1.25;
- color: #32324d;
- }
-
- .c25 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #32324d;
- }
-
- .c33 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #666687;
- text-transform: uppercase;
- }
-
- .c35 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #4945ff;
- text-transform: uppercase;
- }
-
- .c37 {
- font-size: 0.75rem;
- line-height: 1.33;
- color: #666687;
- }
-
- .c39 {
- font-size: 0.75rem;
- line-height: 1.33;
- font-weight: 600;
- color: #b72b1a;
- text-transform: uppercase;
- }
-
- .c1 {
- background: #f6f6f9;
- padding-top: 40px;
- padding-right: 56px;
- padding-bottom: 40px;
- padding-left: 56px;
- }
-
- .c3 {
- min-width: 0;
- }
-
- .c7 {
- background: #4945ff;
- padding: 8px;
- padding-right: 16px;
- padding-left: 16px;
- border-radius: 4px;
- border-color: #4945ff;
- border: 1px solid #4945ff;
- cursor: pointer;
- }
-
- .c13 {
- padding-right: 56px;
- padding-left: 56px;
- }
-
- .c15 {
- padding-bottom: 56px;
- }
-
- .c18 {
- background: #ffffff;
- padding: 24px;
- border-radius: 4px;
- box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
- }
-
- .c23 {
- max-width: 320px;
- }
-
- .c27 {
- background: #f6f6f9;
- padding: 4px;
- border-radius: 4px;
- border-style: solid;
- border-width: 1px;
- border-color: #dcdce4;
- position: relative;
- cursor: pointer;
- }
-
- .c30 {
- background: transparent;
- padding-top: 8px;
- padding-right: 12px;
- padding-bottom: 8px;
- padding-left: 12px;
- border-radius: 4px;
- border-color: #f6f6f9;
- border: 1px solid #f6f6f9;
- -webkit-flex: 1 1 50%;
- -ms-flex: 1 1 50%;
- flex: 1 1 50%;
- }
-
- .c34 {
- background: #ffffff;
- padding-right: 12px;
- padding-left: 12px;
- border-radius: 4px;
- border-color: #dcdce4;
- border: 1px solid #dcdce4;
- -webkit-flex: 1 1 50%;
- -ms-flex: 1 1 50%;
- flex: 1 1 50%;
- }
-
- .c38 {
- background: #ffffff;
- padding-top: 8px;
- padding-right: 12px;
- padding-bottom: 8px;
- padding-left: 12px;
- border-radius: 4px;
- border-color: #dcdce4;
- border: 1px solid #dcdce4;
- -webkit-flex: 1 1 50%;
- -ms-flex: 1 1 50%;
- flex: 1 1 50%;
- }
-
- .c40 {
- background: transparent;
- padding-right: 12px;
- padding-left: 12px;
- border-radius: 4px;
- border-color: #f6f6f9;
- border: 1px solid #f6f6f9;
- -webkit-flex: 1 1 50%;
- -ms-flex: 1 1 50%;
- flex: 1 1 50%;
- }
-
- .c2 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
- justify-content: space-between;
- }
-
- .c4 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- }
-
- .c8 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- gap: 8px;
- }
-
- .c17 {
- -webkit-align-items: stretch;
- -webkit-box-align: stretch;
- -ms-flex-align: stretch;
- align-items: stretch;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- gap: 12;
- }
-
- .c19 {
- -webkit-align-items: stretch;
- -webkit-box-align: stretch;
- -ms-flex-align: stretch;
- align-items: stretch;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- gap: 16px;
- }
-
- .c24 {
- -webkit-align-items: stretch;
- -webkit-box-align: stretch;
- -ms-flex-align: stretch;
- align-items: stretch;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- gap: 4px;
- }
-
- .c28 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap;
- }
-
- .c31 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
- align-items: center;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- }
-
- .c9 {
- position: relative;
- outline: none;
- }
-
- .c9 > svg {
- height: 12px;
- width: 12px;
- }
-
- .c9 > svg > g,
- .c9 > svg path {
- fill: #ffffff;
- }
-
- .c9[aria-disabled='true'] {
- pointer-events: none;
- }
-
- .c9: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;
- }
-
- .c9:focus-visible {
- outline: none;
- }
-
- .c9:focus-visible:after {
- border-radius: 8px;
- content: '';
- position: absolute;
- top: -5px;
- bottom: -5px;
- left: -5px;
- right: -5px;
- border: 2px solid #4945ff;
- }
-
- .c10 {
- height: 2rem;
- }
-
- .c10 svg {
- height: 0.75rem;
- width: auto;
- }
-
- .c10[aria-disabled='true'] {
- border: 1px solid #dcdce4;
- background: #eaeaef;
- }
-
- .c10[aria-disabled='true'] .c5 {
- color: #666687;
- }
-
- .c10[aria-disabled='true'] svg > g,
- .c10[aria-disabled='true'] svg path {
- fill: #666687;
- }
-
- .c10[aria-disabled='true']:active {
- border: 1px solid #dcdce4;
- background: #eaeaef;
- }
-
- .c10[aria-disabled='true']:active .c5 {
- color: #666687;
- }
-
- .c10[aria-disabled='true']:active svg > g,
- .c10[aria-disabled='true']:active svg path {
- fill: #666687;
- }
-
- .c10:hover {
- border: 1px solid #7b79ff;
- background: #7b79ff;
- }
-
- .c10:active {
- border: 1px solid #4945ff;
- background: #4945ff;
- }
-
- .c10 svg > g,
- .c10 svg path {
- fill: #ffffff;
- }
-
- .c26 {
- 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;
- }
-
- .c21 {
- display: grid;
- grid-template-columns: repeat(12,1fr);
- gap: 24px;
- }
-
- .c22 {
- grid-column: span 6;
- max-width: 100%;
- }
-
- .c14 {
- display: grid;
- grid-template-columns: 1fr;
- }
-
- .c16 {
- overflow-x: hidden;
- }
-
- .c0:focus-visible {
- outline: none;
- }
-
- .c29 {
- outline: none;
- box-shadow: 0;
- -webkit-transition-property: border-color,box-shadow,fill;
- transition-property: border-color,box-shadow,fill;
- -webkit-transition-duration: 0.2s;
- transition-duration: 0.2s;
- }
-
- .c29:focus-within {
- border: 1px solid #4945ff;
- box-shadow: #4945ff 0px 0px 0px 2px;
- }
-
- .c32 {
- padding-top: 6px;
- padding-bottom: 6px;
- }
-
- .c36 {
- height: 100%;
- left: 0;
- opacity: 0;
- position: absolute;
- top: 0;
- z-index: 0;
- width: 100%;
- }
-
- @media (max-width:68.75rem) {
- .c22 {
- grid-column: span 12;
- }
- }
-
- @media (max-width:34.375rem) {
- .c22 {
- grid-column: span;
- }
- }
-
-
-
-
-
-
-
- `);
+ expect(getByRole('checkbox', { name: 'responsiveDimensions' })).toBeInTheDocument();
+ expect(getByRole('checkbox', { name: 'sizeOptimization' })).toBeInTheDocument();
+ expect(getByRole('checkbox', { name: 'autoOrientation' })).toBeInTheDocument();
});
it('should display the form correctly with the initial values', async () => {
- const { getByTestId } = render(App);
+ const { getByRole, queryByText } = render();
- await waitFor(() => {
- const responsiveDimension = getByTestId('responsiveDimensions');
- const sizeOptimization = getByTestId('sizeOptimization');
- const autoOrientation = getByTestId('autoOrientation');
- const saveButton = getByTestId('save-button');
+ await waitFor(() => expect(queryByText('Loading content.')).not.toBeInTheDocument());
- expect(responsiveDimension.checked).toBe(true);
- expect(autoOrientation.checked).toBe(true);
- expect(sizeOptimization.checked).toBe(false);
- expect(saveButton).toBeDisabled();
- });
+ expect(getByRole('button', { name: 'Save' })).toBeDisabled();
+
+ expect(getByRole('checkbox', { name: 'responsiveDimensions' })).toBeChecked();
+ expect(getByRole('checkbox', { name: 'sizeOptimization' })).toBeChecked();
+ expect(getByRole('checkbox', { name: 'autoOrientation' })).toBeChecked();
});
});
diff --git a/packages/core/upload/admin/src/pages/SettingsPage/tests/reducer.test.js b/packages/core/upload/admin/src/pages/SettingsPage/tests/reducer.test.js
index 981c39838f..b7e367fd2a 100644
--- a/packages/core/upload/admin/src/pages/SettingsPage/tests/reducer.test.js
+++ b/packages/core/upload/admin/src/pages/SettingsPage/tests/reducer.test.js
@@ -1,24 +1,6 @@
import reducer from '../reducer';
-describe('MEDIA LIBRARY | pages | SettingsPage | reducer', () => {
- describe('CANCEL_CHANGES', () => {
- it('should set the modifiedData with the initialData', () => {
- const action = {
- type: 'CANCEL_CHANGES',
- };
- const state = {
- initialData: 'test',
- modifiedData: 'new test',
- };
- const expected = {
- initialData: 'test',
- modifiedData: 'test',
- };
-
- expect(reducer(state, action)).toEqual(expected);
- });
- });
-
+describe('SettingsPage | reducer', () => {
describe('GET_DATA_SUCCEEDED', () => {
it('should set the modifiedData and the initialData correctly', () => {
const action = {
@@ -27,12 +9,10 @@ describe('MEDIA LIBRARY | pages | SettingsPage | reducer', () => {
};
const state = {
initialData: null,
- isLoading: true,
modifiedData: null,
};
const expected = {
initialData: { test: true },
- isLoading: false,
modifiedData: { test: true },
};
@@ -51,40 +31,12 @@ describe('MEDIA LIBRARY | pages | SettingsPage | reducer', () => {
initialData: {
responsiveDimensions: true,
},
- isLoading: false,
modifiedData: {
responsiveDimensions: true,
},
};
const expected = {
initialData: { responsiveDimensions: true },
- isLoading: false,
- modifiedData: { responsiveDimensions: false },
- };
-
- expect(reducer(state, action)).toEqual(expected);
- });
- });
-
- describe('SUBMIT_SUCCEEDED', () => {
- it('should set the initialData with the modifiedData correctly', () => {
- const action = {
- type: 'SUBMIT_SUCCEEDED',
- };
- const state = {
- initialData: {
- responsiveDimensions: true,
- },
- isLoading: false,
- isSubmiting: true,
- modifiedData: {
- responsiveDimensions: false,
- },
- };
- const expected = {
- initialData: { responsiveDimensions: false },
- isLoading: false,
- isSubmiting: false,
modifiedData: { responsiveDimensions: false },
};
diff --git a/packages/core/upload/admin/src/pages/SettingsPage/tests/utils/server.js b/packages/core/upload/admin/src/pages/SettingsPage/tests/utils/server.js
deleted file mode 100644
index 6f8a2dd190..0000000000
--- a/packages/core/upload/admin/src/pages/SettingsPage/tests/utils/server.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { rest } from 'msw';
-import { setupServer } from 'msw/node';
-
-const handlers = [
- rest.get('*/settings', (req, res, ctx) => {
- return res(
- ctx.status(200),
- ctx.json({
- data: { autoOrientation: true, responsiveDimensions: true, sizeOptimization: false },
- })
- );
- }),
-];
-
-const server = setupServer(...handlers);
-
-export default server;
diff --git a/packages/core/upload/admin/src/utils/tests/downloadFile.test.js b/packages/core/upload/admin/src/utils/tests/downloadFile.test.js
index 38380820f0..fa7ca36cc8 100644
--- a/packages/core/upload/admin/src/utils/tests/downloadFile.test.js
+++ b/packages/core/upload/admin/src/utils/tests/downloadFile.test.js
@@ -1,28 +1,6 @@
-import { rest } from 'msw';
-import { setupServer } from 'msw/node';
-
import { downloadFile } from '../downloadFile';
-const server = setupServer(
- rest.get('*/some/file', async (req, res, ctx) => {
- const file = new File([new Blob(['1'.repeat(1024 * 1024 + 1)])], 'image.png', {
- type: 'image/png',
- });
- const buffer = await new Response(file).arrayBuffer();
-
- return res(ctx.set('Content-Type', 'image/png'), ctx.body(buffer));
- })
-);
-
-describe('Upload | utils | downloadFile', () => {
- beforeAll(() => {
- server.listen();
- });
-
- afterAll(() => {
- server.close();
- });
-
+describe('downloadFile', () => {
test('Download target as blob', async () => {
const setAttributeSpy = jest.fn();
const clickSpy = jest.fn();
diff --git a/packages/core/upload/admin/tests/server.js b/packages/core/upload/admin/tests/server.js
new file mode 100644
index 0000000000..0340e74283
--- /dev/null
+++ b/packages/core/upload/admin/tests/server.js
@@ -0,0 +1,192 @@
+import { rest } from 'msw';
+import { setupServer } from 'msw/node';
+import qs from 'qs';
+
+export const server = setupServer(
+ ...[
+ rest.get('/upload/configuration', async (req, res, ctx) => {
+ return res(
+ ctx.json({
+ data: {
+ /**
+ * we send the pageSize slightly different to defaults because
+ * in tests we can track that the async functions have finished.
+ */
+ pageSize: 20,
+ sort: 'updatedAt:DESC',
+ },
+ })
+ );
+ }),
+ rest.put('/upload/configuration', async (req, res, ctx) => {
+ return res(ctx.status(200));
+ }),
+ rest.get('/upload/folders/:id', async (req, res, ctx) => {
+ return res(
+ ctx.json({
+ data: {
+ id: 1,
+ name: 'test',
+ pathId: 1,
+ path: '/1',
+ createdAt: '2023-06-26T12:48:54.054Z',
+ updatedAt: '2023-06-26T12:48:54.054Z',
+ parent: null,
+ children: {
+ count: 2,
+ },
+ files: {
+ count: 0,
+ },
+ },
+ })
+ );
+ }),
+ rest.get('/upload/folders', async (req, res, ctx) => {
+ const query = qs.parse(req.url.search.slice(1));
+
+ if (query._q) {
+ return res(
+ ctx.json({
+ data: [
+ {
+ createdAt: '2023-06-26T12:48:54.054Z',
+ id: 1,
+ name: query._q,
+ pathId: 1,
+ path: '/1',
+ updatedAt: '2023-06-26T12:48:54.054Z',
+ children: {
+ count: 2,
+ },
+ files: {
+ count: 0,
+ },
+ },
+ ],
+ })
+ );
+ }
+
+ if (Array.isArray(query.filters?.$and)) {
+ const [{ parent }] = query.filters.$and;
+
+ if (parent.id === '1') {
+ return res(
+ ctx.json({
+ data: [
+ {
+ createdAt: '2023-06-26T12:49:31.354Z',
+ id: 3,
+ name: '2022',
+ pathId: 3,
+ path: '/1/3',
+ updatedAt: '2023-06-26T12:49:31.354Z',
+ children: {
+ count: 0,
+ },
+ files: {
+ count: 3,
+ },
+ },
+ {
+ createdAt: '2023-06-26T12:49:08.466Z',
+ id: 2,
+ name: '2023',
+ pathId: 2,
+ path: '/1/2',
+ updatedAt: '2023-06-26T12:49:08.466Z',
+ children: {
+ count: 0,
+ },
+ files: {
+ count: 3,
+ },
+ },
+ ],
+ })
+ );
+ }
+ }
+
+ return res(
+ ctx.json({
+ data: [
+ {
+ createdAt: '2023-06-26T12:48:54.054Z',
+ id: 1,
+ name: 'test',
+ pathId: 1,
+ path: '/1',
+ updatedAt: '2023-06-26T12:48:54.054Z',
+ children: {
+ count: 2,
+ },
+ files: {
+ count: 0,
+ },
+ },
+ ],
+ })
+ );
+ }),
+
+ rest.get('*/some/file', async (req, res, ctx) => {
+ const file = new File([new Blob(['1'.repeat(1024 * 1024 + 1)])], 'image.png', {
+ type: 'image/png',
+ });
+ const buffer = await new Response(file).arrayBuffer();
+
+ return res(ctx.set('Content-Type', 'image/png'), ctx.body(buffer));
+ }),
+
+ rest.get('/upload/settings', async (req, res, ctx) => {
+ return res(
+ ctx.json({
+ data: {
+ sizeOptimization: true,
+ responsiveDimensions: true,
+ autoOrientation: true,
+ },
+ })
+ );
+ }),
+
+ rest.get('/upload/folder-structure', (req, res, ctx) => {
+ return res(
+ ctx.json({
+ data: [
+ {
+ id: 1,
+ name: 'test',
+ children: [
+ {
+ id: 3,
+ name: '2022',
+ children: [],
+ },
+ {
+ id: 2,
+ name: '2023',
+ children: [],
+ },
+ ],
+ },
+ ],
+ })
+ );
+ }),
+
+ rest.get('*/an-image.png', (req, res, ctx) =>
+ res(ctx.set('Content-Type', 'image/png'), ctx.body())
+ ),
+ rest.get('*/a-pdf.pdf', (req, res, ctx) =>
+ res(ctx.set('Content-Type', 'application/pdf'), ctx.body())
+ ),
+ rest.get('*/a-video.mp4', (req, res, ctx) =>
+ res(ctx.set('Content-Type', 'video/mp4'), ctx.body())
+ ),
+ rest.get('*/not-working-like-cors.lutin', (req, res, ctx) => res(ctx.json({}))),
+ rest.get('*/some-where-not-existing.jpg', (req, res) => res.networkError('Failed to fetch')),
+ ]
+);
diff --git a/packages/core/upload/admin/tests/setup.js b/packages/core/upload/admin/tests/setup.js
new file mode 100644
index 0000000000..9b847bc311
--- /dev/null
+++ b/packages/core/upload/admin/tests/setup.js
@@ -0,0 +1,13 @@
+import { server } from './server';
+
+beforeAll(() => {
+ server.listen();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+afterAll(() => {
+ server.close();
+});
diff --git a/packages/core/upload/admin/tests/utils.jsx b/packages/core/upload/admin/tests/utils.jsx
new file mode 100644
index 0000000000..f02a0c0dbc
--- /dev/null
+++ b/packages/core/upload/admin/tests/utils.jsx
@@ -0,0 +1,97 @@
+import * as React from 'react';
+
+import { fixtures } from '@strapi/admin-test-utils';
+import { DesignSystemProvider } from '@strapi/design-system';
+import { RBACContext, NotificationsProvider } from '@strapi/helper-plugin';
+import {
+ renderHook as renderHookRTL,
+ render as renderRTL,
+ waitFor,
+ act,
+ fireEvent,
+ screen,
+} from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import PropTypes from 'prop-types';
+import { IntlProvider } from 'react-intl';
+import { QueryClient, QueryClientProvider } from 'react-query';
+import { MemoryRouter } from 'react-router-dom';
+
+import { server } from './server';
+
+const Providers = ({ children, initialEntries }) => {
+ const rbacContextValue = React.useMemo(
+ () => ({
+ allPermissions: fixtures.permissions.allPermissions,
+ }),
+ []
+ );
+
+ const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ retry: false,
+ // no more errors on the console for tests
+ onError() {},
+ },
+ },
+ });
+
+ return (
+ // en is the default locale of the admin app.
+
+
+
+
+
+ {children}
+
+
+
+
+
+ );
+};
+
+Providers.defaultProps = {
+ initialEntries: undefined,
+};
+
+Providers.propTypes = {
+ children: PropTypes.node.isRequired,
+ initialEntries: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])),
+};
+
+// eslint-disable-next-line react/jsx-no-useless-fragment
+const fallbackWrapper = ({ children }) => <>{children}>;
+
+const render = (ui, { renderOptions, userEventOptions, initialEntries } = {}) => {
+ const { wrapper: Wrapper = fallbackWrapper, ...restOptions } = renderOptions ?? {};
+
+ return {
+ ...renderRTL(ui, {
+ wrapper: ({ children }) => (
+
+ {children}
+
+ ),
+ ...restOptions,
+ }),
+ user: userEvent.setup(userEventOptions),
+ };
+};
+
+const renderHook = (hook, options) => {
+ const { wrapper: Wrapper = fallbackWrapper, ...restOptions } = options ?? {};
+
+ return renderHookRTL(hook, {
+ wrapper: ({ children }) => (
+
+ {children}
+
+ ),
+ ...restOptions,
+ });
+};
+
+export { render, renderHook, waitFor, server, act, fireEvent, screen };
diff --git a/packages/core/upload/jest.config.front.js b/packages/core/upload/jest.config.front.js
index 8cdf1f7080..ccb2e58321 100644
--- a/packages/core/upload/jest.config.front.js
+++ b/packages/core/upload/jest.config.front.js
@@ -3,4 +3,8 @@
module.exports = {
preset: '../../../jest-preset.front.js',
displayName: 'Core upload',
+ moduleNameMapper: {
+ '^@tests/(.*)$': '/admin/tests/$1',
+ },
+ setupFilesAfterEnv: ['./admin/tests/setup.js'],
};
diff --git a/packages/core/upload/jsconfig.json b/packages/core/upload/jsconfig.json
new file mode 100644
index 0000000000..986fd6eba5
--- /dev/null
+++ b/packages/core/upload/jsconfig.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@tests/*": ["./admin/tests/*"]
+ }
+ }
+}
|