Skip to content

Commit b46689e

Browse files
devversionmmalerba
authored andcommitted
fix(snack-bar): prevent content from overriding configured aria-live message (#12294)
* Currently the `announcementMessage` config option is always being overwritten when opening a simple snackbar.
1 parent 8a2dc60 commit b46689e

File tree

3 files changed

+50
-14
lines changed

3 files changed

+50
-14
lines changed

src/lib/snack-bar/snack-bar-config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ export class MatSnackBarConfig<D = any> {
2626
/** The politeness level for the MatAriaLiveAnnouncer announcement. */
2727
politeness?: AriaLivePoliteness = 'assertive';
2828

29-
/** Message to be announced by the MatAriaLiveAnnouncer */
29+
/**
30+
* Message to be announced by the LiveAnnouncer. When opening a snackbar without a custom
31+
* component or template, the announcement message will default to the specified message.
32+
*/
3033
announcementMessage?: string = '';
3134

3235
/** The view container to place the overlay for the snack bar into. */

src/lib/snack-bar/snack-bar.spec.ts

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,21 @@ describe('MatSnackBar', () => {
7575
.toBe('alert', 'Expected snack bar container to have role="alert"');
7676
});
7777

78-
it('should open and close a snackbar without a ViewContainerRef', fakeAsync(() => {
79-
let snackBarRef = snackBar.open('Snack time!', 'Chew');
80-
viewContainerFixture.detectChanges();
78+
it('should open and close a snackbar without a ViewContainerRef', fakeAsync(() => {
79+
let snackBarRef = snackBar.open('Snack time!', 'Chew');
80+
viewContainerFixture.detectChanges();
8181

82-
let messageElement = overlayContainerElement.querySelector('snack-bar-container')!;
83-
expect(messageElement.textContent).toContain('Snack time!',
84-
'Expected snack bar to show a message without a ViewContainerRef');
82+
let messageElement = overlayContainerElement.querySelector('snack-bar-container')!;
83+
expect(messageElement.textContent).toContain('Snack time!',
84+
'Expected snack bar to show a message without a ViewContainerRef');
8585

86-
snackBarRef.dismiss();
87-
viewContainerFixture.detectChanges();
88-
flush();
86+
snackBarRef.dismiss();
87+
viewContainerFixture.detectChanges();
88+
flush();
8989

90-
expect(overlayContainerElement.childNodes.length)
91-
.toBe(0, 'Expected snack bar to be dismissed without a ViewContainerRef');
92-
}));
90+
expect(overlayContainerElement.childNodes.length)
91+
.toBe(0, 'Expected snack bar to be dismissed without a ViewContainerRef');
92+
}));
9393

9494
it('should open a simple message with a button', () => {
9595
let config: MatSnackBarConfig = {viewContainerRef: testViewContainerRef};
@@ -153,6 +153,36 @@ describe('MatSnackBar', () => {
153153
.toBe(0, 'Expected the overlay container element to have no child elements');
154154
}));
155155

156+
157+
it('should default to the passed message for the announcement message', fakeAsync(() => {
158+
spyOn(liveAnnouncer, 'announce');
159+
160+
snackBar.open(simpleMessage);
161+
viewContainerFixture.detectChanges();
162+
163+
expect(overlayContainerElement.childElementCount)
164+
.toBe(1, 'Expected the overlay with the default announcement message to be added');
165+
166+
// Expect the live announcer to have been called with the display message and some
167+
// string for the politeness. We do not want to test for the default politeness here.
168+
expect(liveAnnouncer.announce).toHaveBeenCalledWith(simpleMessage, jasmine.any(String));
169+
}));
170+
171+
it('should be able to specify a custom announcement message', fakeAsync(() => {
172+
spyOn(liveAnnouncer, 'announce');
173+
174+
snackBar.open(simpleMessage, '', {
175+
announcementMessage: 'Custom announcement',
176+
politeness: 'assertive'
177+
});
178+
viewContainerFixture.detectChanges();
179+
180+
expect(overlayContainerElement.childElementCount)
181+
.toBe(1, 'Expected the overlay with a custom `announcementMessage` to be added');
182+
183+
expect(liveAnnouncer.announce).toHaveBeenCalledWith('Custom announcement', 'assertive');
184+
}));
185+
156186
it('should be able to get dismissed through the service', fakeAsync(() => {
157187
snackBar.open(simpleMessage);
158188
viewContainerFixture.detectChanges();

src/lib/snack-bar/snack-bar.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ export class MatSnackBar {
112112
// Since the user doesn't have access to the component, we can
113113
// override the data to pass in our own message and action.
114114
_config.data = {message, action};
115-
_config.announcementMessage = message;
115+
116+
if (!_config.announcementMessage) {
117+
_config.announcementMessage = message;
118+
}
116119

117120
return this.openFromComponent(SimpleSnackBar, _config);
118121
}

0 commit comments

Comments
 (0)