Skip to content

Instantly share code, notes, and snippets.

@maggiesavovska
Created October 4, 2017 16:32
Show Gist options
  • Save maggiesavovska/3002573f6bec1085a1dee888e0563348 to your computer and use it in GitHub Desktop.
Save maggiesavovska/3002573f6bec1085a1dee888e0563348 to your computer and use it in GitHub Desktop.
screenshot and image diff
/**
* @description
* Takes a screenshot of page.
* Stores screenshot url to be embedded in reporter
* Runs image diff
* @param {Object} options
* @param {Object} options.test - test object
* @param {String} [options.filename = 'screenshot'] - keyword for screenshot filename
* @param {String} options.filepath - path to folder where screenshots are stored
* @param {Bool} options.element - provide element selector if only element should be captured
*/
const sanitize = require('sanitize-filename');
const wdioScreenshot = require('wdio-screenshot');
const addContext = require('./addContext.es6').addContext;
const runGenerator = require('./run-generator.es6').runGenerator;
const resemble = require('node-resemble-js');
function scale(shrink, element){
// adjust scale to length of page
let pageHeight = 1500;
process.driver.execute(function(){
var body = document.body,
html = document.documentElement;
var pageHeight = Math.max( body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight );
return pageHeight;
}).then(function(res){
pageHeight = res;
}).catch(function(e){
console.log(e);
});
let scalePercent = '.40';
if(pageHeight > 1000){
scalePercent = '.30';
}
if(pageHeight > 1500){
scalePercent = '.20';
}
var s = '';
// if wdio screenshot not compatible
// scale page to get full screenshot
// scale more for mobile
if(!shrink){
s = 'scale(1)';
}else{
if(element){
s = 'scale(10)';
}else{
s = 'scale(' + scalePercent + ')';
}
}
if(element){
process.driver.execute(function(s, el, shrink){
$(el).css({
transform: s
});
if(shrink){
$(el).css({
'z-index': 1000,
position: 'fixed',
top:'40%',
left:'40%'
});
}else{
$(el).css({
transform:'scale(1)',
'z-index': 'inherit',
position: 'static',
top:'inherit',
left:'inherit'
});
}
//$(el)[0].scrollIntoView();
return 'done scaling';
}, s, element, shrink);
}else{
process.driver.execute(function(scale){
$('body').css({
transform: scale,
transformOrigin: 'left top'
});
return 'done scaling';
}, s);
}
};
exports.screenshot = function (options) {
console.log('in screenshot');
const addData = options.data == undefined ? {} : options.data;
let data;
return new Promise(function (resolve, reject) {
runGenerator(function *main(){
try{
let filename = options.filename + `_${process.cbProcessData.country}_`;
// file name cannot be too long or won't display on windows
filename = sanitize(filename).replace(/\s/g, '_') + utils.getDateStamp();
let p = `${options.filepath + filename}.png`;
let rp = path.normalize(`./screenshots/${filename}.png`);
if(addData){
data = Object.assign(addData, {spath:rp});
}else{
data = {spath:rp};
}
const driver = process.driver;
if(options.imageDiff == true){
// click on a non actionable element
// to make sure there is no hover state that will affect the diff
try{
const headlineVisible = yield process.driver.isVisible('div.blockHeadline');
if(headlineVisible){
yield process.driver.click('div.blockHeadline');
}
}catch(e){
console.log(e);
}
yield process.driver.pause(300);
const suiteDiffDir = path.join('./results/', options.suiteName);
const suiteDiffScreenshotDir = path.join(suiteDiffDir + '/screenshots');
const screenshotDiffName = path.join(suiteDiffScreenshotDir, `${options.filename}.png`);
var hideElement = function(selectors, hide){
var style;
for(var i = 0; i < selectors.length; i++){
var s = selectors[i];
var pid = document.querySelector(s);
if(pid){
if(hide){
pid.style['opacity'] = 0;
}else{
pid.style['opacity'] = 1;
}
style = pid.style;
}
}
return style;
};
var selectors = ['#cleverPurchaseId .accentuate',
'.cbProductActions a.CBHyperLink'];
// hide elements that create false positives
var d = yield driver.execute(hideElement, selectors, true);
var screenshotString = yield wdioScreenshot.makeDocumentScreenshot(driver, {});
var screenshot = new Buffer(screenshotString, 'base64');
// check if file already exists from last run
// if file doesn't exist create it
if(!fs.existsSync(screenshotDiffName)) {
if(!fs.existsSync(suiteDiffDir)){
fs.mkdirSync(suiteDiffDir);
fs.mkdirSync(suiteDiffScreenshotDir);
}
fs.writeFileSync(screenshotDiffName, screenshot);
return resolve();
} else{
// if previous file exists then do a diff
// if previous file exists then do a diff
resemble(screenshotDiffName)
.compareTo(screenshot)
.onComplete(function(data){
if (Number(data.misMatchPercentage) <= 0.01) {
return resolve();
} else {
const diffShotPath = path.join(options.filepath, `diff_${options.filename}.png`);
//save to report
data.getDiffImage().pack().pipe(fs.createWriteStream(diffShotPath));
const embedLink = path.normalize(`./screenshots/diff_${options.filename}.png`);
const edata = Object.assign({spath:embedLink}, data);
addContext(options.test, edata);
return resolve();
}
});
}
yield driver.execute(hideElement, selectors, false);
} else if(options.screenshot !== false){
if (options.element && !process.cbProcessData.ie8 && !options.forceScale) {
console.log('element screenshot');
yield wdioScreenshot.saveElementScreenshot(p, options.element, driver, {});
addContext(options.test, data);
return resolve();
} else if(options.element && !process.cbProcessData.ie8 && options.forceScale){
console.log('element screenshot scale');
scale(true, options.element);
yield process.driver.pause(300);
yield process.driver.saveScreenshot(p);
scale(false);
addContext(options.test, data);
return resolve();
}else if((process.cbProcessData.macos && process.cbProcessData.cloud && !process.cbProcessData.isMobile) || options.forceScale){
console.log('scale..');
// scale page for browsers that don't take full page screenshots
// also scale for mac os in cloud
scale(true);
yield process.driver.saveScreenshot(p);
scale(false);
addContext(options.test, data);
return resolve();
}else if(process.cbProcessData.ie8){
console.log('save screenshot');
yield process.driver.saveScreenshot(p);
addContext(options.test, data);
return resolve();
}else{
console.log('save document screenshot');
yield wdioScreenshot.saveDocumentScreenshot(p, driver, {});
console.log('screenshot done');
addContext(options.test, data);
console.log('add context done');
return resolve();
}
}
}catch(err){
console.log(err);
reject();
}
});//end
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment