简体   繁体   English

在 react-native 中测试 TextInput 组件

[英]Testing TextInput Component in react-native

I have some problems with testing TextInput changes in react-native with jest and enzyme .我在用jest测试react-native 中的TextInput更改时遇到了一些问题。

My component that handles user input basically looks like this (simplified):我处理用户输入的组件基本上是这样的(简化):

class Search extends React.PureComponent {
  onSearchTextChange = input => {
    // do something awesome
  };
  render() {
    return (
      <View>
        <TextInput
          onChangeText={debounce(this.onSearchTextChange, 800)}
        />
      </View>
    );
  }
}

I want to test the text input behaviour.我想测试文本输入行为。 This is what the test looks like right now:这就是测试现在的样子:

it('should render a text input and react to user input', done => {
  const mockOnSearchTextChange = jest.fn();
  Search.prototype.onSearchTextChange = mockOnSearchTextChange;

  const tree = shallow(<Search />);
  const textInput = tree.find('TextInput');
  expect(textInput).toHaveLength(1);
  textInput.simulate('changeText', { target: { value: 'test' } });
  expect(mockOnSearchTextChange).not.toHaveBeenCalled();
  setTimeout(() => {
    expect(mockOnSearchTextChange).toHaveBeenCalledWith('test');
    done();
  }, 1500);
});

When running this test, I get this error message运行此测试时,我收到此错误消息

Expected mock function to have been called with: ["test"]预期的模拟函数已被调用:["test"]

But it was not called.但它没有被调用。

So the mocked function is never called as expected.因此,永远不会按预期调用模拟函数。 What am I missing?我错过了什么?

There is no need to add another library.无需添加另一个库。 Jest and Enzyme can perform the required testing. Jest 和 Enzyme 可以执行所需的测试。 Below is the definition of SearchBar component which receives a function as a prop.下面是 SearchBar 组件的定义,它接收一个函数作为道具。 The function is called with the text typed.使用键入的文本调用该函数。

const SearchBar = ({onSearch}) => {
  return (
    <View>
      <TextInput
        onChangeText={text => onSearch(text)}
      />
    </View>
  );
};

The testing can be carried as follows测试可以如下进行

    const onSearch = jest.fn();
    const wrapper = shallow(<SearchBar onSearch={onSearch} />);
    wrapper.find('TextInput').simulate('changeText', 'test search text');
    expect(onSearch).toHaveBeenCalledWith('test search text');

I was able to do this usingreact-native-testing-library .我能够使用react-native-testing-library做到这一点。

// ...
import { render, act, fireEvent } from 'react-native-testing-library'
// ...
it ('does stuff', () => {
  const mock = jest.fn()
  const component = render(<Search onSearchTextChange={mock}/>)
  fireEvent.changeText(component.findByType(TextInput), 'test')
  expect(mock).toHaveBeenCalledWith('test')
})

You can add and testID in your TextInput Field and accessibilityLabel as one of the props, add both for ios and android compatibility, Here is the TextInput code.您可以在 TextInput 字段中添加 testID 和 accessibilityLabel 作为道具之一,为 ios 和 android 兼容性添加,这是 TextInput 代码。

   <TextInput
         placeholder='Email Address'
         testID='#email'
         accessibilityLabel='#email'
         blurOnSubmit={ false }
         onEndEditing={this.onSubmitLogin}
         >
         </TextInput>

In your test file do a shallow rendering, here在你的测试文件中做一个浅渲染,在这里

    describe('Your component', () => {
     it('Component: renders correctly', () => {
     const tree = renderer.create(<YourComponent/>).toJSON();
     expect(tree).toMatchSnapshot();
  });
  it('Has  TextInput', () => {
   const tree2 = renderer.create(<YourComponent/>).toJSON();
   expect(findElement(tree2, '#email')).toBeDefined();
 });

});

Then define the function findElement above describe.然后定义上面描述的函数findElement。 With console.warn you should see your props of TextInput and in that your testID使用 console.warn 你应该看到你的 TextInput 道具和你的 testID

   const findElement = function (tree2, element) {
   let result = undefined
   console.warn(tree2.children)
   for(node in tree2.children){
   if(tree2.children[node].props.testID = element) {
   result = true
   }
  }
   return result
 }

It will test for all available TextInputs .... Note: Shallow rendering will only work if the TextInput is only one level deep(Inside one view only) if it is nested refer here - https://medium.com/@AidThompsin/heres-how-you-unit-test-textinput-with-react-native-63e1f7692b17它将测试所有可用的 TextInputs .... 注意:如果 TextInput 只有一层深(仅在一个视图内),如果它是嵌套的,则浅渲染才有效,请参阅此处 - https://medium.com/@AidThompsin/ Heres-how-you-unit-test-textinput-with-react-native-63e1f7692b17

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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