Создать тестовую точку входа в приложение для обработки webpack

TL;DR: я могу require все, чтобы приложение выполнялось, но если я require модулей из теста (который находится в приложении - см. структуру dir ниже) файл, целая цепочка зависимостей прерывается.

У меня возникли трудности с require -интервалком компонентов из моего каталога app/test (в приложении для webpack React.js) ниже, что я не испытываю трудности с require -из из любого другого файла в /app папка. Это структура каталогов

app
  /components/checkout.jsx
  /components/button.jsx
  /test/test.js 
  index.jsx  
dist
node_modules
webpack.config.js
package.json

в моем webpack.config.js, у меня есть настройка для использования jsx-loader для моего приложения React вроде этого

entry: {
   app: "./app/index"
},
module: {
   loaders: [
        {
             test: /\.jsx$/,
             loader: 'jsx-loader?insertPragma=React.DOM&harmony',
     }
  ]
},
resolve: {
 extensions: ['', '.js', '.jsx']
}

Это позволяет мне требовать файлы, заканчивающиеся на расширение .jsx. Например, в /app/index.jsx мне требуется /app/components/checkout.jsx, выполняя

 var Checkout = require('./components/Checkout')

И внутри /app/components/checkout.jsx требуется кнопка

var Button = require('./components/Button')

поэтому, когда я требую Checkout из index.jsx, он без проблем справляется с требованием кнопки.

Однако, из app/test/test.js, я делаю

var Checkout = require('../components/Checkout')

и веб-пакет не может найти компонент Checkout. Когда я просматриваю тесты на сервере webpack dev, он не показывает, что искалось расширение .jsx. Он искал

 app/components/Checkout
 app/components/Checkout.webpack.js
 app/components/Checkout.web.js
 app/components/Checkout.js
 app/components/Checkout.json

Поэтому я попытался использовать jsx-loader inline, как этот

 var Checkout = require(jsx-loader!'../components/Checkout')

из тестового каталога, и webpack теперь может найти файл, но он выдает сообщение об ошибке, говоря, что он не может разрешить кнопку Checkout requires. Другими словами, когда я использую require изнутри папки app/test, вся цепочка зависимостей выбрасывается из синхронизации.

Как я могу изменить свой файл webpack.config.js, чтобы иметь возможность требовать файлы приложений в моих тестах с этой структурой каталогов или, в более общем плане, как настроить веб-пакет для запроса файла приложения в тесте?

Update

Структура проекта

/app
  /test/test.js
  /index.jsx
  /components/checkout.jsx (and button.jsx)
/dist
/node_modules
package.json
webpack.config.js

полная версия веб-пакета

var webpack = require('webpack');
module.exports = {
    context: __dirname + "/app",
    entry: {
      vendors: ["d3", "jquery"],
      app: "index"
      // app: "./app/index"

      },
    output: {
        path: './dist',
        filename: 'bundle.js', //this is the default name, so you can skip it
        //at this directory our bundle file will be available
        //make sure port 8090 is used when launching webpack-dev-server
        publicPath: 'http://localhost:8090/assets/'
    },

    externals: {
        //don't bundle the 'react' npm package with our bundle.js
        //but get it from a global 'React' variable

        'react': 'React'
        // 'd3': 'd3'
    },
    resolve: {
        modulesDirectories: ['app', 'node_modules'],
        extensions: ['', '.js', '.jsx'],
        resolveLoader: { fallback: __dirname + "/node_modules" },
        root: ['/app', '/test']
    },
    module: {
        loaders: [
            {
              test: /\.jsx$/, 
              loader: 'jsx-loader?insertPragma=React.DOM&harmony',
            }
        ]
    },

    plugins: [
    // definePlugin,
    new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js')

    ]
}

Ответ 1

Одним из возможных решений может быть требование всегда с расширением файла:

var Checkout = require('./components/Checkout.jsx')

Ответ 2

