Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@percy/webdriver-utils

Package Overview
Dependencies
Maintainers
1
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@percy/webdriver-utils - npm Package Compare versions

Comparing version 1.28.8-beta.1 to 1.28.8-beta.2

dist/playwrightDriver.js

27

dist/index.js
import ProviderResolver from './providers/providerResolver.js';
import utils from '@percy/sdk-utils';
import PlaywrightProvider from './providers/playwrightProvider.js';
export default class WebdriverUtils {
static async automateScreenshot({
static async captureScreenshot({
sessionId,
commandExecutorUrl,
capabilities,
sessionCapabilites,
sessionCapabilities,
frameGuid,
pageGuid,
framework,
snapshotName,

@@ -15,11 +19,17 @@ clientInfo,

}) {
const log = utils.logger('webdriver-utils:automateScreenshot');
const log = utils.logger('webdriver-utils:captureScreenshot');
try {
const startTime = Date.now();
log.info(`[${snapshotName}] : Starting automate screenshot ...`);
const automate = ProviderResolver.resolve(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options, buildInfo);
log.debug(`[${snapshotName}] : Resolved provider ...`);
await automate.createDriver();
log.info(`[${snapshotName}] : Starting automate screenshot capture ...`);
let provider;
switch (framework ? framework.toLowerCase() : null) {
case 'playwright':
provider = new PlaywrightProvider(sessionId, frameGuid, pageGuid, clientInfo, environmentInfo, options, buildInfo);
break;
default:
provider = ProviderResolver.resolve(sessionId, commandExecutorUrl, capabilities, sessionCapabilities, clientInfo, environmentInfo, options, buildInfo);
}
await provider.createDriver();
log.debug(`[${snapshotName}] : Created driver ...`);
const comparisonData = await automate.screenshot(snapshotName, options);
const comparisonData = await provider.screenshot(snapshotName, options);
comparisonData.metadata.cliScreenshotStartTime = startTime;

@@ -35,4 +45,5 @@ comparisonData.metadata.cliScreenshotEndTime = Date.now();

log.error(`[${snapshotName}] : Error Log - ${e.toString()}`);
throw e; // Re-throw the error to maintain consistency in error handling
}
}
}

@@ -5,14 +5,17 @@ import utils from '@percy/sdk-utils';

import Tile from '../util/tile.js';
import NormalizeData from '../metadata/normalizeData.js';
import TimeIt from '../util/timing.js';
import MetaDataResolver from '../metadata/metaDataResolver.js';
import Driver from '../driver.js';
const log = utils.logger('webdriver-utils:automateProvider');
export default class AutomateProvider extends GenericProvider {
constructor(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options, buildInfo) {
super(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options, buildInfo);
this._markedPercy = false;
this.automateResults = null;
}
static supports(commandExecutorUrl) {
return commandExecutorUrl.includes(process.env.AA_DOMAIN || 'browserstack');
}
async createDriver() {
this.driver = new Driver(this.sessionId, this.commandExecutorUrl, this.capabilities);
log.debug(`Passed capabilities -> ${JSON.stringify(this.capabilities)}`);
const caps = await this.driver.getCapabilites();
log.debug(`Fetched capabilities -> ${JSON.stringify(caps)}`);
this.metaData = MetaDataResolver.resolve(this.driver, caps, this.capabilities);
}
async screenshot(name, {

@@ -55,58 +58,8 @@ ignoreRegionXpaths = [],

}
async percyScreenshotBegin(name) {
return await TimeIt.run('percyScreenshotBegin', async () => {
try {
let result = await this.browserstackExecutor('percyScreenshot', {
name,
percyBuildId: this.buildInfo.id,
percyBuildUrl: this.buildInfo.url,
state: 'begin'
});
// Selenium Hub, set status error Code to 13 if an error is thrown
// Handling error with Selenium dialect is != W3C
if ((result === null || result === void 0 ? void 0 : result.status) === 13) throw new Error((result === null || result === void 0 ? void 0 : result.value) || 'Got invalid error response');
this._markedPercy = result.success;
return result;
} catch (e) {
var _e$response, _JSON$parse, _e$response2;
log.debug(`[${name}] : Could not mark Automate session as percy`);
log.error(`[${name}] : error: ${e.toString()}`);
/**
* - Handling Error when dialect is W3C
* ERROR response format from SeleniumHUB `{
* sessionId: ...,
* status: 13,
* value: { error: '', message: ''}
* }
*/
const errResponse = (e === null || e === void 0 ? void 0 : (_e$response = e.response) === null || _e$response === void 0 ? void 0 : _e$response.body) && ((_JSON$parse = JSON.parse(e === null || e === void 0 ? void 0 : (_e$response2 = e.response) === null || _e$response2 === void 0 ? void 0 : _e$response2.body)) === null || _JSON$parse === void 0 ? void 0 : _JSON$parse.value) || {};
const errMessage = (errResponse === null || errResponse === void 0 ? void 0 : errResponse.message) || (errResponse === null || errResponse === void 0 ? void 0 : errResponse.error) || (e === null || e === void 0 ? void 0 : e.message) || (e === null || e === void 0 ? void 0 : e.error) || (e === null || e === void 0 ? void 0 : e.value) || e.toString();
throw new Error(errMessage);
}
});
}
async percyScreenshotEnd(name, error) {
return await TimeIt.run('percyScreenshotEnd', async () => {
try {
var _this$buildInfo, _this$options;
await this.browserstackExecutor('percyScreenshot', {
name,
percyScreenshotUrl: (_this$buildInfo = this.buildInfo) === null || _this$buildInfo === void 0 ? void 0 : _this$buildInfo.url,
status: error ? 'failure' : 'success',
statusMessage: error ? `${error}` : '',
state: 'end',
sync: (_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.sync
});
} catch (e) {
log.debug(`[${name}] : Could not execute percyScreenshot command for Automate`);
log.error(e);
}
});
}
async getTiles(fullscreen) {
var _this$options2;
var _this$options;
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
log.debug('Starting actual screenshotting phase');
const dpr = await this.metaData.devicePixelRatio();
const screenshotType = (_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.fullPage ? 'fullpage' : 'singlepage';
const screenshotType = (_this$options = this.options) !== null && _this$options !== void 0 && _this$options.fullPage ? 'fullpage' : 'singlepage';
const response = await TimeIt.run('percyScreenshot:screenshot', async () => {

@@ -148,16 +101,2 @@ return await this.browserstackExecutor('percyScreenshot', {

}
async browserstackExecutor(action, args) {
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
let options = args ? {
action,
arguments: args
} : {
action
};
let res = await this.driver.executeScript({
script: `browserstack_executor: ${JSON.stringify(options)}`,
args: []
});
return res;
}
async setDebugUrl() {

@@ -170,15 +109,4 @@ if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');

async getTag() {
var _automateCaps$os_vers, _ref;
var _this$metaData$orient;
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
if (!this.automateResults) throw new Error('Comparison tag details not available');
const automateCaps = this.automateResults.capabilities;
const normalizeTags = new NormalizeData();
let deviceName = this.automateResults.deviceName;
const osName = normalizeTags.osRollUp(automateCaps.os);
const osVersion = (_automateCaps$os_vers = automateCaps.os_version) === null || _automateCaps$os_vers === void 0 ? void 0 : _automateCaps$os_vers.split('.')[0];
const browserName = normalizeTags.browserRollUp(automateCaps.browserName, this.metaData.device());
const browserVersion = normalizeTags.browserVersionOrDeviceNameRollup(automateCaps.browserVersion, deviceName, this.metaData.device());
if (!this.metaData.device()) {
deviceName = `${osName}_${osVersion}_${browserName}_${browserVersion}`;
}
let {

@@ -189,15 +117,13 @@ width,

const resolution = await this.metaData.screenResolution();
const orientation = (_ref = this.metaData.orientation() || automateCaps.deviceOrientation) === null || _ref === void 0 ? void 0 : _ref.toLowerCase();
return {
name: deviceName,
osName,
osVersion,
const orientation = (_this$metaData$orient = this.metaData.orientation()) === null || _this$metaData$orient === void 0 ? void 0 : _this$metaData$orient.toLowerCase();
const device = this.metaData.device();
const tagData = {
width,
height,
resolution,
orientation,
browserName,
browserVersion,
resolution
device
};
return await super.getTag(tagData);
}
}
import utils from '@percy/sdk-utils';
import TimeIt from '../util/timing.js';
import Tile from '../util/tile.js';
import Driver from '../../src/driver.js';
import MetaDataResolver from '../metadata/metaDataResolver.js';
import Tile from '../util/tile.js';
import Driver from '../driver.js';
import NormalizeData from '../metadata/normalizeData.js';
const log = utils.logger('webdriver-utils:genericProvider');
export default class GenericProvider {
clientInfo = new Set();
environmentInfo = new Set();
options = {};
constructor(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options, buildInfo) {
this.sessionId = sessionId;
this.commandExecutorUrl = commandExecutorUrl;
this.capabilities = capabilities;
this.sessionCapabilites = sessionCapabilites;
this.addClientInfo(clientInfo);
this.addEnvironmentInfo(environmentInfo);
this.options = options;
this.buildInfo = buildInfo;
this.driver = null;
clientInfoDetails = new Set();
environmentInfoDetails = new Set();
constructor(args) {
Object.assign(this, args);
this.addClientInfo(this.clientInfo);
this.addEnvironmentInfo(this.environmentInfo);
this._markedPercy = false;
this.metaData = null;
this.debugUrl = null;
this.driver = null;
this.header = 0;

@@ -39,3 +36,3 @@ this.footer = 0;

log.debug(`Fetched capabilities -> ${JSON.stringify(caps)}`);
this.metaData = await MetaDataResolver.resolve(this.driver, caps, this.capabilities);
this.metaData = MetaDataResolver.resolve(this.driver, caps, this.capabilities);
}

@@ -47,3 +44,3 @@ static supports(_commandExecutorUrl) {

for (let i of [].concat(info)) {
if (i) this.clientInfo.add(i);
if (i) this.clientInfoDetails.add(i);
}

@@ -53,3 +50,3 @@ }

for (let i of [].concat(info)) {
if (i) this.environmentInfo.add(i);
if (i) this.environmentInfoDetails.add(i);
}

@@ -80,2 +77,68 @@ }

}
async browserstackExecutor(action, args) {
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
let options = args ? {
action,
arguments: args
} : {
action
};
let res = await this.driver.executeScript({
script: `browserstack_executor: ${JSON.stringify(options)}`,
args: []
});
return res;
}
async percyScreenshotBegin(name) {
return await TimeIt.run('percyScreenshotBegin', async () => {
try {
let result = await this.browserstackExecutor('percyScreenshot', {
name,
percyBuildId: this.buildInfo.id,
percyBuildUrl: this.buildInfo.url,
state: 'begin'
});
// Selenium Hub, set status error Code to 13 if an error is thrown
// Handling error with Selenium dialect is != W3C
if ((result === null || result === void 0 ? void 0 : result.status) === 13) {
throw new Error((result === null || result === void 0 ? void 0 : result.value) || 'Got invalid error response');
}
this._markedPercy = result.success;
return result;
} catch (e) {
var _e$response, _JSON$parse, _e$response2;
log.debug(`[${name}] : Could not mark Automate session as percy`);
log.error(`[${name}] : error: ${e.toString()}`);
/**
* - Handling Error when dialect is W3C
* ERROR response format from SeleniumHUB `{
* sessionId: ...,
* status: 13,
* value: { error: '', message: ''}
* }
*/
const errResponse = (e === null || e === void 0 ? void 0 : (_e$response = e.response) === null || _e$response === void 0 ? void 0 : _e$response.body) && ((_JSON$parse = JSON.parse(e === null || e === void 0 ? void 0 : (_e$response2 = e.response) === null || _e$response2 === void 0 ? void 0 : _e$response2.body)) === null || _JSON$parse === void 0 ? void 0 : _JSON$parse.value) || {};
const errMessage = (errResponse === null || errResponse === void 0 ? void 0 : errResponse.message) || (errResponse === null || errResponse === void 0 ? void 0 : errResponse.error) || (e === null || e === void 0 ? void 0 : e.message) || (e === null || e === void 0 ? void 0 : e.error) || (e === null || e === void 0 ? void 0 : e.value) || e.toString();
throw new Error(errMessage);
}
});
}
async percyScreenshotEnd(name, error) {
return await TimeIt.run('percyScreenshotEnd', async () => {
try {
var _this$buildInfo, _this$options;
await this.browserstackExecutor('percyScreenshot', {
name,
percyScreenshotUrl: (_this$buildInfo = this.buildInfo) === null || _this$buildInfo === void 0 ? void 0 : _this$buildInfo.url,
status: error ? 'failure' : 'success',
statusMessage: error ? `${error}` : '',
state: 'end',
sync: (_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.sync
});
} catch (e) {
log.debug(`[${name}] : Could not execute percyScreenshot command for Automate`);
log.error(e);
}
});
}
async screenshot(name, {

@@ -117,4 +180,4 @@ ignoreRegionXpaths = [],

},
environmentInfo: [...this.environmentInfo].join('; '),
clientInfo: [...this.clientInfo].join(' '),
environmentInfo: this.getUserAgentString(this.environmentInfoDetails),
clientInfo: this.getUserAgentString(this.clientInfoDetails),
domInfoSha: tiles.domInfoSha,

@@ -124,2 +187,11 @@ metadata: tiles.metadata || null

}
getUserAgentString(data) {
let result = '';
if (data instanceof Set) {
result = [...data].join('; ');
} else if (typeof data === 'string') {
result = data;
}
return result;
}

@@ -159,22 +231,2 @@ // TODO: get dom sha for non-automate

}
async getTag() {
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
let {
width,
height
} = await this.metaData.windowSize();
const resolution = await this.metaData.screenResolution();
const orientation = this.metaData.orientation();
return {
name: this.metaData.deviceName(),
osName: this.metaData.osName(),
osVersion: this.metaData.osVersion(),
width,
height,
orientation: orientation,
browserName: this.metaData.browserName(),
browserVersion: this.metaData.browserVersion(),
resolution: resolution
};
}

@@ -186,3 +238,3 @@ // TODO: Add Debugging Url for non-automate

async doTransformations() {
var _this$options;
var _this$options2;
const hideScrollbarStyle = `

@@ -208,3 +260,3 @@ /* Hide scrollbar for Chrome, Safari and Opera */

});
if ((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.fullPage || this.isIOS()) {
if ((_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.fullPage || this.isIOS()) {
await this.getInitialScrollLocation();

@@ -237,7 +289,7 @@ }

async getRegionObjectFromBoundingBox(selector, element) {
var _this$options2;
var _this$options3;
const scaleFactor = await this.metaData.devicePixelRatio();
let scrollX = 0,
scrollY = 0;
if ((_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.fullPage) {
if ((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.fullPage) {
scrollX = this.initialScrollLocation.value[0];

@@ -278,3 +330,3 @@ scrollY = this.initialScrollLocation.value[1];

async updatePageShiftFactor(location, scaleFactor, scrollFactors) {
var _this$options3;
var _this$options4;
if (this.isIOS() || this.currentTag.osName === 'OS X' && parseInt(this.currentTag.browserVersion) > 13 && this.currentTag.browserName.toLowerCase() === 'safari') {

@@ -286,3 +338,3 @@ this.pageYShiftFactor = this.statusBarHeight;

this.pageXShiftFactor = this.isIOS() ? 0 : -(scrollFactors.value[0] * scaleFactor);
if (this.isIOS() && !((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.fullPage)) {
if (this.isIOS() && !((_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.fullPage)) {
if (scrollFactors.value[0] !== this.initialScrollLocation.value[0] || scrollFactors.value[1] !== this.initialScrollLocation.value[1]) {

@@ -297,3 +349,3 @@ this.pageXShiftFactor = -1 * this.removeElementShiftFactor;

async getRegionObject(selector, elementId) {
var _this$options4;
var _this$options5;
const scaleFactor = await this.metaData.devicePixelRatio();

@@ -312,3 +364,3 @@ const rect = await this.driver.rect(elementId);

const scrollFactors = await this.getScrollDetails();
if ((_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.fullPage) {
if ((_this$options5 = this.options) !== null && _this$options5 !== void 0 && _this$options5.fullPage) {
scrollX = scrollFactors.value[0];

@@ -379,2 +431,36 @@ scrollY = scrollFactors.value[1];

}
async getTag(tagData) {
var _automateCaps$os_vers;
if (!this.automateResults) throw new Error('Comparison tag details not available');
const automateCaps = this.automateResults.capabilities;
const normalizeTags = new NormalizeData();
let deviceName = this.automateResults.deviceName;
const osName = normalizeTags.osRollUp(automateCaps.os);
const osVersion = (_automateCaps$os_vers = automateCaps.os_version) === null || _automateCaps$os_vers === void 0 ? void 0 : _automateCaps$os_vers.split('.')[0];
const browserName = normalizeTags.browserRollUp(automateCaps.browserName, tagData.device);
const browserVersion = normalizeTags.browserVersionOrDeviceNameRollup(automateCaps.browserVersion, deviceName, tagData.device);
if (!tagData.device) {
deviceName = `${osName}_${osVersion}_${browserName}_${browserVersion}`;
}
let {
width,
height
} = {
width: tagData.width,
height: tagData.height
};
const resolution = tagData.resolution;
const orientation = tagData.orientation || automateCaps.deviceOrientation || 'landscape';
return {
name: deviceName,
osName,
osVersion,
width,
height,
orientation,
browserName,
browserVersion,
resolution
};
}
}

@@ -6,5 +6,15 @@ import GenericProvider from './genericProvider.js';

// We can safely do [0] because GenericProvider is catch all
const Klass = [AutomateProvider, GenericProvider].filter(x => x.supports(commandExecutorUrl))[0];
return new Klass(sessionId, commandExecutorUrl, capabilities, sessionCapabilities, clientInfo, environmentInfo, options, buildInfo);
const Klass = [AutomateProvider, GenericProvider].filter(provider => provider.supports(commandExecutorUrl))[0];
const args = {
sessionId,
commandExecutorUrl,
capabilities,
sessionCapabilities,
clientInfo,
environmentInfo,
options,
buildInfo
};
return new Klass(args);
}
}
{
"name": "@percy/webdriver-utils",
"version": "1.28.8-beta.1",
"version": "1.28.8-beta.2",
"license": "MIT",

@@ -32,6 +32,6 @@ "repository": {

"dependencies": {
"@percy/config": "1.28.8-beta.1",
"@percy/sdk-utils": "1.28.8-beta.1"
"@percy/config": "1.28.8-beta.2",
"@percy/sdk-utils": "1.28.8-beta.2"
},
"gitHead": "d31a9746c7be6d74db284b8f30c3248d2bba916e"
"gitHead": "6c954bcd0fa6a825ad636167f0a07251f124b710"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc