2021.12.27 星期一 :

Taro方式

Taro文档-进阶指南-第三方工具-Jest: https://nervjs.github.io/taro-docs/docs/external-libraries#jest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
// ...
globals: {
// ...
window: true,
ENABLE_INNER_HTML: true,
ENABLE_ADJACENT_HTML: true,
ENABLE_SIZE_APIS: true,
ENABLE_TEMPLATE_CONTENT: true,
ENABLE_CLONE_NODE: true,
ENABLE_CONTAINS: true,
ENABLE_MUTATION_OBSERVER: true,
},
moduleNameMapper: {
// ...
'@tarojs/taro': '@tarojs/taro-h5',
// '@tarojs/components': '@tarojs/components/dist-h5/react',
// '@tarojs/plugin-framework-react/dist/runtime': '<rootDir>/__mocks__/taro-framework',
// '@tarojs/plugin-framework-vue2/dist/runtime': '<rootDir>/__mocks__/taro-framework',
// '@tarojs/plugin-framework-vue3/dist/runtime': '<rootDir>/__mocks__/taro-framework',
}
}

该方法不适用路由跳转和部分生命周期测试。

PS: 没跑通。直接mock了整个taro.js。

配置

注意配置snapshotSerializers,否则快照内容为空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* test/setup.js */
import { configure } from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';

configure({ adapter: new Adapter() });

/* test/jest.config.js */
module.exports = {
// verbose: true,
testEnvironment: "jsdom",
rootDir: path.resolve(__dirname, "../"),
setupFilesAfterEnv: ["<rootDir>/test/setup"],
moduleNameMapper: {
'@tarojs/components': '@tarojs/components/dist-h5/react',
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/test/mocks/emptyMock.js",
"\\.(css|less|scss)$": "<rootDir>/test/mocks/emptyMock.js",
'^@/(.*)$': '<rootDir>/src/$1',
},
transform: {
"^.+\\.[t|j]sx?$": "babel-jest",
},
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!((@tarojs)|(@base))/)',
],
snapshotSerializers: ["enzyme-to-json/serializer"],
setupFilesAfterEnv: ["<rootDir>/test/setup"],
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
testPathIgnorePatterns: [
"/node_modules",
// '^.+\\.(css|sass|scss|less)$',
],
};

taroMock

通过moduleNameMappermock了整个taro.js。
并不关心taro的内部实现;还可以加速。

Taro-H5 中使用到的 API 实际上并不在 @tarojs/taro 的入口文件之下。
使用 Jest 测试也是类似,需要添加配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import handleApiMock from './apiMock';

export const getApp = jest.fn(() => ({}));
export const getCurrentInstance = jest.fn(() => ({
page: {},
router: {
params: {
dealId: '245777499999', // follow
dealState: '18', // follow
id: '', // remind
phone: '' // remind
}
}
}));
export const getCurrentPages = jest.fn(() => ({}));
export const setNavigationBarTitle = jest.fn();
export const getStorageSync = jest.fn();
export const setStorageSync = jest.fn();
export const getSystemInfoSync = jest.fn(() => ({}));
export const getSystemInfo = jest.fn();
export const useDidShow = jest.fn();
export const useDidHide = jest.fn();
export const useReachBottom = jest.fn();
export const useShareAppMessage = jest.fn();
export const getEnv = jest.fn();
// export const request = jest.fn();
export const request = jest.fn().mockImplementation(handleApiMock);
export const addInterceptor = jest.fn();
export const getNetworkType = jest.fn();
export const usePageScroll = jest.fn();
export const commonGetData = jest.fn();
export const showToast = jest.fn();
export const showModal = jest.fn(({success, fail}) => {
success && success();
fail && fail();
});
export const eventCenter = {
on: jest.fn(() => eventCenter),
off: jest.fn(() => eventCenter),
}
const Taro = {
getApp,
getCurrentInstance,
getCurrentPages,
setNavigationBarTitle,
getStorageSync,
setStorageSync,
getSystemInfoSync,
getSystemInfo,
useDidShow,
useDidHide,
useShareAppMessage,
useReachBottom,
getEnv,
ENV_TYPE: {},
request,
addInterceptor,
getNetworkType,
usePageScroll,
commonGetData,
showModal,
showToast,
eventCenter,
}

export default Taro

分支测试

process.env.TARO_ENV
package.json "test": "cross-env JEST_REPORT_FILE='./test/report/test-report.json' TARO_ENV=h5 jest --config test/jest.conf.js",

1
2
3
globals: {
"process.env.TARO_ENV": process.env.TARO_ENV,
},

另一种方式:在jest配置文件中直接赋值process.env = Object.assign(process.env, {TARO_ENV: 'h5'});

问题:ReferenceError: $RefreshSig$ is not definedReferenceError: $RefreshReg$ is not defined
setup.js

1
2
global.$RefreshReg$ = () => {};
global.$RefreshSig$ = () => () => {};

问题

  1. taro项目中cookie是多端文件,会报错。RangeError: Maximum call stack size exceeded
    解决:用mockModule的方式,指向index.h5.js。
    原因:可能是在小程序的cookie utils中发生了什么事情。

  2. 引入tarojs/components 出错。已经指向了h5的components了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    SyntaxError: Cannot use import statement outside a module

    1 | import React, { useState, useEffect, useRef, useCallback } from "react";
    > 2 | import { View, Text } from "@tarojs/components";
    3 | import styles from "./index.module.scss";

    ...
    By default "node_modules" folder is ignored by transformers.
    ...

默认忽略了node_modules 文件夹。
所以要进行配置。包括其他node_modules需要忽略的依赖。

1
2
3
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!((@tarojs)|(@base/datetime)|(@base/logger))/)',
],

  1. tarojs 引用出错。
    1
    2
    3
    4
    5
    6
    ReferenceError: ENABLE_INNER_HTML is not defined

    1 | import React, { useState, useRef, useEffect, useCallback } from "react";
    > 2 | import Taro from "@tarojs/taro";
    | ^
    3 | import { View, Text, Image } from "@tarojs/components";

看出是tarojs的api 引入出错。
所以需要mock。可以在每个文件中单独mock,或者通过映射(moduleNameMapper)统一处理。

  1. 引用路径/别名出错。
    包括webpack别名的设置。
    Could not locate module @/utils/Cookie mapped as: /Users/myfolder/shop/order/src/$1. 需要配置模块映射。(优先从上面找)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    moduleNameMapper: {
    '@tarojs/taro': '<rootDir>/test/mocks/taroMock.js',
    '@tarojs/components': '@tarojs/components/dist-h5/react',
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
    "<rootDir>/test/mocks/fileMock.js",
    "\\.(css|less|scss)$": "<rootDir>/test/mocks/styleMock.js",
    '@/utils/Cookie': '<rootDir>/src/utils/Cookie/index.h5.js',
    '^@/(.*)$': '<rootDir>/src/$1',
    },

可以看到还有一些css和tarojs 的映射。