Мне нужно перенести мое приложение из классов в функции. Во время рефакторинга я обнаружил две проблемы с модульными тестами.
- Как получить доступ к функции внутреннего компонента, которая отображает другой компонент React?
- Как смоделировать презентационный компонент внутри метода визуализации контейнера?
Рассмотрим два компонента:
ComponentToTest
import React from "react";
import PropTypes from "prop-types";
import {ViewToTest} from "./ViewToTest";
export function ComponentToTest(props) {
const internalFunction = () => {
return 'internal function'
};
React.useEffect(() => {
internalFunction();
}, []);
return (
<ViewToTest clientProductId={props.clientProductId} productShortName={props.productShortName}/>
)
}
ComponentToTest.propTypes = {
clientProductId: PropTypes.number.isRequired,
DataProductGeolocations: PropTypes.shape({
clientProductGeolocationCountries: PropTypes.arrayOf(PropTypes.object),
loading: PropTypes.bool,
}),
productShortName: PropTypes.string.isRequired,
};
ComponentToTest.defaultProps = {
DataProductGeolocations: {
clientProductGeolocationCountries: [],
loading: false,
},
};
и ViewToTest
import React from "react";
import PropTypes from "prop-types";
export const ViewToTest = (props) => {
return (
<>
<div>ViewToTest</div>
<div>{props}</div>
</>
)
};
ViewToTest.propTypes = {
clientProductId: PropTypes.number.isRequired,
productShortName: PropTypes.string.isRequired,
};
ViewToTest.displayName = 'ViewToTest';
Я написал простой тест для ComponentToTest
import React from "react";
import {ComponentToTest} from "./ComponentToTest";
jest.mock('./ViewToTest', () => {
return function MockedViewToTest(props) {
return (
<div>
<div>clientProductId: {props.clientProductId}</div>
<div>productShortName: {props.productShortName}</div>
</div>
)
}
});
describe('A ComponentToTest suite', () => {
test('should match snapshot', () => {
const component = shallow(
<ComponentToTest clientProductId={666} productShortName={'lco'} />
);
expect(component.debug()).toMatchSnapshot();
});
test('should call internalFunction() after first render', () => {
const component = shallow(
<ComponentToTest clientProductId={666} productShortName={'lco'} />
);
const instance = component.instance();
expect(instance.internalFunction()).toHaveBeenCalled();
});
});
Первый тест генерирует моментальный снимок:
<Component clientProductId={666} productShortName=\"lco\" />
И вопрос в том, как изменить имя макетируемого компонента с Компонент на * ViewToTest *?
Второй тест не пройден с предупреждением:
Предупреждение: React.createElement: тип недействителен - ожидается строка (для встроенных компонентов) или класс / функция (для составных компонентов), но получено: undefined. Скорее всего, вы забыли экспортировать компонент из файла, в котором он определен, или вы перепутали импорт по умолчанию и имя.
и ошибка:
Ошибка ввода: Ошибка чтения свойство 'internalFunction' равно нулю
Если вы проверите, что такое компонент , отображаемый с shallow , вы увидите:
<Component clientProductId={666} productShortName="lco" />
вместо из ComponentToTest
Как мне написать тест, чтобы иметь правильное имя компонента в снимке и экземпляр ComponentToTest во втором тесте?