| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const path = require("path"); | 
					
						
							| 
									
										
										
										
											2019-06-11 19:09:42 +08:00
										 |  |  | const fs = require("graceful-fs"); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | const vm = require("vm"); | 
					
						
							| 
									
										
										
										
											2019-12-28 04:25:56 +08:00
										 |  |  | const rimraf = require("rimraf"); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | const checkArrayExpectation = require("./checkArrayExpectation"); | 
					
						
							|  |  |  | const createLazyTestEnv = require("./helpers/createLazyTestEnv"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-09 21:26:35 +08:00
										 |  |  | const webpack = require(".."); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const casesPath = path.join(__dirname, "hotCases"); | 
					
						
							|  |  |  | let categories = fs | 
					
						
							|  |  |  | 	.readdirSync(casesPath) | 
					
						
							|  |  |  | 	.filter(dir => fs.statSync(path.join(casesPath, dir)).isDirectory()); | 
					
						
							|  |  |  | categories = categories.map(cat => { | 
					
						
							|  |  |  | 	return { | 
					
						
							|  |  |  | 		name: cat, | 
					
						
							|  |  |  | 		tests: fs | 
					
						
							|  |  |  | 			.readdirSync(path.join(casesPath, cat)) | 
					
						
							|  |  |  | 			.filter(folder => folder.indexOf("_") < 0) | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const describeCases = config => { | 
					
						
							|  |  |  | 	describe(config.name, () => { | 
					
						
							|  |  |  | 		categories.forEach(category => { | 
					
						
							|  |  |  | 			describe(category.name, () => { | 
					
						
							|  |  |  | 				category.tests.forEach(testName => { | 
					
						
							|  |  |  | 					describe(testName, () => { | 
					
						
							|  |  |  | 						it( | 
					
						
							|  |  |  | 							testName + " should compile", | 
					
						
							|  |  |  | 							done => { | 
					
						
							|  |  |  | 								const testDirectory = path.join( | 
					
						
							|  |  |  | 									casesPath, | 
					
						
							|  |  |  | 									category.name, | 
					
						
							|  |  |  | 									testName | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								const outputDirectory = path.join( | 
					
						
							|  |  |  | 									__dirname, | 
					
						
							|  |  |  | 									"js", | 
					
						
							|  |  |  | 									`hot-cases-${config.name}`, | 
					
						
							|  |  |  | 									category.name, | 
					
						
							|  |  |  | 									testName | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2019-12-28 04:25:56 +08:00
										 |  |  | 								rimraf.sync(outputDirectory); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 								const recordsPath = path.join(outputDirectory, "records.json"); | 
					
						
							|  |  |  | 								const fakeUpdateLoaderOptions = { | 
					
						
							|  |  |  | 									updateIndex: 0 | 
					
						
							|  |  |  | 								}; | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 								const configPath = path.join( | 
					
						
							|  |  |  | 									testDirectory, | 
					
						
							|  |  |  | 									"webpack.config.js" | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 								let options = {}; | 
					
						
							|  |  |  | 								if (fs.existsSync(configPath)) options = require(configPath); | 
					
						
							|  |  |  | 								if (!options.mode) options.mode = "development"; | 
					
						
							|  |  |  | 								if (!options.devtool) options.devtool = false; | 
					
						
							|  |  |  | 								if (!options.context) options.context = testDirectory; | 
					
						
							|  |  |  | 								if (!options.entry) options.entry = "./index.js"; | 
					
						
							|  |  |  | 								if (!options.output) options.output = {}; | 
					
						
							|  |  |  | 								if (!options.output.path) options.output.path = outputDirectory; | 
					
						
							|  |  |  | 								if (!options.output.filename) | 
					
						
							|  |  |  | 									options.output.filename = "bundle.js"; | 
					
						
							|  |  |  | 								if (!options.output.chunkFilename) | 
					
						
							| 
									
										
										
										
											2018-12-28 21:09:35 +08:00
										 |  |  | 									options.output.chunkFilename = "[name].chunk.[fullhash].js"; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 								if (options.output.pathinfo === undefined) | 
					
						
							|  |  |  | 									options.output.pathinfo = true; | 
					
						
							| 
									
										
										
										
											2020-04-25 06:28:27 +08:00
										 |  |  | 								if (options.output.library === undefined) | 
					
						
							|  |  |  | 									options.output.library = { type: "commonjs2" }; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 								if (!options.optimization) options.optimization = {}; | 
					
						
							|  |  |  | 								if (!options.optimization.moduleIds) | 
					
						
							|  |  |  | 									options.optimization.moduleIds = "named"; | 
					
						
							|  |  |  | 								if (!options.module) options.module = {}; | 
					
						
							|  |  |  | 								if (!options.module.rules) options.module.rules = []; | 
					
						
							|  |  |  | 								options.module.rules.push({ | 
					
						
							|  |  |  | 									loader: path.join( | 
					
						
							|  |  |  | 										__dirname, | 
					
						
							|  |  |  | 										"hotCases", | 
					
						
							|  |  |  | 										"fake-update-loader.js" | 
					
						
							|  |  |  | 									), | 
					
						
							|  |  |  | 									enforce: "pre" | 
					
						
							|  |  |  | 								}); | 
					
						
							|  |  |  | 								if (!options.target) options.target = config.target; | 
					
						
							|  |  |  | 								if (!options.plugins) options.plugins = []; | 
					
						
							|  |  |  | 								options.plugins.push( | 
					
						
							|  |  |  | 									new webpack.HotModuleReplacementPlugin(), | 
					
						
							|  |  |  | 									new webpack.LoaderOptionsPlugin(fakeUpdateLoaderOptions) | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								if (!options.recordsPath) options.recordsPath = recordsPath; | 
					
						
							|  |  |  | 								const compiler = webpack(options); | 
					
						
							|  |  |  | 								compiler.run((err, stats) => { | 
					
						
							|  |  |  | 									if (err) return done(err); | 
					
						
							|  |  |  | 									const jsonStats = stats.toJson({ | 
					
						
							|  |  |  | 										errorDetails: true | 
					
						
							|  |  |  | 									}); | 
					
						
							|  |  |  | 									if ( | 
					
						
							|  |  |  | 										checkArrayExpectation( | 
					
						
							|  |  |  | 											testDirectory, | 
					
						
							|  |  |  | 											jsonStats, | 
					
						
							|  |  |  | 											"error", | 
					
						
							|  |  |  | 											"Error", | 
					
						
							|  |  |  | 											done | 
					
						
							|  |  |  | 										) | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										return; | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									if ( | 
					
						
							|  |  |  | 										checkArrayExpectation( | 
					
						
							|  |  |  | 											testDirectory, | 
					
						
							|  |  |  | 											jsonStats, | 
					
						
							|  |  |  | 											"warning", | 
					
						
							|  |  |  | 											"Warning", | 
					
						
							|  |  |  | 											done | 
					
						
							|  |  |  | 										) | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										return; | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									const window = { | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 										fetch: url => { | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 											return Promise.resolve({ | 
					
						
							|  |  |  | 												ok: true, | 
					
						
							|  |  |  | 												json() { | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 													return Promise.resolve( | 
					
						
							|  |  |  | 														require(path.resolve(outputDirectory, url)) | 
					
						
							|  |  |  | 													); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 												} | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 											}); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 										}, | 
					
						
							|  |  |  | 										importScripts: url => { | 
					
						
							|  |  |  | 											_require("./" + url); | 
					
						
							|  |  |  | 										}, | 
					
						
							|  |  |  | 										document: { | 
					
						
							|  |  |  | 											createElement(type) { | 
					
						
							|  |  |  | 												return { | 
					
						
							|  |  |  | 													_type: type, | 
					
						
							|  |  |  | 													_attrs: {}, | 
					
						
							|  |  |  | 													setAttribute(name, value) { | 
					
						
							|  |  |  | 														this._attrs[name] = value; | 
					
						
							| 
									
										
										
										
											2020-06-05 00:13:58 +08:00
										 |  |  | 													}, | 
					
						
							|  |  |  | 													parentNode: { | 
					
						
							|  |  |  | 														removeChild(node) { | 
					
						
							|  |  |  | 															// ok
 | 
					
						
							|  |  |  | 														} | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 													} | 
					
						
							|  |  |  | 												}; | 
					
						
							|  |  |  | 											}, | 
					
						
							|  |  |  | 											head: { | 
					
						
							|  |  |  | 												appendChild(element) { | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 													if (element._type === "script") { | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 														// run it
 | 
					
						
							|  |  |  | 														Promise.resolve().then(() => { | 
					
						
							|  |  |  | 															_require("./" + element.src); | 
					
						
							|  |  |  | 														}); | 
					
						
							|  |  |  | 													} | 
					
						
							|  |  |  | 												} | 
					
						
							|  |  |  | 											}, | 
					
						
							|  |  |  | 											getElementsByTagName(name) { | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 												if (name === "head") return [this.head]; | 
					
						
							| 
									
										
										
										
											2020-06-05 00:13:58 +08:00
										 |  |  | 												if (name === "script") return []; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 												throw new Error("Not supported"); | 
					
						
							|  |  |  | 											} | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 									}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									function _next(callback) { | 
					
						
							|  |  |  | 										fakeUpdateLoaderOptions.updateIndex++; | 
					
						
							|  |  |  | 										compiler.run((err, stats) => { | 
					
						
							|  |  |  | 											if (err) return callback(err); | 
					
						
							|  |  |  | 											const jsonStats = stats.toJson({ | 
					
						
							|  |  |  | 												errorDetails: true | 
					
						
							|  |  |  | 											}); | 
					
						
							|  |  |  | 											if ( | 
					
						
							|  |  |  | 												checkArrayExpectation( | 
					
						
							|  |  |  | 													testDirectory, | 
					
						
							|  |  |  | 													jsonStats, | 
					
						
							|  |  |  | 													"error", | 
					
						
							|  |  |  | 													"errors" + fakeUpdateLoaderOptions.updateIndex, | 
					
						
							|  |  |  | 													"Error", | 
					
						
							|  |  |  | 													callback | 
					
						
							|  |  |  | 												) | 
					
						
							|  |  |  | 											) { | 
					
						
							|  |  |  | 												return; | 
					
						
							|  |  |  | 											} | 
					
						
							|  |  |  | 											if ( | 
					
						
							|  |  |  | 												checkArrayExpectation( | 
					
						
							|  |  |  | 													testDirectory, | 
					
						
							|  |  |  | 													jsonStats, | 
					
						
							|  |  |  | 													"warning", | 
					
						
							|  |  |  | 													"warnings" + fakeUpdateLoaderOptions.updateIndex, | 
					
						
							|  |  |  | 													"Warning", | 
					
						
							|  |  |  | 													callback | 
					
						
							|  |  |  | 												) | 
					
						
							|  |  |  | 											) { | 
					
						
							|  |  |  | 												return; | 
					
						
							|  |  |  | 											} | 
					
						
							|  |  |  | 											callback(null, jsonStats); | 
					
						
							|  |  |  | 										}); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									function _require(module) { | 
					
						
							|  |  |  | 										if (module.substr(0, 2) === "./") { | 
					
						
							|  |  |  | 											const p = path.join(outputDirectory, module); | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 											if (module.endsWith(".json")) { | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 												return JSON.parse(fs.readFileSync(p, "utf-8")); | 
					
						
							|  |  |  | 											} else { | 
					
						
							| 
									
										
										
										
											2019-02-19 15:58:46 +08:00
										 |  |  | 												const fn = vm.runInThisContext( | 
					
						
							|  |  |  | 													"(function(require, module, exports, __dirname, __filename, it, expect, self, window, fetch, document, importScripts, NEXT, STATS) {" + | 
					
						
							|  |  |  | 														"global.expect = expect;" + | 
					
						
							|  |  |  | 														'function nsObj(m) { Object.defineProperty(m, Symbol.toStringTag, { value: "Module" }); return m; }' + | 
					
						
							|  |  |  | 														fs.readFileSync(p, "utf-8") + | 
					
						
							|  |  |  | 														"\n})", | 
					
						
							|  |  |  | 													p | 
					
						
							|  |  |  | 												); | 
					
						
							|  |  |  | 												const m = { | 
					
						
							|  |  |  | 													exports: {} | 
					
						
							|  |  |  | 												}; | 
					
						
							|  |  |  | 												fn.call( | 
					
						
							|  |  |  | 													m.exports, | 
					
						
							|  |  |  | 													_require, | 
					
						
							|  |  |  | 													m, | 
					
						
							|  |  |  | 													m.exports, | 
					
						
							|  |  |  | 													outputDirectory, | 
					
						
							|  |  |  | 													p, | 
					
						
							|  |  |  | 													_it, | 
					
						
							|  |  |  | 													expect, | 
					
						
							|  |  |  | 													window, | 
					
						
							|  |  |  | 													window, | 
					
						
							|  |  |  | 													window.fetch, | 
					
						
							|  |  |  | 													window.document, | 
					
						
							|  |  |  | 													window.importScripts, | 
					
						
							|  |  |  | 													_next, | 
					
						
							|  |  |  | 													jsonStats | 
					
						
							|  |  |  | 												); | 
					
						
							|  |  |  | 												return m.exports; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 											} | 
					
						
							|  |  |  | 										} else return require(module); | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2020-04-25 06:28:27 +08:00
										 |  |  | 									let promise = Promise.resolve(); | 
					
						
							|  |  |  | 									const info = stats.toJson({ all: false, entrypoints: true }); | 
					
						
							|  |  |  | 									if (config.target === "web") { | 
					
						
							|  |  |  | 										for (const file of info.entrypoints.main.assets) | 
					
						
							|  |  |  | 											_require(`./${file}`); | 
					
						
							|  |  |  | 									} else { | 
					
						
							|  |  |  | 										const assets = info.entrypoints.main.assets; | 
					
						
							|  |  |  | 										const result = _require(`./${assets[assets.length - 1]}`); | 
					
						
							|  |  |  | 										if (typeof result === "object" && "then" in result) | 
					
						
							|  |  |  | 											promise = promise.then(() => result); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									promise.then( | 
					
						
							|  |  |  | 										() => { | 
					
						
							|  |  |  | 											if (getNumberOfTests() < 1) | 
					
						
							|  |  |  | 												return done( | 
					
						
							|  |  |  | 													new Error("No tests exported by test case") | 
					
						
							|  |  |  | 												); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 06:28:27 +08:00
										 |  |  | 											done(); | 
					
						
							|  |  |  | 										}, | 
					
						
							|  |  |  | 										err => { | 
					
						
							|  |  |  | 											console.log(err); | 
					
						
							|  |  |  | 											done(err); | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 									); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 								}); | 
					
						
							|  |  |  | 							}, | 
					
						
							| 
									
										
										
										
											2018-11-30 20:40:29 +08:00
										 |  |  | 							20000 | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 						); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						const { it: _it, getNumberOfTests } = createLazyTestEnv( | 
					
						
							|  |  |  | 							jasmine.getEnv(), | 
					
						
							| 
									
										
										
										
											2018-11-30 20:40:29 +08:00
										 |  |  | 							20000 | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 						); | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports.describeCases = describeCases; |