Skip to content

Commit

Permalink
Merge pull request #697 from relative-ci/update-validation
Browse files Browse the repository at this point in the history
fix(utils): Validate webpack stats structure
  • Loading branch information
vio authored Apr 10, 2020
2 parents 510ab7d + c2f2ba6 commit 329a5f9
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 23 deletions.
4 changes: 1 addition & 3 deletions packages/utils/locales.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
{
"INVALID": "Invalid webpack source structure, please make sure webpack stats configuration is correct.",
"MISSING_ASSETS": "Assets property is missing!",
"MISSING_MODULES": "Modules property is missing!"
"INVALID": "Invalid webpack stats structure, please make sure webpack stats configuration is correct."
}
17 changes: 15 additions & 2 deletions packages/utils/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"homepage": "https://github.com/relative-ci/bundle-stats/blob/master/packages/utils#readme",
"dependencies": {
"convert-units": "^2.3.4",
"core-js": "^3.1.4"
"core-js": "^3.1.4",
"superstruct": "^0.8.3"
},
"devDependencies": {
"@babel/cli": "7.8.4",
Expand Down
60 changes: 54 additions & 6 deletions packages/utils/src/webpack/__tests__/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,65 @@ import { validate } from '../validate';
describe('Webpack/validate', () => {
test('should return empty string if valid', () => {
const webpackSource = {
assets: [],
modules: [],
chunks: [],
assets: [
{
name: 'main.js',
size: 100,
emitted: true,
chunks: [1, 2],
},
],
};

expect(validate(webpackSource)).toEqual('');
expect(validate({ ...webpackSource, modules: [] })).toEqual('');
expect(
validate({
...webpackSource,
modules: [
{
name: 'node_modules/package-a/main.js',
size: 10,
chunks: [1],
},
],
}),
).toEqual('');
expect(validate({ ...webpackSource, chunks: [] })).toEqual('');
expect(
validate({
...webpackSource,
chunks: [
{
names: ['main'],
entry: true,
initial: true,
id: 1,
files: ['main.js'],
},
],
}),
).toEqual('');
});

test('should return message if data is missing', () => {
expect(validate()).toBeTruthy();
expect(validate({})).toBeTruthy();
expect(validate({ assets: [] })).toBeTruthy();
expect(validate()).toMatch(/assets,modules,chunks/);
expect(validate({})).toMatch(/name,size/);
expect(validate({ assets: [] })).toMatch(/notEmptyArray/);
expect(validate({ assets: [{}] })).toMatch(/name,size/);
expect(validate({ assets: [{ size: 100 }] })).toMatch(/name,size/);
expect(
validate({
assets: [{ name: 'main.js', size: 100 }],
modules: [{ name: 'module-a' }],
}),
).toMatch(/name,size/);
expect(
validate({
assets: [{ name: 'main.js', size: 100 }],
modules: [{ name: 'module-a', size: 10, chunks: [1] }],
chunks: [{ id: 1 }],
}),
).toMatch(/id,entry,initial/);
});
});
1 change: 1 addition & 0 deletions packages/utils/src/webpack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export * from './extract';
export * from './filter';
export * from './metrics';
export * from './selectors';
export * from './struct';
export * from './utils';
export * from './validate';
34 changes: 34 additions & 0 deletions packages/utils/src/webpack/struct.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { superstruct } from 'superstruct';

const struct = superstruct({
types: {
notEmptyArray: (value) => value?.length > 0,
},
});

export const WebpackSourceAssetStruct = struct.interface({
name: 'string',
size: 'number',
});

export const WebpackSourceModuleChunk = struct.interface({
name: 'string',
size: 'number',
chunks: [struct.union(['number', 'string'])],
});

export const WebpackSourceChunkStruct = struct.interface({
id: struct.union(['number', 'string']),
entry: 'boolean',
initial: 'boolean',
names: ['string'],
files: ['string'],
});

export const WebpackSourceStruct = struct.interface({
hash: struct.optional('string'),
builtAt: struct.optional('number'),
assets: struct.intersection([[WebpackSourceAssetStruct], 'notEmptyArray']),
modules: struct.optional([WebpackSourceModuleChunk]),
chunks: struct.optional([WebpackSourceChunkStruct]),
});
20 changes: 9 additions & 11 deletions packages/utils/src/webpack/validate.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { INVALID, MISSING_ASSETS, MISSING_MODULES } from '../../locales.json';
import { INVALID } from '../../locales.json';
import { WebpackSourceStruct } from './struct';

/**
* Validate webpack source
*
* @param {Object} [webpackSource]
* @return {String} Message, if invalid, empty string if valid
*/
export const validate = (webpackSource) => {
if (!webpackSource) {
return INVALID;
}

if (!webpackSource.assets) {
return `${MISSING_ASSETS}\n${INVALID}`;
}

if (!webpackSource.modules) {
return `${MISSING_MODULES}\n${INVALID}`;
try {
WebpackSourceStruct(webpackSource);
} catch (err) {
const { path, type } = err;
const key = path[0];
return `${INVALID}\n\nExpected a value of type \`${type}\` for \`${key}\``;
}

return '';
Expand Down

0 comments on commit 329a5f9

Please sign in to comment.