使用react-scripts测试canvas的注意事项

结论

1、react-scripts3的最新版本是3.4.3,该版本的jsdom版本太低,不能支持对canvas进行测试,具体表现为执行document.createElement('canvas').getContext('2d')获得的返回值为undefined。虽然会提示安装canvas包可以解决问题,但由于jsdom版本太低实际上并不行。

2、react-scripts4的jsdom版本支持对canvas进行测试,在安装了canvas包后对canvas的相关函数有很好的支持。但react-scripts4版本无法解析在css、less等样式文件中使用url引用网络文件的方式,会导致使用了url引用文件的项目编译不通过,目前该bug还没有解决。

3、对react-scripts3版本下调整node_modules中的部分目录结构可以实现jsdom版本的升级从而实现在react-scripts3版本下也能支持canvas测试。

 

详细过程

发现getContext('2d')的返回值是null

        在一次编写测试用例的过程中发现报错:Cannot read property 'font' of null,定位发现是在document.createElement('canvas').getContext('2d')上取font属性时报的,也就是说getContext('2d')的结果是null。但是在浏览器中运行时该结果并不是null:

        通过在测试用例中打断点调试,发现在用例运行时,该函数的返回值确实是null,和浏览器中运行的结果不同:

        原因是react-scripts运行测试用例虽然是指定了运行环境是jsdom,但jsdom毕竟是类浏览器环境,和真实的浏览器环境还是有差别,在canvas上jsdom没有做到完全支持。

stackoverflow上对该问题的回答:https://stackoverflow.com/questions/33269093/how-to-add-canvas-support-to-my-tests-in-jest

jsdom官方提供的解决方案:https://github.com/jsdom/jsdom#canvas-support

 

安装了canvas但不生效

        按jsdom官方的说法,jsdom会去寻找canvas包是否安装,如果安装了就可以支持和canvas相关的API,没有安装就会把canvas标签当做div来处理。实际上在测试报错的位置也有相关的提示:

        但是在安装了canvas之后,还是有这个提示,并且getContext('2d')还是返回null。原因是jsdom在v13之后才支持和canvas包协同支持canvas特性,而且还要求canvas的版本>2。

        但是当前使用的react-scripts版本是3.4.3,跟随安装的jsdom的版本是11.12.0,因此即使安装了canvas也无法支持canvas特性:

 

更换了react-scripts4遇到了编译问题

        升级react-scrips到4.0.3之后运行canvas相关api可以得到正确的值了:

        但运行项目的时候遇到了问题:

        控制台提示无法解析,无法解析的代码是这一段,是通过URL网络请求获取图片:

        但是相同的代码在react-scripts3中是可以运行的,通过搜索,最终发现这是react-scripts4的一个bug:https://github.com/facebook/create-react-app/issues/9870,目前这个issue还没有关闭,这个问题应该还没有解决。如果为了解决canvas测试的问题而升级到react-scripts4,会导致项目的编译出问题。

 

如何在react-scripts3中测试canvas

        react-scripts3中的jsdom版本是11.12.0,jsdom支持canvas的版本是13之后,因此react-scripts3中的jsdom不支持对canvas进行测试。如果要支持,得把jsdom的版本单独升级上来。但是如果安装了新的jsdom,会破坏其他三方件的依赖关系,同时react-scripts运行时会提示有重复的jsdom存在,要求先卸载。因此也不能简单地升级。

        在项目中查看jsdom版本时可以看到其实当前项目中有两个jsdom:

        一个是react-scripts中依赖的jest带的jsdom,react-scripts运行单元测试时也是用的这个版本的jsdom。一个是react-scripts自己配置的依赖jest-environment-jsdom-fourteen带的jsdom,这个jsdom版本是14.1.0,满足>=13的要求。可以尝试把jest-config所依赖的jest-environment-jsdom换成jest-environment-jsdom-fourteen,从而实现jsdom版本的升级。

