Skip to content
Snippets Groups Projects
tooltip.directive.spec.ts 7.94 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * 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.
     */
    
    OZGCloud's avatar
    OZGCloud committed
    import { InteractivityChecker } from '@angular/cdk/a11y';
    import { ComponentRef, ElementRef, Renderer2, ViewContainerRef } from '@angular/core';
    
    OZGCloud's avatar
    OZGCloud committed
    import { TestBed } from '@angular/core/testing';
    
    OZGCloud's avatar
    OZGCloud committed
    import { TooltipComponent } from './tooltip.component';
    
    OZGCloud's avatar
    OZGCloud committed
    import { TooltipDirective } from './tooltip.directive';
    
    
    OZGCloud's avatar
    OZGCloud committed
    class MockElementRef extends ElementRef {
      nativeElement = {
        contains: jest.fn(),
        appendChild: jest.fn(),
      };
    }
    
    OZGCloud's avatar
    OZGCloud committed
    
    
    OZGCloud's avatar
    OZGCloud committed
    describe('TooltipDirective', () => {
    
    OZGCloud's avatar
    OZGCloud committed
      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 },
    
    OZGCloud's avatar
    OZGCloud committed
      };
    
    
    OZGCloud's avatar
    OZGCloud committed
      beforeEach((): void => {
        TestBed.configureTestingModule({
    
    OZGCloud's avatar
    OZGCloud committed
          providers: [ViewContainerRef, { provide: ElementRef, useClass: MockElementRef }, Renderer2, InteractivityChecker],
        });
        TestBed.runInInjectionContext(() => {
          directive = new TooltipDirective();
    
    OZGCloud's avatar
    OZGCloud committed
        });
      });
    
    
    OZGCloud's avatar
    OZGCloud committed
      it('should create a directive', () => {
        expect(directive).toBeTruthy();
      });
    
    OZGCloud's avatar
    OZGCloud committed
    
    
      describe('ngAfterViewInit', () => {
        it('should create tooltip', () => {
          directive.createTooltip = jest.fn();
    
          directive.ngAfterViewInit();
    
          expect(directive.createTooltip).toHaveBeenCalled();
        });
      });
    
    
    OZGCloud's avatar
    OZGCloud committed
      describe('ngOnDestroy', () => {
        it('should destroy tooltip', () => {
          directive.destroy = jest.fn();
    
          directive.ngOnDestroy();
    
          expect(directive.destroy).toHaveBeenCalled();
    
    OZGCloud's avatar
    OZGCloud committed
        });
      });
    
    
    OZGCloud's avatar
    OZGCloud committed
      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();
    
    OZGCloud's avatar
    OZGCloud committed
        });
    
        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', () => {
    
    OZGCloud's avatar
    OZGCloud committed
          directive.createTooltip();
    
    
          expect(directive.focusableElement.appendChild).toHaveBeenCalled();
    
    OZGCloud's avatar
    OZGCloud committed
        });
    
    
        it('should set aria-labeledby attribute to parent', () => {
    
    OZGCloud's avatar
    OZGCloud committed
          directive.createTooltip();
    
    
          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();
    
    OZGCloud's avatar
    OZGCloud committed
        });
    
        it('should set tooltip properties', () => {
    
          directive.showTooltip();
    
    OZGCloud's avatar
    OZGCloud committed
    
    
          expect(directive.setTooltipProperties).toHaveBeenCalledWith(true);
    
    OZGCloud's avatar
    OZGCloud committed
        });
      });
    
    
      describe('hideTooltip', () => {
        it('should hide tooltip', () => {
          directive.hide = jest.fn();
    
    OZGCloud's avatar
    OZGCloud committed
    
    
          directive.hideTooltip();
    
    OZGCloud's avatar
    OZGCloud committed
    
    
          expect(directive.hide).toHaveBeenCalled();
    
    OZGCloud's avatar
    OZGCloud committed
        });
      });
    
      describe('onKeydown', () => {
    
        it('should hide tooltip if escape key pressed', () => {
          directive.hide = jest.fn();
    
    OZGCloud's avatar
    OZGCloud committed
          const escapeEvent: KeyboardEvent = { ...new KeyboardEvent('esc'), key: 'Escape' };
    
          directive.onKeydown(escapeEvent);
    
    OZGCloud's avatar
    OZGCloud committed
    
    
          expect(directive.hide).toHaveBeenCalled();
    
    OZGCloud's avatar
    OZGCloud committed
        });
      });
    
      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();
    
    OZGCloud's avatar
    OZGCloud committed
    
    
    OZGCloud's avatar
    OZGCloud committed
          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,
    
    OZGCloud's avatar
    OZGCloud committed
          });
        });
    
    OZGCloud's avatar
    OZGCloud committed
    
        it('should add margin if parent element focused', () => {
          directive.setTooltipProperties(true);
    
          expect(directive.componentRef.instance.top).toBe(1004);
        });
      });
    
    
      describe('setAriaLabeledBy', () => {
    
    OZGCloud's avatar
    OZGCloud committed
        beforeEach(() => {
          directive.renderer.setAttribute = jest.fn();
        });
    
    
        it('should set aria-labeledby attribute', () => {
          directive.setAriaLabeledBy();
    
    OZGCloud's avatar
    OZGCloud committed
    
          expect(directive.renderer.setAttribute).toHaveBeenCalled();
        });
      });
    
    
      describe('removeAriaLabeledBy', () => {
    
    OZGCloud's avatar
    OZGCloud committed
        beforeEach(() => {
          directive.renderer.removeAttribute = jest.fn();
        });
    
    
        it('should remove aria-labeledby attribute', () => {
          directive.removeAriaLabeledBy();
    
    OZGCloud's avatar
    OZGCloud committed
    
          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;
        });
      });
    
    
    OZGCloud's avatar
    OZGCloud committed
      describe('destroy', () => {
        beforeEach(() => {
          directive.componentRef = mockComponentRef;
    
          directive.removeAriaLabeledBy = jest.fn();
    
    OZGCloud's avatar
    OZGCloud committed
        });
    
        it('should set component ref to null', () => {
          directive.destroy();
    
          expect(directive.componentRef).toBeNull();
        });
    
    
        it('should remove aria-labeledby attribute', () => {
    
    OZGCloud's avatar
    OZGCloud committed
          directive.destroy();
    
    
          expect(directive.removeAriaLabeledBy).toHaveBeenCalled();
    
    OZGCloud's avatar
    OZGCloud committed
        });
    
        it('should set focusable element to null', () => {
          directive.destroy();
    
          expect(directive.focusableElement).toBeNull();
        });
    
    OZGCloud's avatar
    OZGCloud committed
      });
    });