blob: 6ac4efcff8a2d4f7224953749fabd569da14a109 [file] [log] [blame]
// This script assumes the following:
// 1. You've installed wd with `npm install wd'.
// 2. You've set the environment variables $SAUCE_USERNAME and $SAUCE_ACCESS_KEY.
// 3. If the environment variable $CIRCLE_ARTIFACTS is not set images will be saved in /tmp
//
// This scripts creates following files for each browser in browserVersions:
// $CIRCLE_ARTIFACTS/imgs/{browser_version_platform}/#.png
//
// The intention of this script is that it will be ran from CircleCI
//
// Example usage:
// node screenshots.js http://localhost:9292/test/visual.html
// node screenshots.js http://google.com
var wd = require('wd');
var fs = require('fs');
var username = process.env['SAUCE_USERNAME'];
var accessKey = process.env['SAUCE_ACCESS_KEY'];
var baseDir = process.env['CIRCLE_ARTIFACTS'] || '/tmp';
var url = process.argv[2];
var allImgsDir = baseDir+'/imgs';
var build_name = process.env.MQ_CI_BUILD_NAME;
fs.mkdirSync(allImgsDir);
var browserVersions = [
{
'version': {
// Expecting IE 8
'browserName': 'Internet Explorer',
'platform': 'Windows XP'
},
'pinned': 'PINNED'
},
{
'version': {
// Expecting IE 11
'browserName': 'Internet Explorer',
'platform': 'Windows 7'
},
'pinned': 'PINNED'
},
{
'version': {
'browserName': 'MicrosoftEdge',
'platform': 'Windows 10'
},
'pinned': 'EVERGREEN'
},
{
'version': {
'browserName': 'Firefox',
'platform': 'OS X 10.11'
},
'pinned': 'EVERGREEN'
},
{
'version': {
'browserName': 'Safari',
'platform': 'OS X 10.11'
},
'pinned': 'EVERGREEN'
},
{
'version': {
'browserName': 'Chrome',
'platform': 'OS X 10.11'
},
'pinned': 'EVERGREEN'
},
{
'version': {
'browserName': 'Firefox',
'platform': 'Linux'
},
'pinned': 'EVERGREEN'
},
];
browserVersions.forEach(function(obj) {
var cfg = obj.version;
var browser = cfg.browserName.replace(/\s/g, '_');
var platform = cfg.platform.replace(/\s/g, '_');
var piecesDir = allImgsDir+'/'+obj.pinned+'_'+platform+'_'+browser;
cfg.build = build_name;
var browserDriver = wd.promiseChainRemote('ondemand.saucelabs.com', 80, username, accessKey);
return browserDriver.init(cfg)
.then(function(_, capabilities) {
console.log(cfg.browserName,cfg.platform,'init');
fs.mkdirSync(piecesDir);
return browserDriver;
})
.get(url)
.then(function() {
console.log(cfg.browserName,cfg.platform,'get');
return [browserDriver.safeExecute('document.documentElement.scrollHeight'),
browserDriver.safeExecute('document.documentElement.clientHeight')];
})
.spread(function(scrollHeight, viewportHeight) {
console.log(cfg.browserName, cfg.platform, 'get scrollHeight, clientHeight', scrollHeight, viewportHeight);
// Firefox and Internet Explorer will take a screenshot of the entire webpage,
if (cfg.browserName != 'Safari' && cfg.browserName != 'Chrome' && cfg.browserName != 'MicrosoftEdge') {
// saves file in the file `piecesDir/browser_version_platform/*.png`
var filename = piecesDir+'/'+browser+'_'+platform+'.png';
console.log(cfg.browserName, cfg.platform, 'about to saveScreenshot');
return browserDriver.saveScreenshot(filename)
.then(willLog(cfg.browserName,cfg.platform,'saveScreenshot'))
.then(function() {
return browserDriver.log('browser')
.then(willLog(cfg.browserName,cfg.platform,'log'), function(err) {
// the Edge/Internet Explorer drivers don't support logs, but the others do
console.log(cfg.browserName, cfg.platform, 'Error fetching logs:', JSON.stringify(err, null, 2));
return [];
});
})
.then(function(logs) {
var logfile = baseDir+'/'+browser+'_'+platform+'.log'
return new Promise(function(resolve, reject) {
fs.writeFile(logfile,logs.join('\n'), function(err) {
if (err) return reject(err);
return resolve(browserDriver.quit());
});
});
});
} else {
var scrollTop = 0;
// loop generates the images. Firefox and Internet Explorer will take
// a screenshot of the entire webpage, but Opera, Safari, and Chrome
// do not. For those browsers we scroll through the page and take
// incremental screenshots.
return (function loop() {
var index = (scrollTop/viewportHeight) + 1;
// saves file in the file `piecesDir/browser_version_platform/#.png`
var filename = piecesDir+'/'+index+'.png';
// Use `window.scrollTo` because thats what jQuery does
// https://github.com/jquery/jquery/blob/1.12.3/src/offset.js#L186
// `window.scrollTo` was used instead of jQuery because jQuery was
// causing a stackoverflow in Safari.
return browserDriver.safeEval('window.scrollTo(0,'+scrollTop+');')
.then(willLog(cfg.browserName,cfg.platform,'safeEval 1'))
.saveScreenshot(filename)
.then(function() {
console.log(cfg.browserName,cfg.platform,'saveScreenshot');
scrollTop += viewportHeight;
if (scrollTop + viewportHeight > scrollHeight) {
return browserDriver.getWindowSize()
.then(function(size) {
console.log(cfg.browserName,cfg.platform,'getWindowSize');
// account for the viewport offset
var extra = size.height - viewportHeight;
return browserDriver.setWindowSize(size.width, (scrollHeight-scrollTop)+extra)
.then(willLog(cfg.browserName,cfg.platform,'setWindowSize'))
.safeEval('window.scrollTo(0,'+scrollHeight+');')
.then(function() {
console.log(cfg.browserName,cfg.platform,'safeEval 2');
index++;
var filename = piecesDir+'/'+index+'.png';
return browserDriver.saveScreenshot(filename)
.then(willLog(cfg.browserName,cfg.platform,'saveScreenshot Final'))
.then(function() {
return browserDriver.log('browser')
.then(willLog(cfg.browserName,cfg.platform,'log'), function(err) {
// the Edge/Internet Explorer drivers don't support logs, but the others do
console.log(cfg.browserName, cfg.platform, 'Error fetching logs:', JSON.stringify(err, null, 2));
return [];
});
})
.then(function(logs) {
var logfile = baseDir+'/'+browser+'_'+platform+'.log'
return new Promise(function(resolve, reject) {
fs.writeFile(logfile,logs.join('\n'), function(err) {
if (err) return reject(err);
console.log(cfg.browserName,cfg.platform,'writeFile');
return resolve(browserDriver.quit());
});
});
});
});
});
} else {
return loop();
}
});
})();
}
})
.fail(function(err) {
console.log('ERROR:', cfg.browserName, cfg.platform);
console.log(JSON.stringify(err, null, 2));
});
function willLog() {
var msg = [].join.call(arguments, ' ');
return function(value) {
console.log(msg);
return value;
};
}
});