mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[ACS-11350] keyboard navigation user incorrect focus order after collapsing the left navigation menu (#11835)
* [ACS-11350] Fixed focus after collapsing navigation menu * [ACS-11350] Unit tests * [ACS-11350] Addressed copilot comments * [ACS-11350] Addressed copilot comment * [ACS-11350] Addressed copilot comment
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
[position]="position"
|
[position]="position"
|
||||||
[disableClose]="!isMobileScreenSize"
|
[disableClose]="!isMobileScreenSize"
|
||||||
[@sidenavAnimation]="sidenavAnimationState"
|
[@sidenavAnimation]="sidenavAnimationState"
|
||||||
[opened]="!isMobileScreenSize || !hideSidenav"
|
[opened]="!isMobileScreenSize && !hideSidenav"
|
||||||
[mode]="isMobileScreenSize ? 'over' : 'side'">
|
[mode]="isMobileScreenSize ? 'over' : 'side'">
|
||||||
<ng-content sidenav select="[app-layout-navigation]" />
|
<ng-content sidenav select="[app-layout-navigation]" />
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
|
|||||||
+35
-14
@@ -17,11 +17,16 @@
|
|||||||
|
|
||||||
import { LayoutContainerComponent } from './layout-container.component';
|
import { LayoutContainerComponent } from './layout-container.component';
|
||||||
import { SimpleChange } from '@angular/core';
|
import { SimpleChange } from '@angular/core';
|
||||||
import { MatSidenav } from '@angular/material/sidenav';
|
|
||||||
import { Direction } from '@angular/cdk/bidi';
|
import { Direction } from '@angular/cdk/bidi';
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { UnitTestingUtils } from '../../../testing/unit-testing-utils';
|
||||||
|
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||||
|
import { MatSidenavHarness } from '@angular/material/sidenav/testing';
|
||||||
|
|
||||||
describe('LayoutContainerComponent', () => {
|
describe('LayoutContainerComponent', () => {
|
||||||
|
let fixture: ComponentFixture<LayoutContainerComponent>;
|
||||||
let layoutContainerComponent: LayoutContainerComponent;
|
let layoutContainerComponent: LayoutContainerComponent;
|
||||||
|
let unitTestingUtils: UnitTestingUtils;
|
||||||
|
|
||||||
const setupComponent = (expandedSidenav: boolean, position: 'start' | 'end', direction: Direction) => {
|
const setupComponent = (expandedSidenav: boolean, position: 'start' | 'end', direction: Direction) => {
|
||||||
layoutContainerComponent.expandedSidenav = expandedSidenav;
|
layoutContainerComponent.expandedSidenav = expandedSidenav;
|
||||||
@@ -45,7 +50,12 @@ describe('LayoutContainerComponent', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
layoutContainerComponent = new LayoutContainerComponent();
|
TestBed.configureTestingModule({
|
||||||
|
imports: [LayoutContainerComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(LayoutContainerComponent);
|
||||||
|
layoutContainerComponent = fixture.componentInstance;
|
||||||
|
unitTestingUtils = new UnitTestingUtils(fixture.debugElement, TestbedHarnessEnvironment.loader(fixture));
|
||||||
layoutContainerComponent.sidenavMin = 70;
|
layoutContainerComponent.sidenavMin = 70;
|
||||||
layoutContainerComponent.sidenavMax = 200;
|
layoutContainerComponent.sidenavMax = 200;
|
||||||
layoutContainerComponent.mediaQueryList = {
|
layoutContainerComponent.mediaQueryList = {
|
||||||
@@ -53,11 +63,6 @@ describe('LayoutContainerComponent', () => {
|
|||||||
addListener: jasmine.createSpy('addListener').and.callFake((callback) => window.addEventListener('resize', callback)),
|
addListener: jasmine.createSpy('addListener').and.callFake((callback) => window.addEventListener('resize', callback)),
|
||||||
removeListener: jasmine.createSpy('removeListener').and.callFake((callback) => window.removeEventListener('resize', callback))
|
removeListener: jasmine.createSpy('removeListener').and.callFake((callback) => window.removeEventListener('resize', callback))
|
||||||
};
|
};
|
||||||
layoutContainerComponent.sidenav = {
|
|
||||||
open: jasmine.createSpy('open'),
|
|
||||||
close: jasmine.createSpy('close'),
|
|
||||||
toggle: jasmine.createSpy('toggle')
|
|
||||||
} as unknown as MatSidenav;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('OnInit', () => {
|
describe('OnInit', () => {
|
||||||
@@ -164,28 +169,40 @@ describe('LayoutContainerComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('toggleMenu()', () => {
|
describe('toggleMenu()', () => {
|
||||||
it('should switch to sidenav to compact state', () => {
|
let sidenav: MatSidenavHarness;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
sidenav = await unitTestingUtils.getMatSidenav();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should switch to sidenav to compact state', async () => {
|
||||||
layoutContainerComponent.expandedSidenav = true;
|
layoutContainerComponent.expandedSidenav = true;
|
||||||
layoutContainerComponent.ngOnInit();
|
layoutContainerComponent.ngOnInit();
|
||||||
layoutContainerComponent.toggleMenu();
|
layoutContainerComponent.toggleMenu();
|
||||||
|
fixture.detectChanges();
|
||||||
expect(layoutContainerComponent.sidenavAnimationState).toEqual({
|
expect(layoutContainerComponent.sidenavAnimationState).toEqual({
|
||||||
value: 'compact',
|
value: 'compact',
|
||||||
params: { width: layoutContainerComponent.sidenavMin }
|
params: { width: layoutContainerComponent.sidenavMin }
|
||||||
});
|
});
|
||||||
|
expect(await sidenav.isOpen()).toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should switch to sidenav to expanded state', () => {
|
it('should switch to sidenav to expanded state', async () => {
|
||||||
layoutContainerComponent.expandedSidenav = false;
|
layoutContainerComponent.expandedSidenav = false;
|
||||||
layoutContainerComponent.ngOnInit();
|
layoutContainerComponent.ngOnInit();
|
||||||
layoutContainerComponent.toggleMenu();
|
layoutContainerComponent.toggleMenu();
|
||||||
|
fixture.detectChanges();
|
||||||
expect(layoutContainerComponent.sidenavAnimationState).toEqual({
|
expect(layoutContainerComponent.sidenavAnimationState).toEqual({
|
||||||
value: 'expanded',
|
value: 'expanded',
|
||||||
params: { width: layoutContainerComponent.sidenavMax }
|
params: { width: layoutContainerComponent.sidenavMax }
|
||||||
});
|
});
|
||||||
|
expect(await sidenav.isOpen()).toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Media query change', () => {
|
describe('Media query change', () => {
|
||||||
|
let sidenav: MatSidenavHarness;
|
||||||
|
|
||||||
const expandedState = {
|
const expandedState = {
|
||||||
value: 'expanded',
|
value: 'expanded',
|
||||||
params: { width: 200 }
|
params: { width: 200 }
|
||||||
@@ -196,14 +213,18 @@ describe('LayoutContainerComponent', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const testMediaQueryChange = (matches: boolean, expectedSidenavState: any, expectedContentState: any) => {
|
const testMediaQueryChange = (matches: boolean, expectedSidenavState: any, expectedContentState: any) => {
|
||||||
layoutContainerComponent.ngOnInit();
|
fixture.detectChanges();
|
||||||
layoutContainerComponent.mediaQueryList.matches = matches;
|
layoutContainerComponent.mediaQueryList.matches = matches;
|
||||||
window.dispatchEvent(new Event('resize'));
|
window.dispatchEvent(new Event('resize'));
|
||||||
expect(layoutContainerComponent.sidenavAnimationState).toEqual(expectedSidenavState);
|
expect(layoutContainerComponent.sidenavAnimationState).toEqual(expectedSidenavState);
|
||||||
expect(layoutContainerComponent.contentAnimationState).toEqual(expectedContentState);
|
expect(layoutContainerComponent.contentAnimationState).toEqual(expectedContentState);
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should close sidenav on mobile and open on desktop', () => {
|
beforeEach(async () => {
|
||||||
|
sidenav = await unitTestingUtils.getMatSidenav();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close sidenav on mobile and open on desktop', async () => {
|
||||||
testMediaQueryChange(true, expandedState, expandedContentState);
|
testMediaQueryChange(true, expandedState, expandedContentState);
|
||||||
layoutContainerComponent.mediaQueryList.matches = false;
|
layoutContainerComponent.mediaQueryList.matches = false;
|
||||||
window.dispatchEvent(new Event('resize'));
|
window.dispatchEvent(new Event('resize'));
|
||||||
@@ -212,10 +233,10 @@ describe('LayoutContainerComponent', () => {
|
|||||||
value: 'compact',
|
value: 'compact',
|
||||||
params: { 'margin-left': layoutContainerComponent.sidenavMax }
|
params: { 'margin-left': layoutContainerComponent.sidenavMax }
|
||||||
});
|
});
|
||||||
expect(layoutContainerComponent.sidenav.open).toHaveBeenCalled();
|
expect(await sidenav.isOpen()).toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should keep sidenav compact when resized back to desktop and hideSidenav is true', () => {
|
it('should keep sidenav compact when resized back to desktop and hideSidenav is true', async () => {
|
||||||
layoutContainerComponent.hideSidenav = true;
|
layoutContainerComponent.hideSidenav = true;
|
||||||
testMediaQueryChange(true, expandedState, expandedContentState);
|
testMediaQueryChange(true, expandedState, expandedContentState);
|
||||||
layoutContainerComponent.mediaQueryList.matches = false;
|
layoutContainerComponent.mediaQueryList.matches = false;
|
||||||
@@ -225,7 +246,7 @@ describe('LayoutContainerComponent', () => {
|
|||||||
value: 'expanded',
|
value: 'expanded',
|
||||||
params: { 'margin-left': layoutContainerComponent.sidenavMin }
|
params: { 'margin-left': layoutContainerComponent.sidenavMin }
|
||||||
});
|
});
|
||||||
expect(layoutContainerComponent.sidenav.open).not.toHaveBeenCalled();
|
expect(await sidenav.isOpen()).toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ export class LayoutContainerComponent implements OnInit, OnDestroy, OnChanges {
|
|||||||
} else {
|
} else {
|
||||||
this.sidenavAnimationState = this.toggledSidenavAnimation;
|
this.sidenavAnimationState = this.toggledSidenavAnimation;
|
||||||
this.contentAnimationState = this.toggledContentAnimation;
|
this.contentAnimationState = this.toggledContentAnimation;
|
||||||
|
this.hideSidenav = this.sidenavAnimationState === this.SIDENAV_STATES.COMPACT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import { MatListOptionHarness } from '@angular/material/list/testing';
|
|||||||
import { MatCellHarness } from '@angular/material/table/testing';
|
import { MatCellHarness } from '@angular/material/table/testing';
|
||||||
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||||
import { MatMenuHarness } from '@angular/material/menu/testing';
|
import { MatMenuHarness } from '@angular/material/menu/testing';
|
||||||
|
import { MatSidenavHarness } from '@angular/material/sidenav/testing';
|
||||||
|
|
||||||
export class UnitTestingUtils {
|
export class UnitTestingUtils {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -496,4 +497,10 @@ export class UnitTestingUtils {
|
|||||||
async getMatMenuByCSS(selector: string): Promise<MatMenuHarness> {
|
async getMatMenuByCSS(selector: string): Promise<MatMenuHarness> {
|
||||||
return this.loader.getHarness(MatMenuHarness.with({ selector }));
|
return this.loader.getHarness(MatMenuHarness.with({ selector }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** MatSidenav related methods */
|
||||||
|
|
||||||
|
async getMatSidenav(): Promise<MatSidenavHarness> {
|
||||||
|
return this.loader.getHarness(MatSidenavHarness);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user