2015-11-24 4 views
12

Попытка протестировать проект с использованием PegJS и requirejs. У меня есть несколько исходных файлов, реализованных в виде модуля (define) AMD, который загружается через требуемый API. Под структурой каталога:Настройте Karma для загрузки pegjs с requirejs

js/ 
    somefile.js 
    main.js 
    parser.js 
test/ 
    parser.spec.js 

Я написал parser.js модуля для загрузки файла грамматики PegJS и использовать PegJS создать колышек анализатор:

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', 
], 

Также есть требуется загрузочный файл с именем тест-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([]) 

Так я пытаюсь включить pegjs в лоа файлов DED кармой таким образом karma.conf.js:

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; 

Так, Intead загрузки модуля NPM, я попытался загрузить модуль Бауэр таким образом:

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, но не повезло.

Так что я не знаю, должны были идти отсюда ...Не удалось найти что-либо актуальное в Google или здесь. Кажется, что это определенная проблема, чтобы требовать/pegjs с кармой ... Любая идея приветствуется.

UPDATE следующий ответ Дэн:

Так что я переключаться с синхронным требуется для асинхронного требуется в 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 }); 
    [...] 

Пробовал включить компонент pegjs Бауэр в кармы .conf.js:

{ 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: Наконец понял и нашел приемлемый решение.

ответ

0

Итак, с помощью различных ответов и комментариев от dan и piecesOpiland я, наконец, пришел к тому, чтобы делать то, что хочу.

Итак, во-первых, pegjs, как и многие библиотеки javascript, выпускаются в двух форматах: модули npm и модули bower.

Модули Npm используются для скриптов, созданных для узла и вызываемых из командной строки. Модули Bower используются для сценария, загруженного в браузер.

Первое непонимание с моей стороны заключалось в том, что «require» будет работать в узле и в браузере нечетко. Это не верно. Кажется, что единственный способ требует модуль так, что он работает в браузере через асинхронный вызов, как:

require(['module'], function(module) { 
    ... 
}); 

Другое недоразумение было то, что я мог загрузить НПМ модули в браузере. Что-то вроде магии будет работать для различных файлов npm, которые будут загружены моей страницей. Это может быть возможно, но только с использованием специального инструмента, такого как , браузера. Без специального преобразования в браузере может быть загружена только версия bower. Кроме того, pegjs Bower модуль выполнен таким образом, так, чтобы глобальные переменные определены следующим образом:

var PEG = { 
... 
} 

module.exports = PEG; 

В основном, модуль Bower подключается к глобальной переменной (на самом деле несколько глобальных переменных) в рамки верхнего уровня.

Так вместо того, чтобы мой код клиента (один работает в браузере и в узле) загрузки модуля, я на самом деле загрузить модуль в любом:

  1. main.js через синхронное требуется НПМ модуль так: var PEG = require('pegjs');
  2. основные-browser.js через глобальную переменную, которая становится доступной при загрузке становой pegjs скрипт (через <script> тег)

И те «сети», затем вводя переменную PEGк моей функции парсера.

кармы работать, мне просто нужно включить модуль pegjs Бауэра в сгенерированной странице (karma.conf.js экстракта):

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', 
], 
+0

Забудьте обо всех требованиях/беседах, не имеющих смысла, сделайте себе одолжение, перейдите на веб-пакет! –

3

Похоже, вы загружаете pegjs через requirejs. Если это так, 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. Если есть файл, который вы пытаетесь загрузить с помощью requirejs, убедитесь, что он отмечен как included: false.

Я считаю, что это отмечает его для предварительной обработки, но я не совсем уверен, почему это имеет такое значение.

+0

Да pieceOpiland, что это один из многих комбинации я но он все еще терпит неудачу. Я уточню вопрос. –

+0

Хм, расширение .js, обычно добавляемое requirejs, отсутствует в последней зарегистрированной ошибке. Не могли бы вы также включить конфигурацию requirejs? – pieceOpiland

+0

Хорошо, я выполнил требуемую конфигурацию, которую я использую, но сомневаюсь, что у вас будет более полезная информация. Обратите внимание, что мой проект отлично работает в командной строке с узлом. Проблема заключается в проверке кармы. –

1

Насколько я знаю, карма - это платформа тестирования, которая будет запускать ваши тесты в браузере.

Это не подходит для тестирования многих модулей узлов.

Браузер не имеет возможности сделать это синхронно: var PEG = require('pegjs'). Вот почему он просит вас использовать require([]), с которым вы передаете обратный вызов, который должен выполняться, когда pegjs заканчивает загрузку.

Использование bower версии pegjs и обеспечение ее загрузки до вызова require('pegjs') может помочь здесь. Это обеспечило бы, что pegjs уже загружен для контекста _ (предположим, по умолчанию я требую контекст).

Он также не может загружать файлы из файловой системы в fs.readFileSync(grammarFile, 'utf8'), поэтому вам придется делать это по-другому. Вы можете попросить Карму разместить вашу грамматику привязки, поместив ее в массив файлов, а затем загрузить ее с помощью requirejs text plugin.

Если тестируемый модуль предназначен для работы на узле.js, а не в браузере, то он может быть более подходящим для использования тестовой среды, которая не запускает код в браузере, но запускает ее в узле так, у вас есть все модули узлов, доступные вам. Если вы нацеливаете это на браузер, я бы переписал его, чтобы более конкретно настроить браузер.

+0

Пробовал это тоже (см. Обновленный вопрос), но, похоже, он не может загрузить версию басов. И вообще, похоже, версия bower несовместима с версией npm, потому что когда я пытаюсь запустить свою программу с помощью командной строки, у меня возникла ошибка, говорящая о том, что одна из функций pegjs (buildParser) недоступна. Поэтому оба модуля (bower/npm) не являются взаимозаменяемыми, что является проблемой. Я хотел бы, чтобы мой синтаксический анализатор использовался в браузере И в командной строке. Я изначально, хотя это была одна из предпосылок nodejs, которые могли бы это сделать. –

+0

В соответствии с вашей точкой в ​​файле грамматики я просто реорганизую свой проект так, чтобы main.js загружал файл, а синтаксический анализатор брал фрагмент текста. Я стараюсь держаться подальше от requirejs mumbo jumbo как можно больше ... –

+0

Нужно ли, чтобы синтаксический анализатор генерировался каждый раз при запуске скрипта? Может ли он быть создан как артефакт сборки, который будет развернут вместе с приложением? Открывает ли консоль разработчика что-нибудь при запуске версии браузера в браузере? Получает ли браузер успешную версию pegjs для бауэров (проверка сетевой вкладки не имеет 404)? Ошибка сценария в отладчике и дает что-то значимое, поскольку обычно это вызвано плохим сценарием? – dan