Using Vitest to test React component that uses custom hook

I'm using Vitest to test a React component that uses a custom hook. The custom hook creates a column for MUI DataGridPro with a custom renderCell function that renders a button in the column. The hook accepts a void callback function that is used for the onClick of the button. When the button is clicked, a modal should open up to display information based on the row. In prod and dev this works as expected, but I'm not sure how to test it. I want a test that will test the clicking of the button to ensure the Modal opens up. If I don't mock the hook, I get an error telling me renderEntryIconColumn is not a function, but when I do mock it and debug the test, renderEntryIconColumn is undefined. Below is the hook and component.

// useEntryIcon.js
const useEntryIcon = (callback) => {
  const [entryIcon, setEntryIcon] = useState('floppy')

  const { api } = useApiContext()

  const renderEntryIconColumn = useCallback(
    ({
      align = 'center',
      headerAlign = 'center',
      filterable = false,
      sortable = false,
      resizable = false,
      disableColumnMenu = false,
      title,
      id,
      ...rest
    }) => ({
      align,
      headerAlign,
      filterable,
      sortable,
      resizable,
      disableColumnMenu,
      renderCell: ({ id: rowId, row }) => {
          const params = { rowId, row }

          return (
            // EntriesIcon renders an svg based on `entryIcon`
            <EntriesIcon
              iconType={entryIcon}
              title={typeof title === 'string' ? title : title(rowId)}
              tabIndex={0}
              onClick={(e) => callback(params, e)}
              onKeyDown={(e) => {
                if (e.key === ' ' || e.key === 'Enter') {
                  callback(params, e)
                }
              }}
            />
          )
        },
      ...rest,
    }),
    [callback, entryIcon]
  )

  useEffect(() => {
    api
      .get('/api/app-info/entry-icon')
      .then(({ data }) => setEntryIcon(data))
      .catch(() => setEntryIcon('floppy'))
  }, [api])

  return renderEntryIconColumn
}


// MyComponent.jsx
function MyComponent({
  columns,
  rows,
  ...rest
}) {
  const [modalConfig, setModalConfig] = useState({
      recordId: '',
      memberId: '',
      open: false
  })
  const renderEntryIconColumn = useEntryIcon(({ row }) => {
      const { recordId, memberId } = row

      if (memberId) {
        setModalConfig({ open: true, recordId: recordId.toString(), memberId })
      }
    }
  )
  const firstColumn = renderEntryIconColumn({
    field: 'entries',
    headerName: 'Entries',
    id: (rowId) => `entries-icon-${rowId}`,
    title: (id) => `render-${id}`,
  })

  return (
    <>
      <DataGridPro columns={[firstColumn, ...columns]} rows={rows} {...rest} />
      <Modal
        {...modalConfig}
        onClose={() => {
          setModalConfig({ open: false, recordId: '', memberId: '' })
        }}
      />
    </>
  )
}
Was this page helpful?