Closed johannesjo closed 7 years ago
There're a few things that need to be fixed in your config:
1.
// we use an index file which imports the other tests
Wallaby doesn't support it. You'll need to add a pattern that includes all tests (and exclude the index.spec.js
pattern). If the file is also initialising some stuff before running tests, then you may use entry patterns for the initialisation code.
You'll need to change
compilers: {
'./app/**/*.js': wallaby.compilers.babel(),
},
preprocessors: {
'**/*.js': file => require('babel-core')
.transform(file.content, {
sourceMap: true,
compact: false,
})
},
to
compilers: {
'**/*.js': wallaby.compilers.babel(),
}
as compiler will do the transpilation job, so no preprocessor is required. It's also safe to use the **/*.js
pattern as compiler is only running for files
/tests
and there's nothing else in there anyway.
The setup
function (that starts tests) is missing:
setup: function () {
// required to trigger test loading
window.__moduleBundler.loadTests();
}
Make sure that you remove babel-loader from your webpack config in wallaby config.
If after applying the fixes suggested above it still doesn't work for you, please share the updated wallaby config (that still doesn't work), the error message (if it has changed to something new), and your ./dev/config/webpack.config.test.js
file.
Thank you very much for your quick and helpful response! I adjusted my config as suggested. Now I'm running into new issues: Several times this occurred:
Runtime error: ReferenceError: Can't find variable: inject
and this:
Runtime error: Error: Cannot find module "../../../../bower_components/angular"
and this:
Runtime error: ReferenceError: Can't find variable: angular
The config file now looks like this:
// wallaby.conf.js
/* eslint-disable strict */
'use strict';
/* eslint-enable strict */
const webpackConfigTest = require('./dev/config/webpack.config.test');
const wallabyWebpack = require('wallaby-webpack');
const wallabyWebpackPostprocessor = wallabyWebpack(webpackConfigTest);
module.exports = (wallaby) => {
return {
localProjectDir: '',
files: [
{ pattern: 'app/**/*.js', load: false, },
{ pattern: 'app/**/*spec.js', ignore: true, },
],
tests: [
{ pattern: 'app/**/*spec.js', load: false, },
{ pattern: 'app/index.spec.js', ignore: true, },
],
testFramework: 'mocha',
compilers: {
'app/**/*.js': wallaby.compilers.babel(),
},
postprocessor: wallabyWebpackPostprocessor,
setup: function () {
// required to trigger test loading
window.__moduleBundler.loadTests();
},
}
};
Without seeing your ./dev/config/webpack.config.test.js
file, I may suggest it may be the issue with module directories. Try setting the absolute path to bower_components
as described in the referenced docs.
Specifying the moduleDirectories didn't do the trick. Here comes the webpack.config.test.js:
/* eslint-disable strict */
// Karma runs with node, which needs the use strict flag
// to use const, let, etc. Therefore disabling it here
'use strict';
/* eslint-enable strict */
const webpackConfig = require('./webpack.config.js');
const platformConfig = require('./platform.config.js');
const developmentSettings = {
defines: {
'process.env': {
NODE_ENV: JSON.stringify('testing'),
},
},
isparta: {
embedSource: true,
noAutoWrap: true,
babel: {
presets: ['es2015'],
},
},
reporters: ['mocha', 'coverage'],
coverageReporter: {
reporters: [
{
type: 'lcov',
dir: `${platformConfig.paths.reports}/coverage/`,
subdir: '.',
}, {
type: 'json',
dir: `${platformConfig.paths.reports}/coverage/`,
subdir: '.',
}, {
type: 'text-summary',
},
],
},
devtool: 'inline-source-map',
testing: true,
};
module.exports = webpackConfig(developmentSettings);
And this is the webpack.config.js:
/* eslint-disable strict */
// Karma runs with node, which needs the use strict flag
// to use const, let, etc. Therefore disabling it here
'use strict';
/* eslint-enable strict */
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const path = require('path');
const ModernizrWebpackPlugin = require('modernizr-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const saveLicense = require('uglify-save-license');
const modernizr = require('./modernizr.config.js');
const platformConfig = require('./platform.config.js');
const paths = platformConfig.paths;
/* ==========================================================================
General configs
========================================================================== */
const output = {
path: paths.dist,
publicPath: '/',
filename: '[name].js',
chunkFilename: '[name].chunk.js',
};
const nodeModules = path.resolve(__dirname, '../../node_modules');
const modulesDirectories = [
paths.vendor,
paths.src,
nodeModules,
path.resolve(__dirname, './'),
];
const dependenciesDirectories = [
paths.vendor,
];
const alias = {
angular: `${paths.vendor}/angular`,
lazysizes: `${paths.vendor}/lazysizes`,
picturefill: `${paths.vendor}/picturefill`,
raf: `${paths.vendor}/raf.js`,
svgxuse: `${paths.vendor}/svgxuse`,
molecules: path.resolve(__dirname, `${paths.src}/components/molecules`),
atoms: path.resolve(__dirname, `${paths.src}/components/atoms`),
};
const compression = {
asset: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$/,
threshold: 10240,
minRatio: 0.8,
};
/* ==========================================================================
Module loaders definition
========================================================================== */
function definePreLoaders(isTesting) {
const preLoaders = [];
if (isTesting) {
// Loads js files with isparta (files will be automatically transpiled)
preLoaders.push({
test: /\.js$/,
loader: 'isparta',
exclude: /(test|node_modules|bower_components|config|\.spec\.js)/,
include: platformConfig.paths.src,
});
}
return preLoaders;
}
const loaders = [{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
include: paths.src,
loaders: ['ng-annotate', 'babel-loader'],
}, {
test: /\.html$/,
loader: 'raw!html-minify',
}, {
test: /\.scss$/,
loader: 'style!css?postcss-loader!sass?sourceMap!',
}, {
test: /\.jpg/,
loader: 'url-loader?limit=10000&mimetype=image/jpg',
}, {
test: /\.gif/,
loader: 'url-loader?limit=10000&mimetype=image/gif',
}, {
test: /\.png/,
loader: 'url-loader?limit=10000&mimetype=image/png',
}, {
test: /\.svg/,
loader: 'url-loader?limit=10000&mimetype=image/svg',
}, {
test: /\.(woff|woff2|eot|ttf|svg)$/,
loader: 'file-loader?limit=100000&name=fonts/[name].[ext]',
}, {
test: /\.json$/,
loader: 'json-loader',
},
];
function postcss() {
const postCssPlugins = [];
postCssPlugins.push(autoprefixer({
browsers: platformConfig.browsers,
}));
return postCssPlugins;
}
/* ==========================================================================
Entry points definition
========================================================================== */
function defineEntry(isDevelopment, isStyleguide) {
const entryPlugins = [];
const webpackPlugins = [];
// When we use webpack, and we import a library in the code
// webpack will automatically add it to the bundle.
// However, we want to deliver two bundles, vendor and main.
// In order to do so, we need to clearly tell webpack, what is
// vendor and what is main. For that, we declare them here.
const angularLibs = [
`${paths.vendor}/angular/angular.js`,
`${paths.vendor}/angularjs-slider/dist/rzslider.min.js`,
`${paths.vendor}/angular-animate/angular-animate.js`,
`${paths.vendor}/angular-cookies/angular-cookies.js`,
`${paths.vendor}/angular-touch/angular-touch.js`,
`${paths.vendor}/angular-sanitize/angular-sanitize.js`,
`${paths.vendor}/angular-messages/angular-messages.js`,
`${paths.vendor}/angular-elastic/elastic.js`,
'ng-dialog',
];
// These libraries are not related to angular, these are polyfill that,
// when loaded in the page, they will be automatically executed
// generating the polyfill for whatever feature they are targeting to.
// We split them in a separate array, so we have the posibility to
// add them to the styleguide, and also load them quicker if it is
// required.
const vendor = [
`${paths.vendor}/picturefill/dist/picturefill.min.js`,
`${paths.vendor}/lazysizes/lazysizes.min.js`,
`${paths.vendor}/raf.js/raf.js`,
`${paths.vendor}/svgxuse/svgxuse.js`,
];
entryPlugins.push(`${paths.src}/core/scripts/${paths.main}`);
if (isDevelopment) {
// This will emulate a full ES2015 environment
entryPlugins.push('babel-polyfill');
// Necessary for hot reloading with IE
webpackPlugins.push('eventsource-polyfill');
}
let entry;
if (!isStyleguide) {
entry = {
'scripts/main': entryPlugins.concat(webpackPlugins),
'scripts/vendor': vendor.concat(angularLibs).concat(webpackPlugins),
};
} else {
entry = {
'styleguide/scripts/main': entryPlugins.concat(webpackPlugins),
'styleguide/scripts/vendor': vendor.concat(webpackPlugins),
};
}
return entry;
}
/* ==========================================================================
Plugins definition
========================================================================== */
function definePlugins(options) {
// More info about the webpack plugins here:
// https://github.com/webpack/docs/wiki/optimization
const plugins = [
// Avoid publishing files when compilation failed
new webpack.NoErrorsPlugin(),
new ModernizrWebpackPlugin(modernizr),
new webpack.optimize.OccurrenceOrderPlugin(true),
];
// Split the vendor dependencies into a separate file
if (!options.styleguide) {
plugins.push(new webpack.optimize.CommonsChunkPlugin('scripts/vendor', 'scripts/vendor.js'));
}
if (options.development) {
// Tell webpack we want hot reloading
plugins.push(new webpack.HotModuleReplacementPlugin());
} else {
// Aggressively remove duplicate modules.
// More info: http://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
plugins.push(new webpack.optimize.DedupePlugin());
}
if (options.environment) {
plugins.push(new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(options.environment),
},
}));
}
if (!(options.development || options.testing)) {
plugins.push(new webpack.optimize.UglifyJsPlugin({
output: {
comments: saveLicense,
},
compress: {
warnings: false,
},
// skip pre-minified libs
exclude: [/\.min\.js$/gi],
mangle: {
// You can specify all variables that should not be mangled.
// For example if your vendor dependency doesn't use modules
// and relies on global variables. Most of angular modules relies on
// angular global variable, so we should keep it unchanged
except: ['$super', '$', 'exports', 'require', 'angular'],
},
}));
}
// Add Compression Plugin
plugins.push(new CompressionPlugin(compression));
return plugins;
}
/**
* Creates the default configuration of webpack.
* It receives an object with parameters changing depending
* on the environment webpack needs to run.
* @param {object} options Object of parameters
* @param {boolean} options.development true if you want to have a development build
* @param {object} options.defines Object setting the environment
* @param {boolean} options.testing True if you are running the tests
* @param {string} options.environment The environment (for bundling defines)
* @return {object} Object of config settings
*/
function webpackConfig(options) {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
const plugins = (!options.testing) ? definePlugins(options) : [];
const entry = (!options.testing) ? defineEntry(options.development, options.styleguide) : {};
const preLoaders = definePreLoaders(options.testing);
const config = {
// For more info about this:
// http://webpack.github.io/docs/configuration.html
entry,
output,
watch: (options.development || options.testing),
// Cache generated modules and chunks to
// improve performance for multiple incremental builds.
cache: options.development || options.testing,
// Switch loaders to debug mode.
debug: options.development,
compress: true,
// http://webpack.github.io/docs/configuration.html#devtool
devtool: (options.development || options.testing) ? '#inline-source-map' : false,
module: {
loaders,
postcss,
preLoaders,
noParse: [
/(node_modules|bower_components|~)\/(min\.|jquery)\//gi,
],
},
resolve: {
modulesDirectories,
alias,
},
resolveLoader: {
dependenciesDirectories,
},
'html-minify-loader': {
// See possible options here:
// https://github.com/kangax/html-minifier#options-quick-reference
// And a recommendation for angular templates here:
// https://www.npmjs.com/package/grunt-angular-templates#htmlmin
collapseBooleanAttributes: true,
collapseWhitespace: true,
conservativeCollapse: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
},
plugins,
};
return config;
}
module.exports = webpackConfig;
Specifying the moduleDirectories didn't do the trick.
Could you please share the wallaby config version with specified modulesDirectories
(that didn't help)?
Does this const paths = platformConfig.paths;
return absolute paths?
It does seem like it:
// from the platform.config.js
paths: {
main: `${mainScript}.js`,
src: path.resolve(__dirname, '../../app'),
documentation: path.resolve(__dirname, '../../documentation'),
ngdocs: path.resolve(__dirname, '../../dist/ngdocs'),
dist: path.resolve(__dirname, '../../dist'),
styleguideSrc: path.resolve(__dirname, '../sc5'),
documentationSrc: path.resolve(__dirname, '../documentation-src'),
publicPath: '../../dist/',
vendor: path.resolve(__dirname, '../../bower_components'),
baseDir: 'dist',
reports: path.resolve(__dirname, '../../reports'),
mocks: path.resolve(__dirname, '../../mocks'),
tests: path.resolve(__dirname, '../../test'),
tmp: path.resolve(__dirname, '../../.tmp'),
server: path.resolve(__dirname, '../server'),
root: path.resolve(__dirname, '../../'),
dev: path.resolve(__dirname, '../'),
esIndexDir: path.resolve(`${__dirname}/../elasticsearch/index`),
}
Here is the updated wallaby.js:
// wallaby.conf.js
/* eslint-disable strict */
'use strict';
/* eslint-enable strict */
const webpackConfigTest = require('./dev/config/webpack.config.test');
const wallabyWebpack = require('wallaby-webpack');
const wallabyWebpackPostprocessor = wallabyWebpack(webpackConfigTest);
module.exports = (wallaby) => {
return {
localProjectDir: '',
modulesDirectories: [require('path').join(__dirname, 'bower_components')],
// I also tried 'bower_components'
files: [
{ pattern: 'app/**/*.js', load: false, },
{ pattern: 'app/**/*spec.js', ignore: true, },
],
tests: [
{ pattern: 'app/**/*spec.js', load: false, },
{ pattern: 'app/index.spec.js', ignore: true, },
],
testFramework: 'mocha',
compilers: {
'app/**/*.js': wallaby.compilers.babel(),
},
postprocessor: wallabyWebpackPostprocessor,
setup: function () {
// required to trigger test loading
window.__moduleBundler.loadTests();
},
}
};
modulesDirectories
is a webpack setting, not a wallaby setting. Try this:
const webpackConfigTest = require('./dev/config/webpack.config.test');
webpackConfigTest.resolve.modulesDirectories = [require('path').join(__dirname, 'bower_components')];
...
If it doesn't work, could you please share a sample project with your configs where I could reproduce the issue? It doesn't have to contain any real code/tests, the error seems to be configuration specific, not project code specific.
Thanks for pointing that out. I tried your snippet. The issue still persists.
I'm afraid that I can't really release an example project. The code is closed source and the project setup quite sophisticated (a little too sophisticated for my taste, but that's another topic).
I'm not sure about issue with inject, but the the other error (Runtime error: ReferenceError: Can't find variable: angular
) refers to instances where there is a simple import of a bower_component like this
import angular from 'angular';
The path in the error (Runtime error: Error: Cannot find module "../../../../bower_components/angular"
) seems to be correct, as the bower_components folder is 4 levels down from the file in question.
Could you please share the package.json
file? I'll try to reproduce it with what's available.
{
"name": "project",
"version": "0.0.0",
"description": "XXX",
"main": "gulpfile.babel.js",
"scripts": {
},
"keywords": [
],
"author": "XXX",
"license": "XXX",
"engines": {
"node": "~5.8.0 <6.0"
},
"engineStrict": true,
"dependencies": {
"angular-mocks": "^1.5.8",
"angular-moment": "^1.0.0",
"assemble": "^0.17.1",
"assemble-collections": "^0.2.1",
"assemble-handlebars-helpers": "^0.1.2",
"autoprefixer": "^6.5.0",
"babel": "^6.5.2",
"babel-core": "^6.16.0",
"babel-eslint": "^7.0.0",
"babel-istanbul-loader": "^0.1.0",
"babel-loader": "^6.2.5",
"babel-plugin-module-alias": "^1.6.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-polyfill": "^6.16.0",
"babel-preset-es2015": "^6.16.0",
"babel-register": "^6.16.0",
"bower": "^1.7.9",
"browser-sync": "^2.16.0",
"chai": "^3.5.0",
"compression": "^1.6.2",
"connect-gzip-static": "^1.0.0",
"css-loader": "^0.25.0",
"del": "^2.2.2",
"doiuse": "^2.5.0",
"engine-handlebars": "^0.8.0",
"eslint": "^3.6.1",
"eslint-config-airbnb-base": "^8.0.0",
"eslint-import-resolver-babel-module-alias": "^1.5.1",
"eslint-plugin-chai-expect": "^1.1.1",
"eslint-plugin-html": "^1.5.3",
"eslint-plugin-import": "^1.16.0",
"eventsource-polyfill": "^0.9.6",
"file-loader": "^0.9.0",
"gulp": "^3.9.1",
"gulp-cache": "^0.4.5",
"gulp-concat": "^2.6.0",
"gulp-csso": "^2.0.0",
"gulp-eslint": "^3.0.1",
"gulp-extname": "^0.2.2",
"gulp-html-angular-validate": "^0.2.0",
"gulp-htmllint": "0.0.11",
"gulp-htmlmin": "^3.0.0",
"gulp-if": "^2.0.1",
"gulp-imagemin": "^3.0.3",
"gulp-insert": "^0.5.0",
"gulp-jscs": "^4.0.0",
"gulp-load-plugins": "^1.3.0",
"gulp-newer": "^1.2.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^6.2.0",
"gulp-sass": "^2.3.2",
"gulp-sass-glob-2": "^1.0.8",
"gulp-size": "^2.1.0",
"gulp-sourcemaps": "^1.6.0",
"gulp-svgmin": "^1.2.3",
"gulp-uglify": "^2.0.0",
"gulp-useref": "^3.1.2",
"gulp-util": "^3.0.7",
"gulp-w3cjs": "^1.3.0",
"handlebars": "^4.0.5",
"handlebars-helpers": "^0.7.5",
"handlebars-wax": "^4.0.4",
"helper-markdown": "^0.2.1",
"isparta": "^4.0.0",
"isparta-loader": "^2.0.0",
"js-yaml": "^3.6.1",
"jscs": "^3.0.7",
"json-loader": "^0.5.4",
"karma": "^1.3.0",
"karma-chai": "^0.1.0",
"karma-coverage": "^1.1.1",
"karma-mocha": "^1.2.0",
"karma-mocha-reporter": "^2.2.0",
"karma-phantomjs-launcher": "^1.0.0",
"karma-sinon": "^1.0.5",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.8.0",
"lodash": "^4.16.2",
"mocha": "^3.1.0",
"moment": "^2.16.0",
"node-sass": "^3.10.0",
"postcss-loader": "^0.13.0",
"postcss-merge-idents": "^2.1.7",
"postcss-merge-rules": "^2.0.10",
"postcss-reporter": "^1.4.1",
"postcss-scss": "^0.3.0",
"postcss-will-change": "^1.1.0",
"protractor": "^4.0.9",
"psi": "^2.0.4",
"resolve-url-loader": "^1.6.0",
"run-sequence": "^1.2.2",
"sass-loader": "^4.0.2",
"sc5-styleguide": "^1.2.0",
"sinon": "^1.17.6",
"style-loader": "^0.13.1",
"stylelint": "^7.3.1",
"stylelint-scss": "^1.3.4",
"stylelint-selector-bem-pattern": "^1.0.0",
"url-loader": "^0.5.7",
"webpack": "^1.13.2"
},
"devDependencies": {
"bodybuilder": "^1.17.0",
"compression-webpack-plugin": "^0.3.2",
"dockerode": "^2.3.1",
"glob": "^7.1.0",
"gulp-batch": "^1.0.5",
"gulp-filter": "^4.0.0",
"gulp-gzip": "^1.4.0",
"gulp-inline": "^0.1.1",
"gulp-modify-css-urls": "^0.2.2",
"gulp-ngdocs": "^0.3.0",
"gulp-rename": "^1.2.2",
"gulp-rev": "^7.1.2",
"gulp-rev-replace": "^0.4.3",
"gulp-svgstore": "^6.0.0",
"gulp-watch": "^4.3.10",
"html-minify-loader": "^1.1.0",
"http-proxy": "^1.15.2",
"js-beautify": "^1.6.4",
"mime-types": "^2.1.12",
"modernizr-webpack-plugin": "^1.0.5",
"ng-annotate-loader": "^0.2.0",
"node-fetch": "^1.6.3",
"npmlog": "^4.0.0",
"qq": "^0.3.5",
"raw-loader": "^0.5.1",
"semver": "^5.3.0",
"uglify-save-license": "^0.4.1"
}
}
If you need more information, just ask!
Thanks. So I have created this sample repo with your file structure and your config files, and a single test, and everything is working for me. Please have a look and try it, if it works, try adding your project specific configs I might have missed to reproduce the issue.
Thank you for your effort. The problem is not with imports inside the test files, but inside the actual components. Have a look at my fork: https://github.com/johannesjo/wallaby-887
The issue was actually related to your .babelrc
. For some reason it transforms all imports fro a few bower components from being normal module imports (that webpack resolves anyway), to be relative imports. When running in wallaby.js cache, there's no bower_components
, hence the error. You may either remove those module-alias
that point to bower componebts from your .babelrc
(it shouldn't change how your build works anyway), or just do it in wallaby config.
We seem to be almost there. The issue with inject still persists though: https://github.com/johannesjo/wallaby-887
Thanks for updating the repo. I can see these 2 errors:
ReferenceError: Can't find variable: inject
at app/a.spec.js:4
at app/a.spec.js:3
ReferenceError: Can't find variable: angular
at app/components/atoms/buttonBack/buttonBack.spec.js:2
at app/components/atoms/buttonBack/buttonBack.spec.js:1
however, they make sense to me. Angular mocks module (that defines inject
and angular.mock
) is not loaded anywhere, and not imported it inside those 2 files, so the errors are expected. If you add:
import 'angular';
import 'angular-mocks';
to those 2 files with errors, it'll start working. If you don't do this in your real app tests, then you're probably doing it somewhere else, perhaps, like I was suggesting earlier, in your index.spec.js
:
If the file is also initialising some stuff before running tests, then you may use entry patterns for the initialisation code.
So as the docs suggest, you may add a file that does the initialisation for all of your tests. I have updated the sample repo to demonstrate it in action.
Thank you very much again! I still have some minor issues (somehow the setupTests.js needs to be in the app folder and can't be at the root and the error Can't find variable: Symbol
) but I will try to figure it out on Monday by myself first and post the updated config then.
somehow the setupTests.js needs to be in the app folder
Should be able to place it anywhere, just need to reflect the location the files
and entryPatterns
lists in the config.
Can't find variable: Symbol
Sounds like a missing babel-polyfill loading.
files: [
{ pattern: 'node_modules/babel-polyfill/dist/polyfill.js', instrument: false },
...
],
Thanks again for everything! Everything works now as it should.
Issue description or question
I can't get my webpack es6 combination to work. For all my test files the error
Runtime error: SyntaxError: Use of reserved word 'import'
keeps popping up.When I click on the link to the affected file, something like this is shown:
Wallaby.js configuration file
Code editor or IDE name and version
IntelliJ IDEA 2016.3 EAP
OS name and version
Ubuntu 16.04