New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: absolute positioning element blackouts in cy.screenshot #22756
Changes from all commits
d4be4c3
77844cb
317a523
12724e2
1002b5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there possibly a cleaner way to reference the body here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prob isn't what you are looking for, but I think we store the AUT frame on the cypress instance There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is fine - since the |
||
|
||
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> { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm open to better selectors here. This seems to be a bit of a coincidence that our blacked out elements are adjacent to the animation disabler element. Also the test assertions below aren't great, but at least should guarantee that the blacked out element is very close to the thing it's trying to black out. |
||
)[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, | ||
) | ||
}, | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we incrementally ad types as we go?
HTMLBodyElement
andHTMLElement
, in this case.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going to create a follow up PR to add types to the screenshot files since it's quite a bit of changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
opened #22768 against this branch and will rebase it once I merge this in