#javascript #reactjs #jestjs #enzyme #ref
#javascript #reactjs #jestjs #фермент #ссылка
Вопрос:
Я пытаюсь издеваться this.ref.current.value
как часть теста функции в моем компоненте React. В настоящее current
время равно нулю, потому что я выполняю неглубокое монтирование своего компонента. Я пытаюсь найти способ издеваться над тем, что current.value
возвращается для моего ref, чтобы я мог протестировать другую часть функции, значение refs на самом деле не имеет значения для этого теста.
Фактическая функция:
copyDefinitionTarget = selectedInput => () => {
// get and select the input value
const copyText = this[`${selectedInput}`].current.value;
// copy to clipboard
navigator.clipboard.writeText(copyText);
};
Тестовый код:
it('calls navigator.clipboard appropriately to copy the text in copyDefinitionTarget', () => {
component = shallow(<Alert {...props} />);
component
.dive()
.find('Item')
.dive()
.find('Button')
.simulate('click');
expect(navigator.clipboard.writeText).toHaveBeenCalled();
});
Сбой теста:
TypeError: Cannot read property 'value' of null
50 | // get and select the input value
> 51 | const copyText = this[`${selectedInput}`].current.value;
Есть ли какой-нибудь способ сделать это? Я забочусь о тестировании того, что navigator.clipboard вызывался не так, как он был вызван.
Обновление, потому что я изменил свой код для использования this.ref
вместо stringRefName
фактической функции:
copyDefinitionTarget = selectedInput => () => {
// get and select the input value
const copyText = selectedInput.current.value;
// copy to clipboard
navigator.clipboard.writeText(copyText);
};
Тестовый код:
it('calls navigator.clipboard appropriately to copy the text in copyDefinitionTarget', () => {
component = shallow(<Alert {...props} />);
instance = component.instance();
// we are clicking on the first Alert Item
// so mock that ref specifically
instance.firstNameRef = {
current: {
value: 'stuff'
}
};
component
.dive()
.find('Item')
.dive()
.find('Button')
.simulate('click');
expect(navigator.clipboard.writeText).toHaveBeenCalled();
});
Вызов функции:
<Item
inputRef={this.firstNameRef}
inputValue={`${realmName}`}
copyDefinitionTarget={this.copyDefinitionTarget(this.firstNameRef)}
/>
Ответ №1:
Вы могли бы пойти дальше и сделать что-то вроде этого:
const component = shallow(<Alert {...props} />);
const selectedInput = 'ref';
component.instance()[selectedInput] = {
current: {
value: 'stuff'
}
}
navigator.clipboard = {writeText: jest.fn()}
component
.dive()
.find('Item')
.dive()
.find('Button')
.simulate('click');
expect(navigator.clipboard.writeText).toHaveBeenCalled();
Примечание: я не уверен, какой selectedInput
должна быть строка, вы можете передать любую строку, которая подходит в соответствии с вашим реальным кодом компонента.
Поскольку ref существует как свойство экземпляра компонента, вы можете просто передать любой объект, который вы хотите, пока он выглядит current.value
, затем вы можете заменить функцию копирования на макет, имитировать щелчок, а затем посмотреть, был ли writeText
вызван.
Комментарии:
1. Это сработало, спасибо! Просто примечание для всех, кто использует это
const selectedInput = 'ref'
;"ref"
должен быть тем, что является ссылкой для ввода, на который вы ориентируетесь, в моем случае это былоfirstNameRef
2. Итак, я обновил свой вызов функции для использования
this
вместо string, так что теперь onClick естьcopyDefinitionTarget={this.copyDefinitionTarget(this.firstNameRef)}
, и макет больше не работает. Знаете ли вы, как мне нужно будет обновить свой тест, чтобы он снова заработал? Я пробую несколько разных способов, но он продолжает говорить, что текущее значение возвращается к нулевому коду: « component.instance().firstNameRef = { current: { value: ‘stuff’ } }; «3. @caraclarke как теперь выглядит функция copyDefinitionTarget? И как именно выглядит тест с вашими изменениями. Не могли бы вы обновить вопрос, пожалуйста?
4. обновил вопрос новым кодом, он вернулся к тому, чтобы выдать мне исходное сообщение об ошибке теста, которое было «Не удается прочитать значение свойства ‘value’ null» и когда я пытаюсь утешить. в журнале
selectedInput
для моего теста написано{current: null}
5. @caraclarke я предполагаю, что дочерний компонент получает свойство до того, как оно было установлено извне в тесте, вы могли бы попробовать вызвать component.update() перед попыткой щелчка
Ответ №2:
Публикуем другой подход, который может быть использован в случае, если вы передаете фактическую ссылку вместо строки. Я извлек значение из ref в его собственную функцию и высмеял это в своем тесте
Фактический код:
// get the value from ref
getRefValue = ref => ref.current.value;
// copy value
copyDefinitionTarget = selectedInput => () => {
// get and select the input value
const copyText = this.getRefValue(selectedInput);
// copy to clipboard
navigator.clipboard.writeText(copyText);
};
Тестовый код:
it('calls navigator.clipboard appropriately to copy the text in copyDefinitionTarget', () => {
component = shallow(<MetadataAlert {...props} />);
instance = component.instance();
jest.spyOn(instance, 'getRefValue').mockImplementationOnce(() => '💻');
component
.dive()
.find('Item')
.dive()
.find('Button')
.simulate('click');
expect(navigator.clipboard.writeText).toHaveBeenCalled();
});