2016-07-12 22 views
15

Angenommen, ich habe folgendes Modul:Wie kann ich Webpack's require.context in Jest vortäuschen?

var modulesReq = require.context('.', false, /\.js$/); 
modulesReq.keys().forEach(function(module) { 
    modulesReq(module); 
}); 

Jest beschwert, weil sie nicht kennt require.context:

FAIL /foo/bar.spec.js (0s) 
● Runtime Error 
    - TypeError: require.context is not a function 

Wie kann ich es verspotten? Ich habe versucht, setupTestFrameworkScriptFile Jest Konfiguration verwenden, aber die Tests können keine Änderungen sehen, die ich in require gemacht habe.

+0

Haben Sie Ihre Antwort gefunden? – BigDong

Antwort

4

Ich hatte das gleiche Problem, dann mache ich eine "Lösung".

Ich bin mir ziemlich sicher, dass dies nicht die beste Wahl ist. Ich landete stoping es verwendet wird, durch die beantwortet Punkte hier:

https://github.com/facebookincubator/create-react-app/issues/517 https://github.com/facebook/jest/issues/2298

Aber wenn es wirklich brauchen, sollten Sie die polyfill unten in jeder Datei enthalten, die Sie nennen es (nicht auf die Tests selbst, weil die require in einer Node-Umgebung nicht global übersteuert wird).

// This condition actually should detect if it's an Node environment 
if (typeof require.context === 'undefined') { 
    const fs = require('fs'); 
    const path = require('path'); 

    require.context = (base = '.', scanSubDirectories = false, regularExpression = /\.js$/) => { 
    const files = {}; 

    function readDirectory(directory) { 
     fs.readdirSync(directory).forEach((file) => { 
     const fullPath = path.resolve(directory, file); 

     if (fs.statSync(fullPath).isDirectory()) { 
      if (scanSubDirectories) readDirectory(fullPath); 

      return; 
     } 

     if (!regularExpression.test(fullPath)) return; 

     files[fullPath] = true; 
     }); 
    } 

    readDirectory(path.resolve(__dirname, base)); 

    function Module(file) { 
     return require(file); 
    } 

    Module.keys =() => Object.keys(files); 

    return Module; 
    }; 
} 

Mit dieser Funktion geben Sie brauchen keinen require.context Aufruf zu ändern, wird es mit dem gleichen Verhalten auszuführen (wenn auf webpack ist, das Original verwendet wird, und wenn in Jest, die verspottet Funktion).

5

den Anruf an einen separaten Modul Extract:

// src/js/lib/loader.js 
const loadModule = require('lib/bundle-loader') 
// ... 

ein Modell für die neu erstellte Paket-Lademodul erstellen:

// src/js/lib/bundle-loader.js 
/* istanbul ignore next */ 
module.exports = require.context('bundle-loader?lazy!../components/', false, /.*\.vue$/) 

Verwenden Sie das neue Modul in dem Modul, wo Sie es aus extrahierten :

// test/unit/specs/__mocks__/lib/bundle-loader.js 
export default() =>() => 'foobar' 

die Mock in Ihrem Test verwenden:

// test/unit/specs/lib/loader.spec.js 
jest.mock('lib/bundle-loader') 
import Loader from 'lib/loader' 

describe('lib/loader',() => { 
    describe('Loader',() => { 
    it('should load',() => { 
     const loader = new Loader('[data-module]') 
     expect(loader).toBeInstanceOf(Loader) 
    }) 
    }) 
}) 
+0

Sehr gut. Aber wenn ich eigentlich die Originalmodule brauche? Ich denke, der einzige Ausweg ist die Verwendung meiner Implementierung in der Antwort (die auch nicht perfekt ist). IMO, ich bleibe, dass die beste Wahl ist, es zu stoppen. –