| Index: browsertests.js | 
| =================================================================== | 
| new file mode 100644 | 
| --- /dev/null | 
| +++ b/browsertests.js | 
| @@ -0,0 +1,228 @@ | 
| +/* | 
| + * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| + * Copyright (C) 2006-2016 Eyeo GmbH | 
| + * | 
| + * Adblock Plus is free software: you can redistribute it and/or modify | 
| + * it under the terms of the GNU General Public License version 3 as | 
| + * published by the Free Software Foundation. | 
| + * | 
| + * Adblock Plus is distributed in the hope that it will be useful, | 
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| + * GNU General Public License for more details. | 
| + * | 
| + * You should have received a copy of the GNU General Public License | 
| + * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| + */ | 
| + | 
| +"use strict"; | 
| + | 
| +try | 
| +{ | 
| +  var fs = require("fs"); | 
| +  var system = require("system"); | 
| +  var webpage = require("webpage"); | 
| + | 
| +  var nodeunitUrl = system.args[1]; | 
| +  var urls = system.args.slice(2); | 
| + | 
| +  // No need to load anything, about:blank will do for us | 
| +  var page = webpage.create(); | 
| +  page.evaluate(initPage, nodeunitUrl); | 
| +  window.setTimeout(function() | 
| +  { | 
| +    runTests(urls, function() | 
| +    { | 
| +      phantom.exit(); | 
| +    }); | 
| +  }, 0); | 
| +} | 
| +catch(e) | 
| +{ | 
| +  console.error(e); | 
| +  phantom.exit(); | 
| +} | 
| + | 
| +function runTests(urls, callback) | 
| +{ | 
| +  page.onError = function(msg, trace) | 
| +  { | 
| +    var message = "Error: " + msg + "\n"; | 
| +    if (trace) | 
| +    { | 
| +      for (var i = 0; i < trace.length; i++) | 
| +      { | 
| +        message += "\n  " + trace[i].file + ":" + trace[i].line + | 
| +                   (trace[i].function ? " in function " + trace[i].function | 
| +                                      : " in global code"); | 
| +      } | 
| +    } | 
| +    console.error(message); | 
| +  }; | 
| + | 
| +  page.onCallback = function(data) | 
| +  { | 
| +    function bold(str) | 
| +    { | 
| +      return "\u001B[1m" + str + "\u001B[22m"; | 
| +    } | 
| + | 
| +    function ok(str) | 
| +    { | 
| +      return "\u001B[32m" + str + "\u001B[39m"; | 
| +    } | 
| + | 
| +    function error(str) | 
| +    { | 
| +      return "\u001B[31m" + str + "\u001B[39m"; | 
| +    } | 
| + | 
| +    if (data.type == "moduleStart") | 
| +      console.log(bold(data.name)); | 
| +    else if (data.type == "testDone") | 
| +    { | 
| +      if (data.failures.length == 0) | 
| +        console.log("\u2714 " + data.name); | 
| +      else | 
| +      { | 
| +        console.log(error("\u2716 " + data.name) + "\n"); | 
| +        data.failures.forEach(function(failure) | 
| +        { | 
| +          console.log(failure.join("\n") + "\n"); | 
| +        }) | 
| +      } | 
| +    } | 
| +    else if (data.type == "done") | 
| +    { | 
| +      if (data.failures) | 
| +      { | 
| +        console.log( | 
| +          "\n" + | 
| +          bold(error("FAILURES: ")) + | 
| +          data.failures + "/" + data.assertions + " assertions failed" | 
| +        ); | 
| +      } | 
| +      else | 
| +      { | 
| +        console.log("\n" + bold(ok("OK: ")) + data.assertions + " assertions"); | 
| +      } | 
| + | 
| +      page.close(); | 
| +      callback(); | 
| +    } | 
| +    else if (data.type == "log") | 
| +    { | 
| +      console.log(data.args.join(" ")); | 
| +    } | 
| +    else if (data.type == "error") | 
| +    { | 
| +      console.error(data.args.join(" ")); | 
| +    } | 
| +  }; | 
| + | 
| +  page.evaluate(runTestsContent, urls); | 
| +} | 
| + | 
| +function initPage(nodeunitUrl) | 
| +{ | 
| +  function normalizeArgs(args) | 
| +  { | 
| +    var normalized = []; | 
| +    for (var i = 0; i < args.length; i++) | 
| +    { | 
| +      try | 
| +      { | 
| +        if (typeof args[i] == "string") | 
| +          normalized.push(args[i]); | 
| +        else | 
| +          normalized.push(JSON.stringify(args[i])); | 
| +      } | 
| +      catch (e) | 
| +      { | 
| +        normalized.push(String(args[i])); | 
| +      } | 
| +    } | 
| +    return normalized; | 
| +  } | 
| + | 
| +  window.console = { | 
| +    log: function() | 
| +    { | 
| +      window.callPhantom({type: "log", args: normalizeArgs(arguments)}); | 
| +    }, | 
| +    error: function() | 
| +    { | 
| +      window.callPhantom({type: "error", args: normalizeArgs(arguments)}); | 
| +    } | 
| +  }; | 
| + | 
| +  window.loadScript = function(url, callback) | 
| +  { | 
| +    var script = document.createElement("script"); | 
| +    script.src = url; | 
| +    script.async = false; | 
| +    document.head.appendChild(script); | 
| +    if (callback) | 
| +      window.setTimeout(callback, 0); | 
| +  }; | 
| + | 
| +  loadScript(nodeunitUrl); | 
| +} | 
| + | 
| +function runTestsContent(urls) | 
| +{ | 
| +  var modules = {}; | 
| + | 
| +  var loadNext = function() | 
| +  { | 
| +    if (urls.length) | 
| +    { | 
| +      window.exports = {}; | 
| +      window.module = {exports: window.exports}; | 
| + | 
| +      var url = urls.shift(); | 
| +      var name = url.split("/").pop(); | 
| +      loadScript(url, function() | 
| +      { | 
| +        modules[name] = nodeunit.testCase(window.module.exports); | 
| +        loadNext(); | 
| +      }); | 
| +    } | 
| +    else | 
| +    { | 
| +      nodeunit.runModules(modules, { | 
| +        moduleStart: function(name) | 
| +        { | 
| +          window.callPhantom({type: "moduleStart", name: name}); | 
| +        }, | 
| +        testDone: function(name, assertions) | 
| +        { | 
| +          var failures = assertions.filter(function(assertion) | 
| +          { | 
| +            return assertion.failed(); | 
| +          }).map(function(assertion) | 
| +          { | 
| +            return [String(assertion.error), assertion.error.stack]; | 
| +          }); | 
| +          window.callPhantom({ | 
| +            type: "testDone", | 
| +            name: name, | 
| +            failures: failures | 
| +          }); | 
| +        }, | 
| +        done: function(assertions) | 
| +        { | 
| +          window.callPhantom({ | 
| +            type: "done", | 
| +            assertions: assertions.length, | 
| +            failures: assertions.filter(function(assertion) | 
| +            { | 
| +              return assertion.failed(); | 
| +            }).length | 
| +          }); | 
| +        } | 
| +      }); | 
| +    } | 
| +  } | 
| +  loadNext(); | 
| +} | 
|  |