From ee0786b20fbe918992cac1feae69ea425ff1f0ce Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 16 Apr 2025 05:11:44 -0600 Subject: [PATCH] fix(material/select): remove value from aria-labelledby --- src/material/paginator/paginator.spec.ts | 8 +++--- src/material/select/select.spec.ts | 31 +++--------------------- src/material/select/select.ts | 13 ++++++++-- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/material/paginator/paginator.spec.ts b/src/material/paginator/paginator.spec.ts index b39927b72d15..9f141ef2b04a 100644 --- a/src/material/paginator/paginator.spec.ts +++ b/src/material/paginator/paginator.spec.ts @@ -106,11 +106,9 @@ describe('MatPaginator', () => { expect(getNextButton(fixture).getAttribute('aria-label')).toBe('Next page'); const select = fixture.nativeElement.querySelector('.mat-mdc-select'); - const selectLabelIds = select.getAttribute('aria-labelledby')?.split(/\s/g) as string[]; - const selectLabelTexts = selectLabelIds?.map(labelId => { - return fixture.nativeElement.querySelector(`#${labelId}`)?.textContent?.trim(); - }); - expect(selectLabelTexts).toContain('Items per page:'); + const selectLabelId = select.getAttribute('aria-labelledby').trim(); + const selectLabelText = fixture.nativeElement.querySelector(`#${selectLabelId}`)?.textContent; + expect(selectLabelText).toContain('Items per page:'); }); it('should re-render when the i18n labels change', () => { diff --git a/src/material/select/select.spec.ts b/src/material/select/select.spec.ts index 30d9916a751a..038d723544ff 100644 --- a/src/material/select/select.spec.ts +++ b/src/material/select/select.spec.ts @@ -178,31 +178,17 @@ describe('MatSelect', () => { fixture.detectChanges(); const labelId = fixture.nativeElement.querySelector('label').id; - const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id; - expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId} myLabelId`); + expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} myLabelId`); }); - it('should set aria-labelledby to the value and label IDs', () => { + it('should set aria-labelledby to the label ID', () => { fixture.detectChanges(); const labelId = fixture.nativeElement.querySelector('label').id; - const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id; - expect(select.getAttribute('aria-labelledby')).toBe(`${labelId} ${valueId}`); + expect(select.getAttribute('aria-labelledby')).toBe(labelId); }); - it('should trim the trigger aria-labelledby when there is no label', fakeAsync(() => { - fixture.componentInstance.hasLabel = false; - fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - flush(); - fixture.detectChanges(); - - // Note that we assert that there are no spaces around the value. - const valueId = fixture.nativeElement.querySelector('.mat-mdc-select-value').id; - expect(select.getAttribute('aria-labelledby')).toBe(`${valueId}`); - })); - it('should set the tabindex of the select to 0 by default', () => { expect(select.getAttribute('tabindex')).toEqual('0'); }); @@ -297,17 +283,6 @@ describe('MatSelect', () => { expect(select.getAttribute('tabindex')).toEqual('0'); }); - it('should set `aria-labelledby` to the value ID if there is no form field', () => { - fixture.destroy(); - - const labelFixture = TestBed.createComponent(SelectWithChangeEvent); - labelFixture.detectChanges(); - select = labelFixture.debugElement.query(By.css('mat-select'))!.nativeElement; - const valueId = labelFixture.nativeElement.querySelector('.mat-mdc-select-value').id; - - expect(select.getAttribute('aria-labelledby')?.trim()).toBe(valueId); - }); - it('should select options via the UP/DOWN arrow keys on a closed select', fakeAsync(() => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); diff --git a/src/material/select/select.ts b/src/material/select/select.ts index 005312acbe1b..005a466f5b2b 100644 --- a/src/material/select/select.ts +++ b/src/material/select/select.ts @@ -1439,13 +1439,22 @@ export class MatSelect return null; } - const labelId = this._parentFormField?.getLabelId(); - let value = (labelId ? labelId + ' ' : '') + this._valueId; + let value = this._parentFormField?.getLabelId() || ''; if (this.ariaLabelledby) { value += ' ' + this.ariaLabelledby; } + // The value should not be used for the trigger's aria-labelledby, + // but this currently "breaks" accessibility tests since they complain + // there is no aria-labelledby. This is because they are not setting an + // appropriate label on the form field or select. + // TODO: remove this conditional after fixing clients by ensuring their + // selects have a label applied. + if (!value) { + value = this._valueId; + } + return value; }