@percy/core
Advanced tools
Comparing version 1.29.4 to 1.29.5-beta.0
@@ -77,2 +77,8 @@ import fs from 'fs'; | ||
config: percy.config, | ||
widths: { | ||
// This is always needed even if width is passed | ||
mobile: percy.deviceDetails ? percy.deviceDetails.map(d => d.width) : [], | ||
// This will only be used if width is not passed in options | ||
config: percy.config.snapshot.widths | ||
}, | ||
success: true, | ||
@@ -227,2 +233,12 @@ type: percy.client.tokenType() | ||
percy.testing.version = body; | ||
} else if (cmd === 'config') { | ||
var _body$mobile; | ||
percy.config.snapshot.widths = body.config; | ||
percy.deviceDetails = (_body$mobile = body.mobile) === null || _body$mobile === void 0 ? void 0 : _body$mobile.map(w => { | ||
return { | ||
width: w | ||
}; | ||
}); | ||
percy.config.snapshot.responsiveSnapshotCapture = !!body.responsive; | ||
percy.config.percy.deferUploads = !!body.deferUploads; | ||
} else if (cmd === 'error' || cmd === 'disconnect') { | ||
@@ -229,0 +245,0 @@ var _percy$testing8; |
@@ -81,2 +81,6 @@ // Common config options used in Percy commands | ||
}, | ||
responsiveSnapshotCapture: { | ||
type: 'boolean', | ||
default: false | ||
}, | ||
testCase: { | ||
@@ -347,2 +351,5 @@ type: 'string' | ||
}, | ||
responsiveSnapshotCapture: { | ||
$ref: '/config/snapshot#/properties/responsiveSnapshotCapture' | ||
}, | ||
testCase: { | ||
@@ -608,4 +615,17 @@ $ref: '/config/snapshot#/properties/testCase' | ||
cookies: { | ||
oneOf: [{ | ||
type: 'string' | ||
}, { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
} | ||
}] | ||
}, | ||
userAgent: { | ||
type: 'string' | ||
}, | ||
width: { | ||
$ref: '/config/snapshot#/properties/widths/items' | ||
}, | ||
resources: { | ||
@@ -637,2 +657,7 @@ type: 'array', | ||
} | ||
}, { | ||
type: 'array', | ||
items: { | ||
$ref: '/snapshot#/$defs/dom/properties/domSnapshot/oneOf/1' | ||
} | ||
}] | ||
@@ -639,0 +664,0 @@ } |
@@ -56,2 +56,7 @@ import logger from '@percy/logger'; | ||
debugProp(snapshot, 'domSnapshot', Boolean); | ||
if (Array.isArray(snapshot.domSnapshot)) { | ||
debugProp(snapshot, 'domSnapshot.0.userAgent'); | ||
} else { | ||
debugProp(snapshot, 'domSnapshot.userAgent'); | ||
} | ||
for (let added of snapshot.additionalSnapshots || []) { | ||
@@ -66,5 +71,17 @@ log.debug(`Additional snapshot: ${added.name}`, snapshot.meta); | ||
// parse browser cookies in correct format if flag is enabled | ||
// it assumes that cookiesStr is string returned by document.cookie | ||
function parseCookies(cookiesStr) { | ||
if (process.env.PERCY_DO_NOT_USE_CAPTURED_COOKIES === 'true' || !(typeof cookiesStr === 'string' && cookiesStr !== '')) return null; | ||
function parseCookies(cookies) { | ||
if (process.env.PERCY_DO_NOT_USE_CAPTURED_COOKIES === 'true') return null; | ||
// If cookies is collected via SDK | ||
if (Array.isArray(cookies) && cookies.every(item => typeof item === 'object' && 'name' in item && 'value' in item)) { | ||
// omit other fields reason sometimes expiry comes as actual date where we expect it to be double | ||
return cookies.map(c => ({ | ||
name: c.name, | ||
value: c.value, | ||
secure: c.secure | ||
})); | ||
} | ||
if (!(typeof cookies === 'string' && cookies !== '')) return null; | ||
// it assumes that cookiesStr is string returned by document.cookie | ||
const cookiesStr = cookies; | ||
return cookiesStr.split('; ').map(c => { | ||
@@ -101,14 +118,30 @@ const eqIdx = c.indexOf('='); | ||
}) { | ||
if (!domSnapshot) return new Map(); | ||
let isHTML = typeof domSnapshot === 'string'; | ||
let { | ||
html, | ||
resources = [] | ||
} = isHTML ? { | ||
html: domSnapshot | ||
} : domSnapshot; | ||
let rootResource = createRootResource(url, html); | ||
const map = new Map(); | ||
if (!domSnapshot) return map; | ||
let allRootResources = new Set(); | ||
let allResources = new Set(); | ||
if (!Array.isArray(domSnapshot)) { | ||
domSnapshot = [domSnapshot]; | ||
} | ||
for (let dom of domSnapshot) { | ||
let isHTML = typeof dom === 'string'; | ||
let { | ||
html, | ||
resources = [] | ||
} = isHTML ? { | ||
html: dom | ||
} : dom; | ||
resources.forEach(r => allResources.add(r)); | ||
const attrs = dom.width ? { | ||
widths: [dom.width] | ||
} : {}; | ||
let rootResource = createRootResource(url, html, attrs); | ||
allRootResources.add(rootResource); | ||
} | ||
allRootResources = Array.from(allRootResources); | ||
map.set(allRootResources[0].url, allRootResources); | ||
allResources = Array.from(allResources); | ||
// reduce the array of resources into a keyed map | ||
return resources.reduce((map, { | ||
return allResources.reduce((map, { | ||
url, | ||
@@ -127,5 +160,17 @@ content, | ||
// the initial map is created with at least a root resource | ||
}, new Map([[rootResource.url, rootResource]])); | ||
}, map); | ||
} | ||
function createAndApplyPercyCSS({ | ||
percyCSS, | ||
roots | ||
}) { | ||
let css = createPercyCSSResource(roots[0].url, percyCSS); | ||
// replace root contents and associated properties | ||
roots.forEach(root => { | ||
Object.assign(root, createRootResource(root.url, root.content.replace(/(<\/body>)(?!.*\1)/is, `<link data-percy-specific-css rel="stylesheet" href="${css.pathname}"/>` + '$&'))); | ||
}); | ||
return css; | ||
} | ||
// Calls the provided callback with additional resources | ||
@@ -142,7 +187,7 @@ function processSnapshotResources({ | ||
// find any root resource matching the provided dom snapshot | ||
let rootContent = (domSnapshot === null || domSnapshot === void 0 ? void 0 : domSnapshot.html) ?? domSnapshot; | ||
let root = resources.find(r => r.content === rootContent); | ||
// since root resources are stored as array | ||
let roots = resources.find(r => Array.isArray(r)); | ||
// initialize root resources if needed | ||
if (!root) { | ||
if (!roots) { | ||
let domResources = parseDomResources({ | ||
@@ -153,3 +198,3 @@ ...snapshot, | ||
resources = [...domResources.values(), ...resources]; | ||
root = resources[0]; | ||
roots = resources.find(r => Array.isArray(r)); | ||
} | ||
@@ -164,9 +209,12 @@ | ||
} | ||
let css = createPercyCSSResource(root.url, snapshot.percyCSS); | ||
resources.push(css); | ||
// replace root contents and associated properties | ||
Object.assign(root, createRootResource(root.url, root.content.replace(/(<\/body>)(?!.*\1)/is, `<link data-percy-specific-css rel="stylesheet" href="${css.pathname}"/>` + '$&'))); | ||
const percyCSSReource = createAndApplyPercyCSS({ | ||
percyCSS: snapshot.percyCSS, | ||
roots | ||
}); | ||
resources.push(percyCSSReource); | ||
} | ||
// For multi dom root resources are stored as array | ||
resources = resources.flat(); | ||
// include associated snapshot logs matched by meta information | ||
@@ -192,3 +240,3 @@ resources.push(createLogResource(logger.query(log => { | ||
async function* captureSnapshotResources(page, snapshot, options) { | ||
var _snapshot$domSnapshot; | ||
var _snapshot$domSnapshot, _snapshot$domSnapshot2; | ||
const log = logger('core:discovery'); | ||
@@ -207,3 +255,4 @@ let { | ||
} = options; | ||
let cookies = parseCookies(snapshot === null || snapshot === void 0 || (_snapshot$domSnapshot = snapshot.domSnapshot) === null || _snapshot$domSnapshot === void 0 ? void 0 : _snapshot$domSnapshot.cookies); | ||
let cookies = (snapshot === null || snapshot === void 0 || (_snapshot$domSnapshot = snapshot.domSnapshot) === null || _snapshot$domSnapshot === void 0 ? void 0 : _snapshot$domSnapshot.cookies) || (snapshot === null || snapshot === void 0 || (_snapshot$domSnapshot2 = snapshot.domSnapshot) === null || _snapshot$domSnapshot2 === void 0 || (_snapshot$domSnapshot2 = _snapshot$domSnapshot2[0]) === null || _snapshot$domSnapshot2 === void 0 ? void 0 : _snapshot$domSnapshot2.cookies); | ||
cookies = parseCookies(cookies); | ||
@@ -246,8 +295,11 @@ // iterate over device to trigger reqeusts and capture other dpr width | ||
// used to resize the using capture options | ||
let resizePage = width => page.resize({ | ||
height: snapshot.minHeight, | ||
deviceScaleFactor, | ||
mobile, | ||
width | ||
}); | ||
let resizePage = width => { | ||
page.network.intercept.currentWidth = width; | ||
return page.resize({ | ||
height: snapshot.minHeight, | ||
deviceScaleFactor, | ||
mobile, | ||
width | ||
}); | ||
}; | ||
@@ -257,3 +309,4 @@ // navigate to the url | ||
yield page.goto(snapshot.url, { | ||
cookies | ||
cookies, | ||
forceReload: discovery.captureResponsiveAssetsEnabled | ||
}); | ||
@@ -282,3 +335,4 @@ | ||
// which will be already loaded after navigation complete | ||
if (discovery.captureSrcset) { | ||
// Don't run incase of responsiveSnapshotCapture since we are running discovery for all widths so images will get captured in all required widths | ||
if (!snapshot.responsiveSnapshotCapture && discovery.captureSrcset) { | ||
await page.insertPercyDom(); | ||
@@ -308,2 +362,8 @@ yield page.eval('window.PercyDOM.loadAllSrcsetLinks()'); | ||
yield resizePage(width = widths[i + 1]); | ||
if (snapshot.responsiveSnapshotCapture) { | ||
yield page.goto(snapshot.url, { | ||
cookies, | ||
forceReload: true | ||
}); | ||
} | ||
yield page.evaluate(execute === null || execute === void 0 ? void 0 : execute.afterResize); | ||
@@ -435,8 +495,16 @@ } | ||
disallowedHostnames: snapshot.discovery.disallowedHostnames, | ||
getResource: u => snapshot.resources.get(u) || cache.get(u), | ||
getResource: (u, width = null) => { | ||
let resource = snapshot.resources.get(u) || cache.get(u); | ||
if (resource && Array.isArray(resource) && resource[0].root) { | ||
const rootResource = resource.find(r => { | ||
var _r$widths; | ||
return (_r$widths = r.widths) === null || _r$widths === void 0 ? void 0 : _r$widths.includes(width); | ||
}); | ||
resource = rootResource || resource[0]; | ||
} | ||
return resource; | ||
}, | ||
saveResource: r => { | ||
snapshot.resources.set(r.url, r); | ||
if (!r.root) { | ||
cache.set(r.url, r); | ||
} | ||
cache.set(r.url, r); | ||
} | ||
@@ -443,0 +511,0 @@ } |
@@ -387,3 +387,3 @@ import { request as makeRequest } from '@percy/client/utils'; | ||
try { | ||
let resource = network.intercept.getResource(url); | ||
let resource = network.intercept.getResource(url, network.intercept.currentWidth); | ||
network.log.debug(`Handling request: ${url}`, meta); | ||
@@ -536,3 +536,3 @@ if (!(resource !== null && resource !== void 0 && resource.root) && hostnameMatches(disallowedHostnames, url)) { | ||
} | ||
if (resource) { | ||
if (resource && !resource.root) { | ||
network.intercept.saveResource(resource); | ||
@@ -539,0 +539,0 @@ } |
@@ -64,9 +64,17 @@ import fs from 'fs'; | ||
waitUntil = 'load', | ||
cookies | ||
cookies, | ||
forceReload, | ||
skipCookies = false | ||
} = {}) { | ||
this.log.debug(`Navigate to: ${url}`, this.meta); | ||
if (forceReload) { | ||
this.log.debug('Navigating to blank page', this.meta); | ||
await this.goto('about:blank', { | ||
skipCookies: true | ||
}); | ||
} | ||
let navigate = async () => { | ||
const userPassedCookie = this.session.browser.cookies; | ||
// set cookies before navigation so we can default the domain to this hostname | ||
if (userPassedCookie.length || cookies) { | ||
if (!skipCookies && (userPassedCookie.length || cookies)) { | ||
let defaultDomain = hostname(url); | ||
@@ -73,0 +81,0 @@ cookies = this.mergeCookies(userPassedCookie, cookies); |
@@ -115,4 +115,5 @@ import EventEmitter from 'events'; | ||
// here as a convenience since root resources are usually created outside of asset discovery. | ||
export function createRootResource(url, content) { | ||
export function createRootResource(url, content, attrs = {}) { | ||
return createResource(normalizeURL(url), content, 'text/html', { | ||
...attrs, | ||
root: true | ||
@@ -119,0 +120,0 @@ }); |
{ | ||
"name": "@percy/core", | ||
"version": "1.29.4", | ||
"version": "1.29.5-beta.0", | ||
"license": "MIT", | ||
@@ -12,3 +12,3 @@ "repository": { | ||
"access": "public", | ||
"tag": "latest" | ||
"tag": "beta" | ||
}, | ||
@@ -47,7 +47,7 @@ "engines": { | ||
"dependencies": { | ||
"@percy/client": "1.29.4", | ||
"@percy/config": "1.29.4", | ||
"@percy/dom": "1.29.4", | ||
"@percy/logger": "1.29.4", | ||
"@percy/webdriver-utils": "1.29.4", | ||
"@percy/client": "1.29.5-beta.0", | ||
"@percy/config": "1.29.5-beta.0", | ||
"@percy/dom": "1.29.5-beta.0", | ||
"@percy/logger": "1.29.5-beta.0", | ||
"@percy/webdriver-utils": "1.29.5-beta.0", | ||
"content-disposition": "^0.5.4", | ||
@@ -65,3 +65,3 @@ "cross-spawn": "^7.0.3", | ||
}, | ||
"gitHead": "17468058cf55d75557451a81e82b0d6fd5c0e26b" | ||
"gitHead": "1edb0e95570ca077e8ef931b53399c04d71a95bd" | ||
} |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
411989
5555
2
+ Added@percy/client@1.29.5-beta.0(transitive)
+ Added@percy/config@1.29.5-beta.0(transitive)
+ Added@percy/dom@1.29.5-beta.0(transitive)
+ Added@percy/env@1.29.5-beta.0(transitive)
+ Added@percy/logger@1.29.5-beta.0(transitive)
+ Added@percy/sdk-utils@1.29.5-beta.0(transitive)
+ Added@percy/webdriver-utils@1.29.5-beta.0(transitive)
- Removed@percy/client@1.29.4(transitive)
- Removed@percy/config@1.29.4(transitive)
- Removed@percy/dom@1.29.4(transitive)
- Removed@percy/env@1.29.4(transitive)
- Removed@percy/logger@1.29.4(transitive)
- Removed@percy/sdk-utils@1.29.4(transitive)
- Removed@percy/webdriver-utils@1.29.4(transitive)
Updated@percy/client@1.29.5-beta.0
Updated@percy/config@1.29.5-beta.0
Updated@percy/dom@1.29.5-beta.0
Updated@percy/logger@1.29.5-beta.0