From a0bdf7e7ab00cf467ec4157322b104cd3cdaaaa8 Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:55:34 +0200 Subject: [PATCH 1/8] Add customReducers to the TestContext --- packages/ra-test/src/TestContext.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/ra-test/src/TestContext.tsx b/packages/ra-test/src/TestContext.tsx index edd5e2e11ef..015fbe18964 100644 --- a/packages/ra-test/src/TestContext.tsx +++ b/packages/ra-test/src/TestContext.tsx @@ -33,6 +33,7 @@ export interface TestContextProps { initialState?: object; enableReducers?: boolean; history?: History; + customReducers?: object; children: ReactNode | TextContextChildrenFunction; } @@ -69,7 +70,11 @@ export class TestContext extends Component { constructor(props) { super(props); this.history = props.history || createMemoryHistory(); - const { initialState = {}, enableReducers = false } = props; + const { + initialState = {}, + enableReducers = false, + customReducers = {}, + } = props; this.storeWithDefault = enableReducers ? createAdminStore({ @@ -78,6 +83,7 @@ export class TestContext extends Component { Promise.resolve(dataProviderDefaultResponse) ), history: createMemoryHistory(), + customReducers, }) : createStore(() => merge({}, defaultStore, initialState)); } From e0151bfff13e800a49818e831bd8e257c21fd4ef Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:56:45 +0200 Subject: [PATCH 2/8] Add unit test for customReducers to TestContext specs --- packages/ra-test/src/TestContext.spec.tsx | 80 ++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/packages/ra-test/src/TestContext.spec.tsx b/packages/ra-test/src/TestContext.spec.tsx index 40fbea7b763..15ea5332396 100644 --- a/packages/ra-test/src/TestContext.spec.tsx +++ b/packages/ra-test/src/TestContext.spec.tsx @@ -32,6 +32,35 @@ const primedStore = { }, }; +const CHANGE_FOO = 'CHANGE_FOO'; + +const customReducerInitialState = { + foo: 'bar', + foo2: 'bar2', +}; + +const customAction = payload => ({ + type: CHANGE_FOO, + payload, +}); + +const customReducer = (prevState = customReducerInitialState, action) => { + switch (action.type) { + case CHANGE_FOO: + return { + ...prevState, + foo: action.payload, + }; + default: + return prevState; + } +}; + +const eraseRouterKey = state => { + state.router.location.key = ''; // react-router initializes the state with a random key + return state; +}; + describe('TestContext.js', () => { it('should render the given children', () => { const { queryAllByText } = render( @@ -69,8 +98,7 @@ describe('TestContext.js', () => { }} ); - const initialstate = testStore.getState(); - initialstate.router.location.key = ''; // react-router initializes the state with a random key + const initialstate = eraseRouterKey(testStore.getState()); expect(initialstate).toEqual(primedStore); testStore.dispatch(refreshView()); @@ -103,5 +131,53 @@ describe('TestContext.js', () => { expect(testStore.getState()).toEqual(defaultStore); }); + + it('should initilize the state with customReducers initialState', () => { + let testStore; + render( + + {({ store }) => { + testStore = store; + return foo; + }} + + ); + const initialstate = eraseRouterKey(testStore.getState()); + + expect(initialstate).toEqual({ + ...primedStore, + customReducer: customReducerInitialState, + }); + }); + + it('should update the state on customReducers action', () => { + const testValue = 'test'; + let testStore; + render( + + {({ store }) => { + testStore = store; + return foo; + }} + + ); + + testStore.dispatch(customAction(testValue)); + const alteredState = eraseRouterKey(testStore.getState()); + + expect(alteredState).toEqual({ + ...primedStore, + customReducer: { + ...customReducerInitialState, + foo: testValue, + }, + }); + }); }); }); From 32f34aa7064463800de76d3b27b0fd14551031d2 Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:58:31 +0200 Subject: [PATCH 3/8] Add readme for TestContext and customReducers --- packages/ra-test/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/ra-test/README.md b/packages/ra-test/README.md index 4d2dee866f2..d80fcce016c 100644 --- a/packages/ra-test/README.md +++ b/packages/ra-test/README.md @@ -65,6 +65,20 @@ testUtils = render( This means that reducers will work as they will within the app. +### Passing your custom reducers + +If your component relies on customReducers which are passed originally to the `` component, you can plug them in the TestContext using the `customReducers` props: + +```jsx +testUtils = render( + + + +); +``` + +Note you should also enable the default react-admin reducers in order to supply the custom ones. + ### Spying on the store 'dispatch' If you are using `useDispatch` within your components, it is likely you will want to test that actions have been dispatched with the correct arguments. You can return the `store` being used within the tests using a `renderProp`. From 7af009cd162ad0af7edb2bc8abddafdf2f1be4fc Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Fri, 19 Mar 2021 17:07:20 +0200 Subject: [PATCH 4/8] Add customReducers to renderWithRedux --- packages/ra-test/src/renderWithRedux.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/ra-test/src/renderWithRedux.tsx b/packages/ra-test/src/renderWithRedux.tsx index 40abe3c55e8..f8c63cb5112 100644 --- a/packages/ra-test/src/renderWithRedux.tsx +++ b/packages/ra-test/src/renderWithRedux.tsx @@ -27,12 +27,17 @@ export interface RenderWithReduxResult extends RenderResult { export const renderWithRedux = ( component, initialState = {}, - options = {} + options = {}, + customReducers = {} ): RenderWithReduxResult => { let dispatch; let reduxStore; const renderResult = render( - + {({ store }) => { dispatch = jest.spyOn(store, 'dispatch'); reduxStore = store; @@ -46,7 +51,11 @@ export const renderWithRedux = ( ...renderResult, rerender: newComponent => { return renderResult.rerender( - + {({ store }) => { dispatch = jest.spyOn(store, 'dispatch'); reduxStore = store; From 175eb16b26f0ac4acd91549c1d480c0e50016dab Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Fri, 19 Mar 2021 17:09:00 +0200 Subject: [PATCH 5/8] Add inline example for customReducers inside renderWithRedux --- packages/ra-test/src/renderWithRedux.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/ra-test/src/renderWithRedux.tsx b/packages/ra-test/src/renderWithRedux.tsx index f8c63cb5112..f2a7523cadd 100644 --- a/packages/ra-test/src/renderWithRedux.tsx +++ b/packages/ra-test/src/renderWithRedux.tsx @@ -16,9 +16,19 @@ export interface RenderWithReduxResult extends RenderResult { * initialState * ); * + * render with react-testing library adding redux context for unit test and passing customReducers. + * @example + * const { dispatch, reduxStore, ...otherReactTestingLibraryHelper } = renderWithRedux( + * , + * initialState, + * {}, + * customReducers + * ); + * * @param {ReactNode} component: The component you want to test in jsx * @param {Object} initialState: Optional initial state of the redux store * @param {Object} options: Render options, e.g. to use a custom container element + * @param {Object} customReducers: Custom reducers to be added to the default store * @return {{ dispatch, reduxStore, ...rest }} helper function to test rendered component. * Same as @testing-library/react render method with added dispatch and reduxStore helper * dispatch: spy on the redux store dispatch method From 27f18a1d127f994022753fb78a83743fb7441559 Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Fri, 19 Mar 2021 21:26:57 +0200 Subject: [PATCH 6/8] Add docs about renderWithRedux test wrapper --- packages/ra-test/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/ra-test/README.md b/packages/ra-test/README.md index d80fcce016c..c08bc500f68 100644 --- a/packages/ra-test/README.md +++ b/packages/ra-test/README.md @@ -100,6 +100,37 @@ it('should send the user to another url', () => { }); ``` +### Using the 'renderWithRedux' wrapper function + +Instead of wrapping the component under test with the `TestContext` by yourself you can get use of all of the above options and test your components almost natively looking like using just `@testing-library/react` thanks to the `renderWithRedux` wrapper function. +// to the way using + +It will return the same output as `@testing-library/react`'s `render` method with added `dispatch` and `reduxStore` helpers + +```jsx +import { defaultStore } from 'ra-test' +... +const { dispatch, reduxStore, ...testUtils } = renderWithRedux( + , + initialState, + options, + myCustomReducers +); + +it('should initilize store', () => { + const storeState = reduxStore.getState(); + storeState.router.location.key = '' + expect(storeState).toEqual({...defaultStore, ...initialState}); +}); + +it('send the user to another url', () => { + fireEvent.click(testUtils.getByText('Go to next')); + expect(dispatch).toHaveBeenCalledWith(`/next-url`); +}); +``` + +All of the arguments except the first one - the component under test, are optional and could be omitted by passing an empty object - `{}` + ### Testing Permissions As explained on the [Auth Provider chapter](./Authentication.md#authorization), it's possible to manage permissions via the `authProvider` in order to filter page and fields the users can see. From 00148701ade3b783434c6baef3c9c2b812764766 Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Mon, 22 Mar 2021 15:53:47 +0200 Subject: [PATCH 7/8] Update renderWithRedux docs description Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com> --- packages/ra-test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ra-test/README.md b/packages/ra-test/README.md index c08bc500f68..a8eab887637 100644 --- a/packages/ra-test/README.md +++ b/packages/ra-test/README.md @@ -105,7 +105,7 @@ it('should send the user to another url', () => { Instead of wrapping the component under test with the `TestContext` by yourself you can get use of all of the above options and test your components almost natively looking like using just `@testing-library/react` thanks to the `renderWithRedux` wrapper function. // to the way using -It will return the same output as `@testing-library/react`'s `render` method with added `dispatch` and `reduxStore` helpers +It will return the same output as the `render` method from `@testing-library/react` but will add the `dispatch` and `reduxStore` helpers. ```jsx import { defaultStore } from 'ra-test' From e702b3e901c47d6cbf6c1a4d149bd8a5ed060a4c Mon Sep 17 00:00:00 2001 From: Valentin Dimitroff <26602880+ValentinnDimitroff@users.noreply.github.com> Date: Mon, 22 Mar 2021 16:06:33 +0200 Subject: [PATCH 8/8] Apply change requests about renderWithRedux docs --- packages/ra-test/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ra-test/README.md b/packages/ra-test/README.md index a8eab887637..67d0629d960 100644 --- a/packages/ra-test/README.md +++ b/packages/ra-test/README.md @@ -102,8 +102,7 @@ it('should send the user to another url', () => { ### Using the 'renderWithRedux' wrapper function -Instead of wrapping the component under test with the `TestContext` by yourself you can get use of all of the above options and test your components almost natively looking like using just `@testing-library/react` thanks to the `renderWithRedux` wrapper function. -// to the way using +Instead of wrapping the component under test with the `TestContext` by yourself you can use all of the above options and test your components almost like using just `@testing-library/react` thanks to the `renderWithRedux` wrapper function. It will return the same output as the `render` method from `@testing-library/react` but will add the `dispatch` and `reduxStore` helpers.