浏览器测试设置:如何使已经全局的 SystemJS 模块可用于测试代码的 require('systemjs')? [英] Browser test setup: How to make already global SystemJS module available to require('systemjs') of tested code?

查看:23
本文介绍了浏览器测试设置:如何使已经全局的 SystemJS 模块可用于测试代码的 require('systemjs')?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码完全独立于系统,并且在 node.js 或浏览器上运行的代码行很少.我已经设法设置了基于 mocha 的测试,以便它在这两种环境中都可以使用相同的测试和相同的代码模块.我还管理浏览器测试环境,以自动交换对那些始终为浏览器版本调用 node.js 版本的极少数系统相关包的调用.

I have code that is fairly system independent and with few system dependent lines of code runs on node.js or the browser. I already managed to setup mocha-based testing so that it works in both those environments, using the same tests and the same code modules. I also managed the browser testing environment to automatically swap calls for those very few system-dependent packages that always call the node.js version for the browser version.

所以一切都在运行,包括 mocha 和 sinon 以及所有测试.

So everything runs, including mocha and sinon and all tests.

直到我决定将 SystemJS 不仅用于运行测试,而且还用于代码本身.

Until I decided to use SystemJS not just for running the tests but also within the code itself.

node.js 部分仍然有效,包括测试.运行浏览器测试时出现问题.

The node.js part still works including the tests. The problem arises when I run the browser tests.

对于那些我使用运行测试的 index.html 文件的人,下面是它的全部内容.

For those I use a index.html file that runs the tests, below it is in its entirety.

请注意,这与任何后来的生产浏览器环境无关,在这个早期阶段,我只想测试代码(纯粹基于网络和存储,没有任何 GUI 内容,在node.js 和浏览器上的浏览器和 websockets),我已经在浏览器上使用了.

Note that this has nothing to do with any later production browser environment, at this early stage all I want is to test the code (that is purely network and storage based, no GUI stuff whatsoever, using IndexedDB on the browser and websockets on both node.js and browser) that I already have against the browser.

关键是这条线 - 唯一一条新的线,其他一切都工作了几个月

Key is the line - the only line that is new, everything else has worked for months

SystemJS.set('systemjs', SystemJS.newModule(SystemJS));

一个类似的 sinon 已经运行了好几个月,我希望我可以使用完全相同的方法使已经可用的 SystemJS 在模块使用 时可用>require('systemjs').但它不起作用.

A similar one for sinon has worked fine for months, I hoped I could use the exact same method to make the already available SystemJS available when a module uses require('systemjs'). But it does not work.

这是模块在 require 之后看到的:

This is what the module sees after its require:

require">

实际的 SystemJS 模块内容在 Symbol(): tt 下.

The actual SystemJS module contents is under that Symbol(): tt.

我确信答案非常很简单,但是 SystemJS 的文档对我没有帮助,这当然很可能完全是我自己的错,但这就是事实,两个小时后我不得不问,没有结果.我也花了一些时间来完成当前的设置,包括必须阅读 SystemJS 源代码,我自己弄清楚了,但我认为这个微小而非常具体的问题对于 SO 问题来说可能是合理的?

I'm sure the answer is extremely simple, but the documentation of SystemJS was of no help to me, which of course may very well be entirely my own fault but that's just how it is, I have to ask after two hours without a result. It took me a while to get the current setup going too, including having to read SystemJS source code, and I figured it all out by myself, but I think this tiny and very specific question might be justifiable for an SO question?

只是为了完成设置的描述(对于那些好奇的人):我从 WebStorm 运行它,目录设置是一个通常的 node.js 项目,带有 ./test/, <代码>./src/、./lib/,当然还有./node_modules/.html 文件是 ./test/index.html,我告诉 WebStorm运行"它,所以 WS 充当测试的网络服务器.

