diff --git a/src/material/tooltip/tooltip.spec.ts b/src/material/tooltip/tooltip.spec.ts index 06f887ef99ca..75bc71db1a3c 100644 --- a/src/material/tooltip/tooltip.spec.ts +++ b/src/material/tooltip/tooltip.spec.ts @@ -63,6 +63,7 @@ describe('MatTooltip', () => { DynamicTooltipsDemo, TooltipOnTextFields, TooltipOnDraggableElement, + DataBoundAriaLabelTooltip, ], providers: [ {provide: Platform, useFactory: () => platform}, @@ -441,20 +442,31 @@ describe('MatTooltip', () => { expect(overlayContainerElement.textContent).toBe(''); })); - it('should have an aria-described element with the tooltip message', () => { + it('should have an aria-described element with the tooltip message', fakeAsync(() => { const dynamicTooltipsDemoFixture = TestBed.createComponent(DynamicTooltipsDemo); const dynamicTooltipsComponent = dynamicTooltipsDemoFixture.componentInstance; dynamicTooltipsComponent.tooltips = ['Tooltip One', 'Tooltip Two']; dynamicTooltipsDemoFixture.detectChanges(); + tick(); - const buttons = dynamicTooltipsComponent.getButtons(); + const buttons = dynamicTooltipsDemoFixture.nativeElement.querySelectorAll('button'); const firstButtonAria = buttons[0].getAttribute('aria-describedby'); expect(document.querySelector(`#${firstButtonAria}`)!.textContent).toBe('Tooltip One'); const secondButtonAria = buttons[1].getAttribute('aria-describedby'); expect(document.querySelector(`#${secondButtonAria}`)!.textContent).toBe('Tooltip Two'); - }); + })); + + it('should not add an ARIA description for elements that have the same text as a' + + 'data-bound aria-label', fakeAsync(() => { + const ariaLabelFixture = TestBed.createComponent(DataBoundAriaLabelTooltip); + ariaLabelFixture.detectChanges(); + tick(); + + const button = ariaLabelFixture.nativeElement.querySelector('button'); + expect(button.getAttribute('aria-describedby')).toBeFalsy(); + })); it('should not try to dispose the tooltip when destroyed and done hiding', fakeAsync(() => { tooltipDirective.show(); @@ -1011,14 +1023,16 @@ class OnPushTooltipDemo { }) class DynamicTooltipsDemo { tooltips: Array = []; +} - constructor(private _elementRef: ElementRef) {} - - getButtons() { - return this._elementRef.nativeElement.querySelectorAll('button'); - } +@Component({ + template: ``, +}) +class DataBoundAriaLabelTooltip { + message = 'Hello there'; } + @Component({ template: ` { + // The `AriaDescriber` has some functionality that avoids adding a description if it's the + // same as the `aria-label` of an element, however we can't know whether the tooltip trigger + // has a data-bound `aria-label` or when it'll be set for the first time. We can avoid the + // issue by deferring the description by a tick so Angular has time to set the `aria-label`. + Promise.resolve().then(() => { + this._ariaDescriber.describe(this._elementRef.nativeElement, this.message); + }); + }); } }