Reputation: 6805
I'm having trouble understanding how toHaveFocus()
works exactly. Here's my setup:
MyComponent.js
import React from 'react'
import styled from 'styled-components'
import TextArea from './TextArea'
const Container = styled.div`
flex: 1;
height: 100%;
padding: ${props => props.theme.size};
`
const Title = styled(TextArea)`
font-weight: bold;
font-size: ${props => props.theme.sizeLarger};
margin-left: ${props => props.theme.sizeSmall};
`
class MyComponent extends React.Component {
handleTitleChange = e => {
this.props.onTitleChange(e.target.value)
}
handleTitleLostFocus = () => {
this.props.onChangeComplete()
}
render () {
return (
<Container>
<Title
value={this.props.item.title || ''}
onChange={this.handleTitleChange}
onBlur={this.handleTitleLostFocus}
/>
</Container>
)
}
}
export default MyComponent
MyComponent.test.js
import React from 'react'
import {render, fireEvent, prettyDOM} from 'react-testing-library'
import MyComponent from '../MyComponent'
describe('MyComponent', () => {
it('handles title changes', () => {
const title = 'title'
const handleTitleChangeMock = jest.fn()
const {getByText} = render(
<MyComponent
item={{
title: title
}}
onTitleChange={handleTitleChangeMock}
onChangeComplete={() => {}}
/>
)
const titleInput = getByText(title)
console.log(prettyDOM(titleInput))
fireEvent.click(getByText(title))
expect(getByText(title)).toHaveFocus()
fireEvent.change(getByText(title), {target: {value: title.slice(0, -1)}})
expect(handleTitleChangeMock).toHaveBeenCalledTimes(1)
expect(handleTitleChangeMock).toHaveBeenCalledWith(title.slice(0, -1))
})
})
When I do this:
const titleInput = getByText(title)
console.log(prettyDOM(titleInput))
The console logs the following:
<textarea
class="sc-htoDjs dLjZCT sc-bxivhb jdLTBU"
style="height: 0px;"
>
title
</textarea>
That textarea
element is the one I am targeting. But then, when I do this:
fireEvent.click(titleInput)
expect(titleInput).toHaveFocus()
I get this error:
Received:
<body><textarea style="min-height: 0 !important; max-height: none !important; height: 0px !important; visibility: hidden !important; overflow: hidden !important; position: absolute !important; z-index: -1000 !important; top: 0px !important; right: 0px;" /><div><div class="sc-bZQynM ePHCfO"><textarea class="sc-htoDjs dLjZCT sc-bxivhb jdLTBU" style="height: 0px;">title</textarea></div></div></body>
at Object.it (src/__tests__/MyComponent.test.js:84:30)
at new Promise (<anonymous>)
at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
I don't quite understand why when I'm trying to assert a textarea
element toHaveFocus()
, I'm receiving an error that references the entire DOM tree under body
...
Upvotes: 1
Views: 3983
Reputation: 27018
If you give focus using titleInput.focus()
it works. I'm not sure why fireEvent.focus
doesn't work.
You can see it working here https://codesandbox.io/s/y020r74rjj
Upvotes: 2