Just to complete the description of the setup (for those curious): I run it all from WebStorm, directory setup is a usual node.js project with ./test/, ./src/, ./lib/, and of course ./node_modules/. The html file is ./test/index.html and I tell WebStorm to "run" it, so WS acts as the webserver for the tests.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Browser Tests</title>
    <link href="https://cdn.rawgit.com/mochajs/mocha/v3.4.1/mocha.css" rel="stylesheet"/>
    <script src="https://cdn.rawgit.com/mochajs/mocha/v3.4.1/mocha.js"></script>
    <script src="http://sinonjs.org/releases/sinon-2.2.0.js"></script>
    <script src="../node_modules/systemjs/dist/system.js"></script>
    <style>
        #errors pre {
            width: 50em;
            margin: 2em 4em;
            padding: 1em;
            border: 1px solid red;
        }
    </style>
</head>
<body>
<div id="errors"></div>
<div id="mocha"></div>
<script>
    /*global SystemJS */
    mocha.setup('bdd');

    // This hack switches the system-dependent components so that require()
    // statements for modules with node.js specific code are exchanged for their
    // browser versions.
    const resolveOrig = SystemJS.constructor.prototype.resolve;
    SystemJS.constructor.prototype.resolve = function (key, parents) {
        return resolveOrig.call(SystemJS, key.replace('-nodejs.js', '-browser.js'), parents);
    };

    // ======================================================
    // RELEVANT SECTION (what I tried)
    // THIS WORKS:
    SystemJS.set('sinon', SystemJS.newModule(sinon));
    // THIS DOES NOT WORK:
    SystemJS.set('systemjs', SystemJS.newModule(SystemJS));
    // ======================================================

    // These are the test scripts in ./test/ that I want to run in the browser
    const mochaTestScripts = [
        // ... ABRIDGED LIST ....
        'crypto-helpers',
        'map-query',
        'object-helpers',
        'storage'
    ];

    SystemJS.config({
        map: {
            'chai': '../node_modules/chai/chai.js',
            'chai-as-promised': '../node_modules/chai-as-promised/lib/chai-as-promised.js',
            // dependency of chai-as-promised
            'check-error': '../node_modules/check-error/check-error.js',
            'js-sha256': '../node_modules/js-sha256/build/sha256.min.js'
        }
    });

    Promise.all(
        mochaTestScripts.map(testScript =>
            SystemJS.import('./' + testScript + '-test.js')
            .catch(err => {
                const div = document.getElementById('errors');
                const pre = document.createElement('pre');
                pre.appendChild(document.createTextNode('Test: ' + testScript + '\n\n' + err));
                div.appendChild(pre);
            })
        )
    )
    .then(() => {
        mocha.checkLeaks();
        mocha.globals([]);
        mocha.run();
    })
    .catch(err => {
        const div = document.getElementById('errors');
        const pre = document.createElement('pre');
        pre.appendChild(document.createTextNode('GLOBAL ERROR\n' + err));
        div.appendChild(pre);
    });
</script>
</body>
</html>

推荐答案

我自己解决了:

我不得不去 SystemJS 的源代码中找到答案.问题似乎在于 SystemJS 符号不像通常那样只是一个普通对象,其中方法是直接在该对象内部的属性.相反,SystemJS 是一个实例,方法在原型上.

I had to go to the source code of SystemJS to find the answer. The problem seems to be that the SystemJS symbol wasn't just a plain object like it normally is, where the methods are properties directly inside this object. Instead, SystemJS is an instance and the methods are on the prototype.

最终起作用的是 SystemJS 如何在内部使用 newModule,最后起作用的命令是

What finally worked was taken right from how SystemJS used newModule internally, and the final command that worked was

SystemJS.registry.set(
    'systemjs',
    SystemJS.newModule({default: SystemJS, __useDefault: true})
);

这将替换上面 index.html 测试运行程序文件中 //THIS DOES NOT WORK: 下的行.

This replaces the line under // THIS DOES NOT WORK: in the above index.html test runner file.

这篇关于浏览器测试设置:如何使已经全局的 SystemJS 模块可用于测试代码的 require('systemjs')?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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