【问题标题】:Snapshot test with Jest on nested react-navigation component - Object keys change so Snapshot match fails在嵌套反应导航组件上使用 Jest 进行快照测试 - 对象键更改,因此快照匹配失败
【发布时间】:2019-04-26 03:30:17
【问题描述】:

当我在 StackNavigator.test.js 上运行 jest 测试 时,由于生成的密钥,它总是失败:

- Snapshot
+ Received

@@ -79,11 +79,11 @@
              fromRoute={null}
              index={0}
              navigation={
                Object {
                  "_childrenNavigation": Object {
-                   "**id-1542980055400-0**": Object {
+                   "**id-1542980068677-0**": Object {
                      "actions": Object {
                        "dismiss": [Function],
                        "goBack": [Function],
                        "navigate": [Function],
                        "pop": [Function],
@@ -109,11 +109,11 @@
                      "replace": [Function],
                      "reset": [Function],
                      "router": undefined,
                      "setParams": [Function],
                      "state": Object {
-                       "key": "**id-1542980055400-0**",
+                       "key": "**id-1542980068677-0**",
                        "routeName": "SignInOrRegister",
                      },
                    },
                  },
                  "actions": Object {
@@ -157,15 +157,15 @@
                  },
                  "setParams": [Function],
                  "state": Object {
                    "index": 0,
                    "isTransitioning": false,
-                   "key": "**id-1542980055400-1**",
+                   "key": "**id-1542980068677-1**",
                    "routeName": "FluidTransitionNavigator",
                    "routes": Array [
                      Object {
-                       "key": "**id-1542980055400-0**",
+                       "key": "**id-1542980068677-0**",
                        "routeName": "SignInOrRegister",
                      },
                    ],
                  },
                }
@@ -191,11 +191,11 @@
                    "overflow": "hidden",
                  },
                  undefined,
                ]
              }
