Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: chromium_process.js

Issue 29517687: Issue 5079, 5516 - Use webpack for browser tests, modules for content scripts (Closed)
Patch Set: Created Aug. 16, 2017, 3:40 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chromium_process.js
diff --git a/chromium_process.js b/chromium_process.js
index d6f9b82e93e85217e11b76da9cc07b13fc71552e..1a60fe2ca814437d5582b4e853ea10e1ebfacf09 100644
--- a/chromium_process.js
+++ b/chromium_process.js
@@ -26,8 +26,10 @@ const https = require("https");
const os = require("os");
const path = require("path");
-const remoteInterface = require("chrome-remote-interface");
const extractZip = require("extract-zip");
+const remoteInterface = require("chrome-remote-interface");
+const webpack = require("webpack");
+const MemoryFS = require("memory-fs");
Wladimir Palant 2017/08/17 10:05:38 I assume that this module exists because WebPack i
kzar 2017/08/17 12:40:21 Done.
const CHROMIUM_REVISION = 467222;
@@ -248,8 +250,52 @@ function connectRemoteInterface(attempt)
});
}
-function runBootstrap(initialPage, bootstrapPath, bootstrapArgs)
+function webpackInMemory(bundleFilename, options)
+{
+ // Based on this example https://webpack.js.org/api/node/#custom-file-systems
+ let memoryFS = new MemoryFS();
+
+ options.output = {filename: bundleFilename, path: "/"};
+ let webpackCompiler = webpack(options);
+ webpackCompiler.outputFileSystem = memoryFS;
Wladimir Palant 2017/08/17 10:05:37 Nit: It's better to put all the statements above i
kzar 2017/08/17 12:40:21 Done.
+ return new Promise((resolve, reject) =>
+ {
+ webpackCompiler.run((err, stats) =>
+ {
+ // Error handling is based on this example
+ // https://webpack.js.org/api/node/#error-handling
+ if (err)
+ {
+ let reason = err.stack || err;
+ if (err.details)
+ reason += "\n" + err.details;
+ reject(reason);
+ }
+ else if (stats.hasErrors())
+ reject(stats.toJson().errors);
+ else
+ {
+ let bundle = memoryFS.readFileSync("/" + bundleFilename, "utf-8");
+ memoryFS.unlink("/" + bundleFilename, () => { resolve(bundle); });
Wladimir Palant 2017/08/17 10:05:38 Nit: Use memoryFS.unlinkSync() here to make this m
kzar 2017/08/17 12:40:21 Done.
+ }
+ });
+ });
+}
+
+function runBrowserTests(browserTestModules)
{
+ // We need to navigate to this directory because about:blank won't be allowed
+ // to load file:/// URLs.
+ let initialPage = require("url").format({
+ protocol: "file",
+ slashes: "true",
+ pathname: path.resolve(process.cwd(), __dirname).split(path.sep).join("/")
+ });
Wladimir Palant 2017/08/17 10:07:30 Actually, this shouldn't be necessary any more. Ru
kzar 2017/08/17 12:40:21 Done.
+
+ let bootstrapPath = path.join(__dirname, "test", "browser", "_bootstrap.js");
+ let nodeunitPath = path.join(__dirname, "node_modules", "nodeunit",
+ "examples", "browser", "nodeunit.js");
+
return connectRemoteInterface().then(async client =>
{
try
@@ -271,9 +317,32 @@ function runBootstrap(initialPage, bootstrapPath, bootstrapArgs)
await Page.navigate({url: initialPage});
await Runtime.enable();
+
+ let bundleFilename = "bundle.js";
+ let bundle = await webpackInMemory(bundleFilename, {
+ entry: bootstrapPath,
+ module: {
+ rules: [{
+ resource: nodeunitPath,
+ // I would have rathered use exports-loader here, to avoid treating
Wladimir Palant 2017/08/17 10:05:37 "rather used"?
kzar 2017/08/17 12:40:21 Done.
+ // nodeunit as a global. Unfortunately the nodeunit browser example
+ // script is quite slopily put together, if exports isn't falsey it
+ // breaks! As a workaround we need to use script-loader, which means
+ // that exports is falsey for that script as a side-effect.
+ use: ["script-loader"]
+ }]
+ },
+ resolve: {
+ alias: {
+ nodeunit$: nodeunitPath
+ },
+ modules: [path.resolve(__dirname, "lib")]
+ }
+ });
+
let compileResult = await Runtime.compileScript({
- expression: fs.readFileSync(bootstrapPath, "utf-8"),
- sourceURL: bootstrapPath,
+ expression: bundle,
+ sourceURL: bundleFilename,
persistScript: true
});
if (compileResult.exceptionDetails)
@@ -287,8 +356,8 @@ function runBootstrap(initialPage, bootstrapPath, bootstrapArgs)
let callResult = await Runtime.callFunctionOn({
objectId: runResult.result.objectId,
- functionDeclaration: "function(...args) {return this(...args);}",
- arguments: bootstrapArgs.map(url => ({value: url}))
+ functionDeclaration: "function(...modules) {return this(modules);}",
+ arguments: browserTestModules.map(module => ({value: module}))
});
if (callResult.exceptionDetails)
throwException(callResult.exceptionDetails, bootstrapPath);
@@ -306,14 +375,18 @@ function runBootstrap(initialPage, bootstrapPath, bootstrapArgs)
});
}
-module.exports = function(initialPage, bootstrapPath, bootstrapArgs)
+module.exports = function(browserTestFiles)
{
return ensureChromium().then(chromiumPath =>
{
let child = startChromium(chromiumPath);
return Promise.race([
child.done,
- runBootstrap(initialPage, bootstrapPath, bootstrapArgs)
+ runBrowserTests(
+ browserTestFiles.map(
+ m => "." + path.sep + path.relative(path.join("test", "browser"), m)
Wladimir Palant 2017/08/17 10:05:37 The point here is generating a list of module name
kzar 2017/08/17 12:40:21 Done.
+ )
+ )
]).then(result =>
{
child.kill();

Powered by Google App Engine
This is Rietveld