将 Jest 与 Typescript + preact 结合使用
Using Jest with Typescript + preact
在测试中将 JSX 转译为 h()
时出现问题。所有配置文件类似于 create-react-app,不包括 TypeScript
和 preact
的更改
我通过 create-react-app my-app --script=react-scripts-ts
创建应用程序 - 用于 TypeScript 项目。然后弹出并将 react
更改为 preact
(不要使用 preact-compat
)。
为了迁移到 preact
,我将 package.json
添加到 babel.plugins section
新插件 ["babel-plugin-transform-react-jsx", { pragma: "h"}]
- 为了将 <JSX />
转换为 h(JSX)
函数调用,而不是默认 React.createElement(JSX)
(迁移指南 https://preactjs.com/guide/switching-to-preact)。
这很好用。
但是测试有不同的转译配置<JSX />
:默认转译为React.createElement(JSX)
。在测试中我出错了ReferenceError: React is not defined at Object.<anonymous> (src/Linkify/Linkify.test.tsx:39:21)
。如果我在测试和测试文件中手动将 <JSX />
更改为 h(SomeComponent)
- 它可以工作。
如何将 <JSX />
转译为 h(JSX)
进行测试?
// typescriptTransform.js
// Copyright 2004-present Facebook. All Rights Reserved.
'use strict';
const fs = require('fs');
const crypto = require('crypto');
const tsc = require('typescript');
const tsconfigPath = require('app-root-path').resolve('/tsconfig.json');
const THIS_FILE = fs.readFileSync(__filename);
let compilerConfig = {
module: tsc.ModuleKind.CommonJS,
jsx: tsc.JsxEmit.React,
};
if (fs.existsSync(tsconfigPath)) {
try {
const tsconfig = tsc.readConfigFile(tsconfigPath).config;
if (tsconfig && tsconfig.compilerOptions) {
compilerConfig = tsconfig.compilerOptions;
}
} catch (e) {
/* Do nothing - default is set */
}
}
module.exports = {
process(src, path, config, options) {
if (path.endsWith('.ts') || path.endsWith('.tsx')) {
let compilerOptions = compilerConfig;
if (options.instrument) {
// inline source with source map for remapping coverage
compilerOptions = Object.assign({}, compilerConfig);
delete compilerOptions.sourceMap;
compilerOptions.inlineSourceMap = true;
compilerOptions.inlineSources = true;
// fix broken paths in coverage report if `.outDir` is set
delete compilerOptions.outDir;
}
const tsTranspiled = tsc.transpileModule(src, {
compilerOptions: compilerOptions,
fileName: path,
});
return tsTranspiled.outputText;
}
return src;
},
getCacheKey(fileData, filePath, configStr, options) {
return crypto
.createHash('md5')
.update(THIS_FILE)
.update('[=10=]', 'utf8')
.update(fileData)
.update('[=10=]', 'utf8')
.update(filePath)
.update('[=10=]', 'utf8')
.update(configStr)
.update('[=10=]', 'utf8')
.update(JSON.stringify(compilerConfig))
.update('[=10=]', 'utf8')
.update(options.instrument ? 'instrument' : '')
.digest('hex');
},
};
测试样本:
import { h, render } from 'preact';
import Linkify from './Linkify';
it('renders without crashing', () => {
const div = document.createElement('div');
render(<Linkify children={'text'} />, div);
});
我找到了解决方案。
我在 babel.plugins
部分 new plugin ["babel-plugin-transform-react-jsx", { pragma: "h"}]
中错了 - 它没有使用。真的这个 pragma 使用来自 tsconfig.json
- "jsxFactory": "h"
但是这个指令不在 typescriptTransform.js
.
中使用
我正在扩展编译器选项
let compilerConfig = {
module: tsc.ModuleKind.CommonJS,
jsx: tsc.JsxEmit.React,
jsxFactory: "h" // <-- duplicate option in jest transform config file
};
希望有用。
在测试中将 JSX 转译为 h()
时出现问题。所有配置文件类似于 create-react-app,不包括 TypeScript
和 preact
我通过 create-react-app my-app --script=react-scripts-ts
创建应用程序 - 用于 TypeScript 项目。然后弹出并将 react
更改为 preact
(不要使用 preact-compat
)。
为了迁移到 preact
,我将 package.json
添加到 babel.plugins section
新插件 ["babel-plugin-transform-react-jsx", { pragma: "h"}]
- 为了将 <JSX />
转换为 h(JSX)
函数调用,而不是默认 React.createElement(JSX)
(迁移指南 https://preactjs.com/guide/switching-to-preact)。
这很好用。
但是测试有不同的转译配置<JSX />
:默认转译为React.createElement(JSX)
。在测试中我出错了ReferenceError: React is not defined at Object.<anonymous> (src/Linkify/Linkify.test.tsx:39:21)
。如果我在测试和测试文件中手动将 <JSX />
更改为 h(SomeComponent)
- 它可以工作。
如何将 <JSX />
转译为 h(JSX)
进行测试?
// typescriptTransform.js
// Copyright 2004-present Facebook. All Rights Reserved.
'use strict';
const fs = require('fs');
const crypto = require('crypto');
const tsc = require('typescript');
const tsconfigPath = require('app-root-path').resolve('/tsconfig.json');
const THIS_FILE = fs.readFileSync(__filename);
let compilerConfig = {
module: tsc.ModuleKind.CommonJS,
jsx: tsc.JsxEmit.React,
};
if (fs.existsSync(tsconfigPath)) {
try {
const tsconfig = tsc.readConfigFile(tsconfigPath).config;
if (tsconfig && tsconfig.compilerOptions) {
compilerConfig = tsconfig.compilerOptions;
}
} catch (e) {
/* Do nothing - default is set */
}
}
module.exports = {
process(src, path, config, options) {
if (path.endsWith('.ts') || path.endsWith('.tsx')) {
let compilerOptions = compilerConfig;
if (options.instrument) {
// inline source with source map for remapping coverage
compilerOptions = Object.assign({}, compilerConfig);
delete compilerOptions.sourceMap;
compilerOptions.inlineSourceMap = true;
compilerOptions.inlineSources = true;
// fix broken paths in coverage report if `.outDir` is set
delete compilerOptions.outDir;
}
const tsTranspiled = tsc.transpileModule(src, {
compilerOptions: compilerOptions,
fileName: path,
});
return tsTranspiled.outputText;
}
return src;
},
getCacheKey(fileData, filePath, configStr, options) {
return crypto
.createHash('md5')
.update(THIS_FILE)
.update('[=10=]', 'utf8')
.update(fileData)
.update('[=10=]', 'utf8')
.update(filePath)
.update('[=10=]', 'utf8')
.update(configStr)
.update('[=10=]', 'utf8')
.update(JSON.stringify(compilerConfig))
.update('[=10=]', 'utf8')
.update(options.instrument ? 'instrument' : '')
.digest('hex');
},
};
测试样本:
import { h, render } from 'preact';
import Linkify from './Linkify';
it('renders without crashing', () => {
const div = document.createElement('div');
render(<Linkify children={'text'} />, div);
});
我找到了解决方案。
我在 babel.plugins
部分 new plugin ["babel-plugin-transform-react-jsx", { pragma: "h"}]
中错了 - 它没有使用。真的这个 pragma 使用来自 tsconfig.json
- "jsxFactory": "h"
但是这个指令不在 typescriptTransform.js
.
我正在扩展编译器选项
let compilerConfig = {
module: tsc.ModuleKind.CommonJS,
jsx: tsc.JsxEmit.React,
jsxFactory: "h" // <-- duplicate option in jest transform config file
};
希望有用。