UNPKG

igniteui-angular-sovn

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

476 lines (429 loc) 17.9 kB
import { first } from 'rxjs/operators'; import { HorizontalAlignment, VerticalAlignment, Point } from '../services/public_api'; import { DebugElement } from '@angular/core'; export const wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)); // export const waitForGridScroll = grid => new Promise<void>(resolve => grid.gridScroll.pipe(first()).subscribe(() => { // grid.cdr.detectChanges(); // resolve(); // })); export const waitForActiveNodeChange = grid => new Promise<void>(resolve => grid.activeNodeChange.pipe(first()).subscribe(() => { grid.cdr.detectChanges(); resolve(); })); export const waitForSelectionChange = grid => new Promise<void>(resolve => grid.selected.pipe(first()).subscribe(() => { grid.cdr.detectChanges(); resolve(); })); declare let Touch: { prototype: Touch; new(prop): Touch; }; export class UIInteractions { /** * Clears all opened overlays and resets document scrollTop and scrollLeft */ public static clearOverlay() { const overlays = document.getElementsByClassName('igx-overlay') as HTMLCollectionOf<Element>; Array.from(overlays).forEach(element => { element.remove(); }); document.documentElement.scrollTop = 0; document.documentElement.scrollLeft = 0; document.body.style.overflow = 'hidden'; } /** * Clicks an element - native or debug, by dispatching pointerdown, pointerup and click events. * * @param element - Native or debug element. * @param shift - if the shift key is pressed. * @param ctrl - if the ctrl key is pressed. */ public static simulateClickAndSelectEvent(element, shift = false, ctrl = false) { const nativeElement = element.nativeElement ?? element; UIInteractions.simulatePointerOverElementEvent('pointerdown', nativeElement, shift, ctrl); UIInteractions.simulatePointerOverElementEvent('pointerup', nativeElement); nativeElement.dispatchEvent(new MouseEvent('click', { bubbles: true })); } /** * Double click an element - native or debug, by dispatching pointerdown, pointerup and dblclick events. * // TODO - typing of element - whe npassing cell/row, should be CellType/RowTpe * * @param element - Native or debug element. */ public static simulateDoubleClickAndSelectEvent(element: any) { const nativeElement = element.nativeElement ?? element; UIInteractions.simulatePointerOverElementEvent('pointerdown', nativeElement); UIInteractions.simulatePointerOverElementEvent('pointerup', nativeElement); nativeElement.dispatchEvent(new MouseEvent('dblclick')); } /** * click with non primary button on an element - native or debug, by dispatching pointerdown, pointerup and click events. * * @param element - Native or debug element. */ public static simulateNonPrimaryClick(element) { const nativeElement = element.nativeElement ?? element; nativeElement.dispatchEvent(new PointerEvent('pointerdown', { button: 2 })); nativeElement.dispatchEvent(new PointerEvent('pointerup', { button: 2 })); nativeElement.dispatchEvent(new Event('click')); } /** * gets a keyboard event * * @param eventType - name of the event * @param keyPressed- pressed key */ public static getKeyboardEvent(eventType: string, keyPressed: string, altKey = false, shiftKey = false, ctrlKey = false) { const keyboardEvent = { key: keyPressed, altKey, shiftKey, ctrlKey, stopPropagation: () => { }, stopImmediatePropagation: () => { }, preventDefault: () => { } }; return new KeyboardEvent(eventType, keyboardEvent); } /** * gets a mouse event * * @param eventType - name of the event */ public static getMouseEvent(eventType, altKey = false, shiftKey = false, ctrlKey = false) { const clickEvent = { altKey, shiftKey, ctrlKey, stopPropagation: () => { }, stopImmediatePropagation: () => { }, preventDefault: () => { } }; return new MouseEvent(eventType, clickEvent); } /** * Press a key on an element - debug, by triggerEventHandler. * * @param keyPressed - pressed key * @param elem - debug element */ public static triggerEventHandlerKeyDown(key: string, elem: any, altKey = false, shiftKey = false, ctrlKey = false) { const event = { target: elem.nativeElement, key, altKey, shiftKey, ctrlKey, stopPropagation: () => { }, stopImmediatePropagation: () => { }, preventDefault: () => { } }; if (elem.hasOwnProperty('triggerEventHandler')) { elem.triggerEventHandler('keydown', event); } else { (elem.nativeElement as HTMLElement).dispatchEvent(new KeyboardEvent('keydown', { ...event })); } } /** * Trigger key up on an element - debug, by triggerEventHandler. * * @param keyPressed - pressed key * @param elem - debug element */ public static triggerEventHandlerKeyUp(key: string, elem: DebugElement, altKey = false, shiftKey = false, ctrlKey = false) { const event = { key, altKey, shiftKey, ctrlKey, stopPropagation: () => { }, stopImmediatePropagation: () => { }, preventDefault: () => { } }; elem.triggerEventHandler('keyup', event); } /** * Sets an input value- native or debug, by dispatching keydown, input and keyup events. * * @param element - Native or debug element. * @param text - text to be set. * @param fix - if fixture is set it will detect changes on it. */ public static clickAndSendInputElementValue(element, text, fix = null) { const nativeElement = element.nativeElement ?? element; nativeElement.value = text; nativeElement.dispatchEvent(new Event('keydown')); nativeElement.dispatchEvent(new Event('input')); nativeElement.dispatchEvent(new Event('keyup')); if (fix) { fix.detectChanges(); } } /** * Sets an input value- native or debug, by dispatching only input events. * * @param element - Native or debug element. * @param text - text to be set. * @param fix - if fixture is set it will detect changes on it. */ public static setInputElementValue(element, text, fix = null) { const nativeElement = element.nativeElement ?? element; nativeElement.value = text; nativeElement.dispatchEvent(new Event('input')); if (fix) { fix.detectChanges(); } } /** * Sets an input value- debug element. * * @param inputElement - debug element. * @param inputValue - text to be set. */ public static triggerInputEvent(inputElement: DebugElement, inputValue: string) { inputElement.nativeElement.value = inputValue; inputElement.triggerEventHandler('input', { target: inputElement.nativeElement }); } public static triggerInputKeyInteraction(inputValue: string, target: DebugElement) { const startPos = target.nativeElement.selectionStart; const endPos = target.nativeElement.selectionEnd; target.nativeElement.value = target.nativeElement.value.substring(0, startPos) + inputValue + target.nativeElement.value.substring(endPos); // move the caret if (startPos !== endPos) { // replaced selection, cursor goes to end target.nativeElement.selectionStart = target.nativeElement.selectionEnd = startPos + inputValue.length; } else { // typing move the cursor after the typed value target.nativeElement.selectionStart = target.nativeElement.selectionEnd = endPos + inputValue.length; } target.triggerEventHandler('input', { target: target.nativeElement }); } public static simulateTyping(characters: string, target: DebugElement, selectionStart = 0, selectionEnd = 0) { if (characters) { if (selectionStart > selectionEnd) { return Error('Selection start should be less than selection end position'); } const inputEl = target.nativeElement as HTMLInputElement; inputEl.setSelectionRange(selectionStart, selectionEnd); for (const char of characters) { this.triggerEventHandlerKeyDown(char, target); this.triggerInputKeyInteraction(char, target); this.triggerEventHandlerKeyUp(char, target); } } } public static simulatePaste(pasteText: string, target: DebugElement, selectionStart = 0, selectionEnd = 0) { if (selectionStart > selectionEnd) { return Error('Selection start should be less than selection end position'); } const inputEl = target.nativeElement as HTMLInputElement; inputEl.setSelectionRange(selectionStart, selectionEnd); UIInteractions.triggerPasteEvent(target, pasteText); UIInteractions.triggerInputKeyInteraction(pasteText, target); } public static triggerPasteEvent(inputElement: DebugElement, inputValue: string) { const pasteData = new DataTransfer(); pasteData.setData('text/plain', inputValue); const event = new ClipboardEvent('paste', { clipboardData: pasteData }); inputElement.triggerEventHandler('paste', event); } public static simulateCompositionEvent(characters: string, target: DebugElement, selectionStart = 0, selectionEnd = 0, isBlur = true) { if (characters) { if (selectionStart > selectionEnd) { return Error('Selection start should be less than selection end position'); } const inputEl = target.nativeElement as HTMLInputElement; inputEl.setSelectionRange(selectionStart, selectionEnd); target.triggerEventHandler('compositionstart', { target: target.nativeElement }); for (const char of characters) { this.triggerEventHandlerKeyDown(char, target); this.triggerInputKeyInteraction(char, target); this.triggerEventHandlerKeyUp(char, target); } target.triggerEventHandler('compositionend', { target: target.nativeElement }); if (isBlur) { this.triggerInputKeyInteraction(characters, target); } } } public static triggerKeyDownEvtUponElem(key, elem, bubbles = true, altKey = false, shiftKey = false, ctrlKey = false) { const keyboardEvent = new KeyboardEvent('keydown', { key, bubbles, shiftKey, ctrlKey, altKey }); elem.dispatchEvent(keyboardEvent); } public static simulateClickEvent(element, shift = false, ctrl = false) { const event = new MouseEvent('click', { bubbles: true, shiftKey: shift, ctrlKey: ctrl }); element.dispatchEvent(event); } public static simulateMouseEvent(eventName: string, element, clientX, clientY) { const options: MouseEventInit = { view: window, bubbles: true, cancelable: true, clientX, clientY }; element.dispatchEvent(new MouseEvent(eventName, options)); } public static createPointerEvent(eventName: string, point: Point) { const options: PointerEventInit = { view: window, bubbles: true, cancelable: true, pointerId: 1 }; const pointerEvent = new PointerEvent(eventName, options); Object.defineProperty(pointerEvent, 'pageX', { value: point.x, enumerable: true }); Object.defineProperty(pointerEvent, 'pageY', { value: point.y, enumerable: true }); return pointerEvent; } public static simulatePointerEvent(eventName: string, element, x, y) { const options: PointerEventInit = { view: window, bubbles: true, cancelable: true, pointerId: 1 }; const pointerEvent = new PointerEvent(eventName, options); Object.defineProperty(pointerEvent, 'pageX', { value: x, enumerable: true }); Object.defineProperty(pointerEvent, 'pageY', { value: y, enumerable: true }); element.dispatchEvent(pointerEvent); return pointerEvent; } public static simulatePointerOverElementEvent(eventName: string, element, shiftKey = false, ctrlKey = false) { const options: PointerEventInit = { view: window, bubbles: true, cancelable: true, pointerId: 1, buttons: 1, button: eventName === 'pointerenter' ? -1 : 0, shiftKey, ctrlKey }; element.dispatchEvent(new PointerEvent(eventName, options)); } public static simulateDropEvent(nativeElement: HTMLElement, data: any, format: string) { const dataTransfer = new DataTransfer(); dataTransfer.setData(format, data); nativeElement.dispatchEvent(new DragEvent('drop', { dataTransfer })); } public static simulateWheelEvent(element, deltaX, deltaY, shiftKey = false) { const event = new WheelEvent('wheel', { deltaX, deltaY, shiftKey }); Object.defineProperty(event, 'wheelDeltaX', { value: deltaX }); Object.defineProperty(event, 'wheelDeltaY', { value: deltaY }); return new Promise<void>(resolve => { element.dispatchEvent(event); resolve(); }); } public static simulateTouchStartEvent(target, pageX, pageY) { const touchInit = { identifier: 0, target, pageX, pageY }; const t = new Touch(touchInit); const touchEventObject = new TouchEvent('touchstart', { touches: [t] }); return new Promise<void>(resolve => { target.dispatchEvent(touchEventObject); resolve(); }); } public static simulateTouchMoveEvent(element, movedX, movedY) { const touchInit = { identifier: 0, target: element, pageX: movedX, pageY: movedY }; const t = new Touch(touchInit); const touchEventObject = new TouchEvent('touchmove', { touches: [t] }); return new Promise<void>(resolve => { element.dispatchEvent(touchEventObject); resolve(); }); } public static simulateTouchEndEvent(element, movedX, movedY) { const touchInit = { identifier: 0, target: element, pageX: movedX, pageY: movedY }; const t = new Touch(touchInit); const touchEventObject = new TouchEvent('touchend', { touches: [t] }); return new Promise<void>(resolve => { element.dispatchEvent(touchEventObject); resolve(); }); } /** * Calculate point within element * * @param element Element to calculate point for * @param hAlign The horizontal position of the point within the element (defaults to center) * @param vAlign The vertical position of the point within the element (defaults to middle) */ public static getPointFromElement( element: Element, hAlign: HorizontalAlignment = HorizontalAlignment.Center, vAlign: VerticalAlignment = VerticalAlignment.Middle): Point { const elementRect = element.getBoundingClientRect(); return { x: elementRect.right + hAlign * elementRect.width, y: elementRect.bottom + vAlign * elementRect.height }; } public static hoverElement(element: HTMLElement, bubbles = false) { element.dispatchEvent(new MouseEvent('mouseenter', { bubbles })); } public static unhoverElement(element: HTMLElement, bubbles = false) { element.dispatchEvent(new MouseEvent('mouseleave', { bubbles })); } public static clickDragDirective(fix, dragDir) { dragDir.onPointerDown(new PointerEvent('pointerdown', { pointerId: 1 })); dragDir.onPointerUp(new PointerEvent('pointerup')); fix.detectChanges(); } public static moveDragDirective(fix, dragDir, moveX, moveY, triggerPointerUp = false) { const dragElem = dragDir.element.nativeElement; const startingTop = dragElem.getBoundingClientRect().top; const startingLeft = dragElem.getBoundingClientRect().left; const startingBottom = dragElem.getBoundingClientRect().bottom; const startingRight = dragElem.getBoundingClientRect().right; const startingX = (startingLeft + startingRight) / 2; const startingY = (startingTop + startingBottom) / 2; dragDir.onPointerDown({ pointerId: 1, pageX: startingX, pageY: startingY }); fix.detectChanges(); dragDir.onPointerMove({ pointerId: 1, pageX: startingX + 10, pageY: startingY + 10 }); fix.detectChanges(); dragDir.onPointerMove({ pointerId: 1, pageX: startingX + moveX, pageY: startingY + moveY }); fix.detectChanges(); if (triggerPointerUp) { dragDir.onPointerUp({ pointerId: 1, pageX: startingX + moveX, pageY: startingY + moveY }); fix.detectChanges(); } } }