siesta-lite
Version:
Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers
147 lines (110 loc) • 5.43 kB
JavaScript
/*
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)
})
}
}
}
});