How to use inputListener method in devicefarmer-stf

Best JavaScript code snippet using devicefarmer-stf

MultiListener.js

Source:MultiListener.js Github

copy

Full Screen

1// Copyright 2017, University of Colorado Boulder2/**3 * TODO: doc4 *5 * TODO: unit tests6 *7 * TODO: add example usage8 *9 * @author Jonathan Olson <jonathan.olson@colorado.edu>10 */11define( function( require ) {12 'use strict';13 var inherit = require( 'PHET_CORE/inherit' );14 var arrayRemove = require( 'PHET_CORE/arrayRemove' );15 var Vector2 = require( 'DOT/Vector2' );16 var Matrix = require( 'DOT/Matrix' );17 var SingularValueDecomposition = require( 'DOT/SingularValueDecomposition' );18 var Matrix3 = require( 'DOT/Matrix3' );19 var scenery = require( 'SCENERY/scenery' );20 /**21 * @constructor22 *23 * @param {Node} targetNode - The Node that should be transformed by this MultiListener.24 * @param {Object} [options] - See the constructor body (below) for documented options.25 */26 function MultiListener( targetNode, options ) {27 var self = this;28 options = _.extend( {29 mouseButton: 0, // TODO: see PressListener30 pressCursor: 'pointer', // TODO: see PressListener31 targetNode: null, // TODO: required? pass in at front32 allowScale: true,33 allowRotation: true,34 allowMultitouchInterruption: false35 }, options );36 // TODO: type checks for options37 this._targetNode = targetNode;38 this._mouseButton = options.mouseButton;39 this._pressCursor = options.pressCursor;40 this._allowScale = options.allowScale;41 this._allowRotation = options.allowRotation;42 this._allowMultitouchInterruption = options.allowMultitouchInterruption;43 // @private {Array.<Press>}44 this._presses = [];45 // @private {Array.<Press>}46 this._backgroundPresses = [];47 // @private48 this._pressListener = {49 move: function( event ) {50 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener pointer move' );51 sceneryLog && sceneryLog.InputListener && sceneryLog.push();52 self.movePress( self.findPress( event.pointer ) );53 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();54 },55 up: function( event ) {56 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener pointer up' );57 sceneryLog && sceneryLog.InputListener && sceneryLog.push();58 // TODO: consider logging press on the pointer itself?59 self.removePress( self.findPress( event.pointer ) );60 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();61 },62 cancel: function( event ) {63 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener pointer cancel' );64 sceneryLog && sceneryLog.InputListener && sceneryLog.push();65 var press = self.findPress( event.pointer );66 press.interrupted = true;67 self.removePress( press );68 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();69 },70 interrupt: function() {71 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener pointer interrupt' );72 sceneryLog && sceneryLog.InputListener && sceneryLog.push();73 // For the future, we could figure out how to track the pointer that calls this74 self.interrupt();75 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();76 }77 };78 this._backgroundListener = {79 up: function( event ) {80 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener background up' );81 sceneryLog && sceneryLog.InputListener && sceneryLog.push();82 self.removeBackgroundPress( self.findBackgroundPress( event.pointer ) );83 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();84 },85 cancel: function( event ) {86 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener background cancel' );87 sceneryLog && sceneryLog.InputListener && sceneryLog.push();88 self.removeBackgroundPress( self.findBackgroundPress( event.pointer ) );89 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();90 },91 interrupt: function() {92 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener background interrupt' );93 sceneryLog && sceneryLog.InputListener && sceneryLog.push();94 self.removeBackgroundPress( self.findBackgroundPress( event.pointer ) );95 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();96 }97 };98 }99 scenery.register( 'MultiListener', MultiListener );100 inherit( Object, MultiListener, {101 findPress: function( pointer ) {102 for ( var i = 0; i < this._presses.length; i++ ) {103 if ( this._presses[ i ].pointer === pointer ) {104 return this._presses[ i ];105 }106 }107 assert && assert( false, 'Did not find press' );108 return null;109 },110 findBackgroundPress: function( pointer ) {111 // TODO: reduce duplication with findPress?112 for ( var i = 0; i < this._backgroundPresses.length; i++ ) {113 if ( this._backgroundPresses[ i ].pointer === pointer ) {114 return this._backgroundPresses[ i ];115 }116 }117 assert && assert( false, 'Did not find press' );118 return null;119 },120 // TODO: see PressListener121 down: function( event ) {122 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener down' );123 if ( event.pointer.isMouse && event.domEvent.button !== this._mouseButton ) {124 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener abort: wrong mouse button' );125 return;126 }127 sceneryLog && sceneryLog.InputListener && sceneryLog.push();128 assert && assert( _.includes( event.trail.nodes, this._targetNode ),129 'MultiListener down trail does not include targetNode?' );130 var press = new Press( event.pointer, event.trail.subtrailTo( this._targetNode, false ) );131 if ( !event.pointer.isAttached() ) {132 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener unattached, using press' );133 this.addPress( press );134 this.convertBackgroundPresses();135 }136 else if ( this._allowMultitouchInterruption ) {137 if ( this._presses.length || this._backgroundPresses.length ) {138 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener attached, interrupting for press' );139 press.pointer.interruptAttached();140 this.addPress( press );141 this.convertBackgroundPresses();142 }143 else {144 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener attached, adding background press' );145 this.addBackgroundPress( press );146 }147 }148 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();149 },150 addPress: function( press ) {151 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener addPress' );152 sceneryLog && sceneryLog.InputListener && sceneryLog.push();153 this._presses.push( press );154 press.pointer.cursor = this._pressCursor;155 press.pointer.addInputListener( this._pressListener, true );156 this.recomputeLocals();157 this.reposition();158 // TODO: handle interrupted?159 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();160 },161 movePress: function( press ) {162 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener movePress' );163 sceneryLog && sceneryLog.InputListener && sceneryLog.push();164 this.reposition();165 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();166 },167 removePress: function( press ) {168 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener removePress' );169 sceneryLog && sceneryLog.InputListener && sceneryLog.push();170 press.pointer.removeInputListener( this._pressListener );171 press.pointer.cursor = null;172 arrayRemove( this._presses, press );173 this.recomputeLocals();174 this.reposition();175 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();176 },177 addBackgroundPress: function( press ) {178 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener addBackgroundPress' );179 sceneryLog && sceneryLog.InputListener && sceneryLog.push();180 // TODO: handle turning background presses into main presses here181 this._backgroundPresses.push( press );182 press.pointer.addInputListener( this._backgroundListener, false );183 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();184 },185 removeBackgroundPress: function( press ) {186 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener removeBackgroundPress' );187 sceneryLog && sceneryLog.InputListener && sceneryLog.push();188 press.pointer.removeInputListener( this._backgroundListener );189 arrayRemove( this._backgroundPresses, press );190 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();191 },192 convertBackgroundPresses: function() {193 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener convertBackgroundPresses' );194 sceneryLog && sceneryLog.InputListener && sceneryLog.push();195 var presses = this._backgroundPresses.slice();196 for ( var i = 0; i < presses.length; i++ ) {197 var press = presses[ i ];198 this.removeBackgroundPress( press );199 press.pointer.interruptAttached();200 this.addPress( press );201 }202 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();203 },204 reposition: function() {205 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener reposition' );206 sceneryLog && sceneryLog.InputListener && sceneryLog.push();207 this._targetNode.matrix = this.computeMatrix();208 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();209 },210 recomputeLocals: function() {211 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener recomputeLocals' );212 sceneryLog && sceneryLog.InputListener && sceneryLog.push();213 for ( var i = 0; i < this._presses.length; i++ ) {214 this._presses[ i ].recomputeLocalPoint();215 }216 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();217 },218 interrupt: function() {219 sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( 'MultiListener interrupt' );220 sceneryLog && sceneryLog.InputListener && sceneryLog.push();221 while ( this._presses.length ) {222 this.removePress( this._presses[ this._presses.length - 1 ] );223 }224 sceneryLog && sceneryLog.InputListener && sceneryLog.pop();225 },226 // @private?227 computeMatrix: function() {228 if ( this._presses.length === 0 ) {229 return this._targetNode.getMatrix();230 }231 else if ( this._presses.length === 1 ) {232 return this.computeSinglePressMatrix();233 }234 else if ( this._allowScale && this._allowRotation ) {235 return this.computeTranslationRotationScaleMatrix();236 } else if ( this._allowScale ) {237 return this.computeTranslationScaleMatrix();238 } else if ( this._allowRotation ) {239 return this.computeTranslationRotationMatrix();240 } else {241 return this.computeTranslationMatrix();242 }243 },244 // @private245 computeSinglePressMatrix: function() {246 // TODO: scratch things247 var singleTargetPoint = this._presses[ 0 ].targetPoint;248 var singleMappedPoint = this._targetNode.localToParentPoint( this._presses[ 0 ].localPoint );249 var delta = singleTargetPoint.minus( singleMappedPoint );250 return Matrix3.translationFromVector( delta ).timesMatrix( this._targetNode.getMatrix() );251 },252 // @private253 computeTranslationMatrix: function() {254 // translation only. linear least-squares simplifies to sum of differences255 var sum = new Vector2();256 for ( var i = 0; i < this._presses.length; i++ ) {257 sum.add( this._presses[ i ].targetPoint );258 sum.subtract( this._presses[ i ].localPoint );259 }260 return Matrix3.translationFromVector( sum.dividedScalar( this._presses.length ) );261 },262 // @private263 computeTranslationScaleMatrix: function() {264 // TODO: minimize closures265 var localPoints = this._presses.map( function( press ) { return press.localPoint; } );266 var targetPoints = this._presses.map( function( press ) { return press.targetPoint; } );267 var localCentroid = new Vector2();268 var targetCentroid = new Vector2();269 localPoints.forEach( function( localPoint ) { localCentroid.add( localPoint ); } );270 targetPoints.forEach( function( targetPoint ) { targetCentroid.add( targetPoint ); } );271 localCentroid.divideScalar( this._presses.length );272 targetCentroid.divideScalar( this._presses.length );273 var localSquaredDistance = 0;274 var targetSquaredDistance = 0;275 localPoints.forEach( function( localPoint ) { localSquaredDistance += localPoint.distanceSquared( localCentroid ); } );276 targetPoints.forEach( function( targetPoint ) { targetSquaredDistance += targetPoint.distanceSquared( targetCentroid ); } );277 var scale = Math.sqrt( targetSquaredDistance / localSquaredDistance );278 var translateToTarget = Matrix3.translation( targetCentroid.x, targetCentroid.y );279 var translateFromLocal = Matrix3.translation( -localCentroid.x, -localCentroid.y );280 return translateToTarget.timesMatrix( Matrix3.scaling( scale ) ).timesMatrix( translateFromLocal );281 },282 // @private283 computeTranslationRotationMatrix: function() {284 var i;285 var localMatrix = new Matrix( 2, this._presses.length );286 var targetMatrix = new Matrix( 2, this._presses.length );287 var localCentroid = new Vector2();288 var targetCentroid = new Vector2();289 for ( i = 0; i < this._presses.length; i++ ) {290 var localPoint = this._presses[ i ].localPoint;291 var targetPoint = this._presses[ i ].targetPoint;292 localCentroid.add( localPoint );293 targetCentroid.add( targetPoint );294 localMatrix.set( 0, i, localPoint.x );295 localMatrix.set( 1, i, localPoint.y );296 targetMatrix.set( 0, i, targetPoint.x );297 targetMatrix.set( 1, i, targetPoint.y );298 }299 localCentroid.divideScalar( this._presses.length );300 targetCentroid.divideScalar( this._presses.length );301 // determine offsets from the centroids302 for ( i = 0; i < this._presses.length; i++ ) {303 localMatrix.set( 0, i, localMatrix.get( 0, i ) - localCentroid.x );304 localMatrix.set( 1, i, localMatrix.get( 1, i ) - localCentroid.y );305 targetMatrix.set( 0, i, targetMatrix.get( 0, i ) - targetCentroid.x );306 targetMatrix.set( 1, i, targetMatrix.get( 1, i ) - targetCentroid.y );307 }308 var covarianceMatrix = localMatrix.times( targetMatrix.transpose() );309 var svd = new SingularValueDecomposition( covarianceMatrix );310 var rotation = svd.getV().times( svd.getU().transpose() );311 if ( rotation.det() < 0 ) {312 rotation = svd.getV().times( Matrix.diagonalMatrix( [ 1, -1 ] ) ).times( svd.getU().transpose() );313 }314 var rotation3 = new Matrix3().rowMajor( rotation.get( 0, 0 ), rotation.get( 0, 1 ), 0,315 rotation.get( 1, 0 ), rotation.get( 1, 1 ), 0,316 0, 0, 1 );317 var translation = targetCentroid.minus( rotation3.timesVector2( localCentroid ) );318 rotation3.set02( translation.x );319 rotation3.set12( translation.y );320 return rotation3;321 },322 // @private323 computeTranslationRotationScaleMatrix: function() {324 var i;325 var localMatrix = new Matrix( this._presses.length * 2, 4 );326 for ( i = 0; i < this._presses.length; i++ ) {327 // [ x y 1 0 ]328 // [ y -x 0 1 ]329 var localPoint = this._presses[ i ].localPoint;330 localMatrix.set( 2 * i + 0, 0, localPoint.x );331 localMatrix.set( 2 * i + 0, 1, localPoint.y );332 localMatrix.set( 2 * i + 0, 2, 1 );333 localMatrix.set( 2 * i + 1, 0, localPoint.y );334 localMatrix.set( 2 * i + 1, 1, -localPoint.x );335 localMatrix.set( 2 * i + 1, 3, 1 );336 }337 var targetMatrix = new Matrix( this._presses.length * 2, 1 );338 for ( i = 0; i < this._presses.length; i++ ) {339 var targetPoint = this._presses[ i ].targetPoint;340 targetMatrix.set( 2 * i + 0, 0, targetPoint.x );341 targetMatrix.set( 2 * i + 1, 0, targetPoint.y );342 }343 var coefficientMatrix = SingularValueDecomposition.pseudoinverse( localMatrix ).times( targetMatrix );344 var m11 = coefficientMatrix.get( 0, 0 );345 var m12 = coefficientMatrix.get( 1, 0 );346 var m13 = coefficientMatrix.get( 2, 0 );347 var m23 = coefficientMatrix.get( 3, 0 );348 return new Matrix3().rowMajor( m11, m12, m13,349 -m12, m11, m23,350 0, 0, 1 );351 }352 } );353 function Press( pointer, trail ) {354 this.pointer = pointer;355 this.trail = trail;356 this.interrupted = false;357 this.localPoint = null;358 this.recomputeLocalPoint();359 }360 inherit( Object, Press, {361 recomputeLocalPoint: function() {362 this.localPoint = this.trail.globalToLocalPoint( this.pointer.point );363 },364 get targetPoint() {365 return this.trail.globalToParentPoint( this.pointer.point );366 }367 } );368 return MultiListener;...

Full Screen

Full Screen

InputHandler.js

Source:InputHandler.js Github

copy

Full Screen

1/**2 * @author mschuetz / http://mschuetz.at3 *4 *5 */6import {KeyCodes} from "../KeyCodes";7import {Utils} from "../utils";8import {EventDispatcher} from "../EventDispatcher.js";9export class InputHandler extends EventDispatcher {10 constructor (viewer) {11 super();12 this.viewer = viewer;13 this.renderer = viewer.renderer;14 this.domElement = this.renderer.domElement;15 this.enabled = true;16 17 this.scene = null;18 this.interactiveScenes = [];19 this.interactiveObjects = new Set();20 this.inputListeners = [];21 this.blacklist = new Set();22 this.drag = null;23 this.mouse = new THREE.Vector2(0, 0);24 this.selection = [];25 this.hoveredElements = [];26 this.pressedKeys = {};27 this.wheelDelta = 0;28 this.speed = 1;29 this.logMessages = false;30 if (this.domElement.tabIndex === -1) {31 this.domElement.tabIndex = 2222;32 }33 this.domElement.addEventListener('contextmenu', (event) => { event.preventDefault(); }, false);34 this.domElement.addEventListener('click', this.onMouseClick.bind(this), false);35 this.domElement.addEventListener('mousedown', this.onMouseDown.bind(this), false);36 this.domElement.addEventListener('mouseup', this.onMouseUp.bind(this), false);37 this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this), false);38 this.domElement.addEventListener('mousewheel', this.onMouseWheel.bind(this), false);39 this.domElement.addEventListener('DOMMouseScroll', this.onMouseWheel.bind(this), false); // Firefox40 this.domElement.addEventListener('dblclick', this.onDoubleClick.bind(this));41 this.domElement.addEventListener('keydown', this.onKeyDown.bind(this));42 this.domElement.addEventListener('keyup', this.onKeyUp.bind(this));43 this.domElement.addEventListener('touchstart', this.onTouchStart.bind(this));44 this.domElement.addEventListener('touchend', this.onTouchEnd.bind(this));45 this.domElement.addEventListener('touchmove', this.onTouchMove.bind(this));46 }47 addInputListener (listener) {48 this.inputListeners.push(listener);49 }50 removeInputListener (listener) {51 this.inputListeners = this.inputListeners.filter(e => e !== listener);52 }53 getSortedListeners(){54 return this.inputListeners.sort( (a, b) => {55 let ia = (a.importance !== undefined) ? a.importance : 0;56 let ib = (b.importance !== undefined) ? b.importance : 0;57 return ib - ia;58 });59 }60 onTouchStart (e) {61 if (this.logMessages) console.log(this.constructor.name + ': onTouchStart');62 e.preventDefault();63 if (e.touches.length === 1) {64 let rect = this.domElement.getBoundingClientRect();65 let x = e.touches[0].pageX - rect.left;66 let y = e.touches[0].pageY - rect.top;67 this.mouse.set(x, y);68 this.startDragging(null);69 }70 71 for (let inputListener of this.getSortedListeners()) {72 inputListener.dispatchEvent({73 type: e.type,74 touches: e.touches,75 changedTouches: e.changedTouches76 });77 }78 }79 onTouchEnd (e) {80 if (this.logMessages) console.log(this.constructor.name + ': onTouchEnd');81 e.preventDefault();82 for (let inputListener of this.getSortedListeners()) {83 inputListener.dispatchEvent({84 type: 'drop',85 drag: this.drag,86 viewer: this.viewer87 });88 }89 this.drag = null;90 for (let inputListener of this.getSortedListeners()) {91 inputListener.dispatchEvent({92 type: e.type,93 touches: e.touches,94 changedTouches: e.changedTouches95 });96 }97 }98 onTouchMove (e) {99 if (this.logMessages) console.log(this.constructor.name + ': onTouchMove');100 e.preventDefault();101 if (e.touches.length === 1) {102 let rect = this.domElement.getBoundingClientRect();103 let x = e.touches[0].pageX - rect.left;104 let y = e.touches[0].pageY - rect.top;105 this.mouse.set(x, y);106 if (this.drag) {107 this.drag.mouse = 1;108 this.drag.lastDrag.x = x - this.drag.end.x;109 this.drag.lastDrag.y = y - this.drag.end.y;110 this.drag.end.set(x, y);111 if (this.logMessages) console.log(this.constructor.name + ': drag: ');112 for (let inputListener of this.getSortedListeners()) {113 inputListener.dispatchEvent({114 type: 'drag',115 drag: this.drag,116 viewer: this.viewer117 });118 }119 }120 }121 for (let inputListener of this.getSortedListeners()) {122 inputListener.dispatchEvent({123 type: e.type,124 touches: e.touches,125 changedTouches: e.changedTouches126 });127 }128 // DEBUG CODE129 // let debugTouches = [...e.touches, {130 // pageX: this.domElement.clientWidth / 2,131 // pageY: this.domElement.clientHeight / 2}];132 // for(let inputListener of this.getSortedListeners()){133 // inputListener.dispatchEvent({134 // type: e.type,135 // touches: debugTouches,136 // changedTouches: e.changedTouches137 // });138 // }139 }140 onKeyDown (e) {141 if (this.logMessages) console.log(this.constructor.name + ': onKeyDown');142 // DELETE143 if (e.keyCode === KeyCodes.DELETE && this.selection.length > 0) {144 this.dispatchEvent({145 type: 'delete',146 selection: this.selection147 });148 this.deselectAll();149 }150 this.dispatchEvent({151 type: 'keydown',152 keyCode: e.keyCode,153 event: e154 });155 // for(let l of this.getSortedListeners()){156 // l.dispatchEvent({157 // type: "keydown",158 // keyCode: e.keyCode,159 // event: e160 // });161 // }162 this.pressedKeys[e.keyCode] = true;163 // e.preventDefault();164 }165 onKeyUp (e) {166 if (this.logMessages) console.log(this.constructor.name + ': onKeyUp');167 delete this.pressedKeys[e.keyCode];168 e.preventDefault();169 }170 onDoubleClick (e) {171 if (this.logMessages) console.log(this.constructor.name + ': onDoubleClick');172 let consumed = false;173 for (let hovered of this.hoveredElements) {174 if (hovered._listeners && hovered._listeners['dblclick']) {175 hovered.object.dispatchEvent({176 type: 'dblclick',177 mouse: this.mouse,178 object: hovered.object179 });180 consumed = true;181 break;182 }183 }184 if (!consumed) {185 for (let inputListener of this.getSortedListeners()) {186 inputListener.dispatchEvent({187 type: 'dblclick',188 mouse: this.mouse,189 object: null190 });191 }192 }193 e.preventDefault();194 }195 onMouseClick (e) {196 if (this.logMessages) console.log(this.constructor.name + ': onMouseClick');197 e.preventDefault();198 }199 onMouseDown (e) {200 if (this.logMessages) console.log(this.constructor.name + ': onMouseDown');201 e.preventDefault();202 let consumed = false;203 let consume = () => { return consumed = true; };204 if (this.hoveredElements.length === 0) {205 for (let inputListener of this.getSortedListeners()) {206 inputListener.dispatchEvent({207 type: 'mousedown',208 viewer: this.viewer,209 mouse: this.mouse210 });211 }212 }else{213 for(let hovered of this.hoveredElements){214 let object = hovered.object;215 object.dispatchEvent({216 type: 'mousedown',217 viewer: this.viewer,218 consume: consume219 });220 if(consumed){221 break;222 }223 }224 }225 if (!this.drag) {226 let target = this.hoveredElements227 .find(el => (228 el.object._listeners &&229 el.object._listeners['drag'] &&230 el.object._listeners['drag'].length > 0));231 if (target) {232 this.startDragging(target.object, {location: target.point});233 } else {234 this.startDragging(null);235 }236 }237 if (this.scene) {238 this.viewStart = this.scene.view.clone();239 }240 }241 onMouseUp (e) {242 if (this.logMessages) console.log(this.constructor.name + ': onMouseUp');243 e.preventDefault();244 let noMovement = this.getNormalizedDrag().length() === 0;245 246 let consumed = false;247 let consume = () => { return consumed = true; };248 if (this.hoveredElements.length === 0) {249 for (let inputListener of this.getSortedListeners()) {250 inputListener.dispatchEvent({251 type: 'mouseup',252 viewer: this.viewer,253 mouse: this.mouse,254 consume: consume255 });256 if(consumed){257 break;258 }259 }260 }else{261 let hovered = this.hoveredElements262 .map(e => e.object)263 .find(e => (e._listeners && e._listeners['mouseup']));264 if(hovered){265 hovered.dispatchEvent({266 type: 'mouseup',267 viewer: this.viewer,268 consume: consume269 });270 }271 }272 if (this.drag) {273 if (this.drag.object) {274 if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);275 this.drag.object.dispatchEvent({276 type: 'drop',277 drag: this.drag,278 viewer: this.viewer279 });280 } else {281 for (let inputListener of this.getSortedListeners()) {282 inputListener.dispatchEvent({283 type: 'drop',284 drag: this.drag,285 viewer: this.viewer286 });287 }288 }289 // check for a click290 let clicked = this.hoveredElements.map(h => h.object).find(v => v === this.drag.object) !== undefined;291 if(clicked){292 if (this.logMessages) console.log(`${this.constructor.name}: click ${this.drag.object.name}`);293 this.drag.object.dispatchEvent({294 type: 'click',295 viewer: this.viewer,296 consume: consume,297 });298 }299 this.drag = null;300 }301 if(!consumed){302 if (e.button === THREE.MOUSE.LEFT) {303 if (noMovement) {304 let selectable = this.hoveredElements305 .find(el => el.object._listeners && el.object._listeners['select']);306 if (selectable) {307 selectable = selectable.object;308 if (this.isSelected(selectable)) {309 this.selection310 .filter(e => e !== selectable)311 .forEach(e => this.toggleSelection(e));312 } else {313 this.deselectAll();314 this.toggleSelection(selectable);315 }316 } else {317 this.deselectAll();318 }319 }320 } else if ((e.button === THREE.MOUSE.RIGHT) && noMovement) {321 this.deselectAll();322 }323 }324 }325 onMouseMove (e) {326 e.preventDefault();327 let rect = this.domElement.getBoundingClientRect();328 let x = e.clientX - rect.left;329 let y = e.clientY - rect.top;330 this.mouse.set(x, y);331 let hoveredElements = this.getHoveredElements();332 if(hoveredElements.length > 0){333 let names = hoveredElements.map(h => h.object.name).join(", ");334 if (this.logMessages) console.log(`${this.constructor.name}: onMouseMove; hovered: '${names}'`);335 }336 if (this.drag) {337 this.drag.mouse = e.buttons;338 this.drag.lastDrag.x = x - this.drag.end.x;339 this.drag.lastDrag.y = y - this.drag.end.y;340 this.drag.end.set(x, y);341 if (this.drag.object) {342 if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);343 this.drag.object.dispatchEvent({344 type: 'drag',345 drag: this.drag,346 viewer: this.viewer347 });348 } else {349 if (this.logMessages) console.log(this.constructor.name + ': drag: ');350 let dragConsumed = false;351 for (let inputListener of this.getSortedListeners()) {352 inputListener.dispatchEvent({353 type: 'drag',354 drag: this.drag,355 viewer: this.viewer,356 consume: () => {dragConsumed = true;}357 });358 if(dragConsumed){359 break;360 }361 }362 }363 }else{364 let curr = hoveredElements.map(a => a.object).find(a => true);365 let prev = this.hoveredElements.map(a => a.object).find(a => true);366 if(curr !== prev){367 if(curr){368 if (this.logMessages) console.log(`${this.constructor.name}: mouseover: ${curr.name}`);369 curr.dispatchEvent({370 type: 'mouseover',371 object: curr,372 });373 }374 if(prev){375 if (this.logMessages) console.log(`${this.constructor.name}: mouseleave: ${prev.name}`);376 prev.dispatchEvent({377 type: 'mouseleave',378 object: prev,379 });380 }381 }382 if(hoveredElements.length > 0){383 let object = hoveredElements384 .map(e => e.object)385 .find(e => (e._listeners && e._listeners['mousemove']));386 387 if(object){388 object.dispatchEvent({389 type: 'mousemove',390 object: object391 });392 }393 }394 }395 396 // for (let inputListener of this.getSortedListeners()) {397 // inputListener.dispatchEvent({398 // type: 'mousemove',399 // object: null400 // });401 // }402 403 this.hoveredElements = hoveredElements;404 }405 406 onMouseWheel(e){407 if(!this.enabled) return;408 if(this.logMessages) console.log(this.constructor.name + ": onMouseWheel");409 410 e.preventDefault();411 let delta = 0;412 if (e.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9413 delta = e.wheelDelta;414 } else if (e.detail !== undefined) { // Firefox415 delta = -e.detail;416 }417 let ndelta = Math.sign(delta);418 // this.wheelDelta += Math.sign(delta);419 if (this.hoveredElement) {420 this.hoveredElement.object.dispatchEvent({421 type: 'mousewheel',422 delta: ndelta,423 object: this.hoveredElement.object424 });425 } else {426 for (let inputListener of this.getSortedListeners()) {427 inputListener.dispatchEvent({428 type: 'mousewheel',429 delta: ndelta,430 object: null431 });432 }433 }434 }435 startDragging (object, args = null) {436 let name = object ? object.name : "no name";437 if (this.logMessages) console.log(`${this.constructor.name}: startDragging: '${name}'`);438 this.drag = {439 start: this.mouse.clone(),440 end: this.mouse.clone(),441 lastDrag: new THREE.Vector2(0, 0),442 startView: this.scene.view.clone(),443 object: object444 };445 if (args) {446 for (let key of Object.keys(args)) {447 this.drag[key] = args[key];448 }449 }450 }451 getMousePointCloudIntersection (mouse) {452 return Utils.getMousePointCloudIntersection(453 this.mouse, 454 this.scene.getActiveCamera(), 455 this.viewer, 456 this.scene.pointclouds);457 }458 toggleSelection (object) {459 let oldSelection = this.selection;460 let index = this.selection.indexOf(object);461 if (index === -1) {462 this.selection.push(object);463 object.dispatchEvent({464 type: 'select'465 });466 } else {467 this.selection.splice(index, 1);468 object.dispatchEvent({469 type: 'deselect'470 });471 }472 this.dispatchEvent({473 type: 'selection_changed',474 oldSelection: oldSelection,475 selection: this.selection476 });477 }478 deselect(object){479 let oldSelection = this.selection;480 let index = this.selection.indexOf(object);481 if(index >= 0){482 this.selection.splice(index, 1);483 object.dispatchEvent({484 type: 'deselect'485 });486 this.dispatchEvent({487 type: 'selection_changed',488 oldSelection: oldSelection,489 selection: this.selection490 });491 }492 }493 deselectAll () {494 for (let object of this.selection) {495 object.dispatchEvent({496 type: 'deselect'497 });498 }499 let oldSelection = this.selection;500 if (this.selection.length > 0) {501 this.selection = [];502 this.dispatchEvent({503 type: 'selection_changed',504 oldSelection: oldSelection,505 selection: this.selection506 });507 }508 }509 isSelected (object) {510 let index = this.selection.indexOf(object);511 return index !== -1;512 }513 registerInteractiveObject(object){514 this.interactiveObjects.add(object);515 }516 removeInteractiveObject(object){517 this.interactiveObjects.delete(object);518 }519 registerInteractiveScene (scene) {520 let index = this.interactiveScenes.indexOf(scene);521 if (index === -1) {522 this.interactiveScenes.push(scene);523 }524 }525 unregisterInteractiveScene (scene) {526 let index = this.interactiveScenes.indexOf(scene);527 if (index > -1) {528 this.interactiveScenes.splice(index, 1);529 }530 }531 getHoveredElement () {532 let hoveredElements = this.getHoveredElements();533 if (hoveredElements.length > 0) {534 return hoveredElements[0];535 } else {536 return null;537 }538 }539 getHoveredElements () {540 let scenes = this.interactiveScenes.concat(this.scene.scene);541 let interactableListeners = ['mouseup', 'mousemove', 'mouseover', 'mouseleave', 'drag', 'drop', 'click', 'select', 'deselect'];542 let interactables = [];543 for (let scene of scenes) {544 scene.traverseVisible(node => {545 if (node._listeners && node.visible && !this.blacklist.has(node)) {546 let hasInteractableListener = interactableListeners.filter((e) => {547 return node._listeners[e] !== undefined;548 }).length > 0;549 if (hasInteractableListener) {550 interactables.push(node);551 }552 }553 });554 }555 556 let camera = this.scene.getActiveCamera();557 let ray = Utils.mouseToRay(this.mouse, camera, this.domElement.clientWidth, this.domElement.clientHeight);558 559 let raycaster = new THREE.Raycaster();560 raycaster.ray.set(ray.origin, ray.direction);561 raycaster.linePrecision = 0.2;562 let intersections = raycaster.intersectObjects(interactables.filter(o => o.visible), false);563 return intersections;564 // if(intersections.length > 0){565 // return intersections[0];566 // }else{567 // return null;568 // }569 }570 setScene (scene) {571 this.deselectAll();572 this.scene = scene;573 }574 update (delta) {575 }576 getNormalizedDrag () {577 if (!this.drag) {578 return new THREE.Vector2(0, 0);579 }580 let diff = new THREE.Vector2().subVectors(this.drag.end, this.drag.start);581 diff.x = diff.x / this.domElement.clientWidth;582 diff.y = diff.y / this.domElement.clientHeight;583 return diff;584 }585 getNormalizedLastDrag () {586 if (!this.drag) {587 return new THREE.Vector2(0, 0);588 }589 let lastDrag = this.drag.lastDrag.clone();590 lastDrag.x = lastDrag.x / this.domElement.clientWidth;591 lastDrag.y = lastDrag.y / this.domElement.clientHeight;592 return lastDrag;593 }...

Full Screen

Full Screen

index.ts

Source:index.ts Github

copy

Full Screen

...14import {createBenchmark} from '../micro_bench';15import {createAndRenderLView} from '../setup';16`17<div>18 <button (click)="clickListener()" (input)="inputListener()"></button>19 <button (click)="clickListener()" (input)="inputListener()"></button>20 <button (click)="clickListener()" (input)="inputListener()"></button>21 <button (click)="clickListener()" (input)="inputListener()"></button>22 <button (click)="clickListener()" (input)="inputListener()"></button>23 <button (click)="clickListener()" (input)="inputListener()"></button>24 <button (click)="clickListener()" (input)="inputListener()"></button>25 <button (click)="clickListener()" (input)="inputListener()"></button>26 <button (click)="clickListener()" (input)="inputListener()"></button>27 <button (click)="clickListener()" (input)="inputListener()"></button>28</div>29`;30function testTemplate(rf: RenderFlags, ctx: any) {31 if (rf & 1) {32 ɵɵelementStart(0, 'div');33 ɵɵelementStart(1, 'button', 0);34 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});35 ɵɵelementEnd();36 ɵɵelementStart(2, 'button', 0);37 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});38 ɵɵelementEnd();39 ɵɵelementStart(3, 'button', 0);40 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});41 ɵɵelementEnd();42 ɵɵelementStart(4, 'button', 0);43 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});44 ɵɵelementEnd();45 ɵɵelementStart(5, 'button', 0);46 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});47 ɵɵelementEnd();48 ɵɵelementStart(6, 'button', 0);49 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});50 ɵɵelementEnd();51 ɵɵelementStart(7, 'button', 0);52 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});53 ɵɵelementEnd();54 ɵɵelementStart(8, 'button', 0);55 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});56 ɵɵelementEnd();57 ɵɵelementStart(9, 'button', 0);58 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});59 ɵɵelementEnd();60 ɵɵelementStart(10, 'button', 0);61 ɵɵlistener('click', function clickListener() {})('input', function inputListener() {});62 ɵɵelementEnd();63 ɵɵelementEnd();64 }65}66const rootLView = createLView(67 null, createTView(TViewType.Root, null, null, 0, 0, null, null, null, null, null), {},68 LViewFlags.IsRoot, null, null, null, null, null, null);69const viewTNode = createTNode(null!, null, TNodeType.Element, -1, null, null);70const embeddedTView = createTView(71 TViewType.Embedded, null, testTemplate, 11, 0, null, null, null, null, [[3, 'click', 'input']]);72// create view once so we don't profile the first create pass73createAndRenderLView(rootLView, embeddedTView, viewTNode);74const listenersCreate = createBenchmark('listeners create');75const createTime = listenersCreate('create');...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var inputListener = require('devicefarmer-stf').inputListener;2var listener = inputListener();3listener.on('data', function(data) {4 console.log(data);5});6listener.on('error', function(err) {7 console.error(err);8});9listener.on('close', function() {10 console.log('Connection closed');11});12listener.on('end', function() {13 console.log('Connection ended');14});15listener.on('connect', function() {16 console.log('Connected');17});18listener.on('ready', function() {19 console.log('Ready');20});21listener.connect();22var inputListener = require('devicefarmer-stf').inputListener;23var listener = inputListener();24listener.on('data', function(data) {25 console.log(data);26});27listener.on('error', function(err) {28 console.error(err);29});30listener.on('close', function() {31 console.log('Connection closed');32});33listener.on('end', function() {34 console.log('Connection ended');35});36listener.on('connect', function() {37 console.log('Connected');38});39listener.on('ready', function() {40 console.log('Ready');41});42listener.connect();43var inputListener = require('devicefarmer-stf').inputListener;44var listener = inputListener();45listener.on('data', function(data) {46 console.log(data);47});48listener.on('error', function(err) {49 console.error(err);50});51listener.on('close', function() {52 console.log('Connection closed');53});54listener.on('end', function() {55 console.log('Connection ended');56});57listener.on('connect', function() {58 console.log('Connected');59});60listener.on('ready', function() {61 console.log('Ready');62});63listener.connect();64var inputListener = require('devicefarmer-stf').inputListener;65var listener = inputListener();66listener.on('data', function(data) {67 console.log(data);68});69listener.on('error', function(err) {70 console.error(err);71});72listener.on('close', function() {73 console.log('Connection closed');74});75listener.on('end', function() {76 console.log('Connection ended');77});78listener.on('connect', function()

Full Screen

Using AI Code Generation

copy

Full Screen

1var inputListener = require('devicefarmer-stf-api').inputListener;2var stfService = require('devicefarmer-stf-api').stfService;3var stfService = require('devicefarmer-stf-api').stfService;4var stfService = require('devicefarmer-stf-api').stfService;5var stfService = require('devicefarmer-stf-api').stfService;6var stfService = require('devicefarmer-stf-api').stfService;7var stfService = require('devicefarmer-stf-api').stfService;8var stfService = require('devicefarmer-stf-api').stfService;9var stfService = require('devicefarmer-stf-api').stfService;10var stfService = require('devicefarmer-stf-api').stfService;11var stfService = require('devicefarmer-stf-api').stfService;12var stfService = require('devicefarmer-stf-api').stfService;13var stfService = require('devicefarmer-stf-api').stfService;14var stfService = require('devicefarmer-stf-api').stfService;15var stfService = require('devicefarmer-stf-api').stfService;

Full Screen

Using AI Code Generation

copy

Full Screen

1var stf = require('devicefarmer-stf');2var inputListener = stf.inputListener;3var stf = require('devicefarmer-stf');4var inputListener = stf.inputListener;5var stf = require('devicefarmer-stf');6var inputListener = stf.inputListener;7var stf = require('devicefarmer-stf');8var inputListener = stf.inputListener;9var stf = require('devicefarmer-stf');10var inputListener = stf.inputListener;11var stf = require('devicefarmer-stf');12var inputListener = stf.inputListener;13var stf = require('devicefarmer-stf');14var inputListener = stf.inputListener;15var stf = require('devicefarmer-stf');16var inputListener = stf.inputListener;17var stf = require('devicefarmer-stf');18var inputListener = stf.inputListener;19var stf = require('devicefarmer-stf');20var inputListener = stf.inputListener;21var stf = require('devicefarmer-stf');22var inputListener = stf.inputListener;23var stf = require('devicefarmer-stf');24var inputListener = stf.inputListener;25var stf = require('devicefarmer-stf');26var inputListener = stf.inputListener;27var stf = require('devicefarmer-stf');28var inputListener = stf.inputListener;29var stf = require('devicefar

Full Screen

Using AI Code Generation

copy

Full Screen

1var inputListener = require('devicefarmer-stf-client').inputListener;2var listener = new inputListener();3listener.on('data', function(data) {4 console.log(data);5});6listener.on('error', function(err) {7 console.log(err);8});9listener.on('close', function() {10 console.log('close');11});12listener.on('end', function() {13 console.log('end');14});15listener.on('finish', function() {16 console.log('finish');17});18listener.on('unpipe', function() {19 console.log('unpipe');20});21listener.start();22var inputSender = require('devicefarmer-stf-client').inputSender;23var sender = new inputSender();24sender.on('data', function(data) {25 console.log(data);26});27sender.on('error', function(err) {28 console.log(err);29});30sender.on('close', function() {31 console.log('close');32});33sender.on('end', function() {34 console.log('end');35});36sender.on('finish', function() {37 console.log('finish');38});39sender.on('unpipe', function() {40 console.log('unpipe');41});42sender.start();43var screenListener = require('devicefarmer-stf-client').screenListener;44var screen = new screenListener();45screen.on('data', function(data) {46 console.log(data);47});48screen.on('error', function(err) {49 console.log(err);50});51screen.on('close', function() {52 console.log('close');53});54screen.on('end', function() {55 console.log('end');56});57screen.on('finish', function() {58 console.log('finish');59});60screen.on('unpipe', function() {61 console.log('unpipe');62});63screen.start();64var screenSender = require('devicefarmer-stf-client').screenSender;65var sender = new screenSender();66sender.on('data', function(data) {67 console.log(data);68});69sender.on('error', function(err) {70 console.log(err);71});72sender.on('close', function() {73 console.log('close');74});75sender.on('end', function() {76 console.log('end');77});78sender.on('finish', function() {79 console.log('finish');80});

Full Screen

Using AI Code Generation

copy

Full Screen

1var inputListener = require('devicefarmer-stf').inputListener;2var input = new inputListener();3input.on('touch', function(touch) {4 console.log(touch);5});6input.on('key', function(key) {7 console.log(key);8});9input.on('rotary', function(rotary) {10 console.log(rotary);11});12input.on('swipe', function(swipe) {13 console.log(swipe);14});15input.on('error', function(err) {16 console.log(err);17});18input.start();19{20 "dependencies": {21 }22}23var inputListener = require('devicefarmer-stf').inputListener;24var input = new inputListener();25input.on('touch', function(touch) {26 console.log(touch);27});28input.on('key', function(key) {29 console.log(key);30});31input.on('rotary', function(rotary) {32 console.log(rotary);33});34input.on('swipe', function(swipe) {35 console.log(swipe);36});37input.on('error', function(err) {38 console.log(err);39});40input.start();41{42 "dependencies": {43 }44}45var inputListener = require('devicefarmer-stf').inputListener;46var input = new inputListener();47input.on('touch', function(touch) {48 console.log(touch);49});50input.on('key', function(key) {51 console.log(key);52});53input.on('rotary', function(rotary) {54 console.log(rotary);55});56input.on('swipe', function(swipe) {57 console.log(swipe);58});59input.on('error', function(err) {60 console.log(err);61});62input.start();63{

Full Screen

Using AI Code Generation

copy

Full Screen

1var stf = require('devicefarmer-stf');2var inputListener = stf.inputListener;3var events = require('events');4var util = require('util');5var eventEmitter = new events.EventEmitter();6var input = new inputListener(eventEmitter);7eventEmitter.on('touch', function(e){8 console.log(e);9});10eventEmitter.on('swipe', function(e){11 console.log(e);12});13eventEmitter.on('key', function(e){14 console.log(e);15});16eventEmitter.on('rotation', function(e){17 console.log(e);18});19eventEmitter.on('orientation', function(e){20 console.log(e);21});22eventEmitter.on('text', function(e){23 console.log(e);24});25eventEmitter.on('battery', function(e){26 console.log(e);27});28eventEmitter.on('power', function(e){29 console.log(e);30});31eventEmitter.on('network', function(e){32 console.log(e);33});34eventEmitter.on('clipboard', function(e){35 console.log(e);36});37eventEmitter.on('wifi', function(e){38 console.log(e);39});40eventEmitter.on('display', function(e){41 console.log(e);42});43eventEmitter.on('phone', function(e){44 console.log(e);45});46eventEmitter.on('sms', function(e){47 console.log(e);48});49eventEmitter.on('call', function(e){50 console.log(e);51});52eventEmitter.on('app', function(e){53 console.log(e);54});55eventEmitter.on('media', function(e){56 console.log(e);57});58eventEmitter.on('browser', function(e){59 console.log(e);60});61eventEmitter.on('location', function(e){62 console.log(e);63});

Full Screen

Using AI Code Generation

copy

Full Screen

1var devicefarmer = require('devicefarmer-stf');2var stf = new devicefarmer();3var device = stf.getDevice();4device.inputListener(function(data){5 console.log(data);6});7var devicefarmer = require('devicefarmer-stf');8var stf = new devicefarmer();9var device = stf.getDevice();10device.inputListener(function(data){11 console.log(data);12});13var devicefarmer = require('devicefarmer-stf');14var stf = new devicefarmer();15var device = stf.getDevice();16device.inputListener(function(data){17 console.log(data);18});19var devicefarmer = require('devicefarmer-stf');20var stf = new devicefarmer();21var device = stf.getDevice();22device.inputListener(function(data){23 console.log(data);24});25var devicefarmer = require('devicefarmer-stf');26var stf = new devicefarmer();27var device = stf.getDevice();28device.inputListener(function(data){29 console.log(data);30});31var devicefarmer = require('devicefarmer-stf');32var stf = new devicefarmer();33var device = stf.getDevice();34device.inputListener(function(data){35 console.log(data);36});37var devicefarmer = require('devicefarmer-stf');38var stf = new devicefarmer();39var device = stf.getDevice();40device.inputListener(function(data){41 console.log(data);42});43var devicefarmer = require('devicefarmer-stf');44var stf = new devicefarmer();45var device = stf.getDevice();46device.inputListener(function(data){47 console.log(data);48});

Full Screen

Using AI Code Generation

copy

Full Screen

1var stf = require('devicefarmer-stf-client');2var stfDevice = new stf.Device(stfClient, "8c4e4d2e");3stfDevice.inputListener(function(err, data) {4 if (err) {5 console.log(err);6 } else {7 console.log(data);8 }9});10{ type: 'input',11 finger: 0 }12{ type: 'input',13 finger: 0 }14{ type: 'input',15 finger: 0 }16{ type: 'input',17 finger: 0 }18{ type: 'input',19 finger: 0 }20{ type: 'input',21 finger: 0 }22{ type: 'input',23 finger: 0 }24{ type: 'input',

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run devicefarmer-stf automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful