igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
380 lines (319 loc) • 13.6 kB
text/typescript
import {
Component,
Directive,
NgZone,
OnInit,
ViewChild,
ElementRef
} from '@angular/core';
import { TestBed, ComponentFixture, fakeAsync, tick, waitForAsync } from '@angular/core/testing';
import { IgxScrollInertiaDirective } from './scroll_inertia.directive';
import { configureTestSuite } from '../../test-utils/configure-suite';
import { wait } from '../../test-utils/ui-interactions.spec';
describe('Scroll Inertia Directive - Rendering', () => {
let fix: ComponentFixture<ScrollInertiaComponent>;
configureTestSuite();
beforeAll(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
IgxTestScrollInertiaDirective,
ScrollInertiaComponent
]
}).compileComponents().then(() => {
fix = TestBed.createComponent(ScrollInertiaComponent);
fix.detectChanges();
});
}));
it('should initialize directive on non-scrollable container.', () => {
expect(fix.componentInstance.scrInertiaDir).toBeDefined('scroll inertia initializing through markup failed');
});
// Unit tests for inertia function.
it('inertia should accelerate and then deccelerate vertically.', async () => {
pending('This should be tested in the e2e test');
const scrInertiaDir = fix.componentInstance.scrInertiaDir;
// vertical inertia
scrInertiaDir._inertiaInit(0, 1);
await wait(1500);
const scrTopStepArray = fix.componentInstance.scrTopStepArray;
expect(scrTopStepArray.length).toEqual(57);
const first = scrTopStepArray[0];
const mid = scrTopStepArray[9];
const end = scrTopStepArray[56];
expect(first).toBeLessThan(mid);
expect(end).toBeLessThan(mid);
});
it('inertia should accelerate and then deccelerate horizontally.', async () => {
pending('This should be tested in the e2e test');
const scrInertiaDir = fix.componentInstance.scrInertiaDir;
// horizontal inertia
scrInertiaDir._inertiaInit(1, 0);
await wait(1500);
const scrLeftStepArray = fix.componentInstance.scrLeftStepArray;
expect(scrLeftStepArray.length).toEqual(57);
const first = scrLeftStepArray[0];
const mid = scrLeftStepArray[9];
const end = scrLeftStepArray[56];
expect(first).toBeLessThan(mid);
expect(end).toBeLessThan(mid);
});
});
describe('Scroll Inertia Directive - Scrolling', () => {
let scrollInertiaDir: IgxTestScrollInertiaDirective;
let scrollContainerMock;
beforeEach(() => {
const mockZone = jasmine.createSpyObj('NgZone', ['runOutsideAngular']);
scrollContainerMock = {
scrollLeft: 0,
scrollTop: 0,
offsetHeight: 500,
children: [{ style: { width: '50px', height: '500px', scrollHeight: 100 } }]
};
scrollInertiaDir = new IgxTestScrollInertiaDirective(null, mockZone);
scrollInertiaDir.IgxScrollInertiaScrollContainer = scrollContainerMock;
scrollInertiaDir.smoothingDuration = 0;
});
// Unit test for wheel - wheelDelataY/wheelDeltaX supported on Chrome, Safari, Opera.
it('should change scroll top for related scrollbar if onWheel is executed with wheelDeltaY.', () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'vertical';
const evt = {wheelDeltaY: -240, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(2 * scrollInertiaDir.wheelStep);
});
it('should change scroll left for related scrollbar if onWheel is executed with wheelDeltaX.', () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'horizontal';
const evt = {wheelDeltaX: -240, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollLeft).toEqual(2 * scrollInertiaDir.wheelStep);
});
// Unit tests for wheel on other browsers that don't provide wheelDelta - use deltaX and deltaY.
it('should change scroll top for related scrollbar if onWheel is executed with deltaY.', () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'vertical';
const evt = {deltaY: 1, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(scrollInertiaDir.wheelStep);
});
it('should change scroll left for related scrollbar if onWheel is executed with deltaX.', () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'horizontal';
const evt = {deltaX: 1, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollLeft).toEqual(scrollInertiaDir.wheelStep);
});
it('should not throw error if there is no associated scrollbar and wheel event is called.', () => {
scrollInertiaDir.IgxScrollInertiaScrollContainer = null;
const evt = {preventDefault: () => {}};
expect (() => scrollInertiaDir.onWheel(evt)).not.toThrow();
});
it('should change scroll left when shift + wheel is triggered' , () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'horizontal';
const evt = {shiftKey: true, wheelDeltaY: -240, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(0);
expect(scrollContainerMock.scrollLeft).toEqual(2 * scrollInertiaDir.wheelStep);
});
it('should be able to scroll to left/right when shift + wheel is triggered' , () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'horizontal';
let evt = {shiftKey: true, wheelDeltaY: -240, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(0);
expect(scrollContainerMock.scrollLeft).toEqual(2 * scrollInertiaDir.wheelStep);
evt = {shiftKey: true, wheelDeltaY: 120, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(0);
expect(scrollContainerMock.scrollLeft).toEqual(scrollInertiaDir.wheelStep);
});
it('should change scroll left when shift + wheel is called with with deltaY' , () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'horizontal';
const evt = {shiftKey: true, deltaY: 1, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(0);
expect(scrollContainerMock.scrollLeft).toEqual(scrollInertiaDir.wheelStep);
});
it('should be able to scroll to left/right when shift + wheel is called with with deltaY' , () => {
scrollInertiaDir.IgxScrollInertiaDirection = 'horizontal';
let evt = {shiftKey: true, deltaY: 1, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(0);
expect(scrollContainerMock.scrollLeft).toEqual(scrollInertiaDir.wheelStep);
evt = {shiftKey: true, deltaY: -1, preventDefault: () => {}};
scrollInertiaDir.onWheel(evt);
expect(scrollContainerMock.scrollTop).toEqual(0);
expect(scrollContainerMock.scrollLeft).toEqual(0);
});
// Unit tests for touch events with inertia - Chrome, FireFox, Safari.
it('should change scroll top for related scrollbar on touch start/move/end', fakeAsync(() => {
let evt = {
touches: [{
pageX: 0,
pageY: 0
}],
preventDefault: () => {}
};
scrollInertiaDir.onTouchStart(evt);
evt = {
touches: [{
pageX: 0,
pageY: -100
}],
preventDefault: () => {}
};
tick(10);
scrollInertiaDir.onTouchMove(evt);
scrollInertiaDir.onTouchEnd(evt);
// wait for inertia to complete
tick(300);
expect(scrollContainerMock.scrollTop).toBeGreaterThan(3000);
}));
it('should stop inertia if another touch event is initiated while inertia is executing.', fakeAsync(() => {
let evt = {
touches: [{
pageX: 0,
pageY: 0
}],
preventDefault: () => {}
};
scrollInertiaDir.onTouchStart(evt);
evt = {
touches: [{
pageX: 0,
pageY: -100
}],
preventDefault: () => {}
};
tick(10);
scrollInertiaDir.onTouchMove(evt);
scrollInertiaDir.onTouchEnd(evt);
tick(10);
// don't wait for inertia to end. Instead start another touch interaction.
evt = {
touches: [{
pageX: 0,
pageY: 0
}],
preventDefault: () => {}
};
scrollInertiaDir.onTouchStart(evt);
expect(scrollContainerMock.scrollTop).toBeLessThan(1000);
}));
it('should honor the defined swipeToleranceX.', fakeAsync(() => {
// if scroll is initiated on Y and on X within the defined tolerance no scrolling should occur on X.
let evt = {
touches: [{
pageX: 0,
pageY: 0
}],
preventDefault: () => {}
};
scrollInertiaDir.onTouchStart(evt);
evt = {
touches: [{
pageX: -10,
pageY: -50
}],
preventDefault: () => {}
};
tick(10);
scrollInertiaDir.onTouchMove(evt);
scrollInertiaDir.onTouchEnd(evt);
tick(300);
expect(scrollContainerMock.scrollLeft).toEqual(0);
expect(scrollContainerMock.scrollTop).toBeGreaterThan(100);
}));
it('should change scroll left for related scrollbar on touch start/move/end', fakeAsync(() => {
let evt = {
touches: [{
pageX: 0,
pageY: 0
}],
preventDefault: () => {}
};
scrollInertiaDir.onTouchStart(evt);
evt = {
touches: [{
pageX: -100,
pageY: 0
}],
preventDefault: () => {}
};
tick(10);
scrollInertiaDir.onTouchMove(evt);
scrollInertiaDir.onTouchEnd(evt);
// wait for inertia to complete
tick(300);
expect(scrollContainerMock.scrollLeft).toBeGreaterThan(3000);
}));
it('should not throw errors on touch start/move/end if no scrollbar is associated.', () => {
scrollInertiaDir.IgxScrollInertiaScrollContainer = null;
const evt = {preventDefault: () => {}};
expect (() => scrollInertiaDir.onTouchStart(evt)).not.toThrow();
expect (() => scrollInertiaDir.onTouchMove(evt)).not.toThrow();
expect (() => scrollInertiaDir.onTouchEnd(evt)).not.toThrow();
});
});
/** igxScroll inertia for testing */
({
selector: '[igxTestScrollInertia]',
standalone: true
})
export class IgxTestScrollInertiaDirective extends IgxScrollInertiaDirective {
constructor(element: ElementRef, _zone: NgZone) {
super(element, _zone);
}
public override onWheel(evt) {
super.onWheel(evt);
}
public override onTouchStart(evt) {
return super.onTouchStart(evt);
}
public override onTouchEnd(evt) {
super.onTouchEnd(evt);
}
public override onTouchMove(evt) {
return super.onTouchMove(evt);
}
public override _inertiaInit(speedX, speedY) {
super._inertiaInit(speedX, speedY);
}
}
/** igxScroll inertia component */
({
template: `
<div #container style='width:calc(100% - 50px); height: 500px; float: left;'>
<ng-template igxTestScrollInertia #scrInertiaContainer></ng-template>
</div>
<div #scrBar [style.height]='height' style='overflow: auto; width: 50px; float:right;'>
<div [style.height]='innerHeight' [style.width]='innerWidth'></div>
</div>
`,
standalone: true,
imports: [IgxTestScrollInertiaDirective]
})
export class ScrollInertiaComponent implements OnInit {
('container', { static: true }) public container: ElementRef;
('scrBar', { static: true }) public scrollContainer: ElementRef;
('scrInertiaContainer', { read: IgxTestScrollInertiaDirective, static: true })
public scrInertiaDir: IgxTestScrollInertiaDirective;
public height = '500px';
public innerHeight = '5000px';
public innerWidth = '5000px';
public scrTopArray = [];
public scrTopStepArray = [];
public scrLeftArray = [];
public scrLeftStepArray = [];
public ngOnInit() {
this.scrInertiaDir.IgxScrollInertiaScrollContainer = this.scrollContainer.nativeElement;
this.scrollContainer.nativeElement.addEventListener('scroll', (evt) => {
this.onScroll(evt);
});
}
public onScroll(evt) {
const ind = this.scrTopArray.length - 1;
const prevScrTop = ind < 0 ? 0 : this.scrTopArray[ind];
const prevScrLeft = ind < 0 ? 0 : this.scrLeftArray[ind];
this.scrTopArray.push(evt.target.scrollTop);
this.scrLeftArray.push(evt.target.scrollLeft);
const calcScrollStep = evt.target.scrollTop - prevScrTop;
const calcScrollLeftStep = evt.target.scrollLeft - prevScrLeft;
this.scrTopStepArray.push(calcScrollStep);
this.scrLeftStepArray.push(calcScrollLeftStep);
}
}