尝试使用PegJS和requirejs测试一个项目。我有两个源文件,实现为AMD模块(定义),通过需求API加载。在目录结构下面:
js/
somefile.js
main.js
parser.js
test/
parser.spec.js
我编写了一个parser.js模块来加载PegJS语法文件,并使用PegJS创建一个peg解析器:
define(function() {
'use strict';
var PEG = require('pegjs');
var grammarFile = 'grammar.peg'
return {
parse: function(fs, content, debug) {
var grammar = fs.readFileSync(grammarFile, 'utf8').toString();
// Build parser from grammar
var parser = PEG.buildParser(grammar, { trace: debug });
[...]
对于在带有节点的命令行上执行的main.js来说,这很好。现在我想用业力,茉莉花和PhantomJS来测试我的项目。我有一个这样的karma.conf.js:
frameworks: ['jasmine', 'requirejs'],
files: [
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js',
],
还有一个名为test-main.js的需要引导文件,其配置方式如下:
'use strict';
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
console.log(file);
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(file);
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base/js',
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
现在,当我启动我的测试(grunt karma
)时,我得到了以下错误:
PhantomJS 1.9.8 (Linux 0.0.0) ERROR: Error{message: 'Module name "pegjs" has not been loaded yet for context: _. Use require([])
因此,我尝试在Karma以karma.conf.js方式加载的文件中包含pegjs。
files: [
{ pattern: 'node_modules/pegjs/lib/**/*.js', included: true },
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js'
],
当我这样做的时候,我仍然会发现一个错误:
Error: Module name "utils/arrays" has not been loaded yet for context: _. Use require([])
从pegjs模块内部看,确实有一个arrays.js文件:
compiler/
compiler.js
grammar-error.js
parser.js
peg.js
utils/
arrays.js
classes.js
objects.js
因此,也试图包括数组:
files: [
{ pattern: 'node_modules/pegjs/lib/utils/arrays.js', included: true },
{ pattern: 'node_modules/pegjs/lib/**/*.js', included: true },
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js'
],
我得到:
ReferenceError: Can't find variable: module
at /blabla/node_modules/pegjs/lib/utils/arrays.js:108
因为:
108 module.exports = arrays;
因此,在加载npm模块时,我尝试以这样的方式加载bower模块:
files: [
{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: true },
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js'
],
你又来了:
PhantomJS 1.9.8 (Linux 0.0.0) ERROR: Error{message: 'Module name "pegjs" has not been loaded yet for context: _. Use require([])
还试图在业力生成的网页中不包含pegjs:
files: [
{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: false },
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js'
],
但它失败了,因为:
PhantomJS 1.9.8 (Linux 0.0.0) ERROR: 'There is no timestamp for /base/bower_components/pegjs/peg-0.9.0!'
试图将bower_component文件夹放入js文件夹中,但没有找到任何结果。
所以我不知道从这里开始.在谷歌或这里找不到任何相关的东西。这似乎是一个特殊的问题,要求与业力.任何想法都是欢迎的。
丹回答后的更新:
因此,在parser.js中,我从同步需求切换到异步需求。
define(['../bower_components/pegjs/peg-0.9.0'], function(PEG) {
'use strict';
var grammarFile = 'grammar.peg'
return {
parse: function(fs, content, debug) {
var grammar = fs.readFileSync(grammarFile, 'utf8').toString();
// Build parser from grammar
var parser = PEG.buildParser(grammar, { trace: debug });
[...]
尝试在karma.conf.js中包含pegjs bower组件
{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: false },
或不包括在内:
{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: true },
但总是有相同的错误:
Error: Script error for "/blabla/bower_components/pegjs/peg-0.9.0", needed by: /blabla/js/parser.js
http://requirejs.org/docs/errors.html#scripterror
at /blabla/node_modules/requirejs/require.js:140
是的,该文件存在:
$ file /home/aa024149/share/logofrjs/bower_components/pegjs/peg-0.9.0.js
/blabla/bower_components/pegjs/peg-0.9.0.js: ASCII text, with very long lines
UPDATE2:最终理解并找到了一个可接受的解决方案。
发布于 2015-12-01 23:32:20
因此,在丹和pieceOpiland的各种回答和评论的帮助下,我终于找到了一种我想做的事情。
因此,首先,与许多javascript库一样,pegjs有两种格式: npm模块和bower模块。
Npm模块用于为节点制作脚本并从命令行调用。Bower模块用于在浏览器中加载脚本。
我的第一个误解是,“require”在节点和浏览器中都会不清楚地工作。这是错误的。似乎只有通过异步调用才能使模块在浏览器中工作,如下所示:
require(['module'], function(module) {
...
});
另一个误解是,我可以在浏览器中加载npm模块。某种魔法将操作各种npm文件,以加载我的页面。这可能是可能的,但只能使用一些特殊的工具,比如、browserify。在没有特殊转换的情况下,只能在浏览器中加载bower版本。此外,pegjs bower模块是以这样的方式生成的,因此全局变量的定义如下:
var PEG = {
...
}
module.exports = PEG;
基本上,bower模块将全局变量(实际上是几个全局变量)插入到顶层范围。
因此,与其让我的客户端代码(在浏览器和节点中运行的代码)加载模块,我实际上将模块加载在以下两种方式中:
var PEG = require('pegjs');
<script>
标记)可用)。然后这两个‘main’都将PEG变量注入到我的解析器函数中。
为了使业力发挥作用,我只需要在生成的页面(karma.conf.js提取中包含pegjs bower模块):
files: [
{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: true },
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js',
],
发布于 2015-11-29 14:00:31
听起来好像你是通过需求来加载连接的。如果是这样的话,pegjs不应该是包含在其中的文件。在您的karma.conf.js中,您是否尝试过以下方法:
files: [
{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: false },
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js'
],
包含的值指示业力服务器生成的网页是否应该有该文件的脚本标记(参见http://karma-runner.github.io/0.13/config/files.html)。所以你的karma.config:
files: [
{ pattern: 'bower_components/pegjs/peg-0.9.0.js', included: true },
{ pattern: './test/**/*.spec.js', included: false },
{ pattern: './js/**/*.js', included: false},
'./test/test-main.js'
],
将导致业力生成一个带有头部标记的网页,类似于:
<head>
<script src="/base/bower_components/pegjs/peg-0.9.0.js"></script>
<script src="/base/require.js"></script>
<script src="/base/test/test-main.js"></script>
</head>
在我的经验中,我看到了许多类似于将我的文件标记为included: true
导致的行为。如果有一个文件正在尝试加载,请确保它被标记为included: false
。
我相信这标志着它是一个预处理工作,但我不完全确定为什么这会产生如此大的差异。
发布于 2015-12-01 02:17:12
据我所知,Karma是一个测试框架,它将在浏览器中运行您的测试。
这不适合于测试许多节点模块。
浏览器没有同步完成此操作的工具:var PEG = require('pegjs')
。这就是为什么它要求您使用require([])
,在pegjs完成加载时传递一个回调以执行该回调。
在这里,使用第一个版本的pegjs并确保在调用require('pegjs')
之前加载它可能会有所帮助。这将确保已经为context _(我猜想是默认的需求上下文)加载了pegjs。
它也不能用fs.readFileSync(grammarFile, 'utf8')
从文件系统加载文件,所以您必须用另一种方式来加载文件。您可以通过将它放置在文件数组中,然后使用所需文本插件加载它,从而让Karma托管您的peg语法。
如果您正在测试的模块的目标是在node.js上运行,而不是在浏览器中运行,那么它可能更适合使用一个测试框架,该框架不运行浏览器中的代码,而是在节点中运行它,因此您可以使用所有的节点模块。如果您针对的是浏览器,我会重写它,以便更具体地针对浏览器。
https://stackoverflow.com/questions/33895334
复制