npm + Мокко + RequireJS

У меня довольно много времени, чтобы настроить node/npm с Mocha и RequireJS. Вот что я сделал.

Я создал каталог testing/ со следующей структурой:

testing/
   |
   +-- package.json
   |
   +-- README.md
   |
   +-- test/
         |
         +-- mocha.opts
         |
         +-- widgets/
                |
                +--mywidget/
                       |
                       +-- test.js

Вот что содержит каждый соответствующий файл:

пакет.json:

{
    "name":"testing-project",
    "version":"2.5.0",
    "description":"Testing Project",
    "keywords":["test"],
    "engines": { "node": ">= 0.7.0 < 0.11.0" },
    "scripts" : {
        "test": "./node_modules/.bin/mocha"
    },
    "devDependencies": {
        "mocha": ">= 1.18.2",
        "requirejs": ">= 2.1.11",
        "should": ">= 3.2.0",
        "expect.js": ">= 0.3.1"
    }
}

test/mocha.opts:

--require expect.js
--require should
--require requirejs
--require mocha
--reporter spec
--ui tdd
--recursive
--growl

тест/виджеты/mywidget/test.js

'use strict';
var requirejs = require('requirejs');
// Also tried with:  require('../../../r.js')  which I downloaded from RequireJS' site

requirejs.config({
    baseUrl: '../../../../',
    nodeRequire: require
});

console.log('before require');
requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){
    console.log('after require');

    var expect = require('expect.js');

    // Instead of the above "requirejs['mywidget..." line, I've also tried:
    // var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js');   AND:
    // var myObj = requirejs('../../../../mywidget/trunk/src/mywidgetfile.js');

    describe('My Widget', function(){
        describe('my-widget#getInfo', function(){

            it('should pass this test', function(done){
                expect( myObj.returnString('test') ).to.equal( 'test' );

                done();
            })
        })
    });
});
console.log('done');

Он выведет строки консоли «before require» и «done», но пока у меня есть строка requirejs(['mywidget...), она не попадет в строку after require. Если я удалю строку requirejs (и строку соответствующую закрывающую скобку/пареневую строку), и вместо этого используйте прямую строку «var myObj =», я получаю «не могу найти модуль», и если я использую вторую строку «var myObj», я получаю «Ошибка ссылки: определение не определено ".

Я пытаюсь упаковать все это для удобства других разработчиков с помощью npm, так что я запускаю команду «npm test» из верхнего каталога «testing/».

Я искал ответы и пробовал так много вещей, но я не могу потребовать файл с использованием RequireJS и определить «define ()». Я могу выполнять тесты, это не проблема... я просто пытаюсь вставить RequireJS в микс, когда у меня начинаются проблемы.

Любая помощь будет огромной!

Спасибо!


person Mr Mikkél    schedule 02.04.2014    source источник


Ответы (1)


В том, что вы нам показываете, есть несколько проблем. Вы неправильно используете RequireJS и Mocha.

ТребоватьJS

Я почти уверен, что ваш baseUrl неверен. Кажется, вы думаете, что текущий рабочий каталог Mocha будет установлен на test/widgets/mywidget/, когда он будет выполнять тесты в test/widgets/mywidget/test.js. Это не так. Рабочий каталог находится там, где вы находитесь, когда запускаете npm test. Согласно вашему описанию, вы находитесь в testing/, когда запускаете его. Мне не ясно, каким значением должно быть ваше baseUrl, потому что вы не предоставили достаточно информации в своем вопросе, но я надеюсь, что из только что данного объяснения вы сможете это понять.

Теперь вы можете подумать: «Конечно, мой baseUrl правильный, потому что когда я выполняю requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){, я не получаю ошибки». Это будет неверным выводом. Хотя этот requirejs вызов планирует загрузку вашего модуля, RequireJS не получает возможности попытаться загрузить его, потому что Mocha завершает работу до того, как RequireJS попытается загрузить его. Вы можете проверить это, заменив путь к вашему модулю полным мусором, и вы не получите ошибку.

Как только вы устраните эту проблему baseUrl, использование var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js') будет работать так, как вы ожидаете. Таким образом, вы сможете избежать использования асинхронной формы require (это форма, которая использует массив зависимостей в качестве первого аргумента). (Функция requirejs, которую вы используете, — это просто псевдоним для функции, обычно называемой require в документации RequireJS.)

Мокко

Ваши тесты не запускаются, потому что Mocha их не видит. Mocha работает следующим образом: читает все найденные тестовые файлы и затем выполняет их. Обратные вызовы для каждого describe вызова выполняются сразу, а обратные вызовы для каждого it вызова записываются как тесты, которые необходимо запустить. Как только Mocha выясняет, какие тесты существуют, он запускает их.

Что происходит с вашим тестовым файлом, так это то, что Mocha выполняет его, как обычно. Однако в верхней части вашего тестового файла нет вызова describe или it. В вашем обратном вызове есть вызовы requirejs, но помните, что я сказал выше: RequireJS не получает возможности загрузить модуль, поэтому у него нет возможности запустить обратный вызов. (А даже если бы и запустил, то было бы поздно.) Так что Mocha не видит никаких тестов и сразу же завершает работу.

Путь вперед

Выясните, какие baseUrl вам нужны, и тогда это должно сработать:

'use strict';
var requirejs = require('requirejs');

requirejs.config({
    baseUrl: <whatever value is needed here>,
    nodeRequire: require
});

var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js');

describe('My Widget', function() {
// etc...

Вы также можете полностью исключить RequireJS из своего набора тестов. Я написал библиотеку, которая работает в Node так же хорошо, как и в браузере. Он состоит из модулей AMD и загружается RequireJS в браузере, но я не использую RequireJS в наборе тестов. Это загрузчик, который я использую для загрузки своих модулей в Node. Также есть amdefine, который я не использовал, но должен дать аналогичные возможности.

person Louis    schedule 02.04.2014
comment
Спасибо, @Луи. И спасибо за объяснение. Это очень помогает, и это то, что сработало для меня. Единственное, что по какой-то причине не работает, это baseUrl. Я должен указать: var myObj = requirejs('../mywidget/trunk/src/mywidgetfile.js'); вместо использования basePath. Но все остальное работает прекрасно. Спасибо! - person Mr Mikkél; 04.04.2014