Mocha/Babel如何即时转换我的测试代码? [英] How does mocha / babel transpile my test code on the fly?

查看:115
本文介绍了Mocha/Babel如何即时转换我的测试代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题不是关于为何某事无效的问题,而是有关为何如此的问题.是的.

我有一个小的 nodeJS命令行工具,其中包含nodeJS尚不支持的功能的包装盒中,最引人注目的是:

  • import语句
  • String.includes().

因此交付(构建),我将我的源代码进行编译+捆绑(就像使用webpack一样,使用包裹). /p>

作为一个肯定的奇迹,我所有的(仅一个)摩卡测试直接针对我的课程而不是捆绑软件进行 .仍然,他们工作!包括许多import语句.并包括"ES6自检":

it( 'String - include', () => {
    var s = 'Southern Bananas'
    assert( s.includes( 'anana' ) )
    assert( !s.includes( 'kiwi' ) )
} )

因此:

我的测试代码中有String.include,而不仅仅是受测试的源代码中.而且在任何地方我都无法移植或捆绑我的测试代码...因此,对我的愚蠢问题表示歉意:

这为什么起作用?某个地方是否存在秘密的即时编译? (如果可以,我是否也可以将其用于我的可交付测试中代码的调试风格?)

我的mocha.opts很简单:

--require @babel/register
--require ./test/once.js  (nothing special here, either)
--reporter list
--recursive

我的.babelrc有这个:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "Electron": "3.0",
                    "Node": "8.0"
                }
            }
        ]
    ],
    "plugins": [
        "@babel/plugin-transform-runtime"
    ],
    "retainLines": true,
    "comments": false,
    "sourceMaps": true
}

@babel/plugin-transform-runtime显然不应该受到指责,因为它

minimististik-modern afaik @babel/preset-env中是否包含@babel/polyfill?我在做什么正确的:+​​)?有没有办法在我的(调试)版本中使用此实时编译?

长话短说

从v6.5开始,Node.js支持

String.prototype.includes. @babel/register导致您的代码被即时编译,这就是您的import语句起作用的原因.我怀疑您是否需要@babel/plugin-transform-runtime插件,除非我缺少您要实现的功能.

什么会引起这种混乱?

我认为这个(完全可以理解的)谜团有两个根本原因:

  1. Babel的作者使真的易于使用.有时很难知道它是如何被调用的,何时被调用(尤其是与诸如Mocha之类的其他工具配对时).
  2. 传统上,Node.js本身不支持/不支持的内容(就ES2015,ES2016等而言)

因此,涉及两个奥秘.

String.prototype.includes为什么起作用?

这有一个更简单的解释. String.prototype.includes早在Node.js v6.5之前就已得到本机支持(那里关于如何将其启用为实验功能的一些很好的文章 @babel/register 的工作方式是将其自身绑定"到节点的需求并自动动态编译文件".

以下是@babel/register的基本示例:

从命令行:

$ node main.js
You will see this, because there is no syntax error!

main.js

require('@babel/register');
// This next file is compiled on the fly
require('./file1.js');

file1.js

import path from 'path';
console.log('You will see this, because there is no syntax error!');

好处是,这是Mocha建议您将Babel 集成到其文档中的方式. --require选项基本上可以执行上面的示例:在Mocha使用require导入所有测试文件之前,将调用require('@babel/register');.

希望这会有所帮助!再次,这是在迅速发展的JavaScript的现代时代完全可以理解的谜.

My question is not about why something is not working, but rather why it is. Yes.

I have a small nodeJS command line tool, which contains features that nodeJS does not yet support out of the box, most notably:

  • import statements
  • String.includes().

Thus for delivery(build) I transpile+bundle my source code (using parcel, just like webpack).

As a positive wonder, all (but one) of my mocha tests run directly against my classes, not the bundle. Still, they work! Including many import statements. And including an 'ES6 self-test':

it( 'String - include', () => {
    var s = 'Southern Bananas'
    assert( s.includes( 'anana' ) )
    assert( !s.includes( 'kiwi' ) )
} )

Thus:

I have String.include in my test code, not just in the source under test. And there is no place where I transpile or bundle my test code… Thus apologies for my dumb question:

Why is this working? Is there a secret just-in-time compilation somewhere? (and if yes, could I use that for a debug flavour of my deliverable code-under-test as well?)

my mocha.opts are rather simple:

--require @babel/register
--require ./test/once.js  (nothing special here, either)
--reporter list
--recursive

my .babelrc has this:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "Electron": "3.0",
                    "Node": "8.0"
                }
            }
        ]
    ],
    "plugins": [
        "@babel/plugin-transform-runtime"
    ],
    "retainLines": true,
    "comments": false,
    "sourceMaps": true
}

@babel/plugin-transform-runtime is apparently not to blame praise, as it explicitly states

NOTE: Instance methods such as "foobar".includes("foo") will not work since that would require modification of existing built-ins (you can use @babel/polyfill for that).

Is @babel/polyfill contained in the minimalistik-modern afaik @babel/preset-env? What else an I doing right :+)? Is there a way to use this live compilation for my (debug) build as well?

解决方案

Long story short

String.prototype.includes is supported by Node.js since v6.5. @babel/register is causing your code to be compiled on the fly, that's why your import statements work. I doubt you need the @babel/plugin-transform-runtime plugin, unless I'm missing something that you're trying to achieve.

What can cause this confusion?

I think there are two root causes to this (totally understandable) mystery:

  1. The Babel authors have made it really easy to use the tool; and sometimes it is hard to know how/when it is being invoked (especially when paired with another tool like Mocha).
  2. What is/isn't supported natively by Node.js (in terms of ES2015, ES2016, etc.) has traditionally been hard to keep up with.

So, on to the two mysteries.

Why does String.prototype.includes work?

This one has the easier explanation. String.prototype.includes has been supported natively since as early as Node.js v6.5 (as you can see, a vast majority of ES2015 support has been supported since that version).

So, while you're correct that you don't have @babel/polyfill configured (as far as I can tell) and that you would need it in an environment that doesn't support String.prototype.includes, your environment already supports it!

From a Node.js v8.x REPL:

> 'ES2015'.includes('2015')
true

Why does your import statement work?

As you've stated, Node.js v8.x does not natively support ECMAScript Modules. However, there are some good write ups about how it has been enabled as an experimental feature starting in Node.js v9.x.

So, you get the following with native Node.js v8.x (via REPL):

> import path from 'path';
import path from 'path';
^^^^^^

SyntaxError: Unexpected token import

The reason your imports are working is because your code is being compiled by Babel using the @babel/preset-env preset. Furthermore, that compilation is being triggered by your --require @babel/register Mocha option.

@babel/register works by "bind[ing] itself to node's require and automatically compile files on the fly".

Here is a basic example of @babel/register in action:

From the command line:

$ node main.js
You will see this, because there is no syntax error!

main.js

require('@babel/register');
// This next file is compiled on the fly
require('./file1.js');

file1.js

import path from 'path';
console.log('You will see this, because there is no syntax error!');

The good thing is, this is how Mocha recommends you integrate Babel in their documentation. The --require option basically does what the above example does: require('@babel/register'); is called before Mocha uses require to import all of your test files.

Hope this helps! Again, this is a totally understandable mystery in the modern age of rapidly-evolving JavaScript.

这篇关于Mocha/Babel如何即时转换我的测试代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