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