Pourquoi est-ce que je vois « define non défini » lors de l'exécution d'un test Mocha avec RequireJS?

StackOverflow https://stackoverflow.com/questions/9303945

Question

J'essaie de comprendre comment développer le code Javascript autonome. Je veux écrire un code javscript avec des tests et des modules, depuis la ligne de commande. J'ai donc installé node.js et npm ainsi que les bibliothèques requirejs, underscore et mocha.

Ma structure annuaire se présente comme suit:

> tree .
.
├── node_modules
├── src
│   └── utils.js
└── test
    └── utils.js

src/utils.js est un petit module qui je suis en train d'écrire, avec le code suivant:

> cat src/utils.js 
define(['underscore'], function () {

    "use strict";

    if ('function' !== typeof Object.beget) {
        Object.beget = function (o) {
            var f = function () {
            };
            f.prototype = o;
            return new f();
        };
    }

});

et test/utils.js est le test:

> cat test/utils.js 
var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});

requirejs(['../src/utils'], function(utils) {

    suite('utils', function() {
        test('should always work', function() {
            assert.equal(1, 1);
        })
    })

});

que j'essaie ensuite d'exécuter à partir du répertoire de niveau supérieur (donc mocha voit le répertoire test):

> mocha

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: Calling node's require("../src/utils") failed with error: ReferenceError: define is not defined
    at /.../node_modules/requirejs/bin/r.js:2276:27
    at Function.execCb (/.../node_modules/requirejs/bin/r.js:1872:25)
    at execManager (/.../node_modules/requirejs/bin/r.js:541:31)
    ...

Alors mes questions sont:

  • Est-ce la bonne façon de code de structure?
  • Pourquoi mon test ne fonctionne pas?
  • Quelle est la meilleure façon d'apprendre ce genre de chose? J'ai du mal à trouver de bons exemples avec Google.

Merci ...

[désolé - momentanément affiché des résultats de code erroné; fixe maintenant]

PS J'utilise requirejs parce que je veux aussi exécuter ce code (ou une partie de celui-ci) à partir d'un navigateur, plus tard.

Mise à jour / Solution

Quelque chose qui est pas dans les réponses ci-dessous est que je devais utiliser mocha -u tdd pour le style de test ci-dessus. Voici le test final (qui nécessite également assert) et son utilisation:

> cat test/utils.js 

var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});

requirejs(['../src/utils', 'assert'], function(utils, assert) {

    suite('utils', function() {
        test('should always work', function() {
            assert.equal(1, 1);
        })
    })

});
> mocha -u tdd

  .

  ✔ 1 tests complete (1ms)
Était-ce utile?

La solution

La raison pour laquelle votre test ne fonctionne pas parce que src/utils.js n'est pas une bibliothèque Node.js valide.

Selon la documentation RequireJS, afin de coexister avec Node.js et les CommonJS exigent standard, vous devez ajouter un peu de boilerplate en haut de votre fichier src/utils.js si la fonction define de RequireJS est chargé.

Cependant, depuis RequireJS a été conçu pour être en mesure d'exiger le code source orienté navigateur web « classique », j'ai tendance à utiliser le modèle suivant avec mes bibliothèques Node.js que je veux aussi en cours d'exécution dans le navigateur:

if(typeof require != 'undefined') {
    // Require server-side-specific modules
}

// Insert code here

if(typeof module != 'undefined') {
    module.exports = whateverImExporting;
}

Ceci a l'avantage de ne pas nécessiter une bibliothèque supplémentaire pour les autres utilisateurs Node.js et fonctionne généralement bien avec RequireJS sur le client.

Une fois que vous obtenez votre code en cours d'exécution dans Node.js, vous pouvez commencer à tester. Personnellement, je préfère encore plus Expresso mocha, même si son cadre de test successeur.

Autres conseils

La documentation Mocha manque sur la façon de mettre ce genre de choses, et il est perplexe de comprendre à cause de tous les tours de magie qu'il fait sous le capot.

J'ai trouvé les clés pour obtenir des fichiers de navigateur en utilisant require.js au travail en Mocha sous le nœud: Mocha a pour avoir les fichiers ajoutés à ses suites avec addFile:

mocha.addFile('lib/tests/Main_spec_node');

Et deuxièmement, l'utilisation beforeEach avec le rappel en option pour charger vos modules de manière asynchrone:

describe('Testing "Other"', function(done){
    var Other;
    beforeEach(function(done){
        requirejs(['lib/Other'], function(_File){
            Other = _File;
            done(); // #1 Other Suite will run after this is called
        });
    });

    describe('#1 Other Suite:', function(){
        it('Other.test', function(){
            chai.expect(Other.test).to.equal(true);
        });
    });
});

Je créé un bootstrap pour savoir comment obtenir ce travail tout: https://github.com/clubajax/mocha-bootstrap

Vous essayez d'exécuter des modules JS conçus pour les navigateurs (AMD), mais dans le back-end, il pourrait ne pas fonctionner (comme les modules sont chargés le chemin CommonJS). En raison de cela, vous ferez face à deux problèmes:

  1. Define ne sont pas définis
  2. 0 exécuter des tests

Dans le browserdefine sera défini. Il sera réglé lorsque vous avez besoin quelque chose avec requirejs. Mais NodeJS charge les modules comme CommonJS. define dans ce cas n'est pas défini. Mais il sera défini lorsque nous avons besoin avec requirejs!

Cela signifie que maintenant nous le code NÉCESSITANT de manière asynchrone, et il apporte le deuxième problème, un problème avec l'exécution asynchrone. https://github.com/mochajs/mocha/issues/362

Voici un exemple de travail complet. Regardez que je devais requirejs configure (amd) pour charger les modules, nous n'utilisons pas besoin (nœud / CommonJS) pour charger nos modules.

> cat $PROJECT_HOME/test/test.js

var requirejs = require('requirejs');
var path = require('path')
var project_directory = path.resolve(__dirname, '..')

requirejs.config({
  nodeRequire: require, 
  paths: {
    'widget': project_directory + '/src/js/some/widget'
  }
});

describe("Mocha needs one test in order to wait on requirejs tests", function() {
  it('should wait for other tests', function(){
    require('assert').ok(true);
  });
});


requirejs(['widget/viewModel', 'assert'], function(model, assert){

  describe('MyViewModel', function() {
    it("should be 4 when 2", function () {
        assert.equal(model.square(2),4)
    })
  });

})

Et pour le module que vous voulez tester:

> cat $PROJECT_HOME/src/js/some/widget/viewModel.js

define(["knockout"], function (ko) {

    function VideModel() {
        var self = this;

        self.square = function(n){
            return n*n;
        }

    }

    return new VideModel();
})

Juste au cas réponse de David n'a pas été assez clair, je juste besoin d'ajouter ceci:

if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

Vers le haut du fichier js où j'utilise define, comme décrit dans RequireJS docs ( » construire des modules de noeuds avec AMD ou RequireJS ") et dans le même dossier ajouter le package amdefine:

npm install amdefine

Cela crée le dossier node_modules avec le module amdefine à l'intérieur.

Je ne me requirejs donc je ne suis pas sûr de ce qui ressemble de syntaxe aiment, mais ce que je fais pour exécuter du code à la fois dans les node et browser:

Pour les importations, déterminer si nous courons dans le nœud ou le navigateur:

var root =  typeof exports !== "undefined" && exports !== null ? exports : window;

Ensuite, nous pouvons saisissons toutes les dépendances correctement (ils seront soit disponibles déjà si dans le navigateur ou que nous utilisons require):

var foo = root.foo;
if (!foo && (typeof require !== 'undefined')) {
    foo = require('./foo');
}

var Bar = function() {
    // do something with foo
}

Et puis toutes les fonctionnalités qui doivent être utilisés par d'autres fichiers, nous exportons à la racine:

root.bar = Bar;

En ce qui concerne les exemples, GitHub est une grande source. Il suffit d'aller et de vérifier le code de votre bibliothèque préférée pour voir comment ils l'ont fait :) je mocha pour tester une bibliothèque javascript qui peut être utilisé aussi bien dans le navigateur et le noeud. Le code est disponible à https://github.com/bunkat/later .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top