Я думаю, это может быть связано с установкой "test" в качестве корневого каталога. Но это не ясно, пока вы не разделите свой код. Можете ли вы дать ссылку на репозиторий GitHub или что-то еще?

Ответ 3

Я вижу, что вы используете параметр гармонии, могу ли я предположить, что вы используете, es6?

Если бы у меня была эта проблема раньше, проблема для меня заключалась в том, что файлы, которые были добавлены, как es6 без преобразования, в es5 с помощью jsx-loader/babel-loader.

поэтому мне нужно было добавить:

preLoaders: [{
    test: [/\.jsx$/, /\.js$/],
    include: // modules here
    loaders: ['babel-loader?optional[]=runtime']
}]

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

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

(resolveLoader: { root: path.join(__dirname, "node_modules") })

надеюсь, что это поможет

изменить: ps, глядя на вашу конфигурацию, resolLoader не должен быть частью вашего решения, в другой настройке webpack, которую я использую, у меня есть следующая настройка для разрешения:

resolve: {
  extensions: ['', '.js', '.jsx', '.json'],
  modulesDirectories: ['node_modules', 'node_modules/vl_tooling/node_modules']
},
resolveLoader: {
  modulesDirectories: ['node_modules', 'node_modules/vl_tooling/node_modules']
},

Ответ 4

Я настраиваю отдельную задачу gulp для запуска тестов React, возможно, вы можете повторно использовать идею:

karma.js

var karma = require('gulp-karma'),
  _ = require('lodash'),
  Promise = require('bluebird'),
  plumber = require('gulp-plumber'),
  path = require('path'),
  webpack = require('gulp-webpack'),
  named = require('vinyl-named');

module.exports = function (gulp, options) {
  var root = path.join(options.cwd, 'app'),
    extensions = ['', '.js', '.jsx'],
    modulesDirectories = ['node_modules'];

  gulp.task('karma', ['karma:build'], function () {
    return runAllTests(gulp, options);
  });

  gulp.task('karma:build', function() {
    var optionsForTests = _.merge({
      ignore: ['**/node_modules/**']
    }, options);

    return gulp.src(['**/__tests__/*.js'], optionsForTests).
      pipe(named(function(file){
        // name file bundle.js
        return 'bundle';
      })).
      pipe(webpack({
        module: {
          loaders: [
              // runtime option adds Object.assign support
              { test: /\.(js|jsx)$/, loader: 'babel-loader?optional[]=runtime', exclude: /node_modules/},
              { test: /\.(sass|scss)$/, loader: 'css-loader!sass-loader'},
              { test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/, loader: 'url-loader'},
              { test: /\.(ttf|eot)$/, loader: 'file-loader'},
              { test: /sinon.*\.js$/, loader: 'imports?define=>false' } // hack due to https://github.com/webpack/webpack/issues/304
          ]
        },
        resolve: {
          root: root,
          extensions: extensions,
          modulesDirectories: modulesDirectories
        }
      })).
      pipe(gulp.dest('test-build'));
  })

}

function runAllTests(gulp, options) {
  var optionsForTests = _.merge({
    ignore: ['**/node_modules/**']
  }, options);

  return new Promise(function (resolve, reject) {
    var karmaConfig = path.join(path.resolve(__dirname, '..'), 'karma.conf.js');

    // shim Prototype.function.bind in PhantomJS 1.x
    var testFiles = [
      'node_modules/es5-shim/es5-shim.min.js',
      'node_modules/es5-shim/es5-sham.min.js',
      'test-build/bundle.js'];

    gulp.src(testFiles).
      pipe(plumber({
        errorHandler: function (error) {
          console.log(error);
          this.emit('end');
        }
      })).
      pipe(karma({
        configFile: karmaConfig,
        action: 'run'
      })).
      on('end', function () { resolve(); });
  });
}

Gulp файл:

var gulp = require('gulp');
var auctionataBuild = require('auctionata-build');
var path = require('path');

auctionataBuild.tasks.karma(gulp, {
  cwd: path.resolve(__dirname)
});

Выполнить из терминала:

 gulp karma