Skip to content

Commit 14e0b27

Browse files
committed
feature #371 Add formatter and transformer for module not found error (BackEndTea)
This PR was squashed before being merged into the master branch (closes #371). Discussion ---------- Add formatter and transformer for module not found error Fixes #351 I don't work with js much, so any feedback is appreciated. Commits ------- f496cbf Fix copy paste errors and use template literals eb4dee5 Add formatter and transformer for module not found error
2 parents 656263d + f496cbf commit 14e0b27

File tree

6 files changed

+194
-3
lines changed

6 files changed

+194
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* This file is part of the Symfony Webpack Encore package.
3+
*
4+
* (c) Fabien Potencier <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
'use strict';
11+
12+
const chalk = require('chalk');
13+
14+
function formatErrors(errors) {
15+
if (errors.length === 0) {
16+
return [];
17+
}
18+
19+
let messages = [];
20+
21+
messages.push(
22+
chalk.red('Module build failed: Module not found:')
23+
);
24+
for (let error of errors) {
25+
messages.push(`${error.file} contains a reference to the file ${error.ref}.`);
26+
messages.push('This file can not be found, please check it for typos or update it if the file got moved.');
27+
messages.push('');
28+
}
29+
30+
return messages;
31+
}
32+
33+
function format(errors) {
34+
return formatErrors(errors.filter((e) => (
35+
e.type === 'missing-css-file'
36+
)));
37+
}
38+
39+
module.exports = format;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* This file is part of the Symfony Webpack Encore package.
3+
*
4+
* (c) Fabien Potencier <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
'use strict';
11+
12+
const TYPE = 'missing-css-file';
13+
14+
function isMissingConfigError(e) {
15+
if (e.name !== 'ModuleNotFoundError') {
16+
return false;
17+
}
18+
19+
if (e.message.indexOf('Module not found: Error: Can\'t resolve') === -1) {
20+
return false;
21+
}
22+
23+
return true;
24+
}
25+
26+
function getReference(error) {
27+
const index = error.message.indexOf('Can\'t resolve \'') + 15;
28+
const endIndex = error.message.indexOf('\' in \'');
29+
30+
return error.message.substring(index, endIndex);
31+
}
32+
33+
function transform(error) {
34+
if (!isMissingConfigError(error)) {
35+
return error;
36+
}
37+
38+
error = Object.assign({}, error);
39+
40+
error.type = TYPE;
41+
error.ref = getReference(error);
42+
error.severity = 900;
43+
44+
return error;
45+
}
46+
47+
module.exports = transform;

lib/plugins/friendly-errors.js

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
'use strict';
1111

1212
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
13+
const missingCssFileTransformer = require('../friendly-errors/transformers/missing-css-file');
14+
const missingCssFileFormatter = require('../friendly-errors/formatters/missing-css-file');
1315
const missingLoaderTransformer = require('../friendly-errors/transformers/missing-loader');
1416
const missingLoaderFormatter = require('../friendly-errors/formatters/missing-loader');
1517
const missingPostCssConfigTransformer = require('../friendly-errors/transformers/missing-postcss-config');
@@ -24,10 +26,12 @@ module.exports = function(webpackConfig) {
2426
const friendlyErrorsPluginOptions = {
2527
clearConsole: false,
2628
additionalTransformers: [
29+
missingCssFileTransformer,
2730
missingLoaderTransformer,
2831
missingPostCssConfigTransformer
2932
],
3033
additionalFormatters: [
34+
missingCssFileFormatter,
3135
missingLoaderFormatter,
3236
missingPostCssConfigFormatter
3337
],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This file is part of the Symfony Webpack Encore package.
3+
*
4+
* (c) Fabien Potencier <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
'use strict';
11+
12+
const expect = require('chai').expect;
13+
const formatter = require('../../../lib/friendly-errors/formatters/missing-css-file');
14+
15+
describe('formatters/missing-css-file', () => {
16+
17+
describe('test format()', () => {
18+
it('works with no errors', () => {
19+
const actualErrors = formatter([]);
20+
expect(actualErrors).to.be.empty;
21+
});
22+
23+
it(' filters errors that dont have the correct type', () => {
24+
const errors = [
25+
{ type: 'missing-css-file', file: 'some-file.sass', ref: '../images/foo.png' },
26+
{ type: 'other-type', file: 'other-type.sass' }
27+
];
28+
29+
const actualErrors = formatter(errors);
30+
expect(JSON.stringify(actualErrors)).to.contain('some-file.sass');
31+
expect(JSON.stringify(actualErrors)).to.not.contain('other-type.sass');
32+
});
33+
34+
it('formats the error correctly', () => {
35+
const error = {
36+
type: 'missing-css-file',
37+
file: '/some/file.css',
38+
ref: '../images/foo.png'
39+
};
40+
41+
const actualErrors = formatter([error]);
42+
expect(JSON.stringify(actualErrors)).to.contain('/some/file.css contains a reference to the file ../images/foo.png');
43+
expect(JSON.stringify(actualErrors)).to.contain('This file can not be found, please check it for typos or update it if the file got moved.');
44+
// all needed packages will be present when running tests
45+
expect(JSON.stringify(actualErrors)).to.not.contain('yarn add');
46+
});
47+
});
48+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* This file is part of the Symfony Webpack Encore package.
3+
*
4+
* (c) Fabien Potencier <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
'use strict';
11+
12+
const expect = require('chai').expect;
13+
const transform = require('../../../lib/friendly-errors/transformers/missing-css-file');
14+
15+
describe('transform/missing-css-file', () => {
16+
17+
describe('test transform', () => {
18+
it('Error not with "ModuleNotFoundError" name is ignored', () => {
19+
const startError = {
20+
name: 'OtherParseError',
21+
message: 'You may need an appropriate loader',
22+
file: '/path/to/file.sass'
23+
};
24+
const actualError = transform(Object.assign({}, startError));
25+
26+
expect(actualError).to.deep.equal(startError);
27+
});
28+
29+
it('Error not containing "Module not found: Error: Can\'t resolve" is ignored', () => {
30+
const startError = {
31+
name: 'ModuleNotFoundError',
32+
message: 'Some other message',
33+
file: '/path/to/file.sass'
34+
};
35+
const actualError = transform(Object.assign({}, startError));
36+
37+
expect(actualError).to.deep.equal(startError);
38+
});
39+
40+
it('Matching error is properly transformed', () => {
41+
const startError = {
42+
name: 'ModuleNotFoundError',
43+
message: 'Module build failed: ModuleNotFoundError: Module not found: Error: Can\'t resolve \'./../images/symfony_logo.png2\' in \'/Users/weaverryan/Sites/os/webpack-encore/tmp_project_playing/css\'',
44+
file: '/Users/weaverryan/Sites/os/webpack-encore/tmp_project_playing/css'
45+
};
46+
const actualError = transform(Object.assign({}, startError));
47+
48+
expect(actualError.ref).to.deep.equal('./../images/symfony_logo.png2');
49+
expect(actualError.type).to.deep.equal('missing-css-file');
50+
expect(actualError.file).to.deep.equal('/Users/weaverryan/Sites/os/webpack-encore/tmp_project_playing/css');
51+
});
52+
});
53+
});

test/plugins/friendly-errors.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ describe('plugins/friendly-errors', () => {
3030
const plugin = friendlyErrorsPluginUtil(config);
3131
expect(plugin).to.be.instanceof(FriendlyErrorsWebpackPlugin);
3232
expect(plugin.shouldClearConsole).to.equal(false);
33-
expect(plugin.formatters.length).to.equal(5);
34-
expect(plugin.transformers.length).to.equal(5);
33+
expect(plugin.formatters.length).to.equal(6);
34+
expect(plugin.transformers.length).to.equal(6);
3535
});
3636

3737
it('with options callback', () => {
@@ -46,7 +46,7 @@ describe('plugins/friendly-errors', () => {
4646
expect(plugin).to.be.instanceof(FriendlyErrorsWebpackPlugin);
4747
expect(plugin.shouldClearConsole).to.equal(true);
4848
expect(plugin.formatters.length).to.equal(3);
49-
expect(plugin.transformers.length).to.equal(5);
49+
expect(plugin.transformers.length).to.equal(6);
5050
});
5151

5252
it('with options callback that returns an object', () => {

0 commit comments

Comments
 (0)