/// /// Copyright 2015-2026 Micro Focus or one of its affiliates. /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// import { Component, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed, fakeAsync, flushMicrotasks, tick } from '@angular/core/testing'; import { FormsModule } from '@angular/forms'; import { InfiniteScrollDirective } from './infinite-scroll.directive'; import { InfiniteScrollModule } from './infinite-scroll.module'; @Component({ template: `
`, imports: [InfiniteScrollModule, FormsModule], }) export class InfiniteScrollTestComponent { filterText: unknown; loadOnScroll: boolean = false; @ViewChild(InfiniteScrollDirective) infiniteScrollDirective: InfiniteScrollDirective; load(pageNum: number, pageSize: number, filter: unknown): unknown[] { const items: string[] = []; for (let idx = pageNum * 20; idx < (pageNum + 1) * 20; idx++) { items.push(`Item ${idx}`); } return items; } } describe('Directive - Infinite Scroll', () => { let component: InfiniteScrollTestComponent; let fixture: ComponentFixture; let loadSpy: jasmine.Spy; beforeEach(() => { TestBed.configureTestingModule({ imports: [InfiniteScrollModule, FormsModule, InfiniteScrollTestComponent], }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(InfiniteScrollTestComponent); component = fixture.componentInstance; loadSpy = spyOn(component, 'load').and.callThrough(); fixture.detectChanges(); }); it('should initially call load with filter value of "" if filter input value is undefined', () => { expect(loadSpy).toHaveBeenCalledWith(0, 20, ''); expect(loadSpy).toHaveBeenCalledTimes(1); }); it('should call load with filter value of "" if filter input value changes to null', async () => { component.filterText = null; fixture.detectChanges(); await fixture.whenStable(); expect(loadSpy).toHaveBeenCalledWith(0, 20, ''); expect(loadSpy).toHaveBeenCalledTimes(1); }); it('should call load with filter value of "some string" if filter input value changes to string', async () => { component.filterText = 'some string'; fixture.detectChanges(); await fixture.whenStable(); expect(loadSpy).toHaveBeenCalledWith(0, 20, 'some string'); expect(loadSpy).toHaveBeenCalledTimes(2); }); it('should call load with filter value of 10 if filter input value changes to number', async () => { component.filterText = 10; fixture.detectChanges(); await fixture.whenStable(); expect(loadSpy).toHaveBeenCalledWith(0, 20, 10); expect(loadSpy).toHaveBeenCalledTimes(2); }); it('should call load with filter value of true if filter input value changes to boolean', async () => { component.filterText = true; fixture.detectChanges(); await fixture.whenStable(); expect(loadSpy).toHaveBeenCalledWith(0, 20, true); expect(loadSpy).toHaveBeenCalledTimes(2); }); it('should call load with filter value of { name: "somebody" } if filter input value changes to object', async () => { component.filterText = { name: 'somebody' }; fixture.detectChanges(); await fixture.whenStable(); expect(loadSpy).toHaveBeenCalledWith(0, 20, { name: 'somebody' }); expect(loadSpy).toHaveBeenCalledTimes(2); }); // Test Case for https://portal.digitalsafe.net/browse/EL-4093 it('should not attempt to load a subsequent page if the element is invisible', fakeAsync(() => { // hide the component so it has a height of 0 but is still within the DOM const nativeElement = fixture.nativeElement as HTMLElement; nativeElement.style.display = 'none'; component.loadOnScroll = true; component.filterText = { name: 'somebody' }; fixture.detectChanges(); flushMicrotasks(); loadSpy.calls.reset(); // we trigger a `check` which will attempt to load a page however this should never result // in a call to the `load` function as the typeahead is not visible component.infiniteScrollDirective.check(); // load requests are debounced by 200ms tick(200); expect(loadSpy).not.toHaveBeenCalled(); })); });