javascript 用 Karma 和 RequireJS 测试 CommonJS 语法中的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17281211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 07:45:38  来源:igfitidea点击:

Testing with Karma and RequireJS with files in CommonJS syntax

javascriptrequirejsamdcommonjskarma-runner

提问by ekweible

I'm working on an angular application that is written in CommonJS syntax and uses a grunt task with the grunt-contrib-requirejs task to translate the source files to AMD format and compile it into one output file. My goal is to make Karma work with RequireJS and keep my source files and spec files in CommonJS syntax.

我正在开发一个用 CommonJS 语法编写的 angular 应用程序,并使用 grunt 任务和 grunt-contrib-requirejs 任务将源文件转换为 AMD 格式并将其编译为一个输出文件。我的目标是让 Karma 与 RequireJS 一起工作,并将我的源文件和规范文件保存在 CommonJS 语法中。

I've been able to get a simple test passing in AMD format with the following file structure:

我已经能够通过具有以下文件结构的 AMD 格式的简单测试:

-- karma-test
   |-- spec
   |   `-- exampleSpec.js
   |-- src
   |   `-- example.js
   |-- karma.conf.js
   `-- test-main.js

and the following files:

以及以下文件:

karma.conf.js

业力配置文件

// base path, that will be used to resolve files and exclude
basePath = '';

// list of files / patterns to load in the browser
files = [
  JASMINE,
  JASMINE_ADAPTER,
  REQUIRE,
  REQUIRE_ADAPTER,
  'test-main.js',
  {pattern: 'src/*.js', included: false},
  {pattern: 'spec/*.js', included: false}
];

// list of files to exclude
exclude = [];

// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];

// web server port
port = 9876;

// cli runner port
runnerPort = 9100;

// enable / disable colors in the output (reporters and logs)
colors = true;

// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_DEBUG;

// enable / disable watching file and executing tests whenever any file changes
autoWatch = true;

// Start these browsers, currently available:
browsers = ['Chrome'];

// If browser does not capture in given timeout [ms], kill it
captureTimeout = 60000;

// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = false;

example.js

例子.js

define('example', function() {
    var message = "Hello!";

    return {
        message: message
    };
});

exampleSpec.js

示例规范.js

define(['example'], function(example) {
    describe("Example", function() {
        it("should have a message equal to 'Hello!'", function() {
            expect(example.message).toBe('Hello!');
        });
    });
});

test-main.js

测试main.js

var tests = Object.keys(window.__karma__.files).filter(function (file) {
      return /Spec\.js$/.test(file);
});

requirejs.config({
    // Karma serves files from '/base'
    baseUrl: '/base/src',

    // Translate CommonJS to AMD
    cjsTranslate: true,

    // ask Require.js to load these files (all our tests)
    deps: tests,

    // start test run, once Require.js is done
    callback: window.__karma__.start
});


However, my goal is to write both the source file and the spec file in CommonJS syntax with the same results, like so:

但是,我的目标是使用 CommonJS 语法编写源文件和规范文件,结果相同,如下所示:

example.js

例子.js

var message = "Hello!";

module.exports = {
    message: message
};

exampleSpec.js

示例规范.js

var example = require('example');

describe("Example", function() {
    it("should have a message equal to 'Hello!'", function() {
        expect(example.message).toBe('Hello!');
    });
});

But despite having the cjsTranslateflag set to true, I just receive this error:

但是尽管将cjsTranslate标志设置为true,我还是收到了这个错误:

Uncaught Error: Module name "example" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded
at http://localhost:9876/adapter/lib/require.js?1371450058000:1746


Any ideas on how this can be accomplished?

关于如何实现这一点的任何想法?



Edit: I found this issue for the karma-runner repo: https://github.com/karma-runner/karma/issues/552and there's a few comments that may help with this problem, but I haven't had any luck with them so far.

编辑:我在 karma-runner 存储库中发现了这个问题:https: //github.com/karma-runner/karma/issues/552并且有一些评论可能有助于解决这个问题,但我没有任何运气与他们到目前为止。

采纳答案by ekweible

The solution I ended up finding involved using gruntand writing some custom grunt tasks. The process goes like this:

我最终找到的解决方案涉及使用grunt并编写一些自定义 grunt 任务。这个过程是这样的:

Create a grunt task to build a bootstrap requirejs file by finding all specs using a file pattern, looping through them and building out a traditional AMD style require block and creating a temporary file with code like this:

创建一个 grunt 任务,通过使用文件模式查找所有规范,循环遍历它们并构建传统的 AMD 样式 require 块并使用如下代码创建临时文件来构建引导 requirejs 文件:

require(['spec/example1_spec.js'
,'spec/example2_spec.js',
,'spec/example3_spec.js'
],function(a1,a2){
// this space intentionally left blank
}, "", true);

Create a RequireJS grunt task that compiles the above bootstrap file and outputs a single js file that will effectively include all source code, specs, and libraries.

创建一个 RequireJS grunt 任务,该任务编译上述引导程序文件并输出一个 js 文件,该文件将有效地包含所有源代码、规范和库。

   requirejs: {
        tests: {
            options: {
                baseUrl: './test',
                paths: {}, // paths object for libraries
                shim: {}, // shim object for non-AMD libraries
                // I pulled in almond using npm
                name: '../node_modules/almond/almond.min',
                // This is the file we created above
                include: 'tmp/require-tests',
                // This is the output file that we will serve to karma
                out: 'test/tmp/tests.js',
                optimize: 'none',
                // This translates commonjs syntax to AMD require blocks
                cjsTranslate: true
            }
        }
    }
   requirejs: {
        tests: {
            options: {
                baseUrl: './test',
                paths: {}, // paths object for libraries
                shim: {}, // shim object for non-AMD libraries
                // I pulled in almond using npm
                name: '../node_modules/almond/almond.min',
                // This is the file we created above
                include: 'tmp/require-tests',
                // This is the output file that we will serve to karma
                out: 'test/tmp/tests.js',
                optimize: 'none',
                // This translates commonjs syntax to AMD require blocks
                cjsTranslate: true
            }
        }
    }

Create a grunt task that manually starts a karma server and serve the single compiled js file that we now have for testing.

创建一个 grunt 任务,手动启动 karma 服务器并提供我们现在用于测试的单个已编译 js 文件。

Additionally, I was able to ditch the REQUIRE_ADAPTERin the karma.conf.jsfile and then only include the single compiled js file instead of the patterns that matched all source code and specs, so it looks like this now:

此外,我能够沟REQUIRE_ADAPTERkarma.conf.js的文件,然后只包括单个编译的JS文件,而不是匹配所有的源代码和规格模式,所以它看起来像现在这样:

// base path, that will be used to resolve files and exclude
basePath = '';

// list of files / patterns to load in the browser
files = [
  JASMINE,
  JASMINE_ADAPTER,
  REQUIRE,
  'tmp/tests.js'
];

// list of files to exclude
exclude = [];

// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];

// web server port
port = 9876;

// cli runner port
runnerPort = 9100;

// enable / disable colors in the output (reporters and logs)
colors = true;

// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;

// enable / disable watching file and executing tests whenever any file changes
autoWatch = true;

// Start these browsers, currently available:
browsers = ['PhantomJS'];

// If browser does not capture in given timeout [ms], kill it
captureTimeout = 60000;

// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = true;

In the grunt task configuration for the requirejs compilation, it was also necessary to use almondin order to start the test execution (test execution would hang without it). You can see this used in the requirejs grunt task config above.

在 requirejs 编译的 grunt 任务配置中,还需要使用杏仁来启动测试执行(没有它测试执行会挂起)。您可以在上面的 requirejs grunt 任务配置中看到它的使用。

回答by Simon Boudrias

There's a couple things. First of all: I might have missed some details in your question (as it is super huge) - so sorry about that.

有几件事。首先:我可能错过了您问题中的一些细节(因为它非常庞大)-对此感到抱歉。

In short, you may want to checkout Backbone-Boilerplate wipbranch testing organization: https://github.com/backbone-boilerplate/backbone-boilerplate/tree/wip

简而言之,您可能想查看 Backbone-Boilerplatewip分支测试组织:https: //github.com/backbone-boilerplate/backbone-boilerplate/tree/wip

First: RequireJS does not support unwrapped raw common.js module. cjsTranslateis a R.js (the build tool) option to convert Commonjs to AMD compatible during build. As so, requiring a CJS raw module won't work. To resolve this issue, you can use a server to filter the scripts sent and compile them to AMD format. On BBB, we pass file through a static serve to compile them:

第一:RequireJS 不支持未包装的原始 common.js 模块。cjsTranslate是一个 R.js(构建工具)选项,用于在构建期间将 Commonjs 转换为 AMD 兼容。因此,需要 CJS 原始模块是行不通的。要解决此问题,您可以使用服务器过滤发送的脚本并将它们编译为 AMD 格式。在 BBB 上,我们通过静态服务传递文件来编译它们:

Second: The Karma requirejs plugin isn't working super well - and it's somehow easy to use requireJS directly. On BBB, that's how we managed it: https://github.com/backbone-boilerplate/backbone-boilerplate/blob/wip/test/jasmine/test-runner.js#L16-L36

第二:Karma requirejs 插件运行得不是很好 - 而且它很容易直接使用 requireJS。在 BBB 上,我们是这样管理的:https: //github.com/backbone-boilerplate/backbone-boilerplate/blob/wip/test/jasmine/test-runner.js#L16-L36

Hope this helps!

希望这可以帮助!