目錄
- 目錄
- useNavigate() may be used only in the context of a Router component
- 測試router的邏輯是否要建立router context
- Mui的Drawer render出來一片空
- Mui theme因為沒有context而無法用
## useNavigate() may be used only in the context of a Router component
useNavigate()有無被呼叫
重點
不是react-router-dom是否正常運作,而是useNavigate
(或用到它的event handler)是否被呼叫
,點擊按鈕時path是否改變則交給E2E測試
需要mock react-router-dom的custom function
const mockUseNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
useNavigate: () => mockUsedNavigate,
useMatch: () => mockUseMatch,
}));
router的path有無改變
這會需要建立router context
const router = createBrowserRouter({
// ...
});
const App = () => {
return (
<div>
<RouterProvider router={router}>
// ...
</RouterProvider>
</div>
);
}
但如果未來不用react-router-dom做router、router結構差太多的話可能就要整個拆掉,所以建議用E2E來測
useNavigate() may be used only in the context of a Router component
testing library - React Router
測試router的邏輯是否要建立router context
例如不同權限的使用者能看到的router不同
不用,但需要做一個類似專案結構的router,並把他傳給要測試其邏輯的函式
Mui的Drawer render出來一片空
從Mui提供的範例中可以發現drawer被關掉的時候是不存在DOM上的,打開的時候才會被插入body內
再來跟據官方文件中關於container、baseElement的部分
這兩者都是由 react-testing-library 的 render function 所回傳,且都用於 query DOM
container
By default, React Testing Library will create a div and append that div to the document.body and this is where your React component will be rendered.
If you provide your own HTMLElement container via this option, it will not be appended to the document.body automatically.
baseElement
If the container is specified, then this defaults to that, otherwise this defaults to document.body.
Note: the queries returned by the render looks into baseElement, so you can use queries to test your portal component without the baseElement.
使用 render()時沒有
特別設定 option.container 的話
,container會是建立一個div然後把渲染的組件放進去
const { container } = rende(<p>this is NOT in Portal</p>);
console.log(container.outerHTML);
// <div>
// <p>this is NOT in Portal</p>
// </div>
一樣是沒有特別設定 option.container,baseElement會是body。而container此時是個div,所以它會是baseElement的child
const { baseElement } = rende(<p>this is NOT in Portal</p>);
console.log(baseElement.outerHTML);
// <body>
// <div></div>
// <p>this is in Portal</p>
// </body>
但是需要注意的是有用到portal component
時,因為portal component會直接被插到body下面
,所以container的那個div內就會是空的,所以只能用baseElement
const { container } = render(
<Portal>
<p>this is in Portal</p>
</Portal>,
);
console.log(container.outerHTML);
// <div></div>
const { baseElement } = render(
<Portal>
<p>this is in Portal</p>
</Portal>,
);
console.log(baseElement.outerHTML);
// <body>
// <div>
// <p>this is NOT in Portal</p>
// </div>
// </body>
也就是說container是包住要渲染的組件的那個div,而baseElement是body
const { container, baseElement } = render(
<Portal>
<p>this is in Portal</p>
</Portal>,
);
通常兩者都可以使用,但若測試的組件有用到 MUI 的 portal component 或者 React 的 createPortal(),因為 portal component 是被插在 body 裡,而不是 container 最外層的 div 則只能用 baseElement
Why are material UI components not rendered in jsdom when using Jest?
React Testing Library - API
【Day12】插槽 Portals
【Day21】導航元件 - Drawer
Mui theme因為沒有context而無法用
需要用到react-tesing-library的render,加上
Mui的ThemeProvider
,自行包成另一個render function
// renderApp.ts
import { FunctionComponent, PropsWithChildren, ReactElement } from 'react';
import { RenderOptions, RenderResult, render } from '@testing-library/react';
import { ThemeProvider } from '@mui/material/styles';
import { useMyTheme } from './src/styles/theme';
const renderApp = (children: ReactElement, options?: RenderOptions): RenderResult => {
const theme = useMyTheme();
return render(
<ThemeProvider theme={theme}>{children}</ThemeProvider>
);
};