///
/// 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();
}));
});