简体   繁体   中英

How can I assert which value has been passed to a <li> key attribute in react with jest and testing-library/react

I'm using react+ts and jest+testing-library for testing. I want to unit test the following code and would like to make sure that the person.id is set as the key attribute of the li element. Initially I thought I could assert it by running expect(listItems[1]).toHaveAttribute('key', '2'); but it seems that the key attribute is removed from the final HTML, which is what I seem to be testing. How can I make sure that the person.id is passed to the key attribute of the list item?

import React from 'react';
import Api from '../control/api';

const PersonList = () => {
    const persons = Api.getPersons();

    return (
        <ul>
            {persons.map((person) => {
                return (
                    <li key={person.id}>
                        {`${person.id}: ${person.name.familyName}, ${person.name.givenName}`}
                    </li>
                );
            })}
        </ul>
    );
};

export default PersonList;

The test:

import React from 'react';
import { render, screen } from '@testing-library/react';
import PersonList from '../../components/PersonList';
import { getPersons } from '../../control/api';

jest.mock('../../control/api');

const mockGetPersons = getPersons as jest.MockedFunction<typeof getPersons>;

describe('The PersonList component', () => {
    it('should output empty list if there are no persons returned by the api', () => {
        mockGetPersons.mockReturnValue([]);

        render(<PersonList />);

        const lists = screen.getAllByRole('list');
        expect(lists).toHaveLength(1);
    });

    it('should render one person returned by api', () => {
        mockGetPersons.mockReturnValue([
            {
                id: '1',
                name: {
                    familyName: 'Duck',
                    givenName: 'Donald',
                },
            },
        ]);

        render(<PersonList />);

        const listItems = screen.getAllByRole('listitem');
        expect(listItems).toHaveLength(1);
        expect(listItems[0]).toHaveTextContent('1: Duck, Donald');
    });

    it('should render several persons returned by api', () => {
        mockGetPersons.mockReturnValue([
            {
                id: '1',
                name: {
                    familyName: 'Duck',
                    givenName: 'Donald',
                },
            },
            {
                id: '2',
                name: {
                    familyName: 'Duck',
                    givenName: 'Dagobert',
                },
            },
            {
                id: '3',
                name: {
                    familyName: 'Mouse',
                    givenName: 'Mickey',
                },
            },
        ]);

        render(<PersonList />);

        const listItems = screen.getAllByRole('listitem');
        expect(listItems).toHaveLength(3);
        expect(listItems[0]).toHaveTextContent('1: Duck, Donald');
        // expect(listItems[1]).toHaveAttribute('key', '2');
        expect(listItems[2]).toHaveTextContent('3: Mouse, Mickey');
    });
});

The key property is used internally by react and it does not matter what it is set to, as long as the value is unique for each item in the current list. Therefore none of the users of the code (neither end-user or developer) will use/see/know about the value set there, which means that we should not write tests to assert the key property.

More about the key property in the react docs

Blog article about Testing Implementation Details

Stackoverflow question about Accessing the key property programmatically

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM