我试着用Jest 来测试Animated.View分.当我将属性visible设置为true时,它应该将我的视图从opacity 0设置为opacity 1.

这是我的组件呈现的内容:

<Animated.View
    style={{
        opacity: opacityValue,
    }}
>
    <Text>{message}</Text>
</Animated.View>

其中,props visible发生变化时,opacityValue会更新:

Animated.timing(
    this.opacityValue, {
        toValue: this.props.visible ? 1 : 0,
        duration: 350,
    },
).start(),

我想确保我的视图在设置为属性visible=true时可见.尽管视图需要一些时间才能变得可见,并且随着测试的运行,不透明度等于0.

这是我对它的测试:

it('Becomes visible when visible=true', () => {
    const tree = renderer.create(
        <MessageBar
            visible={true}
        />
    ).toJSON();
    expect(tree).toMatchSnapshot();
});

我在想我怎么能等着呢?或者,当我将props 设置为true时,我如何测试它以确保视图可见?

谢谢

推荐答案

我通过为测试创建动画存根解决了这个问题.

我看到您正在使用visible作为属性,因此一个有效的示例是:

组件代码

import React from 'react';                                                                                                                                                                            
import { Animated, Text, View, TouchableOpacity } from 'react-native';                                                                                                                                

// This class will control the visible prop                                                                                                                                                                                                  
class AnimatedOpacityController extends React.Component {                                                                                                                                             

  constructor(props, ctx) {                                                                                                                                                                           
    super(props, ctx);                                                                                                                                                                                
    this.state = {                                                                                                                                                                                    
      showChild: false,                                                                                                                                                                               
    };                                                                                                                                                                                                
  }                                                                                                                                                                                                   

  render() {                                                                                                                                                                                          
    const { showChild } = this.state;                                                                                                                                                                 
    return (                                                                                                                                                                                          
      <View>                                                                                                                                                                                          
        <AnimatedOpacity visible={this.state.showChild} />                                                                                                                                            
        <TouchableOpacity onPress={() => this.setState({ showChild: !showChild })}>                                                                                                                   
          <Text>{showChild ? 'Hide' : 'Show' } greeting</Text>                                                                                                                                        
        </TouchableOpacity>                                                                                                                                                                           
      </View>                                                                                                                                                                                         
    );                                                                                                                                                                                                 
  }                                                                                                                                                                                                   

}                                                                                                                                                                                                     

// This is your animated Component                                                                                                                                                                                                   
class AnimatedOpacity extends React.Component {                                                                                                                                                       

  constructor(props, ctx) {                                                                                                                                                                           
    super(props, ctx);                                                                                                                                                                                
    this.state = {                                                                                                                                                                                    
      opacityValue: new Animated.Value(props.visible ? 1 : 0),                                                                                                                                                                                                                                                                                                               
    };                                                                                                                                                                                                
  }

  componentWillReceiveProps(nextProps) {                                                                                                                                                              
    if (nextProps.visible !== this.props.visible) {                                                                                                                                                   
      this._animate(nextProps.visible);                                                                                                                                                               
    }                                                                                                                                                                                                 
  }                                                                                                                                                                                                   

  _animate(visible) {                                                                                                                                                                                 
    Animated.timing(this.state.opacityValue, {                                                                                                                                                        
      toValue: visible ? 1 : 0,                                                                                                                                                                       
      duration: 350,                                                                                                                                                                                  
    }).start();                                                                                                                                                       
  }                                                                                                                                                                                                   

  render() {                      
    return (                                                                                                                                                                                          
      <Animated.View style={{ opacity: this.state.opacityValue }}>                                                                                                                                    
        <Text>Hello World</Text>                                                                                                                                                                      
      </Animated.View>                                                                                                                                                                                
    );                                                                                                                                                                                                 

  }                                                                                                                                                                                                   

}                                                                                                                                                                                                     


export { AnimatedOpacityController, AnimatedOpacity };

现在转到测试

import React from 'react';                                                                                                                                                                            
import renderer from 'react-test-renderer';                                                                                                                                                           
import { shallow } from 'enzyme';                                                                                                                                                                                                                                                                                                                                                                       

import { AnimatedOpacityController, AnimatedOpacity } from '../AnimatedOpacity';                                                                                                                    


jest.mock('Animated', () => {                                                                                                                                                                         
  const ActualAnimated = require.requireActual('Animated');                                                                                                                                           
  return {                                                                                                                                                                                            
    ...ActualAnimated,                                                                                                                                                                                
    timing: (value, config) => {                                                                                                                                                                      
      return {                                                                                                                                                                                        
        start: (callback) => {
          value.setValue(config.toValue);
          callback && callback()
        },                                                                                                                                                  
      };                                                                                                                                                                                              
    },                                                                                                                                                                                                
  };                                                                                                                                                                                                  
});                                                                                                                                                                                                                                                                                                                                                                                                     

it('renders visible', () => {                                                                                                                                                                         
  expect(                                                                                                                                                                                             
    renderer.create(                                                                                                                                                                                  
      <AnimatedOpacity visible={true} />                                                                                                                                                              
    ).toJSON()                                                                                                                                                                                        
  ).toMatchSnapshot();                                                                                                                                                                                
});                                                                                                                                                                                                   

it('renders invisible', () => {                                                                                                                                                                       
  expect(                                                                                                                                                                                             
    renderer.create(                                                                                                                                                                                  
      <AnimatedOpacity visible={false} />                                                                                                                                                             
    ).toJSON()                                                                                                                                                                                        
  ).toMatchSnapshot();                                                                                                                                                                                
});                                                                                                                                                                                                   

it('makes transition', () => {                                                                                                                                                                        
  const component = shallow(<AnimatedOpacityController />);                                                                                                                                           
  expect(renderer.create(component.node).toJSON()).toMatchSnapshot();                                                                                                                                 
  component.find('TouchableOpacity').simulate('press');                                                                                                                                               
  expect(renderer.create(component.node).toJSON()).toMatchSnapshot();                                                                                                                                 
  component.find('TouchableOpacity').simulate('press');                                                                                                                                               
  expect(renderer.create(component.node).toJSON()).toMatchSnapshot();                                                                                                                                 
});                                                                                                                                                                                                   

现在,生成的快照将具有预期的不透明度值.

编辑:

上述解决方案只解决了从头到尾的问题.更细粒度的解决方案是:

  1. 不要嘲笑我
  2. Jest 说,我赚global.requestAnimationFrame = null美元
  3. 使用mockdate来模拟日期
  4. Jest 吧.RuntimerToTime用于时间旅行

时间旅行功能是

const timeTravel = (ms, step = 100) => {                                                                                                                                                                              

  const tickTravel = v => {                                                                                                                                                                               
    jest.runTimersToTime(v);                                                                                                                                                                              
    const now = Date.now();                                                                                                                                                                               
    MockDate.set(new Date(now + v));                                                                                                                                                                      
  }                                                                                                                                                                                                       

  let done = 0;                                                                                                                                                                                           
  while (ms - done > step) {                                                                                                                                                                               
    tickTravel(step);                                                                                                                                                                                      
    done += step;                                                                                                                                                                                          
  }                                                                                                                                                                                                       
  tickTravel(ms - done);                                                                                                                                                                                  
};    

由于内部行为活跃,将步骤分成小块非常重要.

React-native相关问答推荐

try 使用JWT-DECODE解码令牌时出错

在我的 React Native 应用程序中获取数据返回 [object Object] 而不是 renderSectionHeader

哪个版本的@stripe/stripe-react-native 模块支持 react native 0.62.0 typscript 模板?

单击react 本机时如何从同一屏幕更改内容

react-redux connect 和 redux 数据的组件生命周期顺序

React Native - 初始属性 Android

在 react-native 中调试原生 java 代码

Xcode 12 问题:Build input file cannot be found

React-Native iOS - 如何通过按下按钮从 React-Native 视图导航到非 React-Native 视图(本机 iOS 视图控制器)?

试图注册两个同名的视图 RNGestureHandlerButton

如何将 View 定位在 ScrollView 的底部?

React Native:ScrollView 中的 TouchableOpacity onPress 问题

如何在 React-Native 的alert中设置alert框标题?

react-native 自动完成文本输入

react-native async 函数返回 promise 但不返回我的 json 数据?

Android 依赖 'com.google.android.gms:play-services-stats' 的编译(16.0.1)和运行时(17.0.0)类路径有不同的版本

使用来自另一个页面的 fetch 调用函数返回结果值

我将如何根据百分比为按钮的宽度设置动画,并且它的背景 colored颜色 也是如此?

在react-native中调试应用程序崩溃

如何在 react-native 中设置 Alert 元素的样式?