-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Can't access the component's instance #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'd suggest that instead of passing a jest spy function as the render prop, you pass an actual render functions as For instance, something like this: import React from 'react'
import { render, wait } from 'react-testing-library'
import TripListState from './TripListState'
describe('<TripListState>', () => {
it('should fetch the trips on load', async () => {
const children = ({ status, filter }) => (
<div>
<div data-testid="status">{status}</div>
<div data-testid="filter">{filter}</div>
</div>
);
const trips = [{ id: 1 }]
// I pass this as a prop so I can avoid mocking the dependency
const fetchTrips = x => Promise.resolve(trips)
render(
<TripListState children={children} fetchTrips={fetchTrips} />
)
expect(getByTestId('status')).toHaveTextContent('LOADING');
expect(getByTestId('filter')).toHaveTextContent('ALL');
})
}) Checking of the |
Thanks @gnapse! For components that expose a render prop API, you may also consider that the "user of your software" is actually a developer who's using the render prop API to build another component, so in that case I'm actually (generally) fine with passing a spy as the render prop value. If you look at the tests in downshift, you'll see we do this a lot (for example). I hope these examples are a help to you. If you come up with something you're happy with, we'd really appreciate it if you could add an example to the As this issue isn't exactly actionable, I'll go ahead and close it. Feel free to continue chatting though :) |
Thanks to both for the help. This is what I ended up doing: import React from 'react'
import { render, wait } from 'react-testing-library'
import TripListState from './TripListState'
describe('<TripListState>', () => {
it('should fetch the trips on load', async () => {
const children = jest.fn(() => null)
const trips = [{ id: 1 }]
const fetchTrips = () => Promise.resolve(trips)
render(<TripListState children={children} fetchTrips={fetchTrips} />)
expect(children).toHaveBeenCalledTimes(1)
expect(children.mock.calls[0][0]).toMatchObject({
status: 'LOADING',
filter: 'ALL',
})
await wait(() => expect(children).toHaveBeenCalledTimes(2))
expect(children.mock.calls[1][0]).toMatchObject({
status: 'READY',
filter: 'ALL',
trips,
})
})
it('should allow to change the filter', async () => {
const children = jest.fn(() => null)
const allTrips = [{ id: 1 }, { id: 2 }]
const pastTrips = [allTrips[0]]
const fetchTrips = filter =>
Promise.resolve(filter === 'ALL' ? allTrips : pastTrips)
render(<TripListState children={children} fetchTrips={fetchTrips} />)
await wait(() => expect(children).toHaveBeenCalledTimes(2))
children.mock.calls[1][0].onChangeFilter('PAST')
expect(children).toHaveBeenCalledTimes(3)
expect(children.mock.calls[2][0]).toMatchObject({
status: 'FILTERING',
filter: 'PAST',
trips: undefined,
})
await wait(() => expect(children).toHaveBeenCalledTimes(4))
expect(children.mock.calls[3][0]).toMatchObject({
status: 'READY',
filter: 'PAST',
trips: pastTrips,
})
})
}) I don't care what @kentcdodds do you think it is worth to generalize this into |
That looks good! It does look a little specific to your use case to include in |
@Gpx hi, if you have to test component's instance, you can try it('test instance exist', () => {
let instance
render(
<Component
ref={node => {
instance = node
}}
/>
)
expect(Object.prototype.toString.call(instance.A)).toBe('[object Function]')
expect(Object.prototype.toString.call(instance.B)).toBe('[object Function]')
}) |
react-testing-library
version: 2.1.1node
version: 9.4.0npm
(oryarn
) version: 5.6.0Relevant code or config
I'm trying to test this component
It simpliy fetches a list of trips and and exposes a method to change the filter value.
What you did:
This is my attempt to test it:
What happened:
Problem description:
The problem is that I can't access my component's instance and its methods. Not sure what the best approach is here.
Suggested solution:
I'm unsure of this, maybe I'm using
react-testing-libraray
for something it was not intended to, or maybe my testing approach is wrong. I'm hoping for suggestions :)The text was updated successfully, but these errors were encountered: