diff --git a/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.html b/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.html index 68ae4ba54..0a83605fc 100644 --- a/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.html +++ b/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.html @@ -4,7 +4,8 @@ class="aca-sidenav-header-title-logo" data-automation-id="app-sidenav-header-title-logo" (click)="toggleNavBar.emit()" - [attr.aria-label]="'APP.TOOLTIPS.COLLAPSE_NAVIGATION' | translate"> + [attr.aria-label]="'APP.TOOLTIPS.COLLAPSE_NAVIGATION' | translate" + #toggleNavbarButton> . + */ + +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { SidenavHeaderComponent } from './sidenav-header.component'; +import { NoopAuthModule, NoopTranslateModule, UnitTestingUtils } from '@alfresco/adf-core'; +import { AppService } from '@alfresco/aca-shared'; +import { Subject } from 'rxjs'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { provideHttpClient } from '@angular/common/http'; +import { provideMockStore } from '@ngrx/store/testing'; + +describe('SidenavHeaderComponent', () => { + let fixture: ComponentFixture; + let unitTestingUtils: UnitTestingUtils; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [SidenavHeaderComponent, NoopAuthModule, NoopTranslateModule], + providers: [ + { + provide: AppService, + useValue: { + toggleAppNavBar$: new Subject() + } + }, + provideHttpClient(), + provideHttpClientTesting(), + provideMockStore({ + initialState: { + app: { + selection: {} + } + } + }) + ] + }); + fixture = TestBed.createComponent(SidenavHeaderComponent); + unitTestingUtils = new UnitTestingUtils(fixture.debugElement); + }); + + describe('Toggle navbar button', () => { + let toggleSidenavButton: Element; + + beforeEach(() => { + document.body.focus(); + fixture.detectChanges(); + toggleSidenavButton = unitTestingUtils.getByCSS('.aca-sidenav-header-title-logo').nativeElement; + }); + + it('should be focused when toggleAppNavBar$ emits on AppService', fakeAsync(() => { + TestBed.inject(AppService).toggleAppNavBar$.next(); + tick(); + + expect(toggleSidenavButton).toBe(document.activeElement); + })); + + it('should not be focused when toggleAppNavBar$ does not emit on AppService', () => { + expect(toggleSidenavButton).not.toBe(document.activeElement); + }); + }); +}); diff --git a/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.ts b/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.ts index a34d3bc09..65c5a395e 100644 --- a/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.ts +++ b/projects/aca-content/src/lib/components/sidenav/components/sidenav-header.component.ts @@ -22,9 +22,9 @@ * from Hyland Software. If not, see . */ -import { Component, DestroyRef, EventEmitter, inject, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { Component, DestroyRef, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { ContentActionRef } from '@alfresco/adf-extensions'; -import { AppExtensionService, AppSettingsService, ToolbarComponent } from '@alfresco/aca-shared'; +import { AppExtensionService, AppService, AppSettingsService, ToolbarComponent } from '@alfresco/aca-shared'; import { CommonModule } from '@angular/common'; import { TranslatePipe } from '@ngx-translate/core'; import { RouterModule } from '@angular/router'; @@ -38,6 +38,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; host: { class: 'app-sidenav-header' } }) export class SidenavHeaderComponent implements OnInit { + private readonly appService = inject(AppService); private readonly appSettings = inject(AppSettingsService); private readonly appExtensions = inject(AppExtensionService); @@ -51,6 +52,9 @@ export class SidenavHeaderComponent implements OnInit { @Output() toggleNavBar = new EventEmitter(); + @ViewChild('toggleNavbarButton') + private readonly toggleNavbarButton!: ElementRef; + ngOnInit() { this.appExtensions .getHeaderActions() @@ -58,5 +62,10 @@ export class SidenavHeaderComponent implements OnInit { .subscribe((actions) => { this.actions = actions; }); + this.appService.toggleAppNavBar$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { + setTimeout(() => { + this.toggleNavbarButton.nativeElement.focus(); + }); + }); } } diff --git a/projects/aca-shared/src/lib/components/page-layout/page-layout.component.html b/projects/aca-shared/src/lib/components/page-layout/page-layout.component.html index 509d4b572..c180fc516 100644 --- a/projects/aca-shared/src/lib/components/page-layout/page-layout.component.html +++ b/projects/aca-shared/src/lib/components/page-layout/page-layout.component.html @@ -3,7 +3,9 @@ mat-icon-button class="aca-content-header-button" (click)="toggleClick()" - title="{{'APP.TOOLTIPS.EXPAND_NAVIGATION' | translate}}"> + [attr.aria-label]="'APP.TOOLTIPS.EXPAND_NAVIGATION' | translate" + title="{{'APP.TOOLTIPS.EXPAND_NAVIGATION' | translate}}" + adf-auto-focus> keyboard_double_arrow_right diff --git a/projects/aca-shared/src/lib/components/page-layout/page-layout.component.spec.ts b/projects/aca-shared/src/lib/components/page-layout/page-layout.component.spec.ts index 6819a85ab..ca06fdb3b 100644 --- a/projects/aca-shared/src/lib/components/page-layout/page-layout.component.spec.ts +++ b/projects/aca-shared/src/lib/components/page-layout/page-layout.component.spec.ts @@ -26,10 +26,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { PageLayoutComponent } from './page-layout.component'; import { AppService } from '../../services/app.service'; import { BehaviorSubject, Subject } from 'rxjs'; +import { NoopTranslateModule, UnitTestingUtils } from '@alfresco/adf-core'; +import { AutoFocusDirective } from '@alfresco/adf-content-services'; +import { DebugElement } from '@angular/core'; describe('PageLayoutComponent', () => { let fixture: ComponentFixture; - let component: PageLayoutComponent; + let unitTestingUtils: UnitTestingUtils; + const appServiceMock = { toggleAppNavBar$: new Subject(), appNavNarMode$: new BehaviorSubject<'collapsed' | 'expanded'>('expanded') @@ -37,7 +41,7 @@ describe('PageLayoutComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [PageLayoutComponent], + imports: [PageLayoutComponent, NoopTranslateModule], providers: [ { provide: AppService, @@ -46,12 +50,28 @@ describe('PageLayoutComponent', () => { ] }); fixture = TestBed.createComponent(PageLayoutComponent); - component = fixture.componentInstance; + unitTestingUtils = new UnitTestingUtils(fixture.debugElement); }); - it('should toggle the appService toggleAppNavBar$ Subject', () => { - spyOn(appServiceMock.toggleAppNavBar$, 'next'); - component.toggleClick(); - expect(appServiceMock.toggleAppNavBar$.next).toHaveBeenCalled(); + describe('Expand button', () => { + let expandButton: DebugElement; + + beforeEach(() => { + appServiceMock.appNavNarMode$.next('collapsed'); + fixture.detectChanges(); + expandButton = unitTestingUtils.getByCSS('.aca-content-header-button'); + }); + + it('should toggle the appService toggleAppNavBar$ Subject', () => { + spyOn(appServiceMock.toggleAppNavBar$, 'next'); + + expandButton.nativeElement.click(); + expect(appServiceMock.toggleAppNavBar$.next).toHaveBeenCalled(); + }); + + it('should have AutoFocusDirective', () => { + fixture.detectChanges(); + expect(expandButton.injector.get(AutoFocusDirective, null)).not.toBeNull(); + }); }); }); diff --git a/projects/aca-shared/src/lib/components/page-layout/page-layout.component.ts b/projects/aca-shared/src/lib/components/page-layout/page-layout.component.ts index 68cfc216f..00856fc4b 100644 --- a/projects/aca-shared/src/lib/components/page-layout/page-layout.component.ts +++ b/projects/aca-shared/src/lib/components/page-layout/page-layout.component.ts @@ -30,9 +30,10 @@ import { TranslatePipe } from '@ngx-translate/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { AutoFocusDirective } from '@alfresco/adf-content-services'; @Component({ - imports: [CommonModule, TranslatePipe, MatButtonModule, MatIconModule], + imports: [CommonModule, TranslatePipe, MatButtonModule, MatIconModule, AutoFocusDirective], selector: 'aca-page-layout', templateUrl: './page-layout.component.html', styleUrls: ['./page-layout.component.scss'],