bf59dfa1f38c50e74b4f80c0f1b4c093d8e91216.svn-base 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. (function(){
  2. "use strict;";
  3. var wd = require('wd'),
  4. http = require("http"),
  5. https = require("https"),
  6. url = require("url"),
  7. path = require("path"),
  8. base64_arraybuffer = require('base64-arraybuffer'),
  9. PNG = require('pngjs').PNG,
  10. Promise = require('bluebird'),
  11. _ = require('lodash'),
  12. humanizeDuration = require("humanize-duration"),
  13. fs = require("fs");
  14. var utils = require('./utils');
  15. var colors = utils.colors;
  16. Promise.promisifyAll(fs);
  17. var port = 8080;
  18. function getPixelArray(base64) {
  19. return new Promise(function(resolve, reject) {
  20. const arraybuffer = base64_arraybuffer.decode(base64);
  21. new PNG().parse(arraybuffer, (error, data) => {
  22. if (error) {
  23. reject(error);
  24. } else {
  25. resolve(data.data);
  26. }
  27. });
  28. });
  29. }
  30. function calculateDifference(h2cPixels, screenPixels) {
  31. var len = h2cPixels.length, index = 0, diff = 0;
  32. for (; index < len; index++) {
  33. if (screenPixels[index] - h2cPixels[index] !== 0) {
  34. diff++;
  35. }
  36. }
  37. return (100 - (Math.round((diff/h2cPixels.length) * 10000) / 100));
  38. }
  39. function captureScreenshots(browser) {
  40. return function() {
  41. return Promise.props({
  42. dataUrl: browser.waitForElementByCss(".html2canvas", 15000).then(function(node) {
  43. return browser.execute("return arguments[0].toDataURL('image/png').substring(22)", [node]);
  44. }),
  45. screenshot: browser.takeScreenshot()
  46. });
  47. };
  48. }
  49. function analyzeResults(test) {
  50. return function(result) {
  51. return Promise.all([getPixelArray(result.dataUrl), getPixelArray(result.screenshot)]).spread(calculateDifference).then(function(accuracy) {
  52. return {
  53. testCase: test,
  54. accuracy: accuracy,
  55. dataUrl: result.dataUrl,
  56. screenshot: result.screenshot
  57. };
  58. });
  59. };
  60. }
  61. function runTestWithRetries(browser, test, retries) {
  62. retries = retries || 0;
  63. return runTest(browser, test)
  64. .timeout(60000)
  65. .catch(Promise.TimeoutError, function() {
  66. if (retries < 3) {
  67. console.log(colors.violet, "Retry", (retries + 1), test);
  68. return runTestWithRetries(browser, test, retries + 1);
  69. } else {
  70. throw new Error("Couldn't run test after 3 retries");
  71. }
  72. });
  73. }
  74. function runTest(browser, test) {
  75. return Promise.resolve(browser
  76. .then(utils.loadTestPage(browser, test, port))
  77. .then(captureScreenshots(browser))
  78. .then(analyzeResults(test)));
  79. }
  80. exports.tests = function(browsers, singleTest) {
  81. var path = "tests/cases";
  82. return (singleTest ? Promise.resolve([singleTest]) : utils.getTests(path)).then(function(tests) {
  83. return Promise.map(browsers, function(settings) {
  84. var browser = utils.initBrowser(settings);
  85. var name = [settings.browserName, settings.version, settings.platform].join("-");
  86. var count = 0;
  87. return Promise.using(browser, function() {
  88. return Promise.map(tests, function(test, index, total) {
  89. console.log(colors.green, "STARTING", "(" + (++count) + "/" + total + ")", name, test, colors.clear);
  90. var start = Date.now();
  91. return runTestWithRetries(browser, test).then(function(result) {
  92. console.log(colors.green, "COMPLETE", humanizeDuration(Date.now() - start), "(" + count + "/" + total + ")", name, result.testCase.substring(path.length), result.accuracy.toFixed(2) + "%", colors.clear);
  93. });
  94. }, {concurrency: 1})
  95. .settle()
  96. .catch(function(error) {
  97. console.log(colors.red, "ERROR", name, error.message);
  98. throw error;
  99. });
  100. });
  101. }, {concurrency: 3});
  102. });
  103. };
  104. })();