diff --git a/Makefile b/Makefile
index 030573e03b1..3923561964f 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,10 @@ build-ra-core:
@echo "Transpiling ra-core files...";
@cd ./packages/ra-core && yarn -s build
+build-ra-test:
+ @echo "Transpiling ra-test files...";
+ @cd ./packages/ra-test && yarn -s build
+
build-ra-ui-materialui:
@echo "Transpiling ra-ui-materialui files...";
@cd ./packages/ra-ui-materialui && yarn -s build
diff --git a/docs/UnitTesting.md b/docs/UnitTesting.md
index 32084cb5966..906bf487784 100644
--- a/docs/UnitTesting.md
+++ b/docs/UnitTesting.md
@@ -17,16 +17,16 @@ That being said, there are still some cases, listed below, where a unit test can
One issue you may run into when attempting to render custom `Create` or `Edit` views is that you need to provide the component with the expected props contained within the react-admin redux store.
-Luckily, react-admin provides access to a `TestContext` wrapper component that can be used to initialise your component with many of the expected react-admin props:
+Luckily, the `ra-test` package provides access to a `TestContext` wrapper component that can be used to initialise your component with many of the expected react-admin props:
```jsx
import * as React from "react";
-import { TestContext } from 'react-admin';
-import { mount } from 'enzyme';
+import { TestContext } from 'ra-test';
+import { render } from '@testing-library/react';
import MyCustomEditView from './my-custom-edit-view';
describe('MyCustomEditView', () => {
- let myCustomEditView;
+ let testUtils;
beforeEach(() => {
const defaultEditProps = {
@@ -37,7 +37,7 @@ describe('MyCustomEditView', () => {
match: {},
};
- myCustomEditView = mount(
+ testUtils = render(
@@ -57,7 +57,7 @@ At this point, your component should `mount` without errors and you can unit tes
If your component relies on a reducer, you can enable reducers using the `enableReducers` prop:
```jsx
-myCustomEditView = mount(
+testUtils = render(
@@ -72,7 +72,7 @@ If you are using `useDispatch` within your components, it is likely you will wan
```jsx
let dispatchSpy;
-myCustomEditView = mount(
+testUtils = render(
{({ store }) => {
dispatchSpy = jest.spyOn(store, 'dispatch');
@@ -82,7 +82,7 @@ myCustomEditView = mount(
);
it('should send the user to another url', () => {
- myCustomEditView.find('.next-button').simulate('click');
+ fireEvent.click(testUtils.getByText('Go to next'));
expect(dispatchSpy).toHaveBeenCalledWith(`/next-url`);
});
```
@@ -93,12 +93,12 @@ As explained on the [Auth Provider chapter](./Authentication.md#authorization),
In order to avoid regressions and make the design explicit to your co-workers, it's better to unit test which fields are supposed to be displayed or hidden for each permission.
-Here is an example with Jest and Enzyme, which is testing the [`UserShow` page of the simple example](https://github.com/marmelab/react-admin/blob/master/examples/simple/src/users/UserShow.js).
+Here is an example with Jest and TestingLibrary, which is testing the [`UserShow` page of the simple example](https://github.com/marmelab/react-admin/blob/master/examples/simple/src/users/UserShow.js).
```jsx
// UserShow.spec.js
import * as React from "react";
-import { shallow } from 'enzyme';
+import { render } from '@testing-library/react';
import { Tab, TextField } from 'react-admin';
import UserShow from './UserShow';
@@ -106,48 +106,71 @@ import UserShow from './UserShow';
describe('UserShow', () => {
describe('As User', () => {
it('should display one tab', () => {
- const wrapper = shallow();
+ const testUtils = render();
- const tab = wrapper.find(Tab);
- expect(tab.length).toBe(1);
+ const tabs = testUtils.queryByRole('tab');
+ expect(tabs.length).toEqual(1);
});
it('should show the user identity in the first tab', () => {
- const wrapper = shallow();
-
- const tab = wrapper.find(Tab);
- const fields = tab.find(TextField);
-
- expect(fields.at(0).prop('source')).toBe('id');
- expect(fields.at(1).prop('source')).toBe('name');
+ const dataProvider = {
+ getOne: jest.fn().resolve({
+ id: 1,
+ name: 'Leila'
+ })
+ }
+ const testUtils = render(
+
+
+
+ );
+
+ expect(testUtils.queryByDisplayValue('1')).not.toBeNull();
+ expect(testUtils.queryByDisplayValue('Leila')).not.toBeNull();
});
});
describe('As Admin', () => {
it('should display two tabs', () => {
- const wrapper = shallow();
+ const testUtils = render();
- const tabs = wrapper.find(Tab);
- expect(tabs.length).toBe(2);
+ const tabs = testUtils.queryByRole('tab');
+ expect(tabs.length).toEqual(2);
});
it('should show the user identity in the first tab', () => {
- const wrapper = shallow();
-
- const tabs = wrapper.find(Tab);
- const fields = tabs.at(0).find(TextField);
-
- expect(fields.at(0).prop('source')).toBe('id');
- expect(fields.at(1).prop('source')).toBe('name');
+ const dataProvider = {
+ getOne: jest.fn().resolve({
+ id: 1,
+ name: 'Leila'
+ })
+ }
+ const testUtils = render(
+
+
+
+ );
+
+ expect(testUtils.queryByDisplayValue('1')).not.toBeNull();
+ expect(testUtils.queryByDisplayValue('Leila')).not.toBeNull();
});
it('should show the user role in the second tab', () => {
- const wrapper = shallow();
-
- const tabs = wrapper.find(Tab);
- const fields = tabs.at(1).find(TextField);
-
- expect(fields.at(0).prop('source')).toBe('role');
+ const dataProvider = {
+ getOne: jest.fn().resolve({
+ id: 1,
+ name: 'Leila',
+ role: 'admin'
+ })
+ }
+ const testUtils = render(
+
+
+
+ );
+
+ fireEvent.click(testUtils.getByText('Security'));
+ expect(testUtils.queryByDisplayValue('admin')).not.toBeNull();
});
});
});
diff --git a/packages/ra-core/package.json b/packages/ra-core/package.json
index 323e55a5a34..de475be21cb 100644
--- a/packages/ra-core/package.json
+++ b/packages/ra-core/package.json
@@ -39,6 +39,7 @@
"final-form": "^4.20.0",
"history": "^4.7.2",
"ignore-styles": "~5.0.1",
+ "ra-test": "^3.12.0",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-final-form": "^6.5.0",
diff --git a/packages/ra-core/src/auth/Authenticated.spec.tsx b/packages/ra-core/src/auth/Authenticated.spec.tsx
index 4c9b3cab865..12b4126777f 100644
--- a/packages/ra-core/src/auth/Authenticated.spec.tsx
+++ b/packages/ra-core/src/auth/Authenticated.spec.tsx
@@ -4,7 +4,7 @@ import { waitFor } from '@testing-library/react';
import Authenticated from './Authenticated';
import AuthContext from './AuthContext';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import { showNotification } from '../actions/notificationActions';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
diff --git a/packages/ra-core/src/auth/useAuthState.spec.tsx b/packages/ra-core/src/auth/useAuthState.spec.tsx
index 03591310b50..6362cce7ddb 100644
--- a/packages/ra-core/src/auth/useAuthState.spec.tsx
+++ b/packages/ra-core/src/auth/useAuthState.spec.tsx
@@ -4,7 +4,7 @@ import { waitFor } from '@testing-library/react';
import useAuthState from './useAuthState';
import AuthContext from './AuthContext';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
const UseAuth = ({ children, authParams }: any) => {
const res = useAuthState(authParams);
diff --git a/packages/ra-core/src/auth/useAuthenticated.spec.tsx b/packages/ra-core/src/auth/useAuthenticated.spec.tsx
index ebeee6c4859..c31f5fc5d06 100644
--- a/packages/ra-core/src/auth/useAuthenticated.spec.tsx
+++ b/packages/ra-core/src/auth/useAuthenticated.spec.tsx
@@ -4,7 +4,7 @@ import { waitFor } from '@testing-library/react';
import Authenticated from './Authenticated';
import AuthContext from './AuthContext';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import { showNotification } from '../actions/notificationActions';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
diff --git a/packages/ra-core/src/auth/usePermissions.spec.tsx b/packages/ra-core/src/auth/usePermissions.spec.tsx
index c270db73d6f..d50874dfd49 100644
--- a/packages/ra-core/src/auth/usePermissions.spec.tsx
+++ b/packages/ra-core/src/auth/usePermissions.spec.tsx
@@ -4,7 +4,7 @@ import { waitFor } from '@testing-library/react';
import usePermissions from './usePermissions';
import AuthContext from './AuthContext';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
const UsePermissions = ({ children, authParams }: any) => {
const res = usePermissions(authParams);
diff --git a/packages/ra-core/src/controller/details/CreateBase.spec.tsx b/packages/ra-core/src/controller/details/CreateBase.spec.tsx
index b6b78df6585..92b44fc61c4 100644
--- a/packages/ra-core/src/controller/details/CreateBase.spec.tsx
+++ b/packages/ra-core/src/controller/details/CreateBase.spec.tsx
@@ -6,7 +6,7 @@ import { CreateBase } from './CreateBase';
import { useSaveContext } from './SaveContext';
import { DataProviderContext } from '../../dataProvider';
import { DataProvider } from '../../types';
-import { renderWithRedux } from '../../util';
+import { renderWithRedux } from 'ra-test';
describe('CreateBase', () => {
afterEach(cleanup);
diff --git a/packages/ra-core/src/controller/details/EditBase.spec.tsx b/packages/ra-core/src/controller/details/EditBase.spec.tsx
index 03c95226f86..cee369646ba 100644
--- a/packages/ra-core/src/controller/details/EditBase.spec.tsx
+++ b/packages/ra-core/src/controller/details/EditBase.spec.tsx
@@ -6,7 +6,7 @@ import { EditBase } from './EditBase';
import { useSaveContext } from './SaveContext';
import { DataProviderContext } from '../../dataProvider';
import { DataProvider } from '../../types';
-import { renderWithRedux } from '../../util';
+import { renderWithRedux } from 'ra-test';
describe('EditBase', () => {
afterEach(cleanup);
diff --git a/packages/ra-core/src/controller/details/useCreateController.spec.tsx b/packages/ra-core/src/controller/details/useCreateController.spec.tsx
index 086d54e55d0..123b2700bf1 100644
--- a/packages/ra-core/src/controller/details/useCreateController.spec.tsx
+++ b/packages/ra-core/src/controller/details/useCreateController.spec.tsx
@@ -4,7 +4,7 @@ import { act } from '@testing-library/react';
import { getRecord } from './useCreateController';
import { CreateController } from './CreateController';
-import renderWithRedux from '../../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import { DataProviderContext } from '../../dataProvider';
import { DataProvider } from '../../types';
diff --git a/packages/ra-core/src/controller/details/useEditController.spec.tsx b/packages/ra-core/src/controller/details/useEditController.spec.tsx
index 3c7f1d6bfb4..9bcbc703a94 100644
--- a/packages/ra-core/src/controller/details/useEditController.spec.tsx
+++ b/packages/ra-core/src/controller/details/useEditController.spec.tsx
@@ -3,7 +3,7 @@ import expect from 'expect';
import { act, waitFor } from '@testing-library/react';
import { EditController } from './EditController';
-import renderWithRedux from '../../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import { DataProviderContext } from '../../dataProvider';
import { DataProvider } from '../../types';
import { SaveContextProvider } from '../../../esm';
diff --git a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx
index a736aeb0cc6..8c532c227cc 100644
--- a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx
+++ b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.spec.tsx
@@ -3,7 +3,7 @@ import expect from 'expect';
import ReferenceArrayFieldController from './ReferenceArrayFieldController';
import { DataProviderContext } from '../../dataProvider';
-import renderWithRedux from '../../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
describe('', () => {
it('should set the loaded prop to false when related records are not yet fetched', () => {
diff --git a/packages/ra-core/src/controller/field/ReferenceFieldController.spec.tsx b/packages/ra-core/src/controller/field/ReferenceFieldController.spec.tsx
index 26fa29de60f..919f19662b9 100644
--- a/packages/ra-core/src/controller/field/ReferenceFieldController.spec.tsx
+++ b/packages/ra-core/src/controller/field/ReferenceFieldController.spec.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import expect from 'expect';
import ReferenceFieldController from './ReferenceFieldController';
-import renderWithRedux from '../../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import { DataProviderContext } from '../../dataProvider';
const defaultState = {
diff --git a/packages/ra-core/src/controller/field/ReferenceManyFieldController.spec.tsx b/packages/ra-core/src/controller/field/ReferenceManyFieldController.spec.tsx
index e0d2af252a2..6b49321b4ab 100644
--- a/packages/ra-core/src/controller/field/ReferenceManyFieldController.spec.tsx
+++ b/packages/ra-core/src/controller/field/ReferenceManyFieldController.spec.tsx
@@ -3,7 +3,7 @@ import { waitFor } from '@testing-library/react';
import expect from 'expect';
import ReferenceManyFieldController from './ReferenceManyFieldController';
-import renderWithRedux from '../../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
describe('', () => {
it('should set loaded to false when related records are not yet fetched', async () => {
diff --git a/packages/ra-core/src/controller/input/ReferenceArrayInputController.spec.tsx b/packages/ra-core/src/controller/input/ReferenceArrayInputController.spec.tsx
index 4c1df5c4589..2d4b6fb3623 100644
--- a/packages/ra-core/src/controller/input/ReferenceArrayInputController.spec.tsx
+++ b/packages/ra-core/src/controller/input/ReferenceArrayInputController.spec.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import expect from 'expect';
import { waitFor, fireEvent } from '@testing-library/react';
import ReferenceArrayInputController from './ReferenceArrayInputController';
-import { renderWithRedux } from '../../util';
+import { renderWithRedux } from 'ra-test';
import { CRUD_GET_MATCHING, CRUD_GET_MANY } from '../../../lib';
describe('', () => {
diff --git a/packages/ra-core/src/controller/input/ReferenceInputController.spec.tsx b/packages/ra-core/src/controller/input/ReferenceInputController.spec.tsx
index c4c3248ed64..a73db2deaa2 100644
--- a/packages/ra-core/src/controller/input/ReferenceInputController.spec.tsx
+++ b/packages/ra-core/src/controller/input/ReferenceInputController.spec.tsx
@@ -4,7 +4,7 @@ import { fireEvent, waitFor } from '@testing-library/react';
import omit from 'lodash/omit';
import expect from 'expect';
-import renderWithRedux from '../../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import ReferenceInputController from './ReferenceInputController';
import { DataProviderContext } from '../../dataProvider';
diff --git a/packages/ra-core/src/controller/input/useGetMatchingReferences.spec.tsx b/packages/ra-core/src/controller/input/useGetMatchingReferences.spec.tsx
index fea8362d060..b6ad49ec1f5 100644
--- a/packages/ra-core/src/controller/input/useGetMatchingReferences.spec.tsx
+++ b/packages/ra-core/src/controller/input/useGetMatchingReferences.spec.tsx
@@ -1,4 +1,4 @@
-import renderHook from '../../util/renderHook';
+import { renderHook } from 'ra-test';
import useMatchingReferences from './useGetMatchingReferences';
describe('useMatchingReferences', () => {
diff --git a/packages/ra-core/src/controller/useFilterState.spec.tsx b/packages/ra-core/src/controller/useFilterState.spec.tsx
index 9495b7ecc67..9af261bc69e 100644
--- a/packages/ra-core/src/controller/useFilterState.spec.tsx
+++ b/packages/ra-core/src/controller/useFilterState.spec.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import renderHook from '../util/renderHook';
+import { renderHook } from 'ra-test';
import useFilterState from './useFilterState';
import { render, act } from '@testing-library/react';
diff --git a/packages/ra-core/src/controller/useListController.spec.tsx b/packages/ra-core/src/controller/useListController.spec.tsx
index fa0c6c7f230..a437f37b015 100644
--- a/packages/ra-core/src/controller/useListController.spec.tsx
+++ b/packages/ra-core/src/controller/useListController.spec.tsx
@@ -10,7 +10,7 @@ import {
sanitizeListRestProps,
} from './useListController';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import { CRUD_CHANGE_LIST_PARAMS } from '../actions';
import { SORT_ASC } from '../reducer/admin/resource/list/queryReducer';
diff --git a/packages/ra-core/src/controller/useListParams.spec.tsx b/packages/ra-core/src/controller/useListParams.spec.tsx
index 3e590d85f7d..56628c5a2e0 100644
--- a/packages/ra-core/src/controller/useListParams.spec.tsx
+++ b/packages/ra-core/src/controller/useListParams.spec.tsx
@@ -5,7 +5,7 @@ import { Router } from 'react-router-dom';
import { stringify } from 'query-string';
import { createMemoryHistory } from 'history';
import { fireEvent, waitFor } from '@testing-library/react';
-import { renderWithRedux, TestContext } from '../util';
+import { renderWithRedux, TestContext } from 'ra-test';
import useListParams, { getQuery, getNumberOrDefault } from './useListParams';
import {
diff --git a/packages/ra-core/src/controller/usePaginationState.spec.ts b/packages/ra-core/src/controller/usePaginationState.spec.ts
index 8232583ebc0..7f355f3c0c6 100644
--- a/packages/ra-core/src/controller/usePaginationState.spec.ts
+++ b/packages/ra-core/src/controller/usePaginationState.spec.ts
@@ -1,4 +1,4 @@
-import renderHook from '../util/renderHook';
+import { renderHook } from 'ra-test';
import usePaginationState from './usePaginationState';
import { act } from '@testing-library/react';
diff --git a/packages/ra-core/src/controller/useReference.spec.tsx b/packages/ra-core/src/controller/useReference.spec.tsx
index 367139bcc63..db4379078c0 100644
--- a/packages/ra-core/src/controller/useReference.spec.tsx
+++ b/packages/ra-core/src/controller/useReference.spec.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import expect from 'expect';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import useReference from './useReference';
import { DataProviderContext } from '../dataProvider';
diff --git a/packages/ra-core/src/controller/useSortState.spec.ts b/packages/ra-core/src/controller/useSortState.spec.ts
index de4b8801df2..809dbba6936 100644
--- a/packages/ra-core/src/controller/useSortState.spec.ts
+++ b/packages/ra-core/src/controller/useSortState.spec.ts
@@ -1,4 +1,4 @@
-import renderHook from '../util/renderHook';
+import { renderHook } from 'ra-test';
import useSortState, { defaultSort } from './useSortState';
import { act } from '@testing-library/react';
diff --git a/packages/ra-core/src/core/CoreAdminRouter.spec.tsx b/packages/ra-core/src/core/CoreAdminRouter.spec.tsx
index b90bbcac66d..261e8dc8ae9 100644
--- a/packages/ra-core/src/core/CoreAdminRouter.spec.tsx
+++ b/packages/ra-core/src/core/CoreAdminRouter.spec.tsx
@@ -4,7 +4,7 @@ import expect from 'expect';
import { Router, Route } from 'react-router-dom';
import { createMemoryHistory } from 'history';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import CoreAdminRouter from './CoreAdminRouter';
import AuthContext from '../auth/AuthContext';
import Resource from './Resource';
diff --git a/packages/ra-core/src/core/Resource.spec.tsx b/packages/ra-core/src/core/Resource.spec.tsx
index 7b2cb542f7e..4ec0ef8564d 100644
--- a/packages/ra-core/src/core/Resource.spec.tsx
+++ b/packages/ra-core/src/core/Resource.spec.tsx
@@ -6,7 +6,7 @@ import { createMemoryHistory } from 'history';
import Resource from './Resource';
import { registerResource, unregisterResource } from '../actions';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import AuthContext from '../auth/AuthContext';
const PostList = () => PostList
;
diff --git a/packages/ra-core/src/dataProvider/Mutation.spec.tsx b/packages/ra-core/src/dataProvider/Mutation.spec.tsx
index 390ba1f2832..62506a591cb 100644
--- a/packages/ra-core/src/dataProvider/Mutation.spec.tsx
+++ b/packages/ra-core/src/dataProvider/Mutation.spec.tsx
@@ -3,10 +3,9 @@ import { fireEvent, waitFor, act, render } from '@testing-library/react';
import expect from 'expect';
import Mutation from './Mutation';
-import renderWithRedux from '../util/renderWithRedux';
import { showNotification, refreshView, setListSelectedIds } from '../actions';
import DataProviderContext from './DataProviderContext';
-import TestContext from '../util/TestContext';
+import { renderWithRedux, TestContext } from 'ra-test';
import { useNotify } from '../sideEffect';
import { History } from 'history';
diff --git a/packages/ra-core/src/dataProvider/Query.spec.tsx b/packages/ra-core/src/dataProvider/Query.spec.tsx
index 766700fadf7..4f3b198b18e 100644
--- a/packages/ra-core/src/dataProvider/Query.spec.tsx
+++ b/packages/ra-core/src/dataProvider/Query.spec.tsx
@@ -4,8 +4,7 @@ import expect from 'expect';
import Query from './Query';
import { CoreAdmin, Resource } from '../core';
-import renderWithRedux from '../util/renderWithRedux';
-import TestContext from '../util/TestContext';
+import { renderWithRedux, TestContext } from 'ra-test';
import DataProviderContext from './DataProviderContext';
import { showNotification, refreshView, setListSelectedIds } from '../actions';
import { useNotify, useRefresh } from '../sideEffect';
diff --git a/packages/ra-core/src/dataProvider/useDataProvider.spec.js b/packages/ra-core/src/dataProvider/useDataProvider.spec.js
index 70ea58dfac4..906dc6b4e60 100644
--- a/packages/ra-core/src/dataProvider/useDataProvider.spec.js
+++ b/packages/ra-core/src/dataProvider/useDataProvider.spec.js
@@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
import { act, fireEvent } from '@testing-library/react';
import expect from 'expect';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import useDataProvider from './useDataProvider';
import useUpdate from './useUpdate';
import { DataProviderContext } from '../dataProvider';
diff --git a/packages/ra-core/src/dataProvider/useGetList.spec.tsx b/packages/ra-core/src/dataProvider/useGetList.spec.tsx
index a3594f5ffc1..070a075801e 100644
--- a/packages/ra-core/src/dataProvider/useGetList.spec.tsx
+++ b/packages/ra-core/src/dataProvider/useGetList.spec.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import expect from 'expect';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import useGetList from './useGetList';
import { DataProviderContext } from '../dataProvider';
diff --git a/packages/ra-core/src/dataProvider/useGetMany.spec.tsx b/packages/ra-core/src/dataProvider/useGetMany.spec.tsx
index aa22fc784cb..a8b007a85d4 100644
--- a/packages/ra-core/src/dataProvider/useGetMany.spec.tsx
+++ b/packages/ra-core/src/dataProvider/useGetMany.spec.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import expect from 'expect';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import useGetMany from './useGetMany';
import { DataProviderContext } from '../dataProvider';
diff --git a/packages/ra-core/src/dataProvider/useMutation.spec.tsx b/packages/ra-core/src/dataProvider/useMutation.spec.tsx
index ade28295dac..450677f1449 100644
--- a/packages/ra-core/src/dataProvider/useMutation.spec.tsx
+++ b/packages/ra-core/src/dataProvider/useMutation.spec.tsx
@@ -4,7 +4,7 @@ import expect from 'expect';
import Mutation from './Mutation';
import { CoreAdmin, Resource } from '../core';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import { DataProviderContext } from '.';
describe('useMutation', () => {
diff --git a/packages/ra-core/src/dataProvider/useQueryWithStore.spec.tsx b/packages/ra-core/src/dataProvider/useQueryWithStore.spec.tsx
index dec381755a8..e7cbc977fa3 100644
--- a/packages/ra-core/src/dataProvider/useQueryWithStore.spec.tsx
+++ b/packages/ra-core/src/dataProvider/useQueryWithStore.spec.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { waitFor } from '@testing-library/react';
import expect from 'expect';
-import renderWithRedux from '../util/renderWithRedux';
+import { renderWithRedux } from 'ra-test';
import useQueryWithStore from './useQueryWithStore';
import { DataProviderContext } from '../dataProvider';
diff --git a/packages/ra-core/src/form/FormWithRedirect.spec.tsx b/packages/ra-core/src/form/FormWithRedirect.spec.tsx
index 3d43a32ef58..8ace2e19536 100644
--- a/packages/ra-core/src/form/FormWithRedirect.spec.tsx
+++ b/packages/ra-core/src/form/FormWithRedirect.spec.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
-import { renderWithRedux } from '../util';
+import { renderWithRedux } from 'ra-test';
import FormWithRedirect from './FormWithRedirect';
import useInput from './useInput';
diff --git a/packages/ra-core/src/form/ValidationError.spec.tsx b/packages/ra-core/src/form/ValidationError.spec.tsx
index 2208288f4db..e17daad9429 100644
--- a/packages/ra-core/src/form/ValidationError.spec.tsx
+++ b/packages/ra-core/src/form/ValidationError.spec.tsx
@@ -4,7 +4,7 @@ import polyglotI18nProvider from 'ra-i18n-polyglot';
import ValidationError from './ValidationError';
import { TranslationProvider } from '../i18n';
-import { renderWithRedux } from '../util';
+import { renderWithRedux } from 'ra-test';
const translate = jest.fn(key => key);
diff --git a/packages/ra-core/src/form/useChoices.spec.tsx b/packages/ra-core/src/form/useChoices.spec.tsx
index a938c02235a..3d236a8807f 100644
--- a/packages/ra-core/src/form/useChoices.spec.tsx
+++ b/packages/ra-core/src/form/useChoices.spec.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import expect from 'expect';
import { render } from '@testing-library/react';
import useChoices from './useChoices';
-import { renderWithRedux } from '../util';
+import { renderWithRedux } from 'ra-test';
import { TestTranslationProvider } from '../i18n';
describe('useChoices hook', () => {
diff --git a/packages/ra-core/src/i18n/useSetLocale.spec.js b/packages/ra-core/src/i18n/useSetLocale.spec.js
index b6a1859ba9e..e7b25af7371 100644
--- a/packages/ra-core/src/i18n/useSetLocale.spec.js
+++ b/packages/ra-core/src/i18n/useSetLocale.spec.js
@@ -6,7 +6,7 @@ import polyglotI18nProvider from 'ra-i18n-polyglot';
import useTranslate from './useTranslate';
import useSetLocale from './useSetLocale';
import { TranslationContext, TranslationProvider } from './';
-import { renderWithRedux } from '../util';
+import { renderWithRedux } from 'ra-test';
describe('useSetLocale', () => {
const Component = () => {
diff --git a/packages/ra-core/src/i18n/useTranslate.spec.tsx b/packages/ra-core/src/i18n/useTranslate.spec.tsx
index d36184ec826..e92e144d81f 100644
--- a/packages/ra-core/src/i18n/useTranslate.spec.tsx
+++ b/packages/ra-core/src/i18n/useTranslate.spec.tsx
@@ -4,7 +4,7 @@ import expect from 'expect';
import useTranslate from './useTranslate';
import TranslationProvider from './TranslationProvider';
import { TranslationContext } from './TranslationContext';
-import { renderWithRedux } from '../util';
+import { renderWithRedux } from 'ra-test';
describe('useTranslate', () => {
const Component = () => {
diff --git a/packages/ra-core/src/util/FieldTitle.spec.tsx b/packages/ra-core/src/util/FieldTitle.spec.tsx
index 98510c10756..9b4eadc5e03 100644
--- a/packages/ra-core/src/util/FieldTitle.spec.tsx
+++ b/packages/ra-core/src/util/FieldTitle.spec.tsx
@@ -4,7 +4,7 @@ import * as React from 'react';
import { FieldTitle } from './FieldTitle';
import TestTranslationProvider from '../i18n/TestTranslationProvider';
-import renderWithRedux from './renderWithRedux';
+import { renderWithRedux } from 'ra-test';
describe('FieldTitle', () => {
it('should return empty span by default', () => {
diff --git a/packages/ra-core/src/util/index.ts b/packages/ra-core/src/util/index.ts
index 058c5bd5de0..1f4fae76dca 100644
--- a/packages/ra-core/src/util/index.ts
+++ b/packages/ra-core/src/util/index.ts
@@ -8,8 +8,6 @@ import removeEmpty from './removeEmpty';
import removeKey from './removeKey';
import Ready from './Ready';
import resolveRedirectTo from './resolveRedirectTo';
-import TestContext from './TestContext';
-import renderWithRedux from './renderWithRedux';
import warning from './warning';
import useWhyDidYouUpdate from './useWhyDidYouUpdate';
import { useSafeSetState, useTimeout } from './hooks';
@@ -25,8 +23,6 @@ export {
removeEmpty,
removeKey,
resolveRedirectTo,
- TestContext,
- renderWithRedux,
warning,
useWhyDidYouUpdate,
useSafeSetState,
diff --git a/packages/ra-test/README.md b/packages/ra-test/README.md
new file mode 100644
index 00000000000..30afc331a12
--- /dev/null
+++ b/packages/ra-test/README.md
@@ -0,0 +1,2 @@
+# ra-test
+
diff --git a/packages/ra-test/package.json b/packages/ra-test/package.json
new file mode 100644
index 00000000000..8051facb929
--- /dev/null
+++ b/packages/ra-test/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "ra-test",
+ "version": "3.12.0",
+ "description": "Test utilities for react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React",
+ "files": [
+ "*.md",
+ "lib",
+ "esm",
+ "src"
+ ],
+ "main": "lib/index",
+ "module": "esm/index.js",
+ "types": "esm/index.d.ts",
+ "sideEffects": false,
+ "authors": [
+ "François Zaninotto",
+ "Gildas Garcia"
+ ],
+ "repository": "marmelab/react-admin",
+ "homepage": "https://github.com/marmelab/react-admin#readme",
+ "bugs": "https://github.com/marmelab/react-admin/issues",
+ "license": "MIT",
+ "scripts": {
+ "build": "yarn run build-cjs && yarn run build-esm",
+ "build-cjs": "rimraf ./lib && tsc",
+ "build-esm": "rimraf ./esm && tsc --outDir esm --module es2015",
+ "watch": "tsc --outDir esm --module es2015 --watch"
+ },
+ "devDependencies": {
+ "@redux-saga/testing-utils": "^1.0.2",
+ "@types/history": "^4.7.2",
+ "@types/node-polyglot": "^0.4.31",
+ "@types/query-string": "5.1.0",
+ "@types/react-redux": "^7.1.1",
+ "@types/react-router": "^5.1.0",
+ "@types/react-router-dom": "^5.1.0",
+ "connected-react-router": "^6.5.2",
+ "cross-env": "^5.2.0",
+ "final-form": "^4.20.0",
+ "history": "^4.7.2",
+ "ignore-styles": "~5.0.1",
+ "react": "^17.0.0",
+ "react-dom": "^17.0.0",
+ "react-redux": "^7.1.0",
+ "react-router": "^5.1.0",
+ "react-router-dom": "^5.1.0",
+ "react-test-renderer": "^16.9.0 || ^17.0.0",
+ "redux": "^3.7.2 || ^4.0.3"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0",
+ "react-dom": "^16.9.0 || ^17.0.0",
+ "react-redux": "^7.1.0",
+ "react-router": "^5.1.0",
+ "react-router-dom": "^5.1.0",
+ "redux": "^3.7.2 || ^4.0.3"
+ },
+ "dependencies": {
+ "@testing-library/react": "^11.2.3",
+ "classnames": "~2.2.5",
+ "lodash": "~4.17.5"
+ }
+}
diff --git a/packages/ra-core/src/util/TestContext.spec.tsx b/packages/ra-test/src/TestContext.spec.tsx
similarity index 98%
rename from packages/ra-core/src/util/TestContext.spec.tsx
rename to packages/ra-test/src/TestContext.spec.tsx
index 0f0c36cf14d..40fbea7b763 100644
--- a/packages/ra-core/src/util/TestContext.spec.tsx
+++ b/packages/ra-test/src/TestContext.spec.tsx
@@ -3,7 +3,7 @@ import { render } from '@testing-library/react';
import * as React from 'react';
import TestContext, { defaultStore } from './TestContext';
-import { refreshView } from '../actions';
+import { refreshView } from 'ra-core';
const primedStore = {
admin: {
diff --git a/packages/ra-core/src/util/TestContext.tsx b/packages/ra-test/src/TestContext.tsx
similarity index 88%
rename from packages/ra-core/src/util/TestContext.tsx
rename to packages/ra-test/src/TestContext.tsx
index 8fa2ccc67bd..1ce1a012bcd 100644
--- a/packages/ra-core/src/util/TestContext.tsx
+++ b/packages/ra-test/src/TestContext.tsx
@@ -6,9 +6,11 @@ import merge from 'lodash/merge';
import { createMemoryHistory, History } from 'history';
import { Router } from 'react-router-dom';
-import createAdminStore from '../core/createAdminStore';
-import { convertLegacyDataProvider } from '../dataProvider';
-import { ReduxState } from '../types';
+import {
+ convertLegacyDataProvider,
+ createAdminStore,
+ ReduxState,
+} from 'ra-core';
export const defaultStore = {
admin: {
@@ -19,7 +21,7 @@ export const defaultStore = {
},
};
-type ChildrenFunction = ({
+export type TextContextChildrenFunction = ({
store,
history,
}: {
@@ -27,11 +29,11 @@ type ChildrenFunction = ({
history: History;
}) => ReactNode;
-interface Props {
+export interface TestContextProps {
initialState?: object;
enableReducers?: boolean;
history?: History;
- children: ReactNode | ChildrenFunction;
+ children: ReactNode | TextContextChildrenFunction;
}
const dataProviderDefaultResponse = { data: null };
@@ -60,7 +62,7 @@ const dataProviderDefaultResponse = { data: null };
*
* );
*/
-class TestContext extends Component {
+export class TestContext extends Component {
storeWithDefault = null;
history: History = null;
@@ -83,7 +85,7 @@ class TestContext extends Component {
renderChildren = () => {
const { children } = this.props;
return typeof children === 'function'
- ? (children as ChildrenFunction)({
+ ? (children as TextContextChildrenFunction)({
store: this.storeWithDefault,
history: this.history,
})
diff --git a/packages/ra-test/src/index.ts b/packages/ra-test/src/index.ts
new file mode 100644
index 00000000000..951d71ecf67
--- /dev/null
+++ b/packages/ra-test/src/index.ts
@@ -0,0 +1,3 @@
+export * from './TestContext';
+export * from './renderHook';
+export * from './renderWithRedux';
diff --git a/packages/ra-core/src/util/renderHook.tsx b/packages/ra-test/src/renderHook.tsx
similarity index 79%
rename from packages/ra-core/src/util/renderHook.tsx
rename to packages/ra-test/src/renderHook.tsx
index 29a80cb75be..c1b3ae863e6 100644
--- a/packages/ra-core/src/util/renderHook.tsx
+++ b/packages/ra-test/src/renderHook.tsx
@@ -1,18 +1,18 @@
import * as React from 'react';
import { render, RenderResult } from '@testing-library/react';
-import renderWithRedux, { RenderWithReduxResult } from './renderWithRedux';
+import { renderWithRedux, RenderWithReduxResult } from './renderWithRedux';
const TestHook = ({ children, hook }) => {
return children(hook());
};
-interface RenderHookResult extends RenderResult {
+export interface RenderHookResult extends RenderResult {
hookValue: any;
childrenMock: jest.Mock;
rerender: (f: any) => any;
}
-interface RenderHookWithReduxResult extends RenderWithReduxResult {
+export interface RenderHookWithReduxResult extends RenderWithReduxResult {
hookValue: any;
childrenMock: jest.Mock;
rerender: (f: any) => any;
@@ -27,13 +27,13 @@ interface RenderHookWithReduxResult extends RenderWithReduxResult {
* @returns {RenderHookResult}
* @returns {RenderHookWithReduxResult}
*/
-function renderHook(
+export function renderHook(
hook: Function,
withRedux?: true,
reduxState?: {}
): RenderHookWithReduxResult;
-function renderHook(hook: Function, withRedux: false): RenderHookResult;
-function renderHook(hook, withRedux = true, reduxState?) {
+export function renderHook(hook: Function, withRedux: false): RenderHookResult;
+export function renderHook(hook, withRedux = true, reduxState?) {
let hookValue = null;
const children = props => {
hookValue = props;
@@ -58,5 +58,3 @@ function renderHook(hook, withRedux = true, reduxState?) {
},
};
}
-
-export default renderHook;
diff --git a/packages/ra-core/src/util/renderWithRedux.tsx b/packages/ra-test/src/renderWithRedux.tsx
similarity index 98%
rename from packages/ra-core/src/util/renderWithRedux.tsx
rename to packages/ra-test/src/renderWithRedux.tsx
index db38cb0d5e9..40abe3c55e8 100644
--- a/packages/ra-core/src/util/renderWithRedux.tsx
+++ b/packages/ra-test/src/renderWithRedux.tsx
@@ -24,7 +24,7 @@ export interface RenderWithReduxResult extends RenderResult {
* dispatch: spy on the redux store dispatch method
* reduxStore: the redux store used by the tested component
*/
-export default (
+export const renderWithRedux = (
component,
initialState = {},
options = {}
diff --git a/packages/ra-test/tsconfig.json b/packages/ra-test/tsconfig.json
new file mode 100644
index 00000000000..e8a21555108
--- /dev/null
+++ b/packages/ra-test/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "lib",
+ "rootDir": "src",
+ "declaration": true,
+ "allowJs": false
+ },
+ "exclude": ["**/*.spec.ts", "**/*.spec.tsx", "**/*.spec.js"],
+ "include": ["src"]
+}
diff --git a/packages/ra-ui-materialui/src/button/Button.spec.tsx b/packages/ra-ui-materialui/src/button/Button.spec.tsx
index 3203ae1b226..b465c4f0b3d 100644
--- a/packages/ra-ui-materialui/src/button/Button.spec.tsx
+++ b/packages/ra-ui-materialui/src/button/Button.spec.tsx
@@ -1,7 +1,7 @@
import { render } from '@testing-library/react';
import * as React from 'react';
import expect from 'expect';
-import { TestContext } from 'ra-core';
+import { TestContext } from 'ra-test';
import { ThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import Button from './Button';
diff --git a/packages/ra-ui-materialui/src/button/CloneButton.spec.tsx b/packages/ra-ui-materialui/src/button/CloneButton.spec.tsx
index aebff27e2b4..40850a5586d 100644
--- a/packages/ra-ui-materialui/src/button/CloneButton.spec.tsx
+++ b/packages/ra-ui-materialui/src/button/CloneButton.spec.tsx
@@ -7,7 +7,7 @@ import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
import { CloneButton } from './CloneButton';
-import { TestContext } from 'ra-core';
+import { TestContext } from 'ra-test';
const theme = createMuiTheme();
diff --git a/packages/ra-ui-materialui/src/button/CreateButton.spec.tsx b/packages/ra-ui-materialui/src/button/CreateButton.spec.tsx
index 1ff2a1950d8..b26a66fc733 100644
--- a/packages/ra-ui-materialui/src/button/CreateButton.spec.tsx
+++ b/packages/ra-ui-materialui/src/button/CreateButton.spec.tsx
@@ -1,7 +1,7 @@
import { render } from '@testing-library/react';
import * as React from 'react';
import expect from 'expect';
-import { TestContext } from 'ra-core';
+import { TestContext } from 'ra-test';
import { ThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import CreateButton from './CreateButton';
diff --git a/packages/ra-ui-materialui/src/button/DeleteWithConfirmButton.spec.tsx b/packages/ra-ui-materialui/src/button/DeleteWithConfirmButton.spec.tsx
index 06c3a750102..bb643c58c95 100644
--- a/packages/ra-ui-materialui/src/button/DeleteWithConfirmButton.spec.tsx
+++ b/packages/ra-ui-materialui/src/button/DeleteWithConfirmButton.spec.tsx
@@ -1,12 +1,8 @@
import { render, waitFor, fireEvent } from '@testing-library/react';
import * as React from 'react';
import expect from 'expect';
-import {
- DataProvider,
- DataProviderContext,
- renderWithRedux,
- TestContext,
-} from 'ra-core';
+import { DataProvider, DataProviderContext } from 'ra-core';
+import { renderWithRedux, TestContext } from 'ra-test';
import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
import DeleteWithConfirmButton from './DeleteWithConfirmButton';
import { Toolbar, SimpleForm } from '../form';
diff --git a/packages/ra-ui-materialui/src/button/DeleteWithUndoButton.spec.tsx b/packages/ra-ui-materialui/src/button/DeleteWithUndoButton.spec.tsx
index f9de0e8fa79..ab52f730bbc 100644
--- a/packages/ra-ui-materialui/src/button/DeleteWithUndoButton.spec.tsx
+++ b/packages/ra-ui-materialui/src/button/DeleteWithUndoButton.spec.tsx
@@ -1,12 +1,8 @@
import { render, waitFor, fireEvent } from '@testing-library/react';
import * as React from 'react';
import expect from 'expect';
-import {
- DataProvider,
- DataProviderContext,
- renderWithRedux,
- TestContext,
-} from 'ra-core';
+import { DataProvider, DataProviderContext } from 'ra-core';
+import { renderWithRedux, TestContext } from 'ra-test';
import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
import { Toolbar, SimpleForm } from '../form';
import { Edit } from '../detail';
diff --git a/packages/ra-ui-materialui/src/button/SaveButton.spec.tsx b/packages/ra-ui-materialui/src/button/SaveButton.spec.tsx
index e2f61127212..b1e27d4ea48 100644
--- a/packages/ra-ui-materialui/src/button/SaveButton.spec.tsx
+++ b/packages/ra-ui-materialui/src/button/SaveButton.spec.tsx
@@ -2,13 +2,12 @@ import * as React from 'react';
import { render, waitFor, fireEvent } from '@testing-library/react';
import expect from 'expect';
import {
- TestContext,
- renderWithRedux,
DataProviderContext,
DataProvider,
SaveContextProvider,
FormContextProvider,
} from 'ra-core';
+import { renderWithRedux, TestContext } from 'ra-test';
import { ThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
diff --git a/packages/ra-ui-materialui/src/detail/Create.spec.js b/packages/ra-ui-materialui/src/detail/Create.spec.js
index bab92de24c3..ccb5c111db0 100644
--- a/packages/ra-ui-materialui/src/detail/Create.spec.js
+++ b/packages/ra-ui-materialui/src/detail/Create.spec.js
@@ -1,6 +1,6 @@
import * as React from 'react';
import expect from 'expect';
-import { renderWithRedux } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import { Create } from './Create';
diff --git a/packages/ra-ui-materialui/src/detail/Edit.spec.js b/packages/ra-ui-materialui/src/detail/Edit.spec.js
index f8adfb8ff38..b1728b403fb 100644
--- a/packages/ra-ui-materialui/src/detail/Edit.spec.js
+++ b/packages/ra-ui-materialui/src/detail/Edit.spec.js
@@ -1,11 +1,8 @@
import * as React from 'react';
import expect from 'expect';
import { waitFor, fireEvent, act } from '@testing-library/react';
-import {
- renderWithRedux,
- DataProviderContext,
- undoableEventEmitter,
-} from 'ra-core';
+import { DataProviderContext, undoableEventEmitter } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import { Edit } from './Edit';
diff --git a/packages/ra-ui-materialui/src/detail/Show.spec.js b/packages/ra-ui-materialui/src/detail/Show.spec.js
index 5ce7a85b96f..38f853834be 100644
--- a/packages/ra-ui-materialui/src/detail/Show.spec.js
+++ b/packages/ra-ui-materialui/src/detail/Show.spec.js
@@ -1,6 +1,7 @@
import * as React from 'react';
import expect from 'expect';
-import { renderWithRedux, DataProviderContext } from 'ra-core';
+import { DataProviderContext } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import { Show } from './Show';
diff --git a/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx b/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx
index d0ef089e3b0..d5beeb5dd35 100644
--- a/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx
+++ b/packages/ra-ui-materialui/src/field/ArrayField.spec.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import { render } from '@testing-library/react';
-import { TestContext } from 'ra-core';
+import { TestContext } from 'ra-test';
import ArrayField from './ArrayField';
import NumberField from './NumberField';
diff --git a/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx b/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx
index 0874b18d7a2..50d2934e3d9 100644
--- a/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx
+++ b/packages/ra-ui-materialui/src/field/ReferenceField.spec.tsx
@@ -2,7 +2,8 @@ import * as React from 'react';
import expect from 'expect';
import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
-import { renderWithRedux, DataProviderContext } from 'ra-core';
+import { DataProviderContext } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import ReferenceField, { ReferenceFieldView } from './ReferenceField';
import TextField from './TextField';
diff --git a/packages/ra-ui-materialui/src/field/SelectField.spec.tsx b/packages/ra-ui-materialui/src/field/SelectField.spec.tsx
index dd7a0003fcc..80a6c148ee6 100644
--- a/packages/ra-ui-materialui/src/field/SelectField.spec.tsx
+++ b/packages/ra-ui-materialui/src/field/SelectField.spec.tsx
@@ -3,7 +3,8 @@ import { FC } from 'react';
import expect from 'expect';
import { render } from '@testing-library/react';
-import { Record, TestTranslationProvider, renderWithRedux } from 'ra-core';
+import { Record, TestTranslationProvider } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import SelectField from './SelectField';
describe('', () => {
diff --git a/packages/ra-ui-materialui/src/form/FormTab.spec.tsx b/packages/ra-ui-materialui/src/form/FormTab.spec.tsx
index c995adfbbf7..0ee7382bdb1 100644
--- a/packages/ra-ui-materialui/src/form/FormTab.spec.tsx
+++ b/packages/ra-ui-materialui/src/form/FormTab.spec.tsx
@@ -1,10 +1,7 @@
import * as React from 'react';
import expect from 'expect';
-import {
- renderWithRedux,
- SaveContextProvider,
- SideEffectContextProvider,
-} from 'ra-core';
+import { SaveContextProvider, SideEffectContextProvider } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import TabbedForm from './TabbedForm';
import FormTab from './FormTab';
diff --git a/packages/ra-ui-materialui/src/form/SimpleForm.spec.tsx b/packages/ra-ui-materialui/src/form/SimpleForm.spec.tsx
index 525235022de..c262b3b5264 100644
--- a/packages/ra-ui-materialui/src/form/SimpleForm.spec.tsx
+++ b/packages/ra-ui-materialui/src/form/SimpleForm.spec.tsx
@@ -1,10 +1,7 @@
import * as React from 'react';
import expect from 'expect';
-import {
- renderWithRedux,
- SaveContextProvider,
- SideEffectContextProvider,
-} from 'ra-core';
+import { SaveContextProvider, SideEffectContextProvider } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import SimpleForm from './SimpleForm';
import TextInput from '../input/TextInput';
diff --git a/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx b/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx
index 3caaf003b12..dea1fae28e6 100644
--- a/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx
+++ b/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx
@@ -1,11 +1,8 @@
import { fireEvent, waitFor, getByText } from '@testing-library/react';
import * as React from 'react';
import expect from 'expect';
-import {
- renderWithRedux,
- SaveContextProvider,
- SideEffectContextProvider,
-} from 'ra-core';
+import { SaveContextProvider, SideEffectContextProvider } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import { ThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
diff --git a/packages/ra-ui-materialui/src/form/TabbedForm.spec.tsx b/packages/ra-ui-materialui/src/form/TabbedForm.spec.tsx
index 52b89230c32..d97aef1698a 100644
--- a/packages/ra-ui-materialui/src/form/TabbedForm.spec.tsx
+++ b/packages/ra-ui-materialui/src/form/TabbedForm.spec.tsx
@@ -2,11 +2,11 @@ import * as React from 'react';
import { MemoryRouter } from 'react-router-dom';
import {
minLength,
- renderWithRedux,
required,
SaveContextProvider,
SideEffectContextProvider,
} from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import TabbedForm from './TabbedForm';
import FormTab from './FormTab';
diff --git a/packages/ra-ui-materialui/src/input/CheckboxGroupInput.spec.tsx b/packages/ra-ui-materialui/src/input/CheckboxGroupInput.spec.tsx
index 0b3b492b554..40747f96f2a 100644
--- a/packages/ra-ui-materialui/src/input/CheckboxGroupInput.spec.tsx
+++ b/packages/ra-ui-materialui/src/input/CheckboxGroupInput.spec.tsx
@@ -3,7 +3,8 @@ import expect from 'expect';
import CheckboxGroupInput from './CheckboxGroupInput';
import { render, fireEvent } from '@testing-library/react';
import { Form } from 'react-final-form';
-import { renderWithRedux, TestTranslationProvider } from 'ra-core';
+import { TestTranslationProvider } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
describe('', () => {
const defaultProps = {
diff --git a/packages/ra-ui-materialui/src/input/TranslatableInputs.spec.tsx b/packages/ra-ui-materialui/src/input/TranslatableInputs.spec.tsx
index 1262d4a6e25..c8d827875a7 100644
--- a/packages/ra-ui-materialui/src/input/TranslatableInputs.spec.tsx
+++ b/packages/ra-ui-materialui/src/input/TranslatableInputs.spec.tsx
@@ -3,12 +3,8 @@ import expect from 'expect';
import { fireEvent } from '@testing-library/react';
import { TranslatableInputs } from './TranslatableInputs';
import TextInput from './TextInput';
-import {
- FormWithRedirect,
- renderWithRedux,
- required,
- useTranslatableContext,
-} from 'ra-core';
+import { FormWithRedirect, required, useTranslatableContext } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import { TranslatableInputsTab } from './TranslatableInputsTab';
import { Tabs } from '@material-ui/core';
diff --git a/packages/ra-ui-materialui/src/list/List.spec.tsx b/packages/ra-ui-materialui/src/list/List.spec.tsx
index 5b0d2afe363..2453c44bcba 100644
--- a/packages/ra-ui-materialui/src/list/List.spec.tsx
+++ b/packages/ra-ui-materialui/src/list/List.spec.tsx
@@ -1,7 +1,8 @@
import * as React from 'react';
import expect from 'expect';
import { waitFor } from '@testing-library/react';
-import { renderWithRedux, DataProviderContext } from 'ra-core';
+import { DataProviderContext } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import { ThemeProvider } from '@material-ui/styles';
import { createMuiTheme } from '@material-ui/core/styles';
import { MemoryRouter } from 'react-router-dom';
diff --git a/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.spec.tsx b/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.spec.tsx
index a1c69645aa3..e2f691cfbf1 100644
--- a/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.spec.tsx
+++ b/packages/ra-ui-materialui/src/list/datagrid/DatagridRow.spec.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import { fireEvent } from '@testing-library/react';
-import { renderWithRedux, linkToRecord } from 'ra-core';
+import { linkToRecord } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
diff --git a/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx b/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx
index 9a0b2e5aee2..e1ccffe04ce 100644
--- a/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx
+++ b/packages/ra-ui-materialui/src/list/filter/FilterForm.spec.tsx
@@ -1,7 +1,7 @@
import expect from 'expect';
import { fireEvent } from '@testing-library/react';
import * as React from 'react';
-import { renderWithRedux } from 'ra-core';
+import { renderWithRedux } from 'ra-test';
import FilterForm, { mergeInitialValuesWithDefaultValues } from './FilterForm';
import TextInput from '../../input/TextInput';