操作步骤(均在node_modules目录下进行):

  1. 重命名jest-environment-jsdom为jest-environment-jsdom-bak;
  2. 重命名jest-environment-jsdom-fourteen为jest-environment-jsdom;

 完成以上步骤后可以实现在react-scripts3下支持canvas测试,也可以正常编译运行项目。

        在查看jsdom版本时会有一些报错信息:

        这是因为修改了目录后部分依赖丢失了导致的,不影响项目运行和测试。

 

{ "name": "@labelu/frontend", "version": "5.8.11", "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", "@labelu/i18n": "1.0.6", "@labelu/audio-annotator-react": "1.8.6", "@labelu/components-react": "1.7.11", "@labelu/image": "1.4.0", "@labelu/formatter": "1.0.2", "@labelu/image-annotator-react": "2.4.6", "@labelu/interface": "1.3.1", "@labelu/video-annotator-react": "1.4.12", "@labelu/video-react": "1.5.3", "@tanstack/react-query": "^5.0.0", "antd": "5.10.1", "axios": "^1.3.4", "classnames": "^2.3.2", "history": "^5.0.0", "iframe-message-bridge": "1.1.1", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "mockjs": "^1.1.0", "react": "^18.2.0", "react-document-title": "^2.0.3", "react-dom": "^18.2.0", "react-hotkeys-hook": "^4.4.1", "react-i18next": "^11.18.6", "react-intl": "^5.24.7", "react-intl-universal": "^2.6.11", "react-monaco-editor": "^0.50.1", "react-responsive": "^9.0.2", "react-router": "^6.8.2", "react-router-dom": "^6.8.2", "styled-components": "^5.3.6", "uuid": "^9.0.0" }, "scripts": { "postinstall": "node ./scripts/generate_css_variables_from_antd_theme_token.js", "start": "vite --port 3004", "preview": "vite preview --port 3007", "build": "cross-env CI=false npm --filter=./packages/* --filter=. run build", "package:dist": "cross-env DIST=true vite", "release": "semantic-release", "type-check": "tsc --noEmit", "openapi": "ts-node openapi.config.ts" }, "author": "wuhui", "keywords": [ "annotation", "canvas", "react" ], "homepage": "/", "bugs": { "url": "https://github.com/opendatalab/labelU.git", "email": "751569801@qq.com" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@octokit/rest": "^19.0.7", "@semantic-release/commit-analyzer": "^9.0.2", "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", "@semantic-release/github": "^8.0.7", "@semantic-release/release-notes-generator": "^10.0.3", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "@types/http-proxy-middleware": "^0.19.3", "@types/jest": "^26.0.15", "@types/lodash": "^4.14.191", "@types/lodash-es": "^4.17.6", "@types/mockjs": "^1.0.2", "@types/node": "^12.20.55", "@types/react": "^18.0.28", "@types/react-document-title": "^2.0.5", "@types/react-dom": "^18.0.11", "@types/recharts": "^1.8.13", "@types/rx": "^4.1.2", "@types/styled-components": "^5.1.26", "@types/uuid": "^9.0.0", "@vitejs/plugin-react": "^3.1.0", "analyze-wiz": "^1.2.0-beta.2", "cross-env": "^7.0.3", "json-schema-library": "^9.1.2", "minimist": "^1.2.7", "prettier": "^2.0.1", "sass": "^1.56.1", "semantic-release": "^19.0.3", "semantic-release-github-pullrequest": "^1.3.0", "shelljs": "^0.8.5", "simple-progress-webpack-plugin": "^2.0.0", "terser-webpack-plugin": "^4.2.3", "typescript": "4.8.4", "vite": "^4.1.1", "vite-plugin-ejs": "^1.6.4", "vite-plugin-imp": "^2.3.1", "vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svgr": "^2.4.0", "vite-plugin-ts-mono-alias": "^1.1.8" } } 我想把@labelu开头的依赖都都通过packages里面的包安装
最新发布
05-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值