最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

react native - How to pass GestureState with fireEvent for PanResponder unit tests - Stack Overflow

programmeradmin0浏览0评论

The _g.dx is not receiving the dx value passed from the test cases. How to pass the it correctly?

  const MyComponent: React.FC<Props> = (props) => {
    const { onStart, onMove,} = props;
    
    function onPanResponderStart() { onStart && onStart()}
  
    const onPanMove = useCallback(
      async (_: any, _g: PanResponderGestureState) => {
        _g.dx > 0 && onMove && onMove()
      },[],
    );
  
    const panResponder = useCallback(
      PanResponder.create({
        onStartShouldSetPanResponder: (e: any, s: any) => true,
        onStartShouldSetPanResponderCapture: (e: any, s: any) => true,
        onMoveShouldSetPanResponder: (e: any, s: any) => true,
        onMoveShouldSetPanResponderCapture: (e: any, s: any) => true,
        onShouldBlockNativeResponder: (e: any, s: any) => true,
        onPanResponderGrant: onPanResponderStart,
        onPanResponderMove: onPanMove,
        onPanResponderRelease: (e: any, s: any) => true,
      }) as any,
      [props],
    );
  
    return (
      <Animated.View {...panResponder.panHandlers} testID="TestAnimView">
        <View><Text>USK</Text></View>
      </Animated.View>
    );
  };

MyComponent.test.tsx

  it("should trigger onMove", () => {
    const onMoveFn = jest.fn();
    
    const { getByTestId } = render(
      <MyComponent onMove={onMoveFn} />,
    );

    // Get the AnimateView element
    const animView = getByTestId("TestAnimView");

    // Simulate the start of the gesture
    fireEvent(animView, "responderGrant", {
        nativeEvent: { touches: [{ clientX: 0 }] },
    });

    // Simulate the movement during the gesture
    fireEvent(animView, "responderMove", {
        nativeEvent: { touches: [{ clientX: 100 }] },
        gestureState: { dx: 100, dy: 0, vx: 0, vy: 0, numberActiveTouches: 1 },
    });

    expect(onMoveFn).toHaveBeenCalled();
  });

Above test failed. So, tried below solutions but none of them are passing the dx value to the callbacks in MyComponent

Solution 2 didn't work

// Simulate the start of the gesture
  fireEvent(animView, 'responderGrant', {
    nativeEvent: { touches: [{ pageX: 0, pageY: 0 }] },
    touchHistory: { touchBank: [] },
  });

  // Simulate the movement during the gesture
  fireEvent(animView, 'responderMove', {
    nativeEvent: { touches: [{ pageX: 250, pageY: 0 }] }, 
    touchHistory: { touchBank: [] },
  });

Solution 3 didn't work

  fireEvent(animView, 'responderGrant', {
    nativeEvent: {
      touches: [{ pageX: 0, pageY: 0 }], // Initial touch position
      changedTouches: [],
      target: animView,
      identifier: 1,
    },
    touchHistory: { touchBank: [] },
  });

  // Simulate the movement during the gesture
  fireEvent(animView, 'responderMove', {
    nativeEvent: {
      touches: [{ pageX: 250, pageY: 0 }], // Swipe 
      changedTouches: [],
      target: animView,
      identifier: 1,
    },
    touchHistory: { touchBank: [] },
    gestureState: {
      dx: 250, // Horizontal distance moved
      dy: 0,   // Vertical distance moved
      vx: 0,   // Horizontal velocity
      vy: 0,   // Vertical velocity
      numberActiveTouches: 1,
    },
  });

Tried many other solutions but none of them are working.

P.S: I agree that we should not test gestures in unit tests. We should extract the logic of callbacks to helpers or hooks and test separately.

