Reputation: 14806
I'm building my app with React Native and I do my unit tests with Jest and Enzyme. How can I test my <FlatList />
's renderItem()
function?
It returns a <ListItem />
from the React-Native-Elements library.
Let me give you the example code:
import { ListItem } from 'react-native-elements'
export class MyList extends Component {
const list = [
{
name: 'Amy Farha',
subtitle: 'Vice President'
},
{
name: 'Chris Jackson',
avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
subtitle: 'Vice Chairman'
},
... // more items
]
keyExtractor = (item, index) => index
renderItem = ({ item }) => (
<ListItem
title={item.name}
subtitle={item.subtitle}
leftAvatar={{
source: item.avatar_url && { uri: item.avatar_url },
title: item.name[0]
}}
/>
)
render () {
return (
<FlatList
keyExtractor={this.keyExtractor}
data={this.state.dataSource}
renderItem={this.renderItem}
/>
)
}
}
I would like to be able to test the renderItem()
function. My problem is, that wrapper.instance().renderItem({item: item})
returns the error: TypeError: wrapper.instance(...).renderItem(...).find is not a function
. Let me give you the code of the test that I wrote:
describe("component methods", () => {
let wrapper;
let props;
let item;
beforeEach(() => {
props = createTestProps();
wrapper = shallow(<MyList {...props} />);
});
describe("renderItem", () => {
describe("user", () => {
beforeEach(() => {
item = {
name: 'Chris Jackson',
avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
subtitle: 'Vice Chairman'
};
});
it("should display the order as a <ListItem />", () => {
expect(
wrapper
.instance()
.renderItem(item)
.find("ListItem")
).toHaveLength(1);
});
});
});
});
How would I have to write this test so that I can test if the function correctly renders a <ListItem />
?
Upvotes: 9
Views: 17470
Reputation: 382
You can also test using the renderProp
function.
const wrapper = shallow(<YourComponent {...defaultProps} />);
const flatList = wrapper.find('FlatList');
const item = flatList.renderProp('renderItem')({ item: yourData });
expect(item).toMatchSnapshot();
Upvotes: 4
Reputation: 2060
You can test FlatList
with react-native-testing-library
Here's example:
const Item = ({ name ) => <Text>{name}</Text>
class LisItem extends React.Component {
_keyExtractor = (item: { id: string }) => item.id
render() {
return (
<View style={styles.container}>
{todos && (
<FlatList
data={this.props.todos}
keyExtractor={this._keyExtractor}
renderItem={({ item: { id, name } }) => (
<Item
key={id}
name={name}
/>
)}
/>
)}
</View>
)
}
}
import { render } from 'react-native-testing-library'
const mockDataTodos = [
{
id: 'id-1',
name: 'Todo-1',
},
{
id: 'id-2',
name: 'Todo-2',
},
{
id: 'id-3',
name: 'Todo-3',
},
]
describe('Testing FlatList', () => {
test('Error component should be render when error is true', () => {
const componentTree = render(
<ListItem todos={mockDataTodos} />,
)
expect(componentTree.getAllByType(FlatList).length).toBe(1)
expect(componentTree.getAllByType(Item).length).toBe(mockDataTodos.length)
})
})
Hope this help!
Upvotes: 8
Reputation: 45830
renderItem()
returns a JSX element. JSX compiles to React.createElement() which returns an object.
Therefore, the return value from renderItem()
is just an object.
You can test that renderItem()
creates the correct object by doing the following:
it("should display the order as a <ListItem />", () => {
const element = wrapper
.instance()
.renderItem(item);
expect(element.type).toBe(ListItem);
expect(element.props).toEqual({
title: 'Chris Jackson',
subtitle: 'Vice Chairman',
leftAvatar: {
source: { uri: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg' },
title: 'C'
}
});
});
Upvotes: 8
Reputation: 1661
So I'm not sure whether you've extracted some code out of a class-based component, but renderItem
itself is a component. I can maybe give you some test code for that and you can adapt it for your needs, assuming you imported shallow and set up your item variable:
describe('renderItem', () => {
it('should display as a ListItem', () => {
const wrapper = shallow(<renderItem item={item} />);
expect(wrapper.find(ListItem).length).toEqual(1);
});
});
There are two key things that are different from your example. One - I assume here you've imported ListItem
into your test. You can then pass that directly into find
. The second bit is you want to pass the result of finding and checking the length into expect
and test the value of that. Think of it is "what I want to test" (the number of ListItem
components it can find) and then off of that you create your assertion (toEqual(1)
).
In your setup, I wouldn't bother to test renderItem
directly. Instead I'd ensure full testing of ListItem
, and then assert things about how MyList
renders FlatList
. This can be done using expect(wrapper).toMatchSnapshot()
, or even better by asserting some things about the props given to FlatList
. If you are really paranoid about all of this, perhaps use mount
instead of shallow to render it completely.
Upvotes: 0