Here I have a component named <TextInput />:
import React, { memo, useCallback, useState } from 'react';
import { View, TextInput as Input, Text } from 'react-native';
import PropTypes from 'prop-types';
import { COLORS } from '@Styles';
import { styles } from './styles';
const TextInput = memo(({ name, form, error = '', ...props }) => {
const [ focus, setFocus ] = useState(false);
const toggleFocus = useCallback((isFocus) => {
setFocus(isFocus);
form && form.handleBlur(name);
});
return (
<View style={styles.inputBox}>
<Input
style={[
styles.input,
props.multiline && styles.multiline,
(props.editable === false) && styles.disable,
error && styles.error,
focus && styles.focus
]}
value={form && form.values[name]}
onFocus={() => toggleFocus(true)}
onBlur={() => toggleFocus(false)}
onChangeText={form && form.handleChange(name)}
underlineColorAndroid="transparent"
placeholderTextColor={COLORS.INPUT.PLACEHOLDER}
{...props}
/>
</View>
);
});
TextInput.propTypes = {
name: PropTypes.string.isRequired,
form: PropTypes.object.isRequired
};
export default TextInput;
Then I create a test like below:
import React from 'react';
import chalk from 'chalk';
import { render, fireEvent } from 'react-native-testing-library';
import TextInput from '@Components/TextInput';
describe(chalk.bgCyan.black('@Component - TextInput'), () => {
describe(chalk.bgGreen.black('### functionality'), () => {
it('textInput values can be changed', () => {
let form = { touched: {}, errors: {}, values: {}, handleChange: jest.fn() };
const { getByPlaceholder } = render(<TextInput name="test" form={form} placeholder="Hey" />);
fireEvent.changeText(getByPlaceholder('Hey'), 'Hello');
expect(form.handleChange).toHaveBeenCalled();
});
});
});
It leads to the error below:
No handler function found for event: "changeText"
46 | const { getByPlaceholder } = render(<TextInput name="test" form={form} placeholder="Hey" />);
47 | console.log(getByPlaceholder('Hey'));
> 48 | fireEvent.changeText(getByPlaceholder('Hey'), 'Hello');
| ^
49 | expect(form.handleChange).toHaveBeenCalled();
50 | });
51 | });
"devDependencies": {
"@babel/core": "7.9.0",
"@babel/runtime": "7.9.2",
"@react-native-community/eslint-config": "1.1.0",
"@testing-library/jest-native": "3.1.0",
"babel-jest": "25.5.0",
"eslint": "6.8.0",
"jest": "25.5.0",
"metro-react-native-babel-preset": "0.59.0",
"react-native-testing-library": "1.14.0",
"react-test-renderer": "16.11.0"
},
I have tried to add console.log(getByPlaceholder('Hey')); and here is the element got:
ReactTestInstance {
_fiber: <ref *1> FiberNode {
tag: 1,
key: null,
elementType: [Function: Component] {
displayName: 'Component',
'$$typeof': Symbol(react.forward_ref),
render: [Function: TextInput],
defaultProps: [Object],
propTypes: [Object],
State: [Object]
},
type: [Function: Component] {
displayName: 'Component',
'$$typeof': Symbol(react.forward_ref),
render: [Function: TextInput],
defaultProps: [Object],
propTypes: [Object],
State: [Object]
},
stateNode: Component {
props: [Object],
context: {},
refs: {},
updater: [Object],
_reactInternalFiber: [Circular *1],
_reactInternalInstance: {},
state: null
},
return: FiberNode {
tag: 5,
key: null,
elementType: 'View',
type: 'View',
stateNode: [Object],
return: [FiberNode],
child: [Circular *1],
sibling: null,
index: 0,
ref: null,
pendingProps: [Object],
memoizedProps: [Object],
updateQueue: null,
memoizedState: null,
dependencies: null,
mode: 0,
effectTag: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
expirationTime: 0,
childExpirationTime: 0,
alternate: null,
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 40,
_debugIsCurrentlyTiming: false,
_debugSource: null,
_debugOwner: [FiberNode],
_debugNeedsRemount: false,
_debugHookTypes: null
},
child: FiberNode {
tag: 5,
key: null,
elementType: 'TextInput',
type: 'TextInput',
stateNode: [Object],
return: [Circular *1],
child: null,
sibling: null,
index: 0,
ref: null,
pendingProps: [Object],
memoizedProps: [Object],
updateQueue: null,
memoizedState: null,
dependencies: null,
mode: 0,
effectTag: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
expirationTime: 0,
childExpirationTime: 0,
alternate: null,
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 42,
_debugIsCurrentlyTiming: false,
_debugSource: null,
_debugOwner: [Circular *1],
_debugNeedsRemount: false,
_debugHookTypes: null
},
sibling: null,
index: 0,
ref: null,
pendingProps: {
style: [Array],
value: undefined,
onFocus: [Function: onFocus],
onBlur: [Function: onBlur],
onChangeText: undefined,
underlineColorAndroid: 'transparent',
placeholderTextColor: '#aaa',
placeholder: 'Hey',
allowFontScaling: true,
rejectResponderTermination: true
},
memoizedProps: {
style: [Array],
value: undefined,
onFocus: [Function: onFocus],
onBlur: [Function: onBlur],
onChangeText: undefined,
underlineColorAndroid: 'transparent',
placeholderTextColor: '#aaa',
placeholder: 'Hey',
allowFontScaling: true,
rejectResponderTermination: true
},
updateQueue: null,
memoizedState: null,
dependencies: null,
mode: 0,
effectTag: 1,
nextEffect: null,
firstEffect: null,
lastEffect: null,
expirationTime: 0,
childExpirationTime: 0,
alternate: null,
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 41,
_debugIsCurrentlyTiming: false,
_debugSource: null,
_debugOwner: FiberNode {
tag: 15,
key: null,
elementType: [Object],
type: [Function (anonymous)],
stateNode: null,
return: [FiberNode],
child: [FiberNode],
sibling: null,
index: 0,
ref: null,
pendingProps: [Object],
memoizedProps: [Object],
updateQueue: null,
memoizedState: [Object],
dependencies: null,
mode: 0,
effectTag: 1,
nextEffect: null,
firstEffect: null,
lastEffect: null,
expirationTime: 0,
childExpirationTime: 0,
alternate: null,
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 38,
_debugIsCurrentlyTiming: false,
_debugSource: null,
_debugOwner: null,
_debugNeedsRemount: false,
_debugHookTypes: [Array]
},
_debugNeedsRemount: false,
_debugHookTypes: null
}
}
render(<TextInput name="test" form={form} placeholder="Hey" />)
There's no onChangeText implemented, hence there's no handler to call and you see the error. It's an expected behavior, you have to implement onChangeText.
Are there any plans to allow fireEvent.changeText to trigger both onChange and onChangeText? Since React Native's TextInput allows for both an onChange: (event) prop and an onChangeText: (string) prop to be used somewhat interchangeably, it would be nice to have fireEvent.changeText trigger both callbacks. Alternatively, pointing this out in the documentation or having the No handler function found for event: "changeText" provide more descriptive information on how to resolve the error would be wonderful
Most helpful comment
Are there any plans to allow fireEvent.changeText to trigger both onChange and onChangeText? Since React Native's TextInput allows for both an
onChange: (event)prop and anonChangeText: (string)prop to be used somewhat interchangeably, it would be nice to havefireEvent.changeTexttrigger both callbacks. Alternatively, pointing this out in the documentation or having theNo handler function found for event: "changeText"provide more descriptive information on how to resolve the error would be wonderful