eyes.utils
Advanced tools
Comparing version 0.0.7 to 0.0.8
{ | ||
"name": "eyes.utils", | ||
"version": "0.0.7", | ||
"version": "0.0.8", | ||
"description": "General purpose Javascript utilities.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -19,10 +19,48 @@ /* | ||
/** | ||
* Waits a specified amount of time before resolving the returned promise. | ||
* @param {int} ms The amount of time to sleep in milliseconds. | ||
* @return {Promise} A promise which is resolved when sleep is done. | ||
*/ | ||
var sleep = function (ms, promiseFactory) { | ||
return promiseFactory.makePromise(function(resolve) { | ||
setTimeout(function() { | ||
resolve(); | ||
}, ms); | ||
}); | ||
}; | ||
/** | ||
* Executes a script using the browser's executeScript function - and optionally waits a timeout. | ||
* @param {Object} browser - The driver using which to execute the script. | ||
* @param {string} script - The code to execute on the given driver. | ||
* @param {Object} - promiseFactory | ||
* @param {number|undefined} stabilizationTimeMs (optional) The amount of time to wait after script execution to | ||
* let the browser a chance to stabilize (e.g., finish rendering). | ||
* | ||
* @return {Promise} A promise which resolves to the result of the script's execution on the tab. | ||
*/ | ||
var executeScript = function (browser, script, promiseFactory, stabilizationTimeMs) { | ||
return browser.executeScript(script) | ||
.then(function(result) { | ||
if (stabilizationTimeMs) { | ||
return sleep(stabilizationTimeMs, promiseFactory) | ||
.then(function() { | ||
return result; | ||
}); | ||
} | ||
return result; | ||
}); | ||
}; | ||
/** | ||
* Gets the device pixel ratio. | ||
* | ||
* @param {WebDriver} browser The driver which will execute the script to get the ratio. | ||
* @param {Object} - promiseFactory | ||
* @return {Promise} A promise which resolves to the device pixel ratio (float type). | ||
*/ | ||
var getDevicePixelRatio = function (browser) { | ||
var getDevicePixelRatio = function (browser, promiseFactory) { | ||
//noinspection JSUnresolvedVariable | ||
return browser.executeScript('return window.devicePixelRatio') | ||
return executeScript(browser, 'return window.devicePixelRatio', promiseFactory, undefined) | ||
.then(function (results) { | ||
@@ -37,32 +75,82 @@ return parseFloat(results); | ||
* @param {WebDriver} browser The driver which will execute the script to get the scroll position. | ||
* @param {Object} - promiseFactory | ||
* @return {Promise} A promise which resolves to the current scroll position ({top: *, left: *}). | ||
*/ | ||
var getCurrentScrollPosition = function (browser) { | ||
var getCurrentScrollPosition = function (browser, promiseFactory) { | ||
//noinspection JSUnresolvedVariable | ||
return browser.executeScript( | ||
return executeScript(browser, | ||
'var doc = document.documentElement; ' + | ||
'var x = (window.scrollX || window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0); ' + | ||
'var y = (window.scrollY || window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); ' + | ||
'return [x,y]' | ||
).then(function (results) { | ||
// If we can't find the current scroll position, we use 0 as default. | ||
var x = parseInt(results[0], 10) || 0; | ||
var y = parseInt(results[1], 10) || 0; | ||
return {left: x, top: y}; | ||
}); | ||
'return [x,y]', promiseFactory, undefined) | ||
.then(function (results) { | ||
// If we can't find the current scroll position, we use 0 as default. | ||
var x = parseInt(results[0], 10) || 0; | ||
var y = parseInt(results[1], 10) || 0; | ||
return {left: x, top: y}; | ||
}); | ||
}; | ||
var scrollTo = function (browser, point) { | ||
return browser.executeScript( | ||
'window.scrollTo(' + parseInt(point.left, 10) + ', ' + parseInt(point.top, 10) + ');' | ||
); | ||
/** | ||
* Get the current transform of page. | ||
* @param {WebDriver} browser The driver which will execute the script to get the scroll position. | ||
* @param {Object} - promiseFactory | ||
* @return {Promise} A promise which resolves to the current transform value. | ||
*/ | ||
var getCurrentTransform = function (browser, promiseFactory) { | ||
return executeScript(browser, "return document.body.style.transform", promiseFactory); | ||
}; | ||
/** | ||
* Set the current transform of the current page. | ||
* @param {WebDriver} browser The driver which will execute the script to set the transform. | ||
* @param {string} transformToSet The transform to set. | ||
* @param {Object} - promiseFactory | ||
* | ||
* @return {Promise} A promise which resolves to the previous transform once the updated transform is set. | ||
*/ | ||
var setTransform = function (browser, transformToSet, promiseFactory) { | ||
if (!transformToSet) { | ||
transformToSet = ''; | ||
} | ||
return executeScript(browser, | ||
"var originalTransform = document.body.style.transform; " + | ||
"document.body.style.transform = '" + transformToSet + "'; " + | ||
"originalTransform", | ||
promiseFactory, 250); | ||
}; | ||
/** | ||
* CSS translate the document to a given location. | ||
* @param {WebDriver} browser The driver which will execute the script to set the transform. | ||
* @param {Object} Point - left; top;. | ||
* @param {Object} - promiseFactory | ||
* @return {Promise} A promise which resolves to the previous transfrom when the scroll is executed. | ||
*/ | ||
var translateTo = function (browser, point, promiseFactory) { | ||
return setTransform(browser, 'translate(-' + point.left + 'px, -' + point.top + 'px)', promiseFactory); | ||
}; | ||
/** | ||
* Scroll to the specified position. | ||
* | ||
* @param {WebDriver} browser - The driver which will execute the script to set the scroll position. | ||
* @param {Object} - point to scroll to | ||
* @param {Object} - promiseFactory | ||
* @return {Promise} A promise which resolves after the action is perfromed and timeout passed. | ||
*/ | ||
var scrollTo = function (browser, point, promiseFactory) { | ||
return executeScript(browser, | ||
'window.scrollTo(' + parseInt(point.left, 10) + ', ' + parseInt(point.top, 10) + ');', | ||
promiseFactory, 100); | ||
}; | ||
/** | ||
* Get the entire page size. | ||
* | ||
* @param {WebDriver} browser The driver used to query the web page. | ||
* @param {Object} - promiseFactory | ||
* @return {Promise} A promise which resolves to an object containing the width/height of the page. | ||
*/ | ||
var getEntirePageSize = function (browser) { | ||
var getEntirePageSize = function (browser, promiseFactory) { | ||
// IMPORTANT: Notice there's a major difference between scrollWidth | ||
@@ -73,5 +161,7 @@ // and scrollHeight. While scrollWidth is the maximum between an | ||
// maximum between them. | ||
return browser.executeScript('return [document.documentElement.scrollWidth, document.body.scrollWidth, ' | ||
return executeScript(browser, | ||
'return [document.documentElement.scrollWidth, document.body.scrollWidth, ' | ||
+ 'document.documentElement.clientHeight, document.body.clientHeight, ' | ||
+ 'document.documentElement.scrollHeight, document.body.scrollHeight];') | ||
+ 'document.documentElement.scrollHeight, document.body.scrollHeight];', | ||
promiseFactory) | ||
.then(function (results) { | ||
@@ -103,6 +193,6 @@ // Notice that each result is itself actually an array (since executeScript returns an Array). | ||
*/ | ||
var setOverflow = function (browser, overflowValue) { | ||
return browser.executeScript( | ||
var setOverflow = function (browser, overflowValue, promiseFactory) { | ||
return executeScript(browser, | ||
'var origOF = document.documentElement.style.overflow; document.documentElement.style.overflow = "' | ||
+ overflowValue + '"; origOF'); | ||
+ overflowValue + '"; origOF', promiseFactory, 100); | ||
}; | ||
@@ -117,6 +207,7 @@ | ||
* @param {Object} imageSize The width and height. | ||
* @param {Object} - promiseFactory | ||
* @return {Promise} A promise which resolves to the normalization factor (float). | ||
*/ | ||
var findImageNormalizationFactor = function (browser, imageSize, viewportSize) { | ||
return getEntirePageSize(browser) | ||
var findImageNormalizationFactor = function (browser, imageSize, viewportSize, promiseFactory) { | ||
return getEntirePageSize(browser, promiseFactory) | ||
.then(function (entirePageSize) { | ||
@@ -127,3 +218,3 @@ if (imageSize.width === viewportSize.width || imageSize.width === entirePageSize.width) { | ||
return getDevicePixelRatio(browser) | ||
return getDevicePixelRatio(browser, promiseFactory) | ||
.then(function (ratio) { | ||
@@ -135,4 +226,4 @@ return 1 / ratio; | ||
var _processPart = function (part, parts, imageObj, browser, promise, promiseFactory, sizeFactor) { | ||
return promise.then(function() { | ||
var _processPart = function (part, parts, imageObj, browser, promise, promiseFactory, sizeFactor, useCssTransition) { | ||
return promise.then(function () { | ||
return promiseFactory.makePromise(function (resolve) { | ||
@@ -153,19 +244,21 @@ // Skip 0,0 as we already got the screenshot | ||
var partImage; | ||
var partCoords = {left: part.left, top: part.top}; | ||
var partCoordsNormalized = {left: part.left / sizeFactor, top: part.top / sizeFactor}; | ||
var promise = useCssTransition ? | ||
translateTo(browser, partCoordsNormalized, promiseFactory).then(function () { | ||
currentPosition = partCoords; | ||
}) : | ||
scrollTo(browser, partCoordsNormalized, promiseFactory).then(function () { | ||
return getCurrentScrollPosition(browser, promiseFactory).then(function (position) { | ||
currentPosition = {left: position.left * sizeFactor, top: position.top * sizeFactor}; | ||
}); | ||
}); | ||
scrollTo(browser, {left: part.left / sizeFactor, top: part.top / sizeFactor}) | ||
.then(function () { | ||
return browser.controlFlow().timeout(100); | ||
}) | ||
.then(function () { | ||
return getCurrentScrollPosition(browser); | ||
}) | ||
.then(function (position) { | ||
currentPosition = {left: position.left * sizeFactor, top: position.top * sizeFactor}; | ||
return browser.takeScreenshot(); | ||
}) | ||
.then(function (part64) { | ||
var partImage = new MutableImage(new Buffer(part64, 'base64'), promiseFactory); | ||
return partImage.asObject(); | ||
}) | ||
.then(function (partObj) { | ||
return promise.then(function () { | ||
return browser.takeScreenshot().then(function (part64) { | ||
partImage = new MutableImage(new Buffer(part64, 'base64'), promiseFactory); | ||
}); | ||
}) | ||
.then(function () { | ||
return partImage.asObject().then(function (partObj) { | ||
parts.push({ | ||
@@ -179,11 +272,14 @@ image: partObj.imageBuffer, | ||
}); | ||
}); | ||
}); | ||
}); | ||
}; | ||
} | ||
var getFullPageScreenshot = function (browser, promiseFactory, viewportSize) { | ||
var MAX_SCROLL_BAR_SIZE = 50; // This should cover all scroll bars (and some fixed position footer elements :). | ||
var getFullPageScreenshot = function (browser, promiseFactory, viewportSize, hideScrollbars, useCssTransition) { | ||
var MIN_SCREENSHOT_PART_HEIGHT = 10; | ||
var maxScrollbarSize = useCssTransition ? 0 : 50; // This should cover all scroll bars (and some fixed position footer elements :). | ||
var sizeFactor = 1; | ||
var originalScrollPosition, | ||
originalOverflow, | ||
originalTransform, | ||
entirePageSize, | ||
@@ -194,36 +290,53 @@ imageObject, | ||
return promiseFactory.makePromise(function (resolve) { | ||
return getCurrentScrollPosition(browser) | ||
.then(function(point) { | ||
return getCurrentScrollPosition(browser, promiseFactory).then(function(point) { | ||
originalScrollPosition = point; | ||
return scrollTo(browser, {left: 0, top: 0}); | ||
return scrollTo(browser, {left: 0, top: 0}, promiseFactory).then(function() { | ||
return getCurrentScrollPosition(browser, promiseFactory).then(function(point) { | ||
if (point.left != 0 || point.top != 0) { | ||
throw new Error("Could not scroll to the top/left corner of the screen"); | ||
} | ||
}); | ||
}); | ||
}) | ||
.then(function () { | ||
return getCurrentScrollPosition(browser); | ||
.then(function() { | ||
if (useCssTransition) { | ||
return getCurrentTransform(browser, promiseFactory).then(function(transform) { | ||
originalTransform = transform; | ||
// Translating to "top/left" of the page (notice this is different from Javascript scrolling). | ||
return translateTo(browser, {left: 0, top: 0}, promiseFactory); | ||
}); | ||
} | ||
}) | ||
.then(function(point) { | ||
if (point.left != 0 || point.top != 0) { | ||
throw new Error("Could not scroll to the top/left corner of the screen"); | ||
.then(function() { | ||
if (hideScrollbars) { | ||
setOverflow(browser, "hidden", promiseFactory).then(function(originalVal) { | ||
originalOverflow = originalVal; | ||
}); | ||
} | ||
return getEntirePageSize(browser); | ||
}) | ||
.then(function(pageSize) { | ||
entirePageSize = pageSize; | ||
.then(function() { | ||
return getEntirePageSize(browser, promiseFactory).then(function(pageSize) { | ||
entirePageSize = pageSize; | ||
}); | ||
}) | ||
.then(function() { | ||
// Take screenshot of the 0,0 tile | ||
return browser.takeScreenshot(); | ||
return browser.takeScreenshot().then(function(screenshot64) { | ||
screenshot = new MutableImage(new Buffer(screenshot64, 'base64'), promiseFactory); | ||
return screenshot.asObject().then(function(imageObj) { | ||
imageObject = imageObj; | ||
}); | ||
}); | ||
}) | ||
.then(function(screenshot64) { | ||
screenshot = new MutableImage(new Buffer(screenshot64, 'base64'), promiseFactory); | ||
return screenshot.asObject(); | ||
}) | ||
.then(function(imageObj) { | ||
imageObject = imageObj; | ||
return findImageNormalizationFactor(browser, imageObj, viewportSize); | ||
}).then(function(factor) { | ||
if (factor === 0.5) { | ||
sizeFactor = 2; | ||
entirePageSize.width *= sizeFactor; | ||
entirePageSize.height *= sizeFactor; | ||
entirePageSize.width = Math.max(entirePageSize.width, imageObject.width); | ||
} | ||
.then(function() { | ||
return findImageNormalizationFactor(browser, imageObject, viewportSize, promiseFactory) | ||
.then(function(factor) { | ||
if (factor === 0.5) { | ||
sizeFactor = 2; | ||
entirePageSize.width *= sizeFactor; | ||
entirePageSize.height *= sizeFactor; | ||
entirePageSize.width = Math.max(entirePageSize.width, imageObject.width); | ||
} | ||
}); | ||
}).then(function() { | ||
return promiseFactory.makePromise(function (resolve) { | ||
@@ -241,3 +354,3 @@ // IMPORTANT This is required! Since when calculating the screenshot parts for full size, | ||
width: imageObject.width, | ||
height: Math.max(imageObject.height - (MAX_SCROLL_BAR_SIZE * sizeFactor), | ||
height: Math.max(imageObject.height - (maxScrollbarSize * sizeFactor), | ||
MIN_SCREENSHOT_PART_HEIGHT * sizeFactor) | ||
@@ -255,14 +368,27 @@ }; | ||
screenshotParts.forEach(function (part) { | ||
promise = _processPart(part, parts, imageObject, browser, promise, promiseFactory, sizeFactor); | ||
promise = _processPart(part, parts, imageObject, browser, promise, | ||
promiseFactory, sizeFactor, useCssTransition); | ||
}); | ||
promise.then(function () { | ||
return ImageUtils.stitchImage(entirePageSize, parts, promiseFactory); | ||
}).then(function (stitchedBuffer) { | ||
screenshot = new MutableImage(stitchedBuffer, promiseFactory); | ||
resolve(); | ||
return ImageUtils.stitchImage(entirePageSize, parts, promiseFactory).then(function (stitchedBuffer) { | ||
screenshot = new MutableImage(stitchedBuffer, promiseFactory); | ||
resolve(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
.then(function() { | ||
if (hideScrollbars) { | ||
return setOverflow(browser, originalOverflow, promiseFactory); | ||
} | ||
}) | ||
.then(function () { | ||
return scrollTo(browser, originalScrollPosition); | ||
if (useCssTransition) { | ||
return setTransform(browser, originalTransform, promiseFactory).then(function() { | ||
return scrollTo(browser, originalScrollPosition, promiseFactory); | ||
}); | ||
} else { | ||
return scrollTo(browser, originalScrollPosition, promiseFactory); | ||
} | ||
}) | ||
@@ -279,2 +405,7 @@ .then(function() { | ||
BrowserUtils.getCurrentScrollPosition = getCurrentScrollPosition; | ||
BrowserUtils.getCurrentTransform = getCurrentTransform; | ||
BrowserUtils.sleep = sleep; | ||
BrowserUtils.executeScript = executeScript; | ||
BrowserUtils.setTransform = setTransform; | ||
BrowserUtils.translateTo = translateTo; | ||
BrowserUtils.scrollTo = scrollTo; | ||
@@ -281,0 +412,0 @@ BrowserUtils.getEntirePageSize = getEntirePageSize; |
@@ -50,5 +50,5 @@ /* | ||
* @param region The region from which we want to extract the sub regions. {left, top, width, height} | ||
* @param maxSubRegionSize The max size of a sub region {width, height} | ||
* @param subRegionSize The max size of a sub region {width, height} | ||
*/ | ||
GeometryUtils.getSubRegions = function (region, maxSubRegionSize) { | ||
GeometryUtils.getSubRegions = function (region, subRegionSize) { | ||
var subRegions = []; | ||
@@ -58,8 +58,11 @@ var currentTop = region.top; | ||
var right = region.left + region.width; | ||
var subRegionWidth = Math.min(region.width, subRegionSize.width); | ||
var subRegionHeight = Math.min(region.height, subRegionSize.height); | ||
var currentBottom, currentLeft, currentRight, currentWidth, currentHeight; | ||
var currentBottom, currentLeft, currentRight; | ||
while (currentTop < bottom) { | ||
currentBottom = currentTop + maxSubRegionSize.height; | ||
currentBottom = currentTop + subRegionHeight; | ||
if (currentBottom > bottom) { | ||
currentBottom = bottom; | ||
currentTop = currentBottom - subRegionHeight; | ||
} | ||
@@ -69,15 +72,13 @@ | ||
while (currentLeft < right) { | ||
currentRight = currentLeft + maxSubRegionSize.width; | ||
currentRight = currentLeft + subRegionWidth; | ||
if (currentRight > right) { | ||
currentRight = right; | ||
currentLeft = currentRight - subRegionWidth; | ||
} | ||
currentHeight = currentBottom - currentTop; | ||
currentWidth = currentRight - currentLeft; | ||
subRegions.push({left: currentLeft, top: currentTop, width: subRegionWidth, height: subRegionHeight}); | ||
subRegions.push({left: currentLeft, top: currentTop, width: currentWidth, height: currentHeight}); | ||
currentLeft += maxSubRegionSize.width; | ||
currentLeft += subRegionWidth; | ||
} | ||
currentTop += maxSubRegionSize.height; | ||
currentTop += subRegionHeight; | ||
} | ||
@@ -84,0 +85,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
63790
1374