【问题标题】:How to unit test React JSX ES6 code with KARMA?如何使用 KARMA 对 React JSX ES6 代码进行单元测试?
【发布时间】:2015-04-03 18:49:52
【问题描述】:

我已经用 ES6 编写了我的 React 应用程序。现在我也想用 ES6 编写我的测试。所以这里的挑战是配置业力。

与 google 一起,我用 karma.config.js 走到了这一步(我省略了配置文件中相同的部分!):

...
files: [
  '../node_modules/karma-babel-preprocessor/node_modules/babel-core/browser-polyfill.js',
  '../app/**/*.jsx',
  '../test/**/*.jsx'],

 preprocessors: {
  'app/**/*.jsx': ['react-jsx', 'babel'],
  'test/**/*.jsx': ['react-jsx', 'babel']
 },
 'babelPreprocessor': {
  options: {
    sourceMap: 'inline'
  },
  filename: function(file) {
    return file.originalPath.replace(/\.jsx$/, '.es5.js');
  },
  sourceFileName: function(file) {
    return file.originalPath;
  }
},
....

我认为这个设置应该做的:1)将 JSX 编译为 JS,接下来babel 应该将 ES6 转换为 ES5。这与polyfill 一起,我希望它应该在 phantomjs 中运行。但是不,这是我运行 karma 时的输出:

PhantomJS 1.9.8 (Mac OS X) ERROR
    SyntaxError: Parse error
    at Projects/ES6/app/js/app.jsx:35
    PhantomJS 1.9.8 (Mac OS X): Executed 0 of 0 ERROR (0.027 secs / 0 secs)
    [20:36:59] Karma has exited with 1

app.jsx 的第 35 行包含实际的 JSX 部分。所以,由于某种原因,预处理器似乎没有那么多。任何有关预处理器的帮助将不胜感激?

更新:我有这个几乎可以工作的 nog。原来我的预处理器应该像这样交换

 '../app/**/*.jsx': ['babel', 'react'], 
 '../test/**/*.jsx': ['babel', 'react']

现在,当我运行它时,我得到:

Uncaught ReferenceError: require is not defined

我以为我有一个 polyfill :(

【问题讨论】:

  • 你在使用 webpack 来构建你的资产吗?我有一篇关于如何使用 Webpack 作为测试预处理器来设置 Karma 的帖子:qiita.com/kimagure/items/f2d8d53504e922fe3c5c 老实说,我从来没有费心尝试单独使用 babel。
  • 我使用browserifybabelify。您的项目似乎处理 JSX,但不是 ES6。这只是 WebPack 中的一个调整(我没有使用过 webpack)吗?
  • 不应该加载输出 JS 文件而不是输入 JSX 吗? (我对 JSX 不熟悉,但是之前也搭建过这样的 ES6/Babel 项目)
  • 这是可能的,但是您总是必须先构建,然后才能进行测试。这样,业力就完成了所有工作!

标签: javascript reactjs karma-runner react-jsx babeljs


【解决方案1】:

我将 ES6 与 Browserify 和 JSX 一起使用。对于编译,我使用 Babel。以下配置对我有用。

karma.conf.js

...
frameworks: ['browserify', 'jasmine'],
files: [
  'Component.js',                     // replace with your component
  '__tests__/Component-test.js'
],
preprocessors: {
  'Component.js': 'browserify',
  './__tests__/Component-test.js': 'browserify'
},
browserify : {
  transform : ['babelify']
},
...

__tests__/Component-test.js

var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Component = require('../Component.js');

describe('Component', () => {

  it('should work', () => {
    var component = <Component />;
    TestUtils.renderIntoDocument(component);
    expect(component).toBeTruthy();
  });

});

如果您有任何问题,请告诉我。

【讨论】:

  • 不错!这周我将有时间进行实验。所以我会尽快发布我的发现!
  • 我已经对其进行了测试,现在我可以在 Chrome 中使用它了。非常感谢!!
  • @JeanlucaScaljeri 你能把你的工作配置文件放在 gist 或其他地方看看吗?
  • 你为什么用var而不是let
【解决方案2】:

@zemirico 的回答对我不起作用,而且有点过时了。

这是我自己的设置,您可以将其用于karma.conf.js

...
frameworks: ['jasmine', 'browserify'],

files: [
    'src/*',
    'tests/*'
],

preprocessors: {
    'src/*': ['browserify'],
    'tests/*': ['browserify']
},

browserify: {
    debug: true,
    transform: ['babelify']
}
...

它使用babelify 而不是reactify,并且有其他依赖项。因此,还需要项目根目录中的.babelrc

{
  presets: ['es2015', 'react']
}

该设置还需要将以下依赖项包含在package.json 文件中:

  "devDependencies": {
    "babel-preset-react": "^6.5.0",
    "babelify": "^7.2.0",
    "browserify": "^13.0.0",
    "jasmine-core": "^2.4.1",
    "karma": "^0.13.22",
    "karma-browserify": "^5.0.3",
    "karma-chrome-launcher": "^0.2.3",
    "karma-jasmine": "^0.3.8",
    "watchify": "^3.7.0",
    "babel-preset-es2015": "^6.6.0",
    "react": "^15.0.1",
    "react-addons-test-utils": "^15.0.1",
    "react-dom": "^15.0.1"
  }

用法

src/my-element.jsx中新建一个React组件:

import React from 'react';

export default class MyElement extends React.Component {

  constructor(props) {
    super(props);
    this.state = {isActive: false};

    this.onClick = this.onClick.bind(this);
  }

  onClick() {
    this.setState({isActive: !this.state.isActive});
  }

  render() {
    return (
      <div onClick={this.onClick}>{this.state.isActive ? "I am active!" : "I am not active :("}</div>
    );
  }
}

然后,通过在tests/my-element-spec.js 中创建规范来对其进行测试:

import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import MyElement from '../src/my-element.jsx';

describe('MyElement', () => {

  // Render a checkbox with label in the document
  const element = TestUtils.renderIntoDocument(<MyElement />);
  const elementNode = ReactDOM.findDOMNode(element);

  it('verity correct default text', () => {
    expect(elementNode.textContent).toEqual('I am not active :(');
  });

  it ('verify text has been changed successfuly after click', () => {
    // Simulate a click and verify that it is now On
    TestUtils.Simulate.click(elementNode);

    // Verify text has been changed successfully
    expect(elementNode.textContent).toEqual('I am active!');
  });
});

演示

Working example on GitHub.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多