Newer
Older
/*
* Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { InteractivityChecker } from '@angular/cdk/a11y';
import { ComponentRef, ElementRef, Renderer2, ViewContainerRef } from '@angular/core';
import { TooltipDirective } from './tooltip.directive';
class MockElementRef extends ElementRef {
nativeElement = {
contains: jest.fn(),
appendChild: jest.fn(),
};
}
let directive: TooltipDirective;
const mockComponentRef: ComponentRef<TooltipComponent> = {
setInput: jest.fn(),
destroy: jest.fn(),
onDestroy: jest.fn(),
componentType: TooltipComponent,
changeDetectorRef: null,
location: null,
hostView: null,
injector: null,
instance: { id: '', left: 0, top: 0, text: '', show: false },
beforeEach((): void => {
TestBed.configureTestingModule({
providers: [ViewContainerRef, { provide: ElementRef, useClass: MockElementRef }, Renderer2, InteractivityChecker],
});
TestBed.runInInjectionContext(() => {
directive = new TooltipDirective();
it('should create a directive', () => {
expect(directive).toBeTruthy();
});
describe('ngAfterViewInit', () => {
it('should create tooltip', () => {
directive.createTooltip = jest.fn();
directive.ngAfterViewInit();
expect(directive.createTooltip).toHaveBeenCalled();
});
});
describe('ngOnDestroy', () => {
it('should destroy tooltip', () => {
directive.destroy = jest.fn();
directive.ngOnDestroy();
expect(directive.destroy).toHaveBeenCalled();
describe('createTooltip', () => {
beforeEach(() => {
directive.viewContainerRef.createComponent = jest.fn().mockReturnValue({ location: { nativeElement: {} } });
directive.setAriaLabeledBy = jest.fn();
directive.getFocusableElement = jest.fn().mockReturnValue({ appendChild: jest.fn() });
directive.interactivityChecker.isFocusable = jest.fn();
});
it('should create tooltip component', () => {
directive.createTooltip();
expect(directive.viewContainerRef.createComponent).toHaveBeenCalled();
});
it('should check if parent element focusable', () => {
directive.createTooltip();
expect(directive.interactivityChecker.isFocusable).toHaveBeenCalled();
});
it('should get focusable element if parent not focusable', () => {
directive.createTooltip();
expect(directive.getFocusableElement).toHaveBeenCalled();
});
it('should insert tooltip component to focusable', () => {
expect(directive.focusableElement.appendChild).toHaveBeenCalled();
it('should set aria-labeledby attribute to parent', () => {
expect(directive.setAriaLabeledBy).toHaveBeenCalled();
});
});
describe('showTooltip', () => {
beforeEach(() => {
directive.setTooltipProperties = jest.fn();
directive.elementRef.nativeElement.contains = jest.fn().mockReturnValue(true);
});
it('should check if element focused', () => {
directive.showTooltip();
expect(directive.elementRef.nativeElement.contains).toHaveBeenCalled();
directive.showTooltip();
expect(directive.setTooltipProperties).toHaveBeenCalledWith(true);
describe('hideTooltip', () => {
it('should hide tooltip', () => {
directive.hide = jest.fn();
directive.hideTooltip();
expect(directive.hide).toHaveBeenCalled();
it('should hide tooltip if escape key pressed', () => {
directive.hide = jest.fn();
const escapeEvent: KeyboardEvent = { ...new KeyboardEvent('esc'), key: 'Escape' };
directive.onKeydown(escapeEvent);
expect(directive.hide).toHaveBeenCalled();
});
});
describe('setTooltipProperties', () => {
beforeEach(() => {
directive.componentRef = mockComponentRef;
directive.elementRef.nativeElement.getBoundingClientRect = jest
.fn()
.mockReturnValue({ left: 0, right: 1000, bottom: 1000 });
});
it('should get bounding client rect', () => {
directive.setTooltipProperties();
expect(directive.elementRef.nativeElement.getBoundingClientRect).toHaveBeenCalled();
});
it('should set tooltip instance properties', () => {
directive.tooltip = 'I am tooltip';
directive.tooltipId = 'tooltip-1';
directive.setTooltipProperties();
expect(directive.componentRef.instance).toStrictEqual({
id: 'tooltip-1',
left: 500,
text: 'I am tooltip',
top: 1000,
it('should add margin if parent element focused', () => {
directive.setTooltipProperties(true);
expect(directive.componentRef.instance.top).toBe(1004);
});
});
describe('setAriaLabeledBy', () => {
beforeEach(() => {
directive.renderer.setAttribute = jest.fn();
});
it('should set aria-labeledby attribute', () => {
directive.setAriaLabeledBy();
expect(directive.renderer.setAttribute).toHaveBeenCalled();
});
});
describe('removeAriaLabeledBy', () => {
beforeEach(() => {
directive.renderer.removeAttribute = jest.fn();
});
it('should remove aria-labeledby attribute', () => {
directive.removeAriaLabeledBy();
expect(directive.renderer.removeAttribute).toHaveBeenCalled();
});
});
describe('getFocusableElement', () => {
it('should return null', () => {
const simpleElement = document.createElement('a');
const result: HTMLElement = directive.getFocusableElement(simpleElement);
expect(result).toBeNull();
});
it('should return focusable child element', () => {
const nestedElement = document.createElement('div');
const buttonElement = document.createElement('button');
nestedElement.appendChild(buttonElement);
const result: HTMLElement = directive.getFocusableElement(nestedElement);
expect(result).toBe(buttonElement);
});
});
describe('hide', () => {
beforeEach(() => {
directive.componentRef = Object.assign(mockComponentRef, { instance: { ...mockComponentRef.instance, show: true } });
});
it('should hide component', () => {
directive.hide();
expect(directive.componentRef.instance.show).toBeFalsy;
});
});
describe('destroy', () => {
beforeEach(() => {
directive.componentRef = mockComponentRef;
directive.removeAriaLabeledBy = jest.fn();
});
it('should set component ref to null', () => {
directive.destroy();
expect(directive.componentRef).toBeNull();
});
it('should remove aria-labeledby attribute', () => {
expect(directive.removeAriaLabeledBy).toHaveBeenCalled();
});
it('should set focusable element to null', () => {
directive.destroy();
expect(directive.focusableElement).toBeNull();
});