-
Notifications
You must be signed in to change notification settings - Fork 64
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
feat: add ability to disable animations in assertView #794
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
BREAKING CHANGE: assertView now disables animations by default
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,9 +33,27 @@ exports.prepareScreenshot = function prepareScreenshot(areas, opts) { | |
} | ||
}; | ||
|
||
exports.disableFrameAnimations = function disableFrameAnimations() { | ||
try { | ||
return disableFrameAnimationsUnsafe(); | ||
} catch (e) { | ||
return { | ||
error: "JS", | ||
message: e.stack || e.message | ||
}; | ||
} | ||
}; | ||
|
||
exports.cleanupFrameAnimations = function cleanupFrameAnimations() { | ||
if (window.__cleanupAnimation) { | ||
window.__cleanupAnimation(); | ||
} | ||
}; | ||
|
||
function prepareScreenshotUnsafe(areas, opts) { | ||
var allowViewportOverflow = opts.allowViewportOverflow; | ||
var captureElementFromTop = opts.captureElementFromTop; | ||
var disableAnimation = opts.disableAnimation; | ||
var scrollElem = window; | ||
|
||
if (opts.selectorToScroll) { | ||
|
@@ -102,6 +120,10 @@ function prepareScreenshotUnsafe(areas, opts) { | |
}; | ||
} | ||
|
||
if (disableAnimation) { | ||
disableFrameAnimationsUnsafe(); | ||
} | ||
|
||
return { | ||
captureArea: rect.scale(pixelRatio).serialize(), | ||
ignoreAreas: findIgnoreAreas(opts.ignoreSelectors, { | ||
|
@@ -125,6 +147,43 @@ function prepareScreenshotUnsafe(areas, opts) { | |
}; | ||
} | ||
|
||
function disableFrameAnimationsUnsafe() { | ||
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.
|
||
var everyElementSelector = "*:not(#hermione-q.hermione-w.hermione-e.hermione-r.hermione-t.hermione-y)"; | ||
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. А почему 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. Это не имеет значения. Главное, чтоб у селектора был и айдишник, и несколько классов, тогда он будет специфичнее даже селектора по айдишнику |
||
var everythingSelector = ["", "::before", "::after"] | ||
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. По итогу тут получаем сильный селектор, на который матчатся все элементы, |
||
.map(function (pseudo) { | ||
return everyElementSelector + pseudo; | ||
}) | ||
.join(", "); | ||
|
||
var styleElements = []; | ||
|
||
util.forEachRoot(function (root) { | ||
var styleElement = document.createElement("style"); | ||
styleElement.innerHTML = | ||
everythingSelector + | ||
[ | ||
"{", | ||
" animation-delay: 0ms !important;", | ||
" animation-duration: 0ms !important;", | ||
" animation-timing-function: step-start !important;", | ||
" transition-timing-function: step-start !important;", | ||
" scroll-behavior: auto !important;", | ||
"}" | ||
Comment on lines
+165
to
+171
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. отключаем анимации, транзишены и делаем "грубый" скролл |
||
].join("\n"); | ||
|
||
root.appendChild(styleElement); | ||
styleElements.push(styleElement); | ||
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. В этом массиве хранятся |
||
}); | ||
|
||
window.__cleanupAnimation = function () { | ||
for (var i = 0; i < styleElements.length; i++) { | ||
styleElements[i].remove(); | ||
} | ||
|
||
delete window.__cleanupAnimation; | ||
}; | ||
} | ||
|
||
exports.resetZoom = function () { | ||
var meta = lib.queryFirst('meta[name="viewport"]'); | ||
if (!meta) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,15 @@ const InvalidPngError = require("./errors/invalid-png-error"); | |
module.exports = browser => { | ||
const screenShooter = ScreenShooter.create(browser); | ||
const { publicAPI: session, config } = browser; | ||
const { assertViewOpts, compareOpts, compositeImage, screenshotDelay, tolerance, antialiasingTolerance } = config; | ||
const { | ||
assertViewOpts, | ||
compareOpts, | ||
compositeImage, | ||
screenshotDelay, | ||
tolerance, | ||
antialiasingTolerance, | ||
disableAnimation, | ||
} = config; | ||
|
||
const { handleNoRefImage, handleImageDiff } = getCaptureProcessors(); | ||
|
||
|
@@ -27,6 +35,7 @@ module.exports = browser => { | |
screenshotDelay, | ||
tolerance, | ||
antialiasingTolerance, | ||
disableAnimation, | ||
}); | ||
|
||
const { hermioneCtx } = session.executionContext; | ||
|
@@ -44,6 +53,7 @@ module.exports = browser => { | |
allowViewportOverflow: opts.allowViewportOverflow, | ||
captureElementFromTop: opts.captureElementFromTop, | ||
selectorToScroll: opts.selectorToScroll, | ||
disableAnimation: opts.disableAnimation, | ||
}); | ||
|
||
const { tempOpts } = RuntimeConfig.getInstance(); | ||
|
@@ -55,7 +65,9 @@ module.exports = browser => { | |
"screenshotDelay", | ||
"selectorToScroll", | ||
]); | ||
const currImgInst = await screenShooter.capture(page, screenshoterOpts); | ||
const currImgInst = await screenShooter | ||
.capture(page, screenshoterOpts) | ||
.finally(() => browser.cleanupScreenshot(opts)); | ||
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.
|
||
const currSize = await currImgInst.getSize(); | ||
const currImg = { path: temp.path(Object.assign(tempOpts, { suffix: ".png" })), size: currSize }; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,9 +83,21 @@ module.exports = class ExistingBrowser extends Browser { | |
`Prepare screenshot failed with error type '${result.error}' and error message: ${result.message}`, | ||
); | ||
} | ||
|
||
// https://github.com/webdriverio/webdriverio/issues/11396 | ||
if (this._config.automationProtocol === "webdriver" && opts.disableAnimation) { | ||
await this._disableIframeAnimations(); | ||
} | ||
Comment on lines
+87
to
+90
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. В |
||
|
||
return result; | ||
} | ||
|
||
async cleanupScreenshot(opts = {}) { | ||
if (opts.disableAnimation) { | ||
await this._cleanupPageAnimations(); | ||
} | ||
} | ||
|
||
open(url) { | ||
return this._session.url(url); | ||
} | ||
|
@@ -285,6 +297,51 @@ module.exports = class ExistingBrowser extends Browser { | |
.then(clientBridge => (this._clientBridge = clientBridge)); | ||
} | ||
|
||
async _runInEachIframe(cb) { | ||
const iframes = await this._session.findElements("css selector", "iframe"); | ||
|
||
try { | ||
for (const iframe of iframes) { | ||
await this._session.switchToFrame(iframe); | ||
await cb(); | ||
} | ||
} finally { | ||
await this._session.switchToParentFrame(); | ||
} | ||
} | ||
|
||
async _disableFrameAnimations() { | ||
const result = await this._clientBridge.call("disableFrameAnimations"); | ||
|
||
if (result && result.error) { | ||
throw new Error( | ||
`Disable animations failed with error type '${result.error}' and error message: ${result.message}`, | ||
); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
async _disableIframeAnimations() { | ||
await this._runInEachIframe(() => this._disableFrameAnimations()); | ||
} | ||
|
||
async _cleanupFrameAnimations() { | ||
return this._clientBridge.call("cleanupFrameAnimations"); | ||
} | ||
|
||
async _cleanupIframeAnimations() { | ||
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. Я бы для этого метода и |
||
await this._runInEachIframe(() => this._cleanupFrameAnimations()); | ||
} | ||
|
||
async _cleanupPageAnimations() { | ||
await this._cleanupFrameAnimations(); | ||
|
||
if (this._config.automationProtocol === "webdriver") { | ||
await this._cleanupIframeAnimations(); | ||
} | ||
} | ||
|
||
_stubCommands() { | ||
for (let commandName of this._session.commandList) { | ||
if (commandName === "deleteSession") { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ module.exports = { | |
diffColor: "#ff00ff", | ||
tolerance: 2.3, | ||
antialiasingTolerance: 4, | ||
disableAnimation: true, | ||
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. breaking change 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. Для hermione@7 нужно выставить в |
||
compareOpts: { | ||
shouldCluster: false, | ||
clustersSize: 10, | ||
|
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.
В процессе отключения анимации, в руты вставляются style-элементы.
Эта функция
__cleanupAnimation
убирает из DOM-дерева эти элементы