我想测试使用 render prop 渲染的 jsx 的内容。我使用react-test-renderer进行测试。
这是Menu
具有我要测试的渲染道具的组件:
<Menu
menuItems={createMenuItems(cities, onOpenCity)}
render={(openMenu, onClick, children) => (
<>
<Button
buttonRef={node => this.anchorEl = node}
onClick={onClick}
className={`${classes.iconWrapper} ${classes.marginIcons} ${openMenu && classes.active}`}
<Book fill={openMenu ? '#000' : '#fff'}/>
</Button>
{children(this.anchorEl)}
</>
)}
>
</Menu>
Menu 组件如下所示:
class Menu extends React.Component {
static propTypes = {
menuItems: PropTypes.arrayOf(PropTypes.shape({text: PropTypes.string, defaultAction: PropTypes.object})).isRequired
};
state = {
openMenu: false,
};
onToggleMenu() {
this.setState(prevState => ({openMenu: !prevState.openMenu}))
}
onCloseMenu() {
this.setState({openMenu: false})
}
render() {
const {openMenu} = this.state;
const {classes, render, menuItems} = this.props;
return render(
openMenu,
() => this.onToggleMenu(),
(anchorEl) => (<Popper open={openMenu} anchorEl={anchorEl} placement="bottom-end" transition
disablePortal>
{({TransitionProps, placement}) => (
<Grow
{...TransitionProps}
id="menu-list-grow"
style={{transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom'}}
>
<Paper>
<ClickAwayListener onClickAway={() => this.onCloseMenu()}>
<MenuList disablePadding>
{menuItems.map(menuItem => (
<MenuItem
key={menuItem.text}
className={classes.menuItem}
onClick={() => {
menuItem.action();
this.onCloseMenu();
}}>{menuItem.text}</MenuItem>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
))
}
}
我正在尝试为此组件编写一些测试:
describe('Menu', () => {
const context = setupTeardownWithTestRenderer();
const menuItems = [
{
text: '1st item',
action: () => {}
}
];
const renderFunction = (openMenu, onClick, children) => children(<Button onClick={onClick}>Menu</Button>);
function renderMenu() {
const WithRootMenu = withRoot(Menu);
const testRenderer = context.render(<WithRootMenu menuItems={menuItems} render={renderFunction}/>);
return testRenderer.root.findByType(Menu.Naked);
}
it('renders menu', () => {
const menu = renderMenu();
expect(menu.instance.state.openMenu).toBeFalsy();
const menuList = menu.findByType(MenuList);
console.log(menuList);
});
});
我正在尝试获取,MenuList
因为我想测试组件onClick
道具上的功能。MenuItem
我正在使用setupTeardownWithTestRenderer
功能设置测试:
export function setupTeardownWithTestRenderer() {
const context = new SimpleTestContext();
context.setupBeforeAfter();
return context;
}
SimpleTestContext 是一个类,它有一些帮助方法来设置测试:
class SimpleTestContext {
defaultNodeMock = {
createNodeMock: (element) => {
if (element.type === 'input') {
// return document.createElement('input');
//console.log('createNodeMock got input', element.props);
}
if (element.type === 'textarea') {
// console.log('createNodeMock got textarea', element.props);
return document.createElement('textarea');
}
return null;
}
};
testRenderer = {unmount: () => {}}; // null object
setup() {
this.consoleErrorSpy = jest.spyOn(global.console, 'error');
this.consoleErrorSpy.mockReset();
Document.prototype.exitFullscreen = jest.fn();
jest.useFakeTimers();
}
tearDown() {
this.testRenderer.unmount();
jest.runAllTimers();
jest.useRealTimers();
expect(this.consoleErrorSpy).not.toHaveBeenCalled();
}
act(func) {
TestRenderer.act(func);
}
render(jsx, options) {
this.testRenderer = TestRenderer.create(jsx, options);
return this.testRenderer;
}
renderWithDefaultNodeMock(jsx) {
return this.render(jsx, this.defaultNodeMock);
}
async waitForComponent(component) {
await waitForExpect(() => expect(
this.testRenderer.root.findAllByType(component)
.map(instance => ({ props: instance.props, type: instance.type }))).toHaveLength(1));
return this.testRenderer.root.findByType(component);
}
async waitForComponentByProps(props) {
await waitForExpect(() => expect(
this.testRenderer.root.findAllByProps(props)
.map(instance => ({props: instance.props, type: instance.type}))).toHaveLength(1));
return this.testRenderer.root.findByProps(props);
}
async waitForComponentToLoad(component) {
const instance = await this.waitForComponent(component);
await waitForExpect(() => expect(instance.instance.state.hasLoaded).toBeTruthy());
return instance;
}
setupBeforeAfter() {
beforeEach(() => {
this.setup();
});
afterEach(() => {
this.tearDown();
});
}
}
我的问题是,如果我在尝试查找 MenuList 的地方运行测试,例如:
it('renders menu', () => {
const menu = renderMenu();
console.log(menu.instance);
const menuList = menu.findByType(MenuList);
console.log(menuList);
});
我收到一个错误:
错误:找不到节点类型的实例:“未定义”
如何测试使用 render prop 渲染 jsx 的组件渲染了什么?