Domanda

Sto cercando di capire come sviluppare codice Javascript stand-alone. Voglio scrivere il codice javscript con i test e moduli, che va dalla linea di comando. Così ho installato node.js e npm insieme con le librerie requirejs, underscore e mocha.

Il mio Directory struttura si presenta come questo:

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

dove src/utils.js è un piccolo modulo che sto scrivendo, con il seguente codice:

> 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();
        };
    }

});

e test/utils.js è la prova:

> 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);
        })
    })

});

che ho poi tenta di eseguire dalla directory di livello superiore (in modo mocha vede la directory 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)
    ...

Quindi le mie domande sono le seguenti:

  • E 'questo il modo corretto per il codice struttura?
  • Perché il mio test non correre?
  • Qual è il modo migliore per imparare questo genere di cose? Sto avendo difficoltà a trovare buoni esempi con Google.

Grazie ...

[dispiace - risultati momentaneamente postato da codice errato; Ora riparato]

PS Sto usando requirejs perché voglio anche eseguire questo codice (o parte di esso) da un browser, più tardi.

Aggiornamento / Soluzione

Una cosa che non è nelle risposte qui di seguito è che avevo bisogno di usare mocha -u tdd per lo stile di prova di cui sopra. Ecco la prova finale (che richiede anche assert) e il suo uso:

> 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)
È stato utile?

Soluzione

Il motivo per il test non è in esecuzione è perché src/utils.js non è una libreria Node.js valido.

Secondo la documentazione RequireJS, al fine di coesistere con Node.js ei CommonJS richiedono standard è necessario aggiungere un po 'di boilerplate alla parte superiore del file in modo src/utils.js funzione define delle RequireJS viene caricato.

Tuttavia, poiché RequireJS è stato progettato per essere in grado di richiedere il codice sorgente del browser web-oriented "classico", tendo a usare lo schema seguente con i miei Node.JS librerie che voglio anche in esecuzione nel browser:

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

// Insert code here

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

Questo ha il vantaggio di non richiedere una libreria in più per gli altri utenti Node.js e generalmente funziona bene con RequireJS sul client.

Una volta che il codice in esecuzione in Node.js, è possibile avviare il test. Io personalmente preferisco ancora espresso nel corso moka, anche se il suo quadro di prova successore.

Altri suggerimenti

La documentazione Mocha è carente su come impostare questa roba, e si perplessi di capire a causa di tutti i trucchi di magia lo fa sotto il cofano.

Ho trovato le chiavi per ottenere file del browser utilizzando require.js al lavoro in Mocha sotto Node: Mocha ha di avere i file aggiunti alle sue suite con addFile:

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

E in secondo luogo, l'uso beforeEach con la richiamata opzionale per caricare i moduli in modo asincrono:

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);
        });
    });
});

ho creato un bootstrap per come ottenere tutto questo lavoro: https://github.com/clubajax/mocha-bootstrap

Si sta cercando di eseguire moduli JS progettati per browser (AMD), ma nel backend potrebbe non funzionare (come moduli vengono caricati il ??modo commonjs). A causa di questo, si dovrà affrontare due questioni:

  1. Definisci non è definito
  2. 0 test eseguire

Nel browserdefine sarà definito. Esso sarà impostato quando si richiede qualcosa con requirejs. Ma nodejs carica i moduli il modo commonjs. define in questo caso non è definito. Ma sarà definito quando abbiamo bisogno con requirejs!

Questo significa che ora stiamo richiedere codice in modo asincrono, e porta il secondo problema, un problema con l'esecuzione asincrona. https://github.com/mochajs/mocha/issues/362

Ecco un esempio di lavoro completo. Guardate che ho dovuto requirejs configure (AMD) per caricare i moduli, non stiamo usando richiedere (node ??/ commonjs) per caricare i nostri moduli.

> 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)
    })
  });

})

E per il modulo che si desidera verificare:

> 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();
})

Nel caso in cui risposta di David non era abbastanza chiaro, ho solo bisogno di aggiungere questo:

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

Per la parte superiore del file js in cui io uso define, come descritto in RequireJS docs (" Creazione di moduli nodi con AMD o RequireJS ") e nella stessa cartella aggiungere il pacchetto amdefine:

npm install amdefine

Questo crea la cartella node_modules con l'interno del modulo amdefine.

Non faccio uso di requirejs quindi non sono sicuro di quello che sembra sintassi del tipo, ma questo è quello che faccio per eseguire codice sia all'interno node e browser:

Per le importazioni, a determinare se ci sono in esecuzione nel nodo o il browser:

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

Poi possiamo afferrare qualsiasi dipendenze correttamente (saranno entrambi disponibili già se nel browser o usiamo require):

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

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

E poi qualsiasi funzionalità che devono essere utilizzati da altri file, esportiamo a radice:

root.bar = Bar;

Per quanto riguarda gli esempi, GitHub è una grande fonte. Basta andare a controllare il codice per la libreria preferita per vedere come hanno fatto :) Ho usato mocha per testare una libreria JavaScript che può essere utilizzato sia nel browser e nodo. Il codice è disponibile presso https://github.com/bunkat/later .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top