Testing
It Is Wise to Perform Accessibility Tests During Integration Testing
Performing accessibility (a11y) tests during integration testing provides a more complete and reliable validation of how users experience the real application.
Full Screen Rendering Enables Accurate Testing
When running accessibility checks at the integration-test level, the entire screen is rendered. This ensures:
- All UI sections are present and loaded.
- Heading hierarchy (H1, H2, H3) is validated in its full context.
- Landmark roles (e.g.,
main,nav,header,footer) can be tested consistently. - Dynamic content, routing, and lazy-loaded modules are visible to the test framework.
By contrast, testing only at the component level can hide structural issues because:
- Components are often tested in isolation without real layout.
- Heading order may appear correct inside a component but becomes incorrect when combined with other components.
- Duplicate IDs or missing ARIA labels only show up in integrated views.
Example
A component may contain an <h1> tag, which seems fine in isolation.
But in the full view, another component might also contain an <h1>,
resulting in multiple H1 headings, which is invalid for
accessibility.
Integration testing would detect this (component testing would not).
Common Accessibility Issues in Angular and How to Avoid Them
Incorrect Heading Hierarchy
Problem: Components each define their own headings, unaware of the page structure.
Prevention: - Define heading levels at the page/screen level. - Pass
heading level as an @Input() so components can adapt.
@Component({
selector: 'app-section-title',
template: '<h{{ level }}>{{ title }}</h{{ level }}>',
})
export class SectionTitleComponent {
@Input() level = 2;
@Input() title = '';
}
Missing or Incorrect ARIA Labels
Problem: Inputs, buttons, or icons without textual labels.
Prevention: - Use Angular Material components where possible ---
they include many ARIA attributes out of the box. - For icon-only
buttons, add aria-label:
<button aria-label="Open settings">
<mat-icon>settings</mat-icon>
</button>
Improper Focus Management After Navigation
Problem: Focus stays in the wrong place after route changes, harming keyboard users.
Prevention: - Use Angular's cdkFocusInitial and
cdkFocusRegionStart. - Programmatically set focus on page load:
constructor(private focus: FocusMonitor, private el: ElementRef) {}
ngAfterViewInit() {
this.el.nativeElement.querySelector('h1')?.focus();
}
Low Color Contrast
Problem: CSS that does not meet WCAG contrast ratios.
Prevention: - Use a design system with validated contrast. - Run automated contrast checks in integration tests using tools like axe-core.
Elements Not Keyboard Accessible
Problem: Custom controls without proper keyboard events.
Prevention: - Pair keydown.enter and keydown.space with click
handlers:
<div role="button" tabindex="0"
(click)="open()"
(keydown.enter)="open()"
(keydown.space)="open()">
Open panel
</div>
Why Integration Testing Catches These Issues
Integration tests allow accessibility tooling to analyze:
- Full DOM structure
- Real routing and screen transitions
- Combined headings and landmarks
- Real user interactions
- Live ARIA attributes
These give a much more accurate representation of what a user experiences.
Summary
Testing accessibility at the (integration-test level) ensures your Angular application:
- Renders the full, real UI structure.
- Enforces the correct heading hierarchy.
- Avoids duplicate IDs and missing ARIA labels.
- Validates dynamic content and navigation.
- Produces a more inclusive and compliant user experience.