2012-12-28 21:41:14 +04:00
|
|
|
(function(){
|
2013-05-29 18:53:47 +04:00
|
|
|
"use strict;";
|
2014-09-17 01:11:47 +04:00
|
|
|
var wd = require('wd'),
|
2013-05-29 18:53:47 +04:00
|
|
|
http = require("http"),
|
2013-05-29 22:16:28 +04:00
|
|
|
https = require("https"),
|
2013-05-29 18:53:47 +04:00
|
|
|
url = require("url"),
|
|
|
|
path = require("path"),
|
|
|
|
base64_arraybuffer = require('base64-arraybuffer'),
|
|
|
|
PNG = require('png-js'),
|
2014-09-17 01:11:47 +04:00
|
|
|
Promise = require('bluebird'),
|
|
|
|
_ = require('lodash'),
|
|
|
|
humanizeDuration = require("humanize-duration"),
|
2014-05-18 18:39:24 +04:00
|
|
|
fs = require("fs");
|
2013-05-29 18:53:47 +04:00
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
Promise.promisifyAll(fs);
|
|
|
|
|
2013-05-29 18:53:47 +04:00
|
|
|
var port = 8080,
|
|
|
|
colors = {
|
|
|
|
red: "\x1b[1;31m",
|
|
|
|
blue: "\x1b[1;36m",
|
|
|
|
violet: "\x1b[0;35m",
|
|
|
|
green: "\x1b[0;32m",
|
|
|
|
clear: "\x1b[0m"
|
|
|
|
};
|
2012-12-28 01:06:47 +04:00
|
|
|
|
2013-05-29 18:53:47 +04:00
|
|
|
function getTests(path) {
|
2014-09-17 01:11:47 +04:00
|
|
|
return fs.readdirAsync(path).map(function(name) {
|
|
|
|
var filename = path + "/" + name;
|
|
|
|
return fs.statAsync(filename).then(function(stat) {
|
|
|
|
return stat.isDirectory() ? getTests(filename) : filename;
|
|
|
|
});
|
|
|
|
});
|
2012-12-28 01:06:47 +04:00
|
|
|
}
|
|
|
|
|
2013-05-29 18:53:47 +04:00
|
|
|
function getPixelArray(base64) {
|
2014-09-17 01:11:47 +04:00
|
|
|
return new Promise(function(resolve) {
|
2013-05-29 18:53:47 +04:00
|
|
|
var arraybuffer = base64_arraybuffer.decode(base64);
|
2014-09-17 01:11:47 +04:00
|
|
|
(new PNG(arraybuffer)).decodePixels(resolve);
|
2013-05-29 18:53:47 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function calculateDifference(h2cPixels, screenPixels) {
|
|
|
|
var len = h2cPixels.length, index = 0, diff = 0;
|
|
|
|
for (; index < len; index++) {
|
|
|
|
if (screenPixels[index] - h2cPixels[index] !== 0) {
|
|
|
|
diff++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (100 - (Math.round((diff/h2cPixels.length) * 10000) / 100));
|
|
|
|
}
|
2012-12-28 21:41:14 +04:00
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
function initBrowser(settings) {
|
|
|
|
var browser = wd.remote({
|
|
|
|
hostname: 'localhost',
|
|
|
|
port: 4445,
|
|
|
|
user: process.env.SAUCE_USERNAME,
|
|
|
|
pwd: process.env.SAUCE_ACCESS_KEY
|
|
|
|
}, 'promiseChain');
|
2014-05-18 18:39:24 +04:00
|
|
|
|
2014-05-18 22:37:56 +04:00
|
|
|
if (process.env.TRAVIS_JOB_NUMBER) {
|
2014-09-17 01:11:47 +04:00
|
|
|
settings["tunnel-identifier"] = process.env.TRAVIS_JOB_NUMBER;
|
|
|
|
settings["name"] = process.env.TRAVIS_COMMIT.substring(0, 10);
|
|
|
|
settings["build"] = process.env.TRAVIS_BUILD_NUMBER;
|
2014-08-26 22:03:54 +04:00
|
|
|
} else {
|
2014-09-17 01:11:47 +04:00
|
|
|
settings["name"] = "Manual run";
|
2014-05-18 22:37:56 +04:00
|
|
|
}
|
2014-05-18 21:25:51 +04:00
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
return browser.resolve(Promise).init(settings).setImplicitWaitTimeout(15000).then(function() {
|
|
|
|
return settings;
|
2013-09-06 23:30:24 +04:00
|
|
|
});
|
2014-09-17 01:11:47 +04:00
|
|
|
}
|
2013-09-06 23:30:24 +04:00
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
function loadTestPage(browser, test) {
|
|
|
|
return function(settings) {
|
|
|
|
return browser.get("http://localhost:" + port + "/" + test + "?selenium").then(function() {
|
|
|
|
return settings;
|
2014-09-09 20:54:13 +04:00
|
|
|
});
|
2014-09-17 01:11:47 +04:00
|
|
|
};
|
2013-09-06 23:30:24 +04:00
|
|
|
}
|
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
function captureScreenshots(browser) {
|
|
|
|
return function() {
|
|
|
|
return Promise.props({
|
|
|
|
dataUrl: browser.elementByCss(".html2canvas").then(function(node) {
|
|
|
|
return browser.execute("return arguments[0].toDataURL('image/png').substring(22)", [node]);
|
|
|
|
}),
|
|
|
|
screenshot: browser.takeScreenshot()
|
|
|
|
});
|
|
|
|
};
|
2013-09-06 23:30:24 +04:00
|
|
|
}
|
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
function analyzeResults(test) {
|
|
|
|
return function(result) {
|
|
|
|
return Promise.all([getPixelArray(result.dataUrl), getPixelArray(result.screenshot)]).spread(calculateDifference).then(function(accuracy) {
|
|
|
|
return {
|
|
|
|
testCase: test,
|
|
|
|
accuracy: accuracy,
|
|
|
|
dataUrl: result.dataUrl,
|
|
|
|
screenshot: result.screenshot
|
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
2013-09-06 23:30:24 +04:00
|
|
|
}
|
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
function runTestWithRetries(browser, test, retries) {
|
|
|
|
retries = retries || 0;
|
|
|
|
return runTest(browser, test)
|
|
|
|
.timeout(60000)
|
|
|
|
.catch(Promise.TimeoutError, function() {
|
|
|
|
if (retries < 3) {
|
2014-09-20 22:09:18 +04:00
|
|
|
console.log(colors.violet, "Retry", (retries + 1), test);
|
2014-09-17 01:11:47 +04:00
|
|
|
return runTestWithRetries(browser, test, retries + 1);
|
|
|
|
} else {
|
|
|
|
throw new Error("Couldn't run test after 3 retries");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2014-05-19 00:31:49 +04:00
|
|
|
|
2014-09-17 01:11:47 +04:00
|
|
|
function runTest(browser, test) {
|
2014-09-20 22:09:18 +04:00
|
|
|
return Promise.resolve(browser
|
2014-09-17 01:11:47 +04:00
|
|
|
.then(loadTestPage(browser, test))
|
|
|
|
.then(captureScreenshots(browser))
|
2014-09-20 22:09:18 +04:00
|
|
|
.then(analyzeResults(test))).cancellable();
|
2013-05-29 18:53:47 +04:00
|
|
|
}
|
|
|
|
|
2014-08-26 22:03:54 +04:00
|
|
|
exports.tests = function(browsers, singleTest) {
|
2014-09-17 01:11:47 +04:00
|
|
|
var path = "tests/cases";
|
|
|
|
return (singleTest ? Promise.resolve([singleTest]) : getTests(path)).then(function(t) {
|
|
|
|
var tests = _.flatten(t);
|
|
|
|
return Promise.map(browsers, function(settings) {
|
|
|
|
var browser = initBrowser(settings);
|
|
|
|
var name = [settings.browserName, settings.version, settings.platform].join("-");
|
|
|
|
var count = 0;
|
|
|
|
return Promise.map(tests, function(test, index, total) {
|
|
|
|
console.log(colors.green, "STARTING", "(" + (++count) + "/" + total + ")", name, test, colors.clear);
|
|
|
|
var start = Date.now();
|
|
|
|
return runTestWithRetries(browser, test).then(function(result) {
|
|
|
|
console.log(colors.green, "COMPLETE", humanizeDuration(Date.now() - start), "(" + count + "/" + total + ")", name, result.testCase.substring(path.length), result.accuracy.toFixed(2) + "%", colors.clear);
|
|
|
|
});
|
|
|
|
}, {concurrency: 1})
|
|
|
|
.settle()
|
|
|
|
.catch(function(error) {
|
|
|
|
console.log(colors.red, "ERROR", name, error.message);
|
|
|
|
throw error;
|
|
|
|
})
|
|
|
|
.finally(function() {
|
|
|
|
return browser.quit();
|
|
|
|
});
|
|
|
|
}, {concurrency: 3});
|
|
|
|
});
|
2014-05-18 18:39:24 +04:00
|
|
|
};
|
|
|
|
})();
|