mirror of https://github.com/status-im/metro.git
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
673b1713f3
commit
d728fa4ec1
|
@ -96,7 +96,6 @@ function* concat<T>(...iterables: Array<Iterable<T>>): Iterable<T> {
|
|||
|
||||
function prelude(optimize) {
|
||||
return virtualModule(
|
||||
`var __DEV__= ${String(!optimize)
|
||||
}, __BUNDLE_START_TIME__ = Date.now();`
|
||||
`var __DEV__=${String(!optimize)},__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';
|
||||
|
||||
const generate = require('babel-generator').default;
|
||||
const stub = require('sinon/lib/sinon/stub');
|
||||
|
||||
exports.fn = () => {
|
||||
|
@ -16,3 +17,7 @@ exports.fn = () => {
|
|||
f.stub = s;
|
||||
return f;
|
||||
};
|
||||
|
||||
const generateOptions = {concise: true};
|
||||
exports.codeFromAst = ast => generate(ast, generateOptions).code;
|
||||
exports.comparableCode = code => code.trim().replace(/\s\s+/g, ' ');
|
||||
|
|
133
react-packager/src/ModuleGraph/worker/__tests__/collect-dependencies-test.js
vendored
Normal file
133
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) {
|
||||
return (
|
||||
callee.type === 'Identifier' && callee.name === 'require' &&
|
||||
firstArg && firstArg.type === 'StringLiteral'
|
||||
firstArg && isLiteralString(firstArg)
|
||||
);
|
||||
}
|
||||
|
||||
getIndex(stringLiteral) {
|
||||
const name = stringLiteral.value;
|
||||
getIndex(stringLiteralOrTemplateLiteral) {
|
||||
const name = stringLiteralOrTemplateLiteral.quasis
|
||||
? stringLiteralOrTemplateLiteral.quasis[0].value.cooked
|
||||
: stringLiteralOrTemplateLiteral.value;
|
||||
let index = this.nameToIndex.get(name);
|
||||
if (index !== undefined) {
|
||||
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 =
|
||||
(ast: AST) => collectDependencies(ast, new Replacement());
|
||||
exports.forOptimization =
|
||||
|
|
Loading…
Reference in New Issue