add tests
Summary: Tests for things introduced over the last 10 weeks Reviewed By: cpojer Differential Revision: D4442404 fbshipit-source-id: cf7a14f237360fde083b7e2ffcd9d70aafd0ced6
This commit is contained in:
parent
212d31e322
commit
2ab7988cbe
|
@ -96,7 +96,6 @@ function* concat<T>(...iterables: Array<Iterable<T>>): Iterable<T> {
|
||||||
|
|
||||||
function prelude(optimize) {
|
function prelude(optimize) {
|
||||||
return virtualModule(
|
return virtualModule(
|
||||||
`var __DEV__= ${String(!optimize)
|
`var __DEV__=${String(!optimize)},__BUNDLE_START_TIME__=Date.now();`
|
||||||
}, __BUNDLE_START_TIME__ = Date.now();`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
jest.disableAutomock();
|
||||||
|
|
||||||
|
const ModuleGraph = require('../ModuleGraph');
|
||||||
|
const defaults = require('../../../../defaults');
|
||||||
|
|
||||||
|
const FILE_TYPE = 'module';
|
||||||
|
|
||||||
|
describe('build setup', () => {
|
||||||
|
const buildSetup = ModuleGraph.createBuildSetup(graph);
|
||||||
|
const noOptions = {};
|
||||||
|
const noEntryPoints = [];
|
||||||
|
|
||||||
|
it('adds a prelude containing start time and `__DEV__` to the build', done => {
|
||||||
|
buildSetup(noEntryPoints, noOptions, (error, result) => {
|
||||||
|
expect(error).toEqual(null);
|
||||||
|
|
||||||
|
const [prelude] = result.modules;
|
||||||
|
expect(prelude).toEqual({
|
||||||
|
dependencies: [],
|
||||||
|
file: {
|
||||||
|
code: 'var __DEV__=true,__BUNDLE_START_TIME__=Date.now();',
|
||||||
|
path: '',
|
||||||
|
type: 'script',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets `__DEV__` to false in the prelude if optimization is enabled', done => {
|
||||||
|
buildSetup(noEntryPoints, {optimize: true}, (error, result) => {
|
||||||
|
const [prelude] = result.modules;
|
||||||
|
expect(prelude.file.code)
|
||||||
|
.toEqual('var __DEV__=false,__BUNDLE_START_TIME__=Date.now();');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('places the module system implementation directly after the prelude', done => {
|
||||||
|
buildSetup(noEntryPoints, noOptions, (error, result) => {
|
||||||
|
const [, moduleSystem] = result.modules;
|
||||||
|
expect(moduleSystem).toEqual({
|
||||||
|
dependencies: [],
|
||||||
|
file: {
|
||||||
|
code: '',
|
||||||
|
path: defaults.moduleSystem,
|
||||||
|
type: FILE_TYPE,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('places polyfills after the module system', done => {
|
||||||
|
buildSetup(noEntryPoints, noOptions, (error, result) => {
|
||||||
|
const polyfills =
|
||||||
|
Array.from(result.modules).slice(2, 2 + defaults.polyfills.length);
|
||||||
|
expect(polyfills).toEqual(defaults.polyfills.map(moduleFromPath));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('places all modules from `defaults.runBeforeMainModule` after the polyfills', done => {
|
||||||
|
buildSetup(noEntryPoints, noOptions, (error, result) => {
|
||||||
|
const additionalModules =
|
||||||
|
Array.from(result.modules).slice(-defaults.runBeforeMainModule.length);
|
||||||
|
expect(additionalModules)
|
||||||
|
.toEqual(defaults.runBeforeMainModule.map(moduleFromPath));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('places all entry points at the end', done => {
|
||||||
|
const entryPoints = ['a', 'b', 'c'];
|
||||||
|
buildSetup(entryPoints, noOptions, (error, result) => {
|
||||||
|
expect(Array.from(result.modules).slice(-3))
|
||||||
|
.toEqual(entryPoints.map(moduleFromPath));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('concatenates `runBeforeMainModule` and entry points as `entryModules`', done => {
|
||||||
|
const entryPoints = ['a', 'b', 'c'];
|
||||||
|
buildSetup(entryPoints, noOptions, (error, result) => {
|
||||||
|
expect(Array.from(result.entryModules)).toEqual(
|
||||||
|
defaults.runBeforeMainModule.concat(entryPoints).map(moduleFromPath));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function moduleFromPath(path) {
|
||||||
|
return {
|
||||||
|
dependencies: [],
|
||||||
|
file: {
|
||||||
|
code: '',
|
||||||
|
path,
|
||||||
|
type: FILE_TYPE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function graph(entryPoints, platform, options, callback) {
|
||||||
|
const modules = Array.from(entryPoints, moduleFromPath);
|
||||||
|
callback(null, {
|
||||||
|
entryModules: modules,
|
||||||
|
modules,
|
||||||
|
});
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const generate = require('babel-generator').default;
|
||||||
const stub = require('sinon/lib/sinon/stub');
|
const stub = require('sinon/lib/sinon/stub');
|
||||||
|
|
||||||
exports.fn = () => {
|
exports.fn = () => {
|
||||||
|
@ -16,3 +17,7 @@ exports.fn = () => {
|
||||||
f.stub = s;
|
f.stub = s;
|
||||||
return f;
|
return f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const generateOptions = {concise: true};
|
||||||
|
exports.codeFromAst = ast => generate(ast, generateOptions).code;
|
||||||
|
exports.comparableCode = code => code.trim().replace(/\s\s+/g, ' ');
|
||||||
|
|
133
packager/react-packager/src/ModuleGraph/worker/__tests__/collect-dependencies-test.js
vendored
Normal file
133
packager/react-packager/src/ModuleGraph/worker/__tests__/collect-dependencies-test.js
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
jest.disableAutomock();
|
||||||
|
|
||||||
|
const collectDependencies = require('../collect-dependencies');
|
||||||
|
const astFromCode = require('babylon').parse;
|
||||||
|
const {codeFromAst, comparableCode} = require('../../test-helpers');
|
||||||
|
|
||||||
|
const {any} = expect;
|
||||||
|
|
||||||
|
describe('dependency collection from ASTs:', () => {
|
||||||
|
it('collects dependency identifiers from the code', () => {
|
||||||
|
const ast = astFromCode(`
|
||||||
|
const a = require('b/lib/a');
|
||||||
|
exports.do = () => require("do");
|
||||||
|
if (!something) {
|
||||||
|
require("setup/something");
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
expect(collectDependencies(ast).dependencies)
|
||||||
|
.toEqual(['b/lib/a', 'do', 'setup/something']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports template literals as arguments', () => {
|
||||||
|
const ast = astFromCode('require(`left-pad`)');
|
||||||
|
|
||||||
|
expect(collectDependencies(ast).dependencies)
|
||||||
|
.toEqual(['left-pad']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores template literals with interpolations', () => {
|
||||||
|
const ast = astFromCode('require(`left${"-"}pad`)');
|
||||||
|
|
||||||
|
expect(collectDependencies(ast).dependencies)
|
||||||
|
.toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores tagged template literals', () => {
|
||||||
|
const ast = astFromCode('require(tag`left-pad`)');
|
||||||
|
|
||||||
|
expect(collectDependencies(ast).dependencies)
|
||||||
|
.toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('exposes a string as `dependencyMapName`', () => {
|
||||||
|
const ast = astFromCode('require("arbitrary")');
|
||||||
|
expect(collectDependencies(ast).dependencyMapName)
|
||||||
|
.toEqual(any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('exposes a string as `dependencyMapName` even without collecting dependencies', () => {
|
||||||
|
const ast = astFromCode('');
|
||||||
|
expect(collectDependencies(ast).dependencyMapName)
|
||||||
|
.toEqual(any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('replaces all required module ID strings with array lookups and keeps the ID as second argument', () => {
|
||||||
|
const ast = astFromCode(`
|
||||||
|
const a = require('b/lib/a');
|
||||||
|
const b = require(123);
|
||||||
|
exports.do = () => require("do");
|
||||||
|
if (!something) {
|
||||||
|
require("setup/something");
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const {dependencyMapName} = collectDependencies(ast);
|
||||||
|
|
||||||
|
expect(codeFromAst(ast)).toEqual(comparableCode(`
|
||||||
|
const a = require(${dependencyMapName}[0], 'b/lib/a');
|
||||||
|
const b = require(123);
|
||||||
|
exports.do = () => require(${dependencyMapName}[1], "do");
|
||||||
|
if (!something) {
|
||||||
|
require(${dependencyMapName}[2], "setup/something");
|
||||||
|
}
|
||||||
|
`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Dependency collection from optimized ASTs:', () => {
|
||||||
|
const dependencyMapName = 'arbitrary';
|
||||||
|
const {forOptimization} = collectDependencies;
|
||||||
|
let ast, names;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
ast = astFromCode(`
|
||||||
|
const a = require(${dependencyMapName}[0], 'b/lib/a');
|
||||||
|
const b = require(123);
|
||||||
|
exports.do = () => require(${dependencyMapName}[1], "do");
|
||||||
|
if (!something) {
|
||||||
|
require(${dependencyMapName}[2], "setup/something");
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
names = ['b/lib/a', 'do', 'setup/something'];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes the `dependencyMapName` through', () => {
|
||||||
|
const result = forOptimization(ast, names, dependencyMapName);
|
||||||
|
expect(result.dependencyMapName).toEqual(dependencyMapName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the list of passed in dependencies', () => {
|
||||||
|
const result = forOptimization(ast, names, dependencyMapName);
|
||||||
|
expect(result.dependencies).toEqual(names);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('only returns dependencies that are in the code', () => {
|
||||||
|
ast = astFromCode(`require(${dependencyMapName}[1], 'do')`);
|
||||||
|
const result = forOptimization(ast, names, dependencyMapName);
|
||||||
|
expect(result.dependencies).toEqual(['do']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('replaces all call signatures inserted by a prior call to `collectDependencies`', () => {
|
||||||
|
forOptimization(ast, names, dependencyMapName);
|
||||||
|
expect(codeFromAst(ast)).toEqual(comparableCode(`
|
||||||
|
const a = require(${dependencyMapName}[0]);
|
||||||
|
const b = require(123);
|
||||||
|
exports.do = () => require(${dependencyMapName}[1]);
|
||||||
|
if (!something) {
|
||||||
|
require(${dependencyMapName}[2]);
|
||||||
|
}
|
||||||
|
`));
|
||||||
|
});
|
||||||
|
});
|
|
@ -28,12 +28,14 @@ class Replacement {
|
||||||
isRequireCall(callee, firstArg) {
|
isRequireCall(callee, firstArg) {
|
||||||
return (
|
return (
|
||||||
callee.type === 'Identifier' && callee.name === 'require' &&
|
callee.type === 'Identifier' && callee.name === 'require' &&
|
||||||
firstArg && firstArg.type === 'StringLiteral'
|
firstArg && isLiteralString(firstArg)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getIndex(stringLiteral) {
|
getIndex(stringLiteralOrTemplateLiteral) {
|
||||||
const name = stringLiteral.value;
|
const name = stringLiteralOrTemplateLiteral.quasis
|
||||||
|
? stringLiteralOrTemplateLiteral.quasis[0].value.cooked
|
||||||
|
: stringLiteralOrTemplateLiteral.value;
|
||||||
let index = this.nameToIndex.get(name);
|
let index = this.nameToIndex.get(name);
|
||||||
if (index !== undefined) {
|
if (index !== undefined) {
|
||||||
return index;
|
return index;
|
||||||
|
@ -132,6 +134,11 @@ function collectDependencies(ast, replacement, dependencyMapIdentifier) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isLiteralString(node) {
|
||||||
|
return node.type === 'StringLiteral' ||
|
||||||
|
node.type === 'TemplateLiteral' && node.quasis.length === 1;
|
||||||
|
}
|
||||||
|
|
||||||
exports = module.exports =
|
exports = module.exports =
|
||||||
(ast: AST) => collectDependencies(ast, new Replacement());
|
(ast: AST) => collectDependencies(ast, new Replacement());
|
||||||
exports.forOptimization =
|
exports.forOptimization =
|
||||||
|
|
Loading…
Reference in New Issue