///
/// 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 { OverlayContainer } from '@angular/cdk/overlay';
import { Component, ViewChild } from '@angular/core';
import {
ComponentFixture,
fakeAsync,
flushMicrotasks,
inject,
TestBed,
tick,
} from '@angular/core/testing';
import { TooltipDirective } from './tooltip.directive';
import { TooltipModule } from './tooltip.module';
@Component({
selector: 'app-tooltip-test',
template: `
@if (showTrigger) {
}
`,
imports: [TooltipModule],
})
export class TooltipDirectiveSpecComponent {
@ViewChild(TooltipDirective, { static: false }) tooltipDirective: TooltipDirective;
isOpen: boolean = false;
showTrigger: boolean = true;
}
describe('Tooltip Directive', () => {
let component: TooltipDirectiveSpecComponent;
let fixture: ComponentFixture;
let overlayContainer: OverlayContainer;
let overlayContainerElement: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TooltipModule, TooltipDirectiveSpecComponent],
});
fixture = TestBed.createComponent(TooltipDirectiveSpecComponent);
component = fixture.componentInstance;
fixture.detectChanges();
// access the overlay container
inject([OverlayContainer], (oc: OverlayContainer) => {
overlayContainer = oc;
overlayContainerElement = oc.getContainerElement();
})();
});
afterEach(() => {
overlayContainer.ngOnDestroy();
});
it('should show tooltip', fakeAsync(() => {
const shownSpy = spyOn(component.tooltipDirective.shown, 'emit');
component.tooltipDirective.show();
tick(0);
expect(getTooltip()).toBeTruthy();
expect(shownSpy).toHaveBeenCalledTimes(1);
}));
it('should show tooltip after delay', fakeAsync(() => {
component.tooltipDirective.delay = 100;
component.tooltipDirective.show();
tick(0);
expect(getTooltip()).toBeFalsy();
tick(100);
expect(getTooltip()).toBeTruthy();
}));
it('should correctly destroy tooltip pending show', fakeAsync(() => {
component.tooltipDirective.delay = 100;
component.tooltipDirective.show();
tick(0);
const tooltipDirective = component.tooltipDirective;
component.showTrigger = false;
fixture.detectChanges();
flushMicrotasks();
tick(100);
expect(getTooltip()).toBeFalsy();
}));
it('should not show tooltip when tooltip is disabled', fakeAsync(() => {
component.tooltipDirective.disabled = true;
component.tooltipDirective.show();
tick(0);
expect(getTooltip()).toBeFalsy();
}));
it('should apply the custom tooltip class', fakeAsync(() => {
component.tooltipDirective.customClass = 'custom-tooltip-class';
component.tooltipDirective.show();
tick(0);
expect(getTooltip()).toBeTruthy();
expect(getInnerTooltip().classList.contains('custom-tooltip-class')).toBeTruthy();
}));
it('should apply the correct tooltip placement', fakeAsync(() => {
component.tooltipDirective.placement = 'right';
component.tooltipDirective.show();
tick(0);
expect(getTooltip()).toBeTruthy();
expect(getInnerTooltip().classList.contains('right')).toBeTruthy();
}));
it('should show the correct tooltip content', fakeAsync(() => {
component.tooltipDirective.show();
tick(0);
expect(getTooltipContent()).toBe('Tooltip content here');
}));
it('should show allow open state to be controlled via the isOpen input', fakeAsync(() => {
component.isOpen = true;
fixture.detectChanges();
tick(0);
expect(getTooltip()).toBeTruthy();
// should also close
component.isOpen = false;
fixture.detectChanges();
tick(0);
expect(getTooltip()).toBeFalsy();
}));
function getTooltip(): HTMLElement | null {
return document.querySelector('ux-tooltip');
}
function getInnerTooltip(): HTMLElement | null {
return getTooltip().querySelector('.tooltip');
}
function getTooltipContent(): string {
return getTooltip().querySelector('.tooltip-inner').innerText.trim();
}
});