2017-02-02 19:56:41 +08:00
|
|
|
/* globals describe, it */
|
2017-01-18 16:03:37 +08:00
|
|
|
"use strict";
|
2013-01-31 01:49:25 +08:00
|
|
|
|
2017-01-18 16:03:37 +08:00
|
|
|
const should = require("should");
|
|
|
|
const path = require("path");
|
2017-06-24 04:30:30 +08:00
|
|
|
const sinon = require("sinon");
|
2013-01-31 01:49:25 +08:00
|
|
|
|
2017-01-18 16:03:37 +08:00
|
|
|
const webpack = require("../");
|
|
|
|
const WebpackOptionsDefaulter = require("../lib/WebpackOptionsDefaulter");
|
2017-12-31 02:34:14 +08:00
|
|
|
const MemoryFs = require("memory-fs");
|
2017-01-18 16:03:37 +08:00
|
|
|
|
|
|
|
describe("Compiler", () => {
|
2013-01-31 01:49:25 +08:00
|
|
|
function compile(entry, options, callback) {
|
2017-01-18 16:03:37 +08:00
|
|
|
const noOutputPath = !options.output || !options.output.path;
|
2018-02-25 09:00:20 +08:00
|
|
|
if (!options.mode) options.mode = "production";
|
2017-09-22 21:03:30 +08:00
|
|
|
options = new WebpackOptionsDefaulter().process(options);
|
2013-01-31 01:49:25 +08:00
|
|
|
options.entry = entry;
|
|
|
|
options.context = path.join(__dirname, "fixtures");
|
2018-02-25 09:00:20 +08:00
|
|
|
if (noOutputPath) options.output.path = "/";
|
2013-01-31 01:49:25 +08:00
|
|
|
options.output.pathinfo = true;
|
2017-12-13 23:05:21 +08:00
|
|
|
options.optimization = {
|
|
|
|
minimize: false
|
|
|
|
};
|
2017-01-18 16:03:37 +08:00
|
|
|
const logs = {
|
2015-01-05 21:13:11 +08:00
|
|
|
mkdirp: [],
|
2018-02-25 09:00:20 +08:00
|
|
|
writeFile: []
|
2015-01-05 21:13:11 +08:00
|
|
|
};
|
2013-01-31 01:49:25 +08:00
|
|
|
|
2017-01-18 16:03:37 +08:00
|
|
|
const c = webpack(options);
|
|
|
|
const files = {};
|
2013-01-31 01:49:25 +08:00
|
|
|
c.outputFileSystem = {
|
2017-02-09 19:28:26 +08:00
|
|
|
join: function() {
|
2017-02-09 19:57:09 +08:00
|
|
|
return [].join.call(arguments, "/").replace(/\/+/g, "/");
|
2017-02-09 19:28:26 +08:00
|
|
|
},
|
2013-01-31 01:49:25 +08:00
|
|
|
mkdirp: function(path, callback) {
|
2015-01-05 21:13:11 +08:00
|
|
|
logs.mkdirp.push(path);
|
2013-01-31 01:49:25 +08:00
|
|
|
callback();
|
|
|
|
},
|
|
|
|
writeFile: function(name, content, callback) {
|
2015-01-05 21:13:11 +08:00
|
|
|
logs.writeFile.push(name, content);
|
2013-01-31 01:49:25 +08:00
|
|
|
files[name] = content.toString("utf-8");
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
};
|
2018-02-25 09:00:20 +08:00
|
|
|
c.hooks.compilation.tap(
|
|
|
|
"CompilerTest",
|
|
|
|
compilation => (compilation.bail = true)
|
|
|
|
);
|
2017-01-18 16:03:37 +08:00
|
|
|
c.run((err, stats) => {
|
2018-02-25 09:00:20 +08:00
|
|
|
if (err) throw err;
|
2013-10-16 14:57:37 +08:00
|
|
|
should.strictEqual(typeof stats, "object");
|
2017-01-18 16:03:37 +08:00
|
|
|
const compilation = stats.compilation;
|
2013-01-31 01:49:25 +08:00
|
|
|
stats = stats.toJson({
|
|
|
|
modules: true,
|
|
|
|
reasons: true
|
|
|
|
});
|
2013-10-16 14:57:37 +08:00
|
|
|
should.strictEqual(typeof stats, "object");
|
2013-01-31 01:49:25 +08:00
|
|
|
stats.should.have.property("errors");
|
2017-01-02 08:44:24 +08:00
|
|
|
Array.isArray(stats.errors).should.be.ok();
|
2018-02-25 09:00:20 +08:00
|
|
|
if (stats.errors.length > 0) {
|
2013-01-31 01:49:25 +08:00
|
|
|
stats.errors[0].should.be.instanceOf(Error);
|
|
|
|
throw stats.errors[0];
|
|
|
|
}
|
2015-01-05 21:13:11 +08:00
|
|
|
stats.logs = logs;
|
2016-12-14 19:03:24 +08:00
|
|
|
callback(stats, files, compilation);
|
2013-01-31 01:49:25 +08:00
|
|
|
});
|
|
|
|
}
|
2015-01-05 21:13:11 +08:00
|
|
|
|
2018-02-25 09:00:20 +08:00
|
|
|
it("should compile a single file to deep output", done => {
|
|
|
|
compile(
|
|
|
|
"./c",
|
|
|
|
{
|
|
|
|
output: {
|
|
|
|
path: "/what",
|
|
|
|
filename: "the/hell.js"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
(stats, files) => {
|
|
|
|
stats.logs.mkdirp.should.eql(["/what", "/what/the"]);
|
|
|
|
done();
|
2015-01-05 21:13:11 +08:00
|
|
|
}
|
2018-02-25 09:00:20 +08:00
|
|
|
);
|
2015-01-05 21:13:11 +08:00
|
|
|
});
|
2017-02-02 19:36:15 +08:00
|
|
|
|
2018-02-25 09:00:20 +08:00
|
|
|
it("should compile a single file", done => {
|
2017-01-18 16:03:37 +08:00
|
|
|
compile("./c", {}, (stats, files) => {
|
2017-02-02 19:36:15 +08:00
|
|
|
files.should.have.property("/main.js").have.type("string");
|
|
|
|
Object.keys(files).should.be.eql(["/main.js"]);
|
2017-03-01 01:23:24 +08:00
|
|
|
const bundle = files["/main.js"];
|
2014-07-28 02:39:22 +08:00
|
|
|
bundle.should.containEql("function __webpack_require__(");
|
2017-12-21 03:41:22 +08:00
|
|
|
bundle.should.containEql("__webpack_require__(/*! ./a */ 0);");
|
2014-07-28 02:39:22 +08:00
|
|
|
bundle.should.containEql("./c.js");
|
|
|
|
bundle.should.containEql("./a.js");
|
|
|
|
bundle.should.containEql("This is a");
|
|
|
|
bundle.should.containEql("This is c");
|
|
|
|
bundle.should.not.containEql("2: function(");
|
|
|
|
bundle.should.not.containEql("window");
|
|
|
|
bundle.should.not.containEql("jsonp");
|
|
|
|
bundle.should.not.containEql("fixtures");
|
2013-01-31 01:49:25 +08:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2017-02-02 19:36:15 +08:00
|
|
|
|
2018-02-25 09:00:20 +08:00
|
|
|
it("should compile a complex file", done => {
|
2017-01-18 16:03:37 +08:00
|
|
|
compile("./main1", {}, (stats, files) => {
|
2017-02-02 19:36:15 +08:00
|
|
|
files.should.have.property("/main.js").have.type("string");
|
|
|
|
Object.keys(files).should.be.eql(["/main.js"]);
|
2017-03-01 01:23:24 +08:00
|
|
|
const bundle = files["/main.js"];
|
2014-07-28 02:39:22 +08:00
|
|
|
bundle.should.containEql("function __webpack_require__(");
|
|
|
|
bundle.should.containEql("__webpack_require__(/*! ./a */");
|
|
|
|
bundle.should.containEql("./main1.js");
|
|
|
|
bundle.should.containEql("./a.js");
|
|
|
|
bundle.should.containEql("./b.js");
|
2017-01-18 05:26:38 +08:00
|
|
|
bundle.should.containEql("./node_modules/m1/a.js");
|
2014-07-28 02:39:22 +08:00
|
|
|
bundle.should.containEql("This is a");
|
|
|
|
bundle.should.containEql("This is b");
|
|
|
|
bundle.should.containEql("This is m1/a");
|
|
|
|
bundle.should.not.containEql("4: function(");
|
|
|
|
bundle.should.not.containEql("window");
|
|
|
|
bundle.should.not.containEql("jsonp");
|
|
|
|
bundle.should.not.containEql("fixtures");
|
2013-01-31 01:49:25 +08:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2017-02-02 19:36:15 +08:00
|
|
|
|
2018-02-25 09:00:20 +08:00
|
|
|
it("should compile a file with transitive dependencies", done => {
|
2017-01-18 16:03:37 +08:00
|
|
|
compile("./abc", {}, (stats, files) => {
|
2017-02-02 19:36:15 +08:00
|
|
|
files.should.have.property("/main.js").have.type("string");
|
|
|
|
Object.keys(files).should.be.eql(["/main.js"]);
|
2017-03-01 01:23:24 +08:00
|
|
|
const bundle = files["/main.js"];
|
2014-07-28 02:39:22 +08:00
|
|
|
bundle.should.containEql("function __webpack_require__(");
|
|
|
|
bundle.should.containEql("__webpack_require__(/*! ./a */");
|
|
|
|
bundle.should.containEql("__webpack_require__(/*! ./b */");
|
|
|
|
bundle.should.containEql("__webpack_require__(/*! ./c */");
|
|
|
|
bundle.should.containEql("./abc.js");
|
|
|
|
bundle.should.containEql("./a.js");
|
|
|
|
bundle.should.containEql("./b.js");
|
|
|
|
bundle.should.containEql("./c.js");
|
|
|
|
bundle.should.containEql("This is a");
|
|
|
|
bundle.should.containEql("This is b");
|
|
|
|
bundle.should.containEql("This is c");
|
|
|
|
bundle.should.not.containEql("4: function(");
|
|
|
|
bundle.should.not.containEql("window");
|
|
|
|
bundle.should.not.containEql("jsonp");
|
|
|
|
bundle.should.not.containEql("fixtures");
|
2013-01-31 01:49:25 +08:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2017-02-02 19:36:15 +08:00
|
|
|
|
2018-02-25 09:00:20 +08:00
|
|
|
it("should compile a file with multiple chunks", done => {
|
2017-01-18 16:03:37 +08:00
|
|
|
compile("./chunks", {}, (stats, files) => {
|
2013-01-31 01:49:25 +08:00
|
|
|
stats.chunks.length.should.be.eql(2);
|
2017-02-02 19:36:15 +08:00
|
|
|
files.should.have.property("/main.js").have.type("string");
|
|
|
|
files.should.have.property("/0.js").have.type("string");
|
|
|
|
Object.keys(files).should.be.eql(["/0.js", "/main.js"]);
|
2017-03-01 01:23:24 +08:00
|
|
|
const bundle = files["/main.js"];
|
|
|
|
const chunk = files["/0.js"];
|
2014-07-28 02:39:22 +08:00
|
|
|
bundle.should.containEql("function __webpack_require__(");
|
|
|
|
bundle.should.containEql("__webpack_require__(/*! ./b */");
|
|
|
|
chunk.should.not.containEql("__webpack_require__(/* ./b */");
|
|
|
|
bundle.should.containEql("./chunks.js");
|
|
|
|
chunk.should.containEql("./a.js");
|
|
|
|
chunk.should.containEql("./b.js");
|
|
|
|
chunk.should.containEql("This is a");
|
|
|
|
bundle.should.not.containEql("This is a");
|
|
|
|
chunk.should.containEql("This is b");
|
|
|
|
bundle.should.not.containEql("This is b");
|
|
|
|
bundle.should.not.containEql("4: function(");
|
|
|
|
bundle.should.not.containEql("fixtures");
|
|
|
|
chunk.should.not.containEql("fixtures");
|
|
|
|
bundle.should.containEql("webpackJsonp");
|
2018-02-25 09:00:20 +08:00
|
|
|
chunk.should.containEql('window["webpackJsonp"] || []).push');
|
2013-01-31 01:49:25 +08:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2017-06-24 04:30:30 +08:00
|
|
|
describe("methods", () => {
|
|
|
|
let compiler;
|
|
|
|
beforeEach(() => {
|
|
|
|
compiler = webpack({
|
|
|
|
entry: "./c",
|
|
|
|
context: path.join(__dirname, "fixtures"),
|
|
|
|
output: {
|
|
|
|
path: "/",
|
2018-02-25 09:00:20 +08:00
|
|
|
pathinfo: true
|
2017-06-24 04:30:30 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("purgeInputFileSystem", () => {
|
2018-02-25 09:00:20 +08:00
|
|
|
it("invokes purge() if inputFileSystem.purge", done => {
|
2017-06-24 04:30:30 +08:00
|
|
|
const mockPurge = sinon.spy();
|
|
|
|
compiler.inputFileSystem = {
|
2018-02-25 09:00:20 +08:00
|
|
|
purge: mockPurge
|
2017-06-24 04:30:30 +08:00
|
|
|
};
|
|
|
|
compiler.purgeInputFileSystem();
|
|
|
|
mockPurge.callCount.should.be.exactly(1);
|
|
|
|
done();
|
|
|
|
});
|
2018-02-25 09:00:20 +08:00
|
|
|
it("does NOT invoke purge() if !inputFileSystem.purge", done => {
|
2017-06-24 04:30:30 +08:00
|
|
|
const mockPurge = sinon.spy();
|
|
|
|
compiler.inputFileSystem = null;
|
|
|
|
compiler.purgeInputFileSystem();
|
|
|
|
mockPurge.callCount.should.be.exactly(0);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("isChild", () => {
|
2018-02-25 09:00:20 +08:00
|
|
|
it("returns booleanized this.parentCompilation", done => {
|
2017-06-24 04:30:30 +08:00
|
|
|
compiler.parentCompilation = "stringyStringString";
|
|
|
|
const response1 = compiler.isChild();
|
|
|
|
response1.should.be.exactly(true);
|
|
|
|
|
|
|
|
compiler.parentCompilation = 123456789;
|
|
|
|
const response2 = compiler.isChild();
|
|
|
|
response2.should.be.exactly(true);
|
|
|
|
|
2017-06-24 04:45:59 +08:00
|
|
|
compiler.parentCompilation = {
|
|
|
|
what: "I belong to an object"
|
|
|
|
};
|
2017-06-24 04:30:30 +08:00
|
|
|
const response3 = compiler.isChild();
|
|
|
|
response3.should.be.exactly(true);
|
|
|
|
|
|
|
|
compiler.parentCompilation = ["Array", 123, true, null, [], () => {}];
|
|
|
|
const response4 = compiler.isChild();
|
|
|
|
response4.should.be.exactly(true);
|
|
|
|
|
|
|
|
compiler.parentCompilation = false;
|
|
|
|
const response5 = compiler.isChild();
|
|
|
|
response5.should.be.exactly(false);
|
|
|
|
|
|
|
|
compiler.parentCompilation = 0;
|
|
|
|
const response6 = compiler.isChild();
|
|
|
|
response6.should.be.exactly(false);
|
|
|
|
|
|
|
|
compiler.parentCompilation = null;
|
|
|
|
const response7 = compiler.isChild();
|
|
|
|
response7.should.be.exactly(false);
|
|
|
|
|
|
|
|
compiler.parentCompilation = "";
|
|
|
|
const response8 = compiler.isChild();
|
|
|
|
response8.should.be.exactly(false);
|
|
|
|
|
|
|
|
compiler.parentCompilation = NaN;
|
|
|
|
const response9 = compiler.isChild();
|
|
|
|
response9.should.be.exactly(false);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-12-31 02:34:14 +08:00
|
|
|
it("should not emit on errors", function(done) {
|
|
|
|
const compiler = webpack({
|
|
|
|
context: __dirname,
|
|
|
|
mode: "production",
|
|
|
|
entry: "./missing",
|
|
|
|
output: {
|
|
|
|
path: "/",
|
|
|
|
filename: "bundle.js"
|
|
|
|
}
|
|
|
|
});
|
|
|
|
compiler.outputFileSystem = new MemoryFs();
|
|
|
|
compiler.run((err, stats) => {
|
2018-02-25 09:00:20 +08:00
|
|
|
if (err) return done(err);
|
|
|
|
if (compiler.outputFileSystem.existsSync("/bundle.js"))
|
2017-12-31 02:34:14 +08:00
|
|
|
return done(new Error("Bundle should not be created on error"));
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2017-12-31 16:53:35 +08:00
|
|
|
it("should not emit on errors (watch)", function(done) {
|
|
|
|
const compiler = webpack({
|
|
|
|
context: __dirname,
|
|
|
|
mode: "production",
|
|
|
|
entry: "./missing",
|
|
|
|
output: {
|
|
|
|
path: "/",
|
|
|
|
filename: "bundle.js"
|
|
|
|
}
|
|
|
|
});
|
|
|
|
compiler.outputFileSystem = new MemoryFs();
|
|
|
|
const watching = compiler.watch({}, (err, stats) => {
|
|
|
|
watching.close();
|
2018-02-25 09:00:20 +08:00
|
|
|
if (err) return done(err);
|
|
|
|
if (compiler.outputFileSystem.existsSync("/bundle.js"))
|
2017-12-31 16:53:35 +08:00
|
|
|
return done(new Error("Bundle should not be created on error"));
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2015-01-05 21:13:11 +08:00
|
|
|
});
|