| 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(); |