Search code examples
react-admin

Unit Testing Edit components and Create components result to error


and thumbs up for your great work!

So I am trying to write some vitest unit test for an Edit component (and Create also) using the tutorial on your website. So having a resource, and an edit component as follows:

<Edit> <SimpleForm> ..... </SimpleForm> </Edit>

So, when I try to write a test as follows:

describe(......
     it('.....', () => { 
       render(
         <AdminContext dataProvider={...someDataProvider...}>
           <MyEditComponent />
         </AdminContext>
       )
      })
)......

I get the following error:

 TypeError: Cannot read properties of undefined (reading 'toLowerCase') 
❯ Object._apply_rules node_modules/inflection/lib/inflection.js:594:53
❯ Object.singularize node_modules/inflection/lib/inflection.js:692:24
❯ node_modules/ra-core/src/core/useGetResourceLabel.ts:46:44 
❯ useEditController node_modules/ra-core/src/controller/edit/useEditController.ts:113:15 
❯ EditBase node_modules/ra-core/src/controller/edit/EditBase.tsx:42:46 
❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 
❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 
❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 
❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 
❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12

Other information:

  • React-admin version: 4.16.0
  • React version: 18.2.0

Any ideas on this one?

Thanks in advance.


Solution

  • Thanks for sharing your solution.

    Indeed this error is due to the fact that <Edit> needs to know what the current resource is. You can either declare a <Resource> component with your edit view (what you ended up doing), but you can also provide the resource manually, either via a <ResourceContextProvider> or via the resource prop.

    The latter is what react-admin does in some of its stories (see an example):

    export const InitialValue = () => (
        <AdminContext
            i18nProvider={i18nProvider}
            dataProvider={
                {
                    getOne: () => Promise.resolve({ data: { id: 1, gender: 'F' } }),
                } as any
            }
        >
            <Edit resource="posts" id="1">
                <SimpleForm>
                    <SelectInput
                        source="gender"
                        choices={[
                            { id: 'M', name: 'Male ' },
                            { id: 'F', name: 'Female' },
                        ]}
                    />
                    <FormInspector name="gender" />
                </SimpleForm>
            </Edit>
        </AdminContext>
    );
    

    This syntax has the advantage to be shorter, which is useful for unit testing.

    Hope this helps.