import {AfterViewInit, Component, ElementRef, Inject, InjectionToken, OnDestroy, ViewChild} from '@angular/core'; import {ComponentFixture, inject, TestBed} from '@angular/core/testing'; import {NgbFocusTrap, NgbFocusTrapFactory} from './focus-trap'; const getElement = (element: HTMLElement, selector: string): HTMLElement => { return element.querySelector(selector) as HTMLElement; }; const Autofocus = new InjectionToken('autofocus'); describe('ngbFocusTrap', () => { beforeEach(() => { TestBed.configureTestingModule({providers: [NgbFocusTrapFactory]}); }); it('should be instantiated manually', inject([NgbFocusTrapFactory], (focusTrapFactory: NgbFocusTrapFactory) => { const element = document.createElement('div'); const focusTrap = focusTrapFactory.create(element); expect(focusTrap).toBeDefined(); focusTrap.destroy(); })); describe('navigation', () => { let fixture: ComponentFixture; let instance; beforeEach(() => { TestBed.configureTestingModule({ declarations: [TestComponent, FocusTrapComponent], providers: [NgbFocusTrapFactory, {provide: Autofocus, useValue: false}] }); fixture = TestBed.createComponent(TestComponent); instance = fixture.componentInstance; fixture.detectChanges(); }); it('should intercept any outside focus when already instantiated', () => { const initial = document.querySelector('#initial') as HTMLElement; const link = getElement(fixture.nativeElement, 'a'); initial.focus(); expect(document.activeElement).toBe(link); }); it('should create/remove the end of document anchor accordingly', () => { expect(document.body.querySelector('.ngb-focustrap-eod')).toBeDefined(); instance.show = false; fixture.detectChanges(); expect(document.body.querySelector('.ngb-focustrap-eod')).toBeNull(); }); }); it('should save/restore focused element when autofocus is set', () => { TestBed.configureTestingModule({ declarations: [TestComponent, FocusTrapComponent], providers: [NgbFocusTrapFactory, {provide: Autofocus, useValue: true}] }); const fixture = TestBed.createComponent(TestComponent); const instance = fixture.componentInstance; instance.show = false; fixture.detectChanges(); // put focus somewhere const initial = document.querySelector('#initial') as HTMLElement; initial.focus(); // let's create the focustrap with autofocus (via ) instance.show = true; fixture.detectChanges(); const button = getElement(fixture.nativeElement, 'button'); expect(document.activeElement).toBe(button); // let's destroy the focustrap (removing ) instance.show = false; fixture.detectChanges(); expect(document.activeElement).toBe(initial); }); }); @Component({ selector: 'focus-trapped', template: `
link not important not important not important
`, }) class FocusTrapComponent implements AfterViewInit, OnDestroy { focusTrap: NgbFocusTrap | null = null; constructor( private _focusTrapFactory: NgbFocusTrapFactory, private _element: ElementRef, @Inject(Autofocus) private _autofocus) {} ngAfterViewInit() { this.focusTrap = this._focusTrapFactory.create(this._element.nativeElement, this._autofocus); } ngOnDestroy() { if (this.focusTrap) { this.focusTrap.destroy(); this.focusTrap = null; } } } @Component({ template: `
` }) class TestComponent { show = true; @ViewChild(FocusTrapComponent) wrapper; }