| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2017 eyeo GmbH | 3 * Copyright (C) 2006-2017 eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 "use strict"; | 21 "use strict"; |
| 22 | 22 |
| 23 const childProcess = require("child_process"); | 23 const childProcess = require("child_process"); |
| 24 const fs = require("fs"); | 24 const fs = require("fs"); |
| 25 const https = require("https"); | 25 const https = require("https"); |
| 26 const os = require("os"); | 26 const os = require("os"); |
| 27 const path = require("path"); | 27 const path = require("path"); |
| 28 | 28 |
| 29 const extractZip = require("extract-zip"); | 29 const extractZip = require("extract-zip"); |
| 30 const remoteInterface = require("chrome-remote-interface"); | 30 const remoteInterface = require("chrome-remote-interface"); |
| 31 const webpack = require("webpack"); | |
| 32 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.
| |
| 33 | 31 |
| 34 const CHROMIUM_REVISION = 467222; | 32 const CHROMIUM_REVISION = 467222; |
| 35 | 33 |
| 36 function rmdir(dirPath) | 34 function rmdir(dirPath) |
| 37 { | 35 { |
| 38 for (let file of fs.readdirSync(dirPath)) | 36 for (let file of fs.readdirSync(dirPath)) |
| 39 { | 37 { |
| 40 let filePath = path.join(dirPath, file); | 38 let filePath = path.join(dirPath, file); |
| 41 try | 39 try |
| 42 { | 40 { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 return new Promise((resolve, reject) => | 241 return new Promise((resolve, reject) => |
| 244 { | 242 { |
| 245 setTimeout(() => | 243 setTimeout(() => |
| 246 { | 244 { |
| 247 connectRemoteInterface(attempt + 1).then(resolve).catch(reject); | 245 connectRemoteInterface(attempt + 1).then(resolve).catch(reject); |
| 248 }, 200); | 246 }, 200); |
| 249 }); | 247 }); |
| 250 }); | 248 }); |
| 251 } | 249 } |
| 252 | 250 |
| 253 function webpackInMemory(bundleFilename, options) | 251 function runScript(script, scriptName, scriptArgs) |
| 254 { | 252 { |
| 255 // Based on this example https://webpack.js.org/api/node/#custom-file-systems | |
| 256 let memoryFS = new MemoryFS(); | |
| 257 | |
| 258 options.output = {filename: bundleFilename, path: "/"}; | |
| 259 let webpackCompiler = webpack(options); | |
| 260 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.
| |
| 261 return new Promise((resolve, reject) => | |
| 262 { | |
| 263 webpackCompiler.run((err, stats) => | |
| 264 { | |
| 265 // Error handling is based on this example | |
| 266 // https://webpack.js.org/api/node/#error-handling | |
| 267 if (err) | |
| 268 { | |
| 269 let reason = err.stack || err; | |
| 270 if (err.details) | |
| 271 reason += "\n" + err.details; | |
| 272 reject(reason); | |
| 273 } | |
| 274 else if (stats.hasErrors()) | |
| 275 reject(stats.toJson().errors); | |
| 276 else | |
| 277 { | |
| 278 let bundle = memoryFS.readFileSync("/" + bundleFilename, "utf-8"); | |
| 279 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.
| |
| 280 } | |
| 281 }); | |
| 282 }); | |
| 283 } | |
| 284 | |
| 285 function runBrowserTests(browserTestModules) | |
| 286 { | |
| 287 // We need to navigate to this directory because about:blank won't be allowed | |
| 288 // to load file:/// URLs. | |
| 289 let initialPage = require("url").format({ | |
| 290 protocol: "file", | |
| 291 slashes: "true", | |
| 292 pathname: path.resolve(process.cwd(), __dirname).split(path.sep).join("/") | |
| 293 }); | |
|
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.
| |
| 294 | |
| 295 let bootstrapPath = path.join(__dirname, "test", "browser", "_bootstrap.js"); | |
| 296 let nodeunitPath = path.join(__dirname, "node_modules", "nodeunit", | |
| 297 "examples", "browser", "nodeunit.js"); | |
| 298 | |
| 299 return connectRemoteInterface().then(async client => | 253 return connectRemoteInterface().then(async client => |
| 300 { | 254 { |
| 301 try | 255 try |
| 302 { | 256 { |
| 303 let {Runtime, Log, Console, Page} = client; | 257 let {Runtime, Log, Console} = client; |
| 304 | 258 |
| 305 await Log.enable(); | 259 await Log.enable(); |
| 306 Log.entryAdded(({entry}) => | 260 Log.entryAdded(({entry}) => |
| 307 { | 261 { |
| 308 reportMessage(entry.text, entry.level); | 262 reportMessage(entry.text, entry.level); |
| 309 }); | 263 }); |
| 310 | 264 |
| 311 await Console.enable(); | 265 await Console.enable(); |
| 312 Console.messageAdded(({message}) => | 266 Console.messageAdded(({message}) => |
| 313 { | 267 { |
| 314 reportMessage(message.text, message.level); | 268 reportMessage(message.text, message.level); |
| 315 }); | 269 }); |
| 316 | 270 |
| 317 await Page.navigate({url: initialPage}); | |
| 318 | |
| 319 await Runtime.enable(); | 271 await Runtime.enable(); |
| 320 | |
| 321 let bundleFilename = "bundle.js"; | |
| 322 let bundle = await webpackInMemory(bundleFilename, { | |
| 323 entry: bootstrapPath, | |
| 324 module: { | |
| 325 rules: [{ | |
| 326 resource: nodeunitPath, | |
| 327 // 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.
| |
| 328 // nodeunit as a global. Unfortunately the nodeunit browser example | |
| 329 // script is quite slopily put together, if exports isn't falsey it | |
| 330 // breaks! As a workaround we need to use script-loader, which means | |
| 331 // that exports is falsey for that script as a side-effect. | |
| 332 use: ["script-loader"] | |
| 333 }] | |
| 334 }, | |
| 335 resolve: { | |
| 336 alias: { | |
| 337 nodeunit$: nodeunitPath | |
| 338 }, | |
| 339 modules: [path.resolve(__dirname, "lib")] | |
| 340 } | |
| 341 }); | |
| 342 | |
| 343 let compileResult = await Runtime.compileScript({ | 272 let compileResult = await Runtime.compileScript({ |
| 344 expression: bundle, | 273 expression: script, |
| 345 sourceURL: bundleFilename, | 274 sourceURL: scriptName, |
| 346 persistScript: true | 275 persistScript: true |
| 347 }); | 276 }); |
| 348 if (compileResult.exceptionDetails) | 277 if (compileResult.exceptionDetails) |
| 349 throwException(compileResult.exceptionDetails, bootstrapPath); | 278 throwException(compileResult.exceptionDetails, scriptName); |
| 350 | 279 |
| 351 let runResult = await Runtime.runScript({ | 280 let runResult = await Runtime.runScript({ |
| 352 scriptId: compileResult.scriptId | 281 scriptId: compileResult.scriptId |
| 353 }); | 282 }); |
| 354 if (runResult.exceptionDetails) | 283 if (runResult.exceptionDetails) |
| 355 throwException(runResult.exceptionDetails, bootstrapPath); | 284 throwException(runResult.exceptionDetails, scriptName); |
| 356 | 285 |
| 357 let callResult = await Runtime.callFunctionOn({ | 286 let callResult = await Runtime.callFunctionOn({ |
| 358 objectId: runResult.result.objectId, | 287 objectId: runResult.result.objectId, |
| 359 functionDeclaration: "function(...modules) {return this(modules);}", | 288 functionDeclaration: "function(...args) { return this(...args); }", |
| 360 arguments: browserTestModules.map(module => ({value: module})) | 289 arguments: scriptArgs.map(arg => ({value: arg})) |
| 361 }); | 290 }); |
| 362 if (callResult.exceptionDetails) | 291 if (callResult.exceptionDetails) |
| 363 throwException(callResult.exceptionDetails, bootstrapPath); | 292 throwException(callResult.exceptionDetails, scriptName); |
| 364 | 293 |
| 365 let promiseResult = await Runtime.awaitPromise({ | 294 let promiseResult = await Runtime.awaitPromise({ |
| 366 promiseObjectId: callResult.result.objectId | 295 promiseObjectId: callResult.result.objectId |
| 367 }); | 296 }); |
| 368 if (promiseResult.exceptionDetails) | 297 if (promiseResult.exceptionDetails) |
| 369 throwException(promiseResult.exceptionDetails, bootstrapPath); | 298 throwException(promiseResult.exceptionDetails, scriptName); |
| 370 } | 299 } |
| 371 finally | 300 finally |
| 372 { | 301 { |
| 373 client.close(); | 302 client.close(); |
| 374 } | 303 } |
| 375 }); | 304 }); |
| 376 } | 305 } |
| 377 | 306 |
| 378 module.exports = function(browserTestFiles) | 307 module.exports = function(script, scriptName, ...scriptArgs) |
| 379 { | 308 { |
| 380 return ensureChromium().then(chromiumPath => | 309 return ensureChromium().then(chromiumPath => |
| 381 { | 310 { |
| 382 let child = startChromium(chromiumPath); | 311 let child = startChromium(chromiumPath); |
| 383 return Promise.race([ | 312 return Promise.race([ |
| 384 child.done, | 313 child.done, |
| 385 runBrowserTests( | 314 runScript(script, scriptName, scriptArgs) |
| 386 browserTestFiles.map( | |
| 387 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.
| |
| 388 ) | |
| 389 ) | |
| 390 ]).then(result => | 315 ]).then(result => |
| 391 { | 316 { |
| 392 child.kill(); | 317 child.kill(); |
| 393 return result; | 318 return result; |
| 394 }).catch(error => | 319 }).catch(error => |
| 395 { | 320 { |
| 396 child.kill(); | 321 child.kill(); |
| 397 throw error; | 322 throw error; |
| 398 }); | 323 }); |
| 399 }); | 324 }); |
| 400 }; | 325 }; |
| LEFT | RIGHT |