UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

147 lines (110 loc) 5.43 kB
/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ /** @class Siesta.Recorder.Role.CanRecordScroll A mixin, providing the feature of recording the "scroll" event. */ Role('Siesta.Recorder.Role.CanRecordScroll', { has : { /** * @cfg {Boolean} recordScroll Set this option to `true` to enable recording of `scroll` events. * This even occurs, when some element on the page, or the page itself, is scrolled by user. * Several consequent `scroll` events on the same element will be merged into one `scrollTo` action. * * Note, that when replaying scripts, recorded with this option enabled, you might want to disable * the {@link Siesta.Project.Browser#autoScrollElementsIntoView autoScrollElementsIntoView} option, * as it will be interfering with the recorded actions. */ recordScroll : false }, override : { initialize : function () { var me = this; me.SUPERARG(arguments); me.onScrollEvent = me.onScrollEvent.bind(me); }, onStart : function () { this.SUPERARG(arguments); var win = this.window; var doc = win.document; // Observe scroll events if (this.recordScroll) { doc.addEventListener('scroll', this.onScrollEvent, true); } }, onStop : function () { this.SUPERARG(arguments); var win = this.window; var doc = win.document; if (this.recordScroll) { doc.removeEventListener('scroll', this.onScrollEvent, true); } }, // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign sign : Math.sign || function(x) { // If x is NaN, the result is NaN. // If x is -0, the result is -0. // If x is +0, the result is +0. // If x is negative and not -0, the result is -1. // If x is positive and not +0, the result is +1. return ((x > 0) - (x < 0)) || +x; }, isSameScrollDirection : function (scrollEvent) { var me = this; var lastAction = this.getLastAction() var win = me.window var doc = win.document var target = scrollEvent.target; if (target === doc) target = this.getElForPageScroll(win); var xSign = this.sign(target.scrollLeft - lastAction.value[0]); var ySign = this.sign(target.scrollTop - lastAction.value[1]); return lastAction.xSign === this.sign(target.scrollLeft - lastAction.value[0]) && lastAction.ySign === this.sign(target.scrollTop - lastAction.value[1]); }, onScrollEvent : function (scrollEvent) { var me = this; var target = scrollEvent.target; var win = me.window var doc = win.document var lastAction = this.getLastAction() // note that "target" here is unchanged and can be a document if (lastAction && lastAction.action === 'scrollTo' && target === lastAction.sourceEvent.target && (typeof lastAction.xSign !== 'number' || this.isSameScrollDirection(scrollEvent))) { // repeated scroll on the same target if (target === doc) target = this.getElForPageScroll(win); lastAction.xSign = this.sign(target.scrollLeft - lastAction.value[0]); lastAction.ySign = this.sign(target.scrollTop - lastAction.value[1]); lastAction.value[0] = target.scrollLeft; lastAction.value[1] = target.scrollTop; this.fireEvent('actionupdate', lastAction) } else { var isPageScroll; // scroll on the new target // page scroll events are fired with document as target, switch it to use body element if (target === doc) { isPageScroll = true; target = this.getElForPageScroll(win); } var cursorPosition = this.cursorPosition // For page scroll we have no way of knowing if it was triggered by direct scrolling or side effect // So always record it if (cursorPosition.length === 2 && !isPageScroll) { var viewportX = this.pageXtoViewportX(cursorPosition[ 0 ], win) var viewportY = this.pageYtoViewportY(cursorPosition[ 1 ], win) // Ignore scroll if cursor is outside of scroll target // we consider such scrolls as happened because of side-effect of some other user action if (!this.isPointWithinElement(viewportX, viewportY, target)) return } this.addAction({ action : 'scrollTo', target : this.getPossibleTargets(scrollEvent, false, target), value : [ target.scrollLeft, target.scrollTop ], sourceEvent : Siesta.Recorder.Event.fromDomEvent(scrollEvent) }) } } } });