-             toRoute="**id-1542980055400-0**"
+             toRoute="**id-1542980068677-0**"
            >
              <View
                style={
                  Object {
                    "bottom": 0,

StackNavigator 组件使用 'react-navigation' 并具有来自 'react-navigation-fluid- 的嵌套 FluidTransition 组件过渡'

StackNavigator.js

import React, { Component } from 'react';
import { Platform, Animated, Easing } from 'react-native';
import { createStackNavigator } from 'react-navigation';
import { ThemeContext, getTheme } from 'react-native-material-ui';
import PropTypes from 'prop-types'

import FluidTransitionNavigator from './FluidTransitionNavigator';
import Dashboard from './../pages/Dashboard';
import Login from './../pages/Login';
import SignInOrRegister from './../pages/SignInOrRegister';

import UniToolbar from './UniToolbar';

const transitionConfig = () => {
  return {
    transitionSpec: {
      duration: 1000,
      easing: Easing.out(Easing.poly(4)),
      timing: Animated.timing,
      useNativeDriver: false,
    },
    screenInterpolator: sceneProps => {
      const { layout, position, scene } = sceneProps

      const thisSceneIndex = scene.index
      const width = layout.initWidth

      const translateX = position.interpolate({
        inputRange: [thisSceneIndex - 1, thisSceneIndex],
        outputRange: [width, 0],
      })

      return { transform: [ { translateX } ] }
    },
  }
}

const StackNavigator = createStackNavigator(
  {
    FluidTransitionNavigator: {
      screen: FluidTransitionNavigator
    },
    Dashboard: {
      screen: Dashboard
    }
  },
  {
    initialRouteName: 'FluidTransitionNavigator',
    headerMode: 'float',
    navigationOptions: (props) => ({
      header: renderHeader(props)
    }),
    transitionConfig: transitionConfig
  }
);

const renderHeader = (props) => {
  let index = props.navigation.state.index;

  const logout = (props.navigation.state.routeName === 'Dashboard');
  let title = '';
  switch (props.navigation.state.routeName) {
    case 'Dashboard':
      title = 'Dashboard';
      break;
    case 'FluidTransitionNavigator':
      if (index !== undefined) {
        switch (props.navigation.state.routes[index].routeName) {
          case 'Login':
            title = 'Sign In';
            break;
          case 'SignInOrRegister':
            title = 'SignInOrRegister';
            break;
          default:
            title = '';
        }
      }
      break;
    default:
      title = '';
  }

  return (['SignInOrRegister', 'Sign In'].includes(title)) ? null : (
    <ThemeContext.Provider value={getTheme(uiTheme)} >
      <UniToolbar navigation={props.navigation} toolbarTitle={title} logout={logout} />
    </ThemeContext.Provider>
  );
};

renderHeader.propTypes = {
  navigation: PropTypes.object
};

const uiTheme = {
    toolbar: {
        container: {
          ...Platform.select({
            ios: {
              height: 70
            },
            android: {
              height: 76
            }
          })
        },
    },
};

export default StackNavigator;

下面是我的测试:

StackNavigator.test.js

import React from "react";
import renderer from "react-test-renderer";
import StackNavigator from "../StackNavigator";

test("renders correctly", () => {
  const tree = renderer.create(<StackNavigator />).toJSON();
  expect(tree).toMatchSnapshot();
});

我在这里看到了一个类似的几乎相同的问题Jest snapshot test failing due to react navigation generated key

接受的答案仍然没有回答我的问题。然而,它确实把我引到了另一个兔子洞:

我尝试使用内联匹配: expect(tree).toMatchInlineSnapshot() 在运行yarn run test:unit 后生成树,然后尝试插入Any&lt;String&gt; 代替所有键。不幸的是,这没有奏效。

我被难住了。我不知道如何解决这个问题。我已经搜索和搜索,尝试了多种方法来解决它,我就是无法解决这个问题。

请问有人可以帮我吗?

【问题讨论】:

    标签: react-native jestjs react-navigation


    【解决方案1】:

    在 ReactNavigation v5 中,您可以像这样模拟它:

    jest.mock('nanoid/non-secure', () => ({
      nanoid: () => 'routeUniqId',
    }));
    

    【讨论】:

      【解决方案2】:

      我解决了我的问题,但不是通过模拟 Date.now 这在许多其他情况下被建议。

      相反,我改编了一个名为 joeybaker 的用户在 https://github.com/react-navigation/react-navigation/issues/2269#issuecomment-369318490 上找到的答案。

      这样做的理由如下:

      密钥对于您的测试目的并不重要。你什么 真正关心的是路线和索引。

      他的代码如下,假设在Redux中使用了actions和reducers:

      // keys are date and order-of-test based, so just removed them
      const filterKeys = (state) => {
        if (state.routes) {
          return {
            ...state,
            routes: state.routes.map((route) => {
              const { key, ...others } = route
              return filterKeys(others)
            }),
          }
        }
        return state
      }
      
      it('clears all other routes', () => {
          const inputState = {}
          const action = { type: AUTH_LOGOUT_SUCCESS }
          const state = filterKeys(reducer(inputState, action))
          expect(state.routes).toBe........
      })
      

      我已经根据我的情况调整了这个(我还没有使用 Redux),如下所示:

      test("renders correctly", () => {
      
        const tree = renderer.create(<StackNavigator />);
        const instance = tree.getInstance();
        const state = filterKeys(instance.state.nav);
      
        expect(state).toMatchSnapshot();
      });
      
      // keys are date and order-of-test based, so just removed them
      const filterKeys = (state) => {
        if (state.routes) {
          return {
            ...state,
            routes: state.routes.map((route) => {
              const { key, ...others } = route
              return filterKeys(others);
            }),
          }
        }
        return state;
      };
      

      得到渲染的测试如下所示:

      // Jest Snapshot v1
      
      exports[`renders correctly 1`] = `
      Object {
        "index": 0,
        "isTransitioning": false,
        "key": "StackRouterRoot",
        "routes": Array [
          Object {
            "index": 0,
            "isTransitioning": false,
            "routeName": "FluidTransitionNavigator",
            "routes": Array [
              Object {
                "routeName": "SignInOrRegister",
              },
            ],
          },
        ],
      }
      `;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-05
        • 2018-12-17
        • 2019-09-17
        • 1970-01-01
        • 2020-01-19
        • 2017-05-21
        • 2021-07-31
        • 2017-02-23
        相关资源
        最近更新 更多