2017-02-14 17:38:47 +08:00
|
|
|
/* globals describe, it, beforeEach, afterEach */
|
|
|
|
"use strict";
|
|
|
|
require("should");
|
|
|
|
const sinon = require("sinon");
|
|
|
|
const NormalModule = require("../lib/NormalModule");
|
2017-04-04 07:07:14 +08:00
|
|
|
const NullDependency = require("../lib/dependencies/NullDependency");
|
2017-02-14 17:38:47 +08:00
|
|
|
const SourceMapSource = require("webpack-sources").SourceMapSource;
|
|
|
|
const OriginalSource = require("webpack-sources").OriginalSource;
|
|
|
|
const RawSource = require("webpack-sources").RawSource;
|
|
|
|
|
|
|
|
describe("NormalModule", function() {
|
|
|
|
let normalModule;
|
|
|
|
let request;
|
|
|
|
let userRequest;
|
|
|
|
let rawRequest;
|
|
|
|
let loaders;
|
|
|
|
let resource;
|
|
|
|
let parser;
|
|
|
|
beforeEach(function() {
|
|
|
|
request = "some/request";
|
|
|
|
userRequest = "some/userRequest";
|
|
|
|
rawRequest = "some/rawRequest";
|
|
|
|
loaders = [];
|
|
|
|
resource = "some/resource";
|
|
|
|
parser = {
|
2017-02-16 05:01:09 +08:00
|
|
|
parse() {}
|
2017-02-14 17:38:47 +08:00
|
|
|
};
|
|
|
|
normalModule = new NormalModule(
|
|
|
|
request,
|
|
|
|
userRequest,
|
|
|
|
rawRequest,
|
|
|
|
loaders,
|
|
|
|
resource,
|
|
|
|
parser
|
|
|
|
);
|
2017-11-06 23:46:29 +08:00
|
|
|
normalModule.cacheable = true;
|
2017-02-14 17:38:47 +08:00
|
|
|
});
|
|
|
|
describe("#identifier", function() {
|
|
|
|
it("returns an identifier for this module", function() {
|
|
|
|
normalModule.identifier().should.eql(request);
|
|
|
|
});
|
2017-04-04 06:40:13 +08:00
|
|
|
it("returns an identifier from toString", function() {
|
|
|
|
normalModule.debugId = 1000;
|
|
|
|
normalModule.toString().should.eql("Module[1000]");
|
|
|
|
normalModule.id = 1;
|
|
|
|
normalModule.toString().should.eql("Module[1]");
|
|
|
|
});
|
2017-02-14 17:38:47 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
describe("#readableIdentifier", function() {
|
|
|
|
it("calls the given requestShortener with the user request", function() {
|
|
|
|
const spy = sinon.spy();
|
|
|
|
normalModule.readableIdentifier({
|
|
|
|
shorten: spy
|
|
|
|
});
|
|
|
|
spy.callCount.should.eql(1);
|
|
|
|
spy.args[0][0].should.eql(userRequest);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("#libIdent", function() {
|
|
|
|
it("contextifies the userRequest of the module", function() {
|
|
|
|
normalModule.libIdent({
|
|
|
|
context: "some/context"
|
|
|
|
}).should.eql("../userRequest");
|
|
|
|
});
|
|
|
|
describe("given a userRequest containing loaders", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
userRequest = "some/userRequest!some/other/userRequest!some/thing/is/off/here";
|
|
|
|
normalModule = new NormalModule(
|
|
|
|
request,
|
|
|
|
userRequest,
|
|
|
|
rawRequest,
|
|
|
|
loaders,
|
|
|
|
resource,
|
|
|
|
parser
|
|
|
|
);
|
|
|
|
});
|
|
|
|
it("contextifies every path in the userRequest", function() {
|
|
|
|
normalModule.libIdent({
|
|
|
|
context: "some/context"
|
|
|
|
}).should.eql("../userRequest!../other/userRequest!../thing/is/off/here");
|
|
|
|
});
|
|
|
|
});
|
2017-08-30 05:50:22 +08:00
|
|
|
describe("given a userRequest containing query parameters", function() {
|
|
|
|
it("ignores paths in query parameters", function() {
|
|
|
|
userRequest = "some/context/loader?query=foo\\bar&otherPath=testpath/other";
|
|
|
|
normalModule = new NormalModule(
|
|
|
|
request,
|
|
|
|
userRequest,
|
|
|
|
rawRequest,
|
|
|
|
loaders,
|
|
|
|
resource,
|
|
|
|
parser
|
|
|
|
);
|
|
|
|
normalModule.libIdent({
|
|
|
|
context: "some/context",
|
|
|
|
}).should.eql("./loader?query=foo\\bar&otherPath=testpath/other");
|
|
|
|
});
|
|
|
|
});
|
2017-02-14 17:38:47 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
describe("#nameForCondition", function() {
|
|
|
|
it("return the resource", function() {
|
|
|
|
normalModule.nameForCondition().should.eql(resource);
|
|
|
|
});
|
|
|
|
describe("given a resource containing a ?-sign", function() {
|
|
|
|
const baseResource = "some/resource";
|
|
|
|
beforeEach(function() {
|
|
|
|
resource = baseResource + "?some=query";
|
|
|
|
normalModule = new NormalModule(
|
|
|
|
request,
|
|
|
|
userRequest,
|
|
|
|
rawRequest,
|
|
|
|
loaders,
|
|
|
|
resource,
|
|
|
|
parser
|
|
|
|
);
|
|
|
|
});
|
|
|
|
it("return only the part before the ?-sign", function() {
|
|
|
|
normalModule.nameForCondition().should.eql(baseResource);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("#createSourceForAsset", function() {
|
|
|
|
let name;
|
|
|
|
let content;
|
|
|
|
let sourceMap;
|
|
|
|
beforeEach(function() {
|
|
|
|
name = "some name";
|
|
|
|
content = "some content";
|
|
|
|
sourceMap = "some sourcemap";
|
|
|
|
});
|
|
|
|
describe("given no sourcemap", function() {
|
|
|
|
it("returns a RawSource", function() {
|
|
|
|
normalModule.createSourceForAsset(name, content).should.be.instanceOf(RawSource);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a string as the sourcemap", function() {
|
|
|
|
it("returns a OriginalSource", function() {
|
|
|
|
normalModule.createSourceForAsset(name, content, sourceMap).should.be.instanceOf(OriginalSource);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a some other kind of sourcemap", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
sourceMap = () => {};
|
|
|
|
});
|
|
|
|
it("returns a SourceMapSource", function() {
|
|
|
|
normalModule.createSourceForAsset(name, content, sourceMap).should.be.instanceOf(SourceMapSource);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("#source", function() {
|
|
|
|
describe("without the module having any source", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
normalModule._source = null;
|
|
|
|
});
|
|
|
|
it("returns a Source containing an Error", function() {
|
|
|
|
normalModule.source().should.be.instanceOf(RawSource);
|
|
|
|
normalModule.source().source().should.eql("throw new Error('No source available');");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-04-03 15:48:55 +08:00
|
|
|
describe("#originalSource", function() {
|
|
|
|
let expectedSource = "some source";
|
|
|
|
beforeEach(function() {
|
|
|
|
normalModule._source = new RawSource(expectedSource);
|
|
|
|
});
|
|
|
|
it("returns an original Source", function() {
|
|
|
|
normalModule.originalSource().should.eql(normalModule._source);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-02-14 17:38:47 +08:00
|
|
|
describe("#updateHashWithSource", function() {
|
|
|
|
let hashSpy;
|
|
|
|
let hash;
|
|
|
|
beforeEach(function() {
|
|
|
|
hashSpy = sinon.spy();
|
|
|
|
hash = {
|
|
|
|
update: hashSpy
|
|
|
|
};
|
|
|
|
});
|
|
|
|
describe("without the module having any source", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
normalModule._source = null;
|
|
|
|
});
|
|
|
|
it("calls hash function with \"null\"", function() {
|
|
|
|
normalModule.updateHashWithSource(hash);
|
|
|
|
hashSpy.callCount.should.eql(1);
|
|
|
|
hashSpy.args[0][0].should.eql("null");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("without the module having source", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
let expectedSource = "some source";
|
2017-02-14 17:38:47 +08:00
|
|
|
beforeEach(function() {
|
|
|
|
normalModule._source = new RawSource(expectedSource);
|
|
|
|
});
|
|
|
|
it("calls hash function with \"source\" and then the actual source of the module", function() {
|
|
|
|
normalModule.updateHashWithSource(hash);
|
|
|
|
hashSpy.callCount.should.eql(2);
|
|
|
|
hashSpy.args[0][0].should.eql("source");
|
|
|
|
hashSpy.args[1][0].should.eql(expectedSource);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-04-04 07:07:14 +08:00
|
|
|
describe("#hasDependencies", function() {
|
|
|
|
it("returns true if has dependencies", function() {
|
|
|
|
normalModule.addDependency(new NullDependency());
|
|
|
|
normalModule.hasDependencies().should.eql(true);
|
|
|
|
});
|
|
|
|
it("returns false if has dependencies", function() {
|
|
|
|
normalModule.hasDependencies().should.eql(false);
|
|
|
|
});
|
|
|
|
});
|
2017-02-14 17:38:47 +08:00
|
|
|
describe("#needRebuild", function() {
|
|
|
|
let fileTimestamps;
|
|
|
|
let contextTimestamps;
|
|
|
|
let fileDependencies;
|
|
|
|
let contextDependencies;
|
|
|
|
let fileA;
|
|
|
|
let fileB;
|
2017-02-14 18:47:55 +08:00
|
|
|
|
2017-02-14 17:38:47 +08:00
|
|
|
function setDeps(
|
|
|
|
fileDependencies,
|
|
|
|
contextDependencies) {
|
|
|
|
normalModule.fileDependencies = fileDependencies;
|
|
|
|
normalModule.contextDependencies = contextDependencies;
|
|
|
|
}
|
2017-02-14 18:47:55 +08:00
|
|
|
|
2017-02-14 17:38:47 +08:00
|
|
|
beforeEach(function() {
|
|
|
|
fileA = "fileA";
|
|
|
|
fileB = "fileB";
|
2017-02-14 18:47:55 +08:00
|
|
|
fileDependencies = [fileA, fileB];
|
|
|
|
contextDependencies = [fileA, fileB];
|
2017-02-14 17:38:47 +08:00
|
|
|
fileTimestamps = {
|
|
|
|
[fileA]: 1,
|
|
|
|
[fileB]: 1,
|
|
|
|
};
|
|
|
|
contextTimestamps = {
|
|
|
|
[fileA]: 1,
|
|
|
|
[fileB]: 1,
|
|
|
|
};
|
|
|
|
normalModule.buildTimestamp = 2;
|
|
|
|
setDeps(fileDependencies, contextDependencies);
|
|
|
|
});
|
|
|
|
describe("given all timestamps are older than the buildTimestamp", function() {
|
|
|
|
it("returns false", function() {
|
|
|
|
normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a file timestamp is newer than the buildTimestamp", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
fileTimestamps[fileA] = 3;
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
|
|
|
normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a no file timestamp exists", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
fileTimestamps = {};
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
|
|
|
normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a context timestamp is newer than the buildTimestamp", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
contextTimestamps[fileA] = 3;
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
|
|
|
normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a no context timestamp exists", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
contextTimestamps = {};
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
|
|
|
normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("#splitVariablesInUniqueNamedChunks", function() {
|
|
|
|
let variables;
|
|
|
|
beforeEach(function() {
|
2017-02-14 18:47:55 +08:00
|
|
|
variables = [{
|
2017-02-16 16:31:58 +08:00
|
|
|
name: "foo"
|
|
|
|
}, {
|
|
|
|
name: "bar"
|
|
|
|
}, {
|
|
|
|
name: "baz"
|
|
|
|
}, {
|
|
|
|
name: "some"
|
|
|
|
}, {
|
|
|
|
name: "more"
|
|
|
|
}];
|
2017-02-14 17:38:47 +08:00
|
|
|
});
|
|
|
|
describe("given an empty array of vars", function() {
|
|
|
|
it("returns an empty array", function() {
|
2017-02-16 16:31:58 +08:00
|
|
|
normalModule.splitVariablesInUniqueNamedChunks([]).should.eql([
|
|
|
|
[]
|
|
|
|
]);
|
2017-02-14 17:38:47 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given an array of distrinct variables", function() {
|
|
|
|
it("returns an array containing an array containing the variables", function() {
|
|
|
|
normalModule.splitVariablesInUniqueNamedChunks(variables).should.eql([variables]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given an array with duplicate variables", function() {
|
|
|
|
it("returns several arrays each containing only distinct variable names", function() {
|
|
|
|
normalModule.splitVariablesInUniqueNamedChunks(variables.concat(variables)).should.eql([variables, variables]);
|
|
|
|
});
|
|
|
|
describe("and a duplicate as the last variable", function() {
|
|
|
|
it("returns correctly split distinct arrays", function() {
|
|
|
|
normalModule.splitVariablesInUniqueNamedChunks(variables.concat(variables).concat(variables[0])).should.eql([variables, variables, [variables[0]]]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-02-14 18:14:57 +08:00
|
|
|
|
|
|
|
describe("#applyNoParseRule", function() {
|
|
|
|
let rule;
|
|
|
|
let content;
|
|
|
|
describe("given a string as rule", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
rule = "some-rule";
|
|
|
|
});
|
|
|
|
describe("and the content starting with the string specified in rule", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
content = rule + "some-content";
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing(rule, content).should.eql(true);
|
2017-02-14 18:14:57 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("and the content does not start with the string specified in rule", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
content = "some-content";
|
|
|
|
});
|
|
|
|
it("returns false", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing(rule, content).should.eql(false);
|
2017-02-14 18:14:57 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a regex as rule", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
rule = /some-rule/;
|
|
|
|
});
|
|
|
|
describe("and the content matches the rule", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
content = rule + "some-content";
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing(rule, content).should.eql(true);
|
2017-02-14 18:14:57 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("and the content does not match the rule", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
content = "some-content";
|
|
|
|
});
|
|
|
|
it("returns false", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing(rule, content).should.eql(false);
|
2017-02-14 18:14:57 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-02-16 05:01:09 +08:00
|
|
|
describe("#shouldPreventParsing", function() {
|
2017-02-14 18:14:57 +08:00
|
|
|
let applyNoParseRuleSpy;
|
|
|
|
beforeEach(function() {
|
|
|
|
applyNoParseRuleSpy = sinon.stub();
|
|
|
|
normalModule.applyNoParseRule = applyNoParseRuleSpy;
|
|
|
|
});
|
|
|
|
describe("given no noParseRule", function() {
|
|
|
|
it("returns false", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing().should.eql(false);
|
2017-02-14 18:14:57 +08:00
|
|
|
applyNoParseRuleSpy.callCount.should.eql(0);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("given a noParseRule", function() {
|
|
|
|
let returnValOfSpy;
|
|
|
|
beforeEach(function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
returnValOfSpy = true;
|
2017-02-14 18:14:57 +08:00
|
|
|
applyNoParseRuleSpy.returns(returnValOfSpy);
|
|
|
|
});
|
|
|
|
describe("that is a string", function() {
|
|
|
|
it("calls and returns whatever applyNoParseRule returns", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing("some rule").should.eql(returnValOfSpy);
|
2017-02-14 18:14:57 +08:00
|
|
|
applyNoParseRuleSpy.callCount.should.eql(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("that is a regex", function() {
|
|
|
|
it("calls and returns whatever applyNoParseRule returns", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing("some rule").should.eql(returnValOfSpy);
|
2017-02-14 18:14:57 +08:00
|
|
|
applyNoParseRuleSpy.callCount.should.eql(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("that is an array", function() {
|
|
|
|
describe("of strings and or regexs", function() {
|
|
|
|
let someRules;
|
|
|
|
beforeEach(function() {
|
|
|
|
someRules = [
|
2017-02-16 05:01:09 +08:00
|
|
|
"some rule",
|
|
|
|
/some rule1/,
|
|
|
|
"some rule2",
|
2017-02-14 18:14:57 +08:00
|
|
|
];
|
|
|
|
});
|
|
|
|
describe("and none of them match", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
returnValOfSpy = false;
|
|
|
|
applyNoParseRuleSpy.returns(returnValOfSpy);
|
|
|
|
});
|
|
|
|
it("returns false", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing(someRules).should.eql(returnValOfSpy);
|
2017-02-14 18:14:57 +08:00
|
|
|
applyNoParseRuleSpy.callCount.should.eql(3);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("and the first of them matches", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
returnValOfSpy = true;
|
|
|
|
applyNoParseRuleSpy.returns(returnValOfSpy);
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing(someRules).should.eql(returnValOfSpy);
|
2017-02-14 18:14:57 +08:00
|
|
|
applyNoParseRuleSpy.callCount.should.eql(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("and the last of them matches", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
returnValOfSpy = true;
|
|
|
|
applyNoParseRuleSpy.onCall(0).returns(false);
|
|
|
|
applyNoParseRuleSpy.onCall(1).returns(false);
|
|
|
|
applyNoParseRuleSpy.onCall(2).returns(true);
|
|
|
|
});
|
|
|
|
it("returns true", function() {
|
2017-02-16 05:01:09 +08:00
|
|
|
normalModule.shouldPreventParsing(someRules).should.eql(returnValOfSpy);
|
2017-02-14 18:14:57 +08:00
|
|
|
applyNoParseRuleSpy.callCount.should.eql(3);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-02-14 17:38:47 +08:00
|
|
|
});
|