Skip to content

Commit

Permalink
fix: Enable enter/space-key for parent-/sub-group navigation for bett…
Browse files Browse the repository at this point in the history
…er accessibility (#18560)

Co-authored-by: Larisa Staroverova <[email protected]>
  • Loading branch information
steinsebastian and Larisa-Staroverova authored Mar 1, 2024
1 parent 3db1725 commit 0ecf4c2
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"
aria-describedby="listOfGroups"
[cxFocus]="{ key: 'cx-menu-back' }"
(click)="navigateUp()"
(click)="navigateUp(currentGroup)"
(keydown)="
switchGroupOnArrowPress(
$event,
Expand Down Expand Up @@ -65,7 +65,7 @@
[cxFocus]="{
key: group.id
}"
(click)="click(group)"
(click)="click(group, currentGroup)"
[tabindex]="getTabIndex(group, currentGroup.id)"
(keydown)="
switchGroupOnArrowPress(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,28 +380,6 @@ describe('ConfigurationGroupMenuComponent', () => {
});
});

it('should set current group in case of clicking on a different group', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
initialize();

component.click(mockProductConfiguration.groups[0]);

expect(configuratorGroupsService.navigateToGroup).toHaveBeenCalled();
expect(hamburgerMenuService.toggle).toHaveBeenCalled();
});

it('should not set current group and not execute navigation in case of clicking on same group', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
initialize();

component.click(mockProductConfiguration.groups[1]);

expect(configuratorGroupsService.navigateToGroup).toHaveBeenCalledTimes(0);
expect(hamburgerMenuService.toggle).toHaveBeenCalledTimes(0);
});

it('should condense groups', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
Expand Down Expand Up @@ -432,46 +410,106 @@ describe('ConfigurationGroupMenuComponent', () => {
});
});

it('should navigate up', () => {
spyOn(configuratorGroupsService, 'getMenuParentGroup').and.returnValue(
of(mockProductConfiguration.groups[0])
);
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
spyOn(configuratorGroupsService, 'getParentGroup').and.returnValue(
mockProductConfiguration.groups[0]
);
initialize();
component.navigateUp();
expect(configuratorGroupsService.getParentGroup).toHaveBeenCalled();
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
});
describe('navigateUp', () => {
it('should navigate up (and not set focus)', () => {
spyOn(configuratorGroupsService, 'getMenuParentGroup').and.returnValue(
of(mockProductConfiguration.groups[0])
);
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
spyOn(configuratorGroupsService, 'getParentGroup').and.returnValue(
mockProductConfiguration.groups[0]
);
initialize();
component.navigateUp();
expect(configuratorGroupsService.getParentGroup).toHaveBeenCalled();
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
expect(configUtils.setFocus).toHaveBeenCalledTimes(0);
});

it('should navigate up, parent group null', () => {
spyOn(configuratorGroupsService, 'getMenuParentGroup').and.returnValue(
of(mockProductConfiguration.groups[0])
);
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
spyOn(configuratorGroupsService, 'getParentGroup').and.callThrough();
initialize();
component.navigateUp();
expect(configuratorGroupsService.getParentGroup).toHaveBeenCalled();
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
it('should navigate up and set focus if current group is provided', () => {
spyOn(configuratorGroupsService, 'getMenuParentGroup').and.returnValue(
of(mockProductConfiguration.groups[0])
);
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
spyOn(configuratorGroupsService, 'getParentGroup').and.returnValue(
mockProductConfiguration.groups[0]
);
initialize();

component.navigateUp(mockProductConfiguration.groups[0]);
expect(configuratorGroupsService.getParentGroup).toHaveBeenCalled();
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
expect(configUtils.setFocus).toHaveBeenCalled();
});

it('should navigate up, parent group null', () => {
spyOn(configuratorGroupsService, 'getMenuParentGroup').and.returnValue(
of(mockProductConfiguration.groups[0])
);
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
spyOn(configuratorGroupsService, 'getParentGroup').and.callThrough();
initialize();
component.navigateUp();
expect(configuratorGroupsService.getParentGroup).toHaveBeenCalled();
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
});
});

it('should call correct methods for groups with and without subgroups', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
initialize();
//Set group
component.click(mockProductConfiguration.groups[2].subGroups[0]);
expect(configuratorGroupsService.navigateToGroup).toHaveBeenCalled();
expect(hamburgerMenuService.toggle).toHaveBeenCalled();

//Display subgroups
component.click(mockProductConfiguration.groups[2]);
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
describe('click', () => {
it('should call correct methods for groups with and without subgroups', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
initialize();
//Set group
component.click(mockProductConfiguration.groups[2].subGroups[0]);
expect(configuratorGroupsService.navigateToGroup).toHaveBeenCalled();
expect(hamburgerMenuService.toggle).toHaveBeenCalled();

//Display subgroups
component.click(mockProductConfiguration.groups[2]);
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
expect(configUtils.setFocus).toHaveBeenCalledTimes(0);
});

it('should call correct methods for subgroups and set focus if current group is provided', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
initialize();

component.click(
mockProductConfiguration.groups[2],
mockProductConfiguration.groups[0]
);
expect(configuratorGroupsService.setMenuParentGroup).toHaveBeenCalled();
expect(configUtils.setFocus).toHaveBeenCalled();
});

it('should set current group in case of clicking on a different group', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
initialize();

component.click(mockProductConfiguration.groups[0]);

expect(configuratorGroupsService.navigateToGroup).toHaveBeenCalled();
expect(hamburgerMenuService.toggle).toHaveBeenCalled();
});

it('should not set current group and not execute navigation in case of clicking on same group', () => {
productConfigurationObservable = of(mockProductConfiguration);
routerStateObservable = of(mockRouterState);
initialize();

component.click(mockProductConfiguration.groups[1]);

expect(configuratorGroupsService.navigateToGroup).toHaveBeenCalledTimes(
0
);
expect(hamburgerMenuService.toggle).toHaveBeenCalledTimes(0);
});
});

it('should return number of conflicts only for conflict header group', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,13 @@ export class ConfiguratorGroupMenuComponent {
protected configExpertModeService: ConfiguratorExpertModeService
) {}

click(group: Configurator.Group): void {
/**
* Selects group or navigates to sub-group depending on clicked group
*
* @param {Configurator.Group} group - Target Group
* @param {Configurator.Group} currentGroup - Current group
*/
click(group: Configurator.Group, currentGroup?: Configurator.Group): void {
this.configuration$.pipe(take(1)).subscribe((configuration) => {
if (configuration.interactionState.currentGroup === group.id) {
return;
Expand All @@ -137,11 +143,19 @@ export class ConfiguratorGroupMenuComponent {
configuration.owner,
group.id
);
if (currentGroup) {
this.setFocusForSubGroup(group, currentGroup.id);
}
}
});
}

navigateUp(): void {
/**
* Navigate up and set focus if current group information is provided
*
* @param {Configurator.Group} currentGroup - Current group
*/
navigateUp(currentGroup?: Configurator.Group): void {
this.displayedParentGroup$
.pipe(take(1))
.subscribe((displayedParentGroup) => {
Expand All @@ -158,6 +172,9 @@ export class ConfiguratorGroupMenuComponent {
});
}
});
if (currentGroup) {
this.setFocusForMainMenu(currentGroup.id);
}
}

/**
Expand Down Expand Up @@ -390,13 +407,11 @@ export class ConfiguratorGroupMenuComponent {
);
} else if (this.isForwardsNavigation(event)) {
if (targetGroup && this.hasSubGroups(targetGroup)) {
this.click(targetGroup);
this.setFocusForSubGroup(targetGroup, currentGroup.id);
this.click(targetGroup, currentGroup);
}
} else if (this.isBackNavigation(event)) {
if (this.configGroupMenuService.isBackBtnFocused(this.groups)) {
this.navigateUp();
this.setFocusForMainMenu(currentGroup.id);
this.navigateUp(currentGroup);
}
}
}
Expand Down

0 comments on commit 0ecf4c2

Please sign in to comment.