The _g.dx is not receiving the dx value passed from the test cases. How to pass the it correctly?

  const MyComponent: React.FC<Props> = (props) => {
    const { onStart, onMove,} = props;
    
    function onPanResponderStart() { onStart && onStart()}
  
    const onPanMove = useCallback(
      async (_: any, _g: PanResponderGestureState) => {
        _g.dx > 0 && onMove && onMove()
      },[],
    );
  
    const panResponder = useCallback(
      PanResponder.create({
        onStartShouldSetPanResponder: (e: any, s: any) => true,
        onStartShouldSetPanResponderCapture: (e: any, s: any) => true,
        onMoveShouldSetPanResponder: (e: any, s: any) => true,
        onMoveShouldSetPanResponderCapture: (e: any, s: any) => true,
        onShouldBlockNativeResponder: (e: any, s: any) => true,
        onPanResponderGrant: onPanResponderStart,
        onPanResponderMove: onPanMove,
        onPanResponderRelease: (e: any, s: any) => true,
      }) as any,
      [props],
    );
  
    return (
      <Animated.View {...panResponder.panHandlers} testID="TestAnimView">
        <View><Text>USK</Text></View>
      </Animated.View>
    );
  };

MyComponent.test.tsx

  it("should trigger onMove", () => {
    const onMoveFn = jest.fn();
    
    const { getByTestId } = render(
      <MyComponent onMove={onMoveFn} />,
    );

    // Get the AnimateView element
    const animView = getByTestId("TestAnimView");

    // Simulate the start of the gesture
    fireEvent(animView, "responderGrant", {
        nativeEvent: { touches: [{ clientX: 0 }] },
    });

    // Simulate the movement during the gesture
    fireEvent(animView, "responderMove", {
        nativeEvent: { touches: [{ clientX: 100 }] },
        gestureState: { dx: 100, dy: 0, vx: 0, vy: 0, numberActiveTouches: 1 },
    });

    expect(onMoveFn).toHaveBeenCalled();
  });

Above test failed. So, tried below solutions but none of them are passing the dx value to the callbacks in MyComponent

Solution 2 didn't work

// Simulate the start of the gesture
  fireEvent(animView, 'responderGrant', {
    nativeEvent: { touches: [{ pageX: 0, pageY: 0 }] },
    touchHistory: { touchBank: [] },
  });

  // Simulate the movement during the gesture
  fireEvent(animView, 'responderMove', {
    nativeEvent: { touches: [{ pageX: 250, pageY: 0 }] }, 
    touchHistory: { touchBank: [] },
  });

Solution 3 didn't work

  fireEvent(animView, 'responderGrant', {
    nativeEvent: {
      touches: [{ pageX: 0, pageY: 0 }], // Initial touch position
      changedTouches: [],
      target: animView,
      identifier: 1,
    },
    touchHistory: { touchBank: [] },
  });

  // Simulate the movement during the gesture
  fireEvent(animView, 'responderMove', {
    nativeEvent: {
      touches: [{ pageX: 250, pageY: 0 }], // Swipe 
      changedTouches: [],
      target: animView,
      identifier: 1,
    },
    touchHistory: { touchBank: [] },
    gestureState: {
      dx: 250, // Horizontal distance moved
      dy: 0,   // Vertical distance moved
      vx: 0,   // Horizontal velocity
      vy: 0,   // Vertical velocity
      numberActiveTouches: 1,
    },
  });

Tried many other solutions but none of them are working.

P.S: I agree that we should not test gestures in unit tests. We should extract the logic of callbacks to helpers or hooks and test separately.

Share Improve this question asked Feb 1 at 19:10 Uday Sravan KUday Sravan K 1,4541 gold badge15 silver badges20 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

After spending significant time in debugging. Here is the solution worked for me.

fireEvent(animView, "responderGrant", {
      nativeEvent: {
        touches: [{ pageX: 0, pageY: 0 }], // Initial touch position
        changedTouches: [],
        target: animView,
        identifier: 1,
      },
      touchHistory: { mostRecentTimeStamp: "2", touchBank: [] },
    });

    // Simulate the movement during the gesture
    fireEvent(animView, "responderMove", {
      touchHistory: {
        mostRecentTimeStamp: "1",
        touchBank: [
          {
            touchActive: true,
            currentTimeStamp: 1,
            currentPageX: 10, // This will be gestureState.dx
            previousPageX: 0,
          },
        ],
        numberActiveTouches: 1,
        indexOfSingleActiveTouch: 0, // for touchBank[0]
      },
    });

You have to adjust the values accordingly to simulate correct gesture values as per your logic in callbacks.

Reason: The GestureState is being determined internally by the values provided through touchHistory and touchBank

发布评论

评论列表(0)

  1. 暂无评论