在本机中测试TextInput组件

时间:2018-08-08 15:37:55

标签: javascript react-native jestjs enzyme

我在用笑话测试反应性中的TextInput变化时遇到一些问题。

我处理用户输入的组件基本上看起来像这样(简化):

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

我想测试文本输入行为。现在的测试是这样的:

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);
});

运行此测试时,我收到此错误消息

  

预期的模拟函数已被调用:   [“测试”]

     

但没有被调用。

因此,模拟函数永远不会按预期方式调用。我想念什么?

3 个答案:

答案 0 :(得分:3)

无需添加其他库。 Jest和Enzyme可以执行所需的测试。下面是SearchBar组件的定义,该组件接收一个函数作为道具。会使用键入的文本来调用该函数。

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

可以进行以下测试

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

答案 1 :(得分:1)

我能够使用react-native-testing-library来做到这一点。

Homepage Component
    -----------------------------

<mat-sidenav-container>

  <mat-sidenav class="sidenav mat-elevation-z6" mode="over">
    <button class="close" color="warn" mat-icon-button>
      <mat-icon color="warn">close</mat-icon>
    </button>
  </mat-sidenav>

  <div style="z-index: 2000; position: fixed; top:0; background:red; height:50px" #stickyHeader>
    logo .....<searchByOption> ...social icons
    MENU
  </div>

  <div>Search here too</div>
  <searchByOption>
  <div>rest of the content</div>

</mat-sidenav-container>


searchByOptionComponent
-----------------------------
<mat-select>
 <mat-option>Test1</mat-option>
 <mat-option>Test2</mat-option>
 <mat-option>Test3</mat-option>
</mat-select>

答案 2 :(得分:0)

您可以在TextInput字段和accessibilityLabel中添加和testID作为道具之一, 同时添加ios和android的兼容性, 这是TextInput代码。

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

在测试文件中,在此处进行浅显示

    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();
 });

});

然后定义上面描述的功能findElement。 使用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
 }

它将测试所有可用的TextInputs .... 注意:如果TextInput是嵌套的,则只有当TextInput只有一层深度(仅在一个视图内)时,浅渲染才会起作用。请参阅-https://medium.com/@AidThompsin/heres-how-you-unit-test-textinput-with-react-native-63e1f7692b17