mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-06 23:10:22 -05:00
fix: absolute positioning element blackouts in cy.screenshot (#22756)
* add regression tests * attempt to fix screenshot blacks basing blackouted element around container instead of body dimensions * move blackout test to screenshot viewport suite and update snapshot * add github issue to test
This commit is contained in:
@@ -337,7 +337,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
|
||||
}
|
||||
}
|
||||
|
||||
const before = ($el) => {
|
||||
const before = ($body, $container) => {
|
||||
return Promise.try(() => {
|
||||
if (disableTimersAndAnimations) {
|
||||
return cy.pauseTimers(true)
|
||||
@@ -349,11 +349,11 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
|
||||
// could fail if iframe is cross-origin, so fail gracefully
|
||||
try {
|
||||
if (disableTimersAndAnimations) {
|
||||
$dom.addCssAnimationDisabler($el)
|
||||
$dom.addCssAnimationDisabler($body)
|
||||
}
|
||||
|
||||
_.each(getBlackout(screenshotConfig), (selector) => {
|
||||
$dom.addBlackouts($el, selector)
|
||||
$dom.addBlackouts($body, $container, selector)
|
||||
})
|
||||
} catch (err) {
|
||||
/* eslint-disable no-console */
|
||||
@@ -366,14 +366,14 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
|
||||
})
|
||||
}
|
||||
|
||||
const after = ($el) => {
|
||||
const after = ($body) => {
|
||||
// could fail if iframe is cross-origin, so fail gracefully
|
||||
try {
|
||||
if (disableTimersAndAnimations) {
|
||||
$dom.removeCssAnimationDisabler($el)
|
||||
$dom.removeCssAnimationDisabler($body)
|
||||
}
|
||||
|
||||
$dom.removeBlackouts($el)
|
||||
$dom.removeBlackouts($body)
|
||||
} catch (err) {
|
||||
/* eslint-disable no-console */
|
||||
console.error('Failed to modify app dom:')
|
||||
@@ -417,7 +417,11 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
|
||||
? subject
|
||||
: $dom.wrap(state('document').documentElement)
|
||||
|
||||
return before($el)
|
||||
// get the current body of the AUT to accurately calculate screenshot blackouts
|
||||
// as well as properly enable/disable CSS animations while screenshotting is happening
|
||||
const $body = Cypress.$('body')
|
||||
|
||||
return before($body, $el)
|
||||
.then(() => {
|
||||
if (onBeforeScreenshot) {
|
||||
onBeforeScreenshot.call(state('ctx'), $el)
|
||||
@@ -444,7 +448,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
|
||||
|
||||
return props
|
||||
})
|
||||
.finally(() => after($el))
|
||||
.finally(() => after($body))
|
||||
}
|
||||
|
||||
interface InternalScreenshotOptions extends Partial<Cypress.Loggable & Cypress.Timeoutable & Cypress.ScreenshotOptions> {
|
||||
|
||||
@@ -32,11 +32,12 @@ function addBlackoutForElement ($body, $el) {
|
||||
$(`<div class="__cypress-blackout" style="${style}">`).appendTo($body)
|
||||
}
|
||||
|
||||
function addBlackouts ($body, selector) {
|
||||
function addBlackouts ($body, $container, selector) {
|
||||
let $el
|
||||
|
||||
try {
|
||||
$el = $body.find(selector)
|
||||
// only scope blacked out elements to to screenshotted element, not necessarily the whole body
|
||||
$el = $container.find(selector)
|
||||
if (!$el.length) return
|
||||
} catch (err) {
|
||||
// if it's an invalid selector, just ignore it
|
||||
|
||||
@@ -18,19 +18,20 @@ exports['e2e screenshot viewport capture / passes'] = `
|
||||
|
||||
|
||||
✓ takes consistent viewport captures
|
||||
✓ properly blacks out absolute elements within a relative container
|
||||
|
||||
1 passing
|
||||
2 passing
|
||||
|
||||
|
||||
(Results)
|
||||
|
||||
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Tests: 1 │
|
||||
│ Passing: 1 │
|
||||
│ Tests: 2 │
|
||||
│ Passing: 2 │
|
||||
│ Failing: 0 │
|
||||
│ Pending: 0 │
|
||||
│ Skipped: 0 │
|
||||
│ Screenshots: 26 │
|
||||
│ Screenshots: 27 │
|
||||
│ Video: true │
|
||||
│ Duration: X seconds │
|
||||
│ Spec Ran: screenshot_viewport_capture.cy.js │
|
||||
@@ -91,6 +92,8 @@ exports['e2e screenshot viewport capture / passes'] = `
|
||||
are (23).png
|
||||
- /XXX/XXX/XXX/cypress/screenshots/screenshot_viewport_capture.cy.js/viewport-comp (1000x660)
|
||||
are (24).png
|
||||
- /XXX/XXX/XXX/cypress/screenshots/screenshot_viewport_capture.cy.js/properly blac (400x400)
|
||||
ks out absolute elements within a relative container.png
|
||||
|
||||
|
||||
(Video)
|
||||
@@ -107,9 +110,9 @@ exports['e2e screenshot viewport capture / passes'] = `
|
||||
|
||||
Spec Tests Passing Failing Pending Skipped
|
||||
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ✔ screenshot_viewport_capture.cy.js XX:XX 1 1 - - - │
|
||||
│ ✔ screenshot_viewport_capture.cy.js XX:XX 2 2 - - - │
|
||||
└────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
✔ All specs passed! XX:XX 1 1 - - -
|
||||
✔ All specs passed! XX:XX 2 2 - - -
|
||||
|
||||
|
||||
`
|
||||
|
||||
@@ -26,3 +26,62 @@ it('takes consistent viewport captures', () => {
|
||||
Cypress._.times(25, fn)
|
||||
})
|
||||
})
|
||||
|
||||
// @see https://github.com/cypress-io/cypress/issues/22173
|
||||
it('properly blacks out absolute elements within a relative container', () => {
|
||||
cy.visit('cypress/fixtures/screenshot-blackout.html')
|
||||
.get('.centered-container')
|
||||
.screenshot({
|
||||
blackout: ['.blue'],
|
||||
onBeforeScreenshot () {
|
||||
const blackedOutElementCoordinates = Cypress.$(
|
||||
'#__cypress-animation-disabler+div.__cypress-blackout',
|
||||
)[0].getBoundingClientRect()
|
||||
|
||||
const actualElementCoordinates = Cypress.$(
|
||||
'.centered-container .blue',
|
||||
)[0].getBoundingClientRect()
|
||||
|
||||
// make sure blackout element is within 1 pixel of it's element it is supposed to black out
|
||||
expect(blackedOutElementCoordinates.bottom).to.be.closeTo(
|
||||
actualElementCoordinates.bottom,
|
||||
1,
|
||||
)
|
||||
|
||||
expect(blackedOutElementCoordinates.height).to.be.closeTo(
|
||||
actualElementCoordinates.height,
|
||||
1,
|
||||
)
|
||||
|
||||
expect(blackedOutElementCoordinates.left).to.be.closeTo(
|
||||
actualElementCoordinates.left,
|
||||
1,
|
||||
)
|
||||
|
||||
expect(blackedOutElementCoordinates.right).to.be.closeTo(
|
||||
actualElementCoordinates.right,
|
||||
1,
|
||||
)
|
||||
|
||||
expect(blackedOutElementCoordinates.top).to.be.closeTo(
|
||||
actualElementCoordinates.top,
|
||||
1,
|
||||
)
|
||||
|
||||
expect(blackedOutElementCoordinates.width).to.be.closeTo(
|
||||
actualElementCoordinates.width,
|
||||
1,
|
||||
)
|
||||
|
||||
expect(blackedOutElementCoordinates.x).to.be.closeTo(
|
||||
actualElementCoordinates.x,
|
||||
1,
|
||||
)
|
||||
|
||||
expect(blackedOutElementCoordinates.y).to.be.closeTo(
|
||||
actualElementCoordinates.y,
|
||||
1,
|
||||
)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.centered-container {
|
||||
position: relative;
|
||||
height: 400px;
|
||||
width: 400px;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.third-container {
|
||||
color: white;
|
||||
}
|
||||
.grey {
|
||||
background-color: grey;
|
||||
}
|
||||
.blue {
|
||||
background-color: blue;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0%;
|
||||
}
|
||||
.red {
|
||||
background-color: red;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 33.33%;
|
||||
}
|
||||
.purple {
|
||||
background-color: purple;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 66.66%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Screenshot Blackout Test Absolute Positioning</h1>
|
||||
<div class="centered-container grey">
|
||||
<div class="third-container blue"> Blue Container</div>
|
||||
<div class="third-container red"> Red Container</div>
|
||||
<div class="third-container purple"> Purple Container</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user