virtual-scroll-viewport.spec.ts (material2-7.3.3) | : | virtual-scroll-viewport.spec.ts (material2-7.3.4) | ||
---|---|---|---|---|
skipping to change at line 15 | skipping to change at line 15 | |||
ScrollDispatcher, | ScrollDispatcher, | |||
ScrollingModule | ScrollingModule | |||
} from '@angular/cdk/scrolling'; | } from '@angular/cdk/scrolling'; | |||
import {dispatchFakeEvent} from '@angular/cdk/testing'; | import {dispatchFakeEvent} from '@angular/cdk/testing'; | |||
import { | import { | |||
Component, | Component, | |||
Input, | Input, | |||
NgZone, | NgZone, | |||
TrackByFunction, | TrackByFunction, | |||
ViewChild, | ViewChild, | |||
ViewContainerRef, | ||||
ViewEncapsulation | ViewEncapsulation | |||
} from '@angular/core'; | } from '@angular/core'; | |||
import {async, ComponentFixture, fakeAsync, flush, inject, TestBed} from '@angul ar/core/testing'; | import {async, ComponentFixture, fakeAsync, flush, inject, TestBed} from '@angul ar/core/testing'; | |||
import {animationFrameScheduler, Subject} from 'rxjs'; | import {animationFrameScheduler, Subject} from 'rxjs'; | |||
describe('CdkVirtualScrollViewport', () => { | describe('CdkVirtualScrollViewport', () => { | |||
describe ('with FixedSizeVirtualScrollStrategy', () => { | describe ('with FixedSizeVirtualScrollStrategy', () => { | |||
let fixture: ComponentFixture<FixedSizeVirtualScroll>; | let fixture: ComponentFixture<FixedSizeVirtualScroll>; | |||
let testComponent: FixedSizeVirtualScroll; | let testComponent: FixedSizeVirtualScroll; | |||
let viewport: CdkVirtualScrollViewport; | let viewport: CdkVirtualScrollViewport; | |||
skipping to change at line 490 | skipping to change at line 489 | |||
data.next([1, 2, 3]); | data.next([1, 2, 3]); | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
expect(viewport.getRenderedRange()) | expect(viewport.getRenderedRange()) | |||
.toEqual({start: 0, end: 3}, 'newly emitted items should be rendered') ; | .toEqual({start: 0, end: 3}, 'newly emitted items should be rendered') ; | |||
})); | })); | |||
it('should trackBy value by default', fakeAsync(() => { | it('should trackBy value by default', fakeAsync(() => { | |||
testComponent.items = []; | testComponent.items = []; | |||
spyOn(testComponent.virtualForViewContainer, 'detach').and.callThrough(); | spyOn(testComponent.virtualForOf, '_detachView').and.callThrough(); | |||
finishInit(fixture); | finishInit(fixture); | |||
testComponent.items = [0]; | testComponent.items = [0]; | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
expect(testComponent.virtualForViewContainer.detach).not.toHaveBeenCalled( ); | expect(testComponent.virtualForOf._detachView).not.toHaveBeenCalled(); | |||
testComponent.items = [1]; | testComponent.items = [1]; | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
expect(testComponent.virtualForViewContainer.detach).toHaveBeenCalled(); | expect(testComponent.virtualForOf._detachView).toHaveBeenCalled(); | |||
})); | })); | |||
it('should trackBy index when specified', fakeAsync(() => { | it('should trackBy index when specified', fakeAsync(() => { | |||
testComponent.trackBy = i => i; | testComponent.trackBy = i => i; | |||
testComponent.items = []; | testComponent.items = []; | |||
spyOn(testComponent.virtualForViewContainer, 'detach').and.callThrough(); | spyOn(testComponent.virtualForOf, '_detachView').and.callThrough(); | |||
finishInit(fixture); | finishInit(fixture); | |||
testComponent.items = [0]; | testComponent.items = [0]; | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
expect(testComponent.virtualForViewContainer.detach).not.toHaveBeenCalled( ); | expect(testComponent.virtualForOf._detachView).not.toHaveBeenCalled(); | |||
testComponent.items = [1]; | testComponent.items = [1]; | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
expect(testComponent.virtualForViewContainer.detach).not.toHaveBeenCalled( ); | expect(testComponent.virtualForOf._detachView).not.toHaveBeenCalled(); | |||
})); | })); | |||
it('should recycle views when template cache is large enough to accommodate' , fakeAsync(() => { | it('should recycle views when template cache is large enough to accommodate' , fakeAsync(() => { | |||
testComponent.trackBy = i => i; | testComponent.trackBy = i => i; | |||
const spy = | const spy = spyOn(testComponent.virtualForOf, '_createEmbeddedViewAt') | |||
spyOn(testComponent.virtualForViewContainer, 'createEmbeddedView').and | .and.callThrough(); | |||
.callThrough(); | ||||
finishInit(fixture); | finishInit(fixture); | |||
// Should create views for the initial rendered items. | // Should create views for the initial rendered items. | |||
expect(testComponent.virtualForViewContainer.createEmbeddedView).toHaveBee | expect(testComponent.virtualForOf._createEmbeddedViewAt) | |||
nCalledTimes(4); | .toHaveBeenCalledTimes(4); | |||
spy.calls.reset(); | spy.calls.reset(); | |||
triggerScroll(viewport, 10); | triggerScroll(viewport, 10); | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
// As we first start to scroll we need to create one more item. This is be cause the first item | // As we first start to scroll we need to create one more item. This is be cause the first item | |||
// is still partially on screen and therefore can't be removed yet. At the same time a new | // is still partially on screen and therefore can't be removed yet. At the same time a new | |||
// item is now partially on the screen at the bottom and so a new view is needed. | // item is now partially on the screen at the bottom and so a new view is needed. | |||
expect(testComponent.virtualForViewContainer.createEmbeddedView).toHaveBee | expect(testComponent.virtualForOf._createEmbeddedViewAt) | |||
nCalledTimes(1); | .toHaveBeenCalledTimes(1); | |||
spy.calls.reset(); | spy.calls.reset(); | |||
const maxOffset = | const maxOffset = | |||
testComponent.itemSize * testComponent.items.length - testComponent.vi ewportSize; | testComponent.itemSize * testComponent.items.length - testComponent.vi ewportSize; | |||
for (let offset = 10; offset <= maxOffset; offset += 10) { | for (let offset = 10; offset <= maxOffset; offset += 10) { | |||
triggerScroll(viewport, offset); | triggerScroll(viewport, offset); | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
} | } | |||
// As we scroll through the rest of the items, no new views should be crea ted, our existing 5 | // As we scroll through the rest of the items, no new views should be crea ted, our existing 5 | |||
// can just be recycled as appropriate. | // can just be recycled as appropriate. | |||
expect(testComponent.virtualForViewContainer.createEmbeddedView).not.toHav | expect(testComponent.virtualForOf._createEmbeddedViewAt) | |||
eBeenCalled(); | .not.toHaveBeenCalled(); | |||
})); | })); | |||
it('should not recycle views when template cache is full', fakeAsync(() => { | it('should not recycle views when template cache is full', fakeAsync(() => { | |||
testComponent.trackBy = i => i; | testComponent.trackBy = i => i; | |||
testComponent.templateCacheSize = 0; | testComponent.templateCacheSize = 0; | |||
const spy = | const spy = spyOn(testComponent.virtualForOf, '_createEmbeddedViewAt') | |||
spyOn(testComponent.virtualForViewContainer, 'createEmbeddedView').and | .and.callThrough(); | |||
.callThrough(); | ||||
finishInit(fixture); | finishInit(fixture); | |||
// Should create views for the initial rendered items. | // Should create views for the initial rendered items. | |||
expect(testComponent.virtualForViewContainer.createEmbeddedView).toHaveBee | expect(testComponent.virtualForOf._createEmbeddedViewAt) | |||
nCalledTimes(4); | .toHaveBeenCalledTimes(4); | |||
spy.calls.reset(); | spy.calls.reset(); | |||
triggerScroll(viewport, 10); | triggerScroll(viewport, 10); | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
// As we first start to scroll we need to create one more item. This is be cause the first item | // As we first start to scroll we need to create one more item. This is be cause the first item | |||
// is still partially on screen and therefore can't be removed yet. At the same time a new | // is still partially on screen and therefore can't be removed yet. At the same time a new | |||
// item is now partially on the screen at the bottom and so a new view is needed. | // item is now partially on the screen at the bottom and so a new view is needed. | |||
expect(testComponent.virtualForViewContainer.createEmbeddedView).toHaveBee | expect(testComponent.virtualForOf._createEmbeddedViewAt) | |||
nCalledTimes(1); | .toHaveBeenCalledTimes(1); | |||
spy.calls.reset(); | spy.calls.reset(); | |||
const maxOffset = | const maxOffset = | |||
testComponent.itemSize * testComponent.items.length - testComponent.vi ewportSize; | testComponent.itemSize * testComponent.items.length - testComponent.vi ewportSize; | |||
for (let offset = 10; offset <= maxOffset; offset += 10) { | for (let offset = 10; offset <= maxOffset; offset += 10) { | |||
triggerScroll(viewport, offset); | triggerScroll(viewport, offset); | |||
fixture.detectChanges(); | fixture.detectChanges(); | |||
flush(); | flush(); | |||
} | } | |||
// Since our template cache size is 0, as we scroll through the rest of th e items, we need to | // Since our template cache size is 0, as we scroll through the rest of th e items, we need to | |||
// create a new view for each one. | // create a new view for each one. | |||
expect(testComponent.virtualForViewContainer.createEmbeddedView).toHaveBee | expect(testComponent.virtualForOf._createEmbeddedViewAt) | |||
nCalledTimes(5); | .toHaveBeenCalledTimes(5); | |||
})); | })); | |||
it('should render up to maxBufferPx when buffer dips below minBufferPx', fak eAsync(() => { | it('should render up to maxBufferPx when buffer dips below minBufferPx', fak eAsync(() => { | |||
testComponent.minBufferPx = testComponent.itemSize; | testComponent.minBufferPx = testComponent.itemSize; | |||
testComponent.maxBufferPx = testComponent.itemSize * 2; | testComponent.maxBufferPx = testComponent.itemSize * 2; | |||
finishInit(fixture); | finishInit(fixture); | |||
expect(viewport.getRenderedRange()) | expect(viewport.getRenderedRange()) | |||
.toEqual({start: 0, end: 6}, 'should have 2 buffer items initially'); | .toEqual({start: 0, end: 6}, 'should have 2 buffer items initially'); | |||
skipping to change at line 830 | skipping to change at line 837 | |||
} | } | |||
.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapp er { | .cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapp er { | |||
flex-direction: row; | flex-direction: row; | |||
} | } | |||
`], | `], | |||
encapsulation: ViewEncapsulation.None, | encapsulation: ViewEncapsulation.None, | |||
}) | }) | |||
class FixedSizeVirtualScroll { | class FixedSizeVirtualScroll { | |||
@ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport; | @ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport; | |||
@ViewChild(CdkVirtualForOf) virtualForOf: CdkVirtualForOf<any>; | // Casting virtualForOf as any so we can spy on private methods | |||
@ViewChild(CdkVirtualForOf, {read: ViewContainerRef}) virtualForViewContainer: | @ViewChild(CdkVirtualForOf) virtualForOf: any; | |||
ViewContainerRef; | ||||
@Input() orientation = 'vertical'; | @Input() orientation = 'vertical'; | |||
@Input() viewportSize = 200; | @Input() viewportSize = 200; | |||
@Input() viewportCrossSize = 100; | @Input() viewportCrossSize = 100; | |||
@Input() itemSize = 50; | @Input() itemSize = 50; | |||
@Input() minBufferPx = 0; | @Input() minBufferPx = 0; | |||
@Input() maxBufferPx = 0; | @Input() maxBufferPx = 0; | |||
@Input() items = Array(10).fill(0).map((_, i) => i); | @Input() items = Array(10).fill(0).map((_, i) => i); | |||
@Input() trackBy: TrackByFunction<number>; | @Input() trackBy: TrackByFunction<number>; | |||
@Input() templateCacheSize = 20; | @Input() templateCacheSize = 20; | |||
skipping to change at line 882 | skipping to change at line 889 | |||
} | } | |||
.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapp er { | .cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapp er { | |||
flex-direction: row; | flex-direction: row; | |||
} | } | |||
`], | `], | |||
encapsulation: ViewEncapsulation.None, | encapsulation: ViewEncapsulation.None, | |||
}) | }) | |||
class FixedSizeVirtualScrollWithRtlDirection { | class FixedSizeVirtualScrollWithRtlDirection { | |||
@ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport; | @ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport; | |||
@ViewChild(CdkVirtualForOf, {read: ViewContainerRef}) virtualForViewContainer: ViewContainerRef; | ||||
@Input() orientation = 'vertical'; | @Input() orientation = 'vertical'; | |||
@Input() viewportSize = 200; | @Input() viewportSize = 200; | |||
@Input() viewportCrossSize = 100; | @Input() viewportCrossSize = 100; | |||
@Input() itemSize = 50; | @Input() itemSize = 50; | |||
@Input() minBufferPx = 0; | @Input() minBufferPx = 0; | |||
@Input() maxBufferPx = 0; | @Input() maxBufferPx = 0; | |||
@Input() items = Array(10).fill(0).map((_, i) => i); | @Input() items = Array(10).fill(0).map((_, i) => i); | |||
@Input() trackBy: TrackByFunction<number>; | @Input() trackBy: TrackByFunction<number>; | |||
@Input() templateCacheSize = 20; | @Input() templateCacheSize = 20; | |||
End of changes. 17 change blocks. | ||||
30 lines changed or deleted | 27 lines changed or added |