Skip to content

Commit

Permalink
Fix repetitive narration in Windows Narrator (#4323)
Browse files Browse the repository at this point in the history
* Fix repetitive narration in Windows Narrator

* Fix test

* Fix tests and repetitives

* Fix test

* Fix repetitive narrations in JAWS

* Remove aria-roledescription
  • Loading branch information
compulim authored Jun 23, 2022
1 parent 392f66b commit d972175
Show file tree
Hide file tree
Showing 56 changed files with 491 additions and 293 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Centralized live region of suggested actions into chat history live region for better live region control
- Suggested actions container is now a `role="toolbar"` and uses roving tab index for multiple suggested action
- Fixes [#4319](https://github.com/microsoft/BotFramework-WebChat/issues/4319). Fixed navigation keys not working in suggested actions under IE Mode, by [@compulim](https://github.com/compulim), in PR [#4320](https://github.com/microsoft/BotFramework-WebChat/pull/4320)
- Fixes [#4315](https://github.com/microsoft/BotFramework-WebChat/issues/4315). Cleaned up localization strings for suggested actions, by [@compulim](https://github.com/compulim), in PR [#4323](https://github.com/microsoft/BotFramework-WebChat/issues/4323)
- Fixes [#4294](https://github.com/microsoft/BotFramework-WebChat/issues/4294). Screen reader should not read message twice when navigating in the chat history, by [@compulim](https://github.com/compulim), in PR [#4323](https://github.com/microsoft/BotFramework-WebChat/issues/4323)
- Fixes [#4295](https://github.com/microsoft/BotFramework-WebChat/issues/4295). Screen reader should not read suggested actions twice when message arrive in live region, by [@compulim](https://github.com/compulim), in PR [#4323](https://github.com/microsoft/BotFramework-WebChat/issues/4323)
- Fixes [#4325](https://github.com/microsoft/BotFramework-WebChat/issues/4325). `aria-keyshortcuts` should use modifier keys according to `KeyboardEvent` key values spec, by [@compulim](https://github.com/compulim), in PR [#4323](https://github.com/microsoft/BotFramework-WebChat/issues/4323)

## [4.15.2] - 2022-05-09

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@

expect(screenReaderTexts).toHaveLength(7);

expect(screenReaderTexts[0]).toBe('Bot said:\nExclamation mark Warning.\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[1]).toBe('Bot said:\nHello\nWorld\nAloha\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[2]).toBe('Bot said:\nHello\nWorld\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[3]).toBe('Bot said:\nUSD\n1.00\nJPY\n0.91\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[4]).toBe('Bot said:\nHello, World!\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[0]).toBe('Bot said:\nExclamation mark Warning.');
expect(screenReaderTexts[1]).toBe('Bot said:\nHello\nWorld\nAloha');
expect(screenReaderTexts[2]).toBe('Bot said:\nHello\nWorld');
expect(screenReaderTexts[3]).toBe('Bot said:\nUSD\n1.00\nJPY\n0.91');
expect(screenReaderTexts[4]).toBe('Bot said:\nHello, World!');
expect(screenReaderTexts[6]).toBe('One or more links in the message. Press shift tab key 2 to 3 times to switch to the chat history. Then click on the message to interact.');

// The screenshot should show the message in Markdown format, i.e. <strong> and <code>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@

// In screen reader transcript, the attachment are rendered and narrated.
expect(screenReaderTexts[0]).toBe(
'Bot said:\nNo “webchat:fallback-text” field.\nA text: Hello.\nA text: World!\nSent at January 1 at 12:34 PM'
'Bot said:\nNo “webchat:fallback-text” field.\nA text: Hello.\nA text: World!'
);

// No attachments should be narrated.
expect(screenReaderTexts[1]).toBe(
'Bot said:\nWith "webchat:fallback-text" field.\nSent at January 1 at 12:34 PM'
'Bot said:\nWith "webchat:fallback-text" field.'
);
expect(screenReaderTexts[2]).toBe('Bot said:\nA text: Hello.\nA text: World!\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[2]).toBe('Bot said:\nA text: Hello.\nA text: World!');

const activityAlts = [].map.call(pageElements.transcriptLiveRegion().children, element =>
testHelpers.getAllTextContents(element).join('\n')
Expand All @@ -92,11 +92,11 @@

// In interactive transcript, this is narrated as "2 attachments".
expect(activityAlts[0]).toBe(
'Bot said:\nNo “webchat:fallback-text” field.\nA text: Hello.\nA text: World!\nSent at January 1 at 12:34 PM'
'Bot said:\nNo “webchat:fallback-text” field.\nA text: Hello.\nA text: World!'
);

expect(activityAlts[1]).toBe('Bot said:\nWith "webchat:fallback-text" field.\nSent at January 1 at 12:34 PM');
expect(activityAlts[2]).toBe('Bot said:\nA text: Hello.\nA text: World!\nSent at January 1 at 12:34 PM');
expect(activityAlts[1]).toBe('Bot said:\nWith "webchat:fallback-text" field.');
expect(activityAlts[2]).toBe('Bot said:\nA text: Hello.\nA text: World!');
});
</script>
</body>
Expand Down
40 changes: 21 additions & 19 deletions __tests__/html/accessibility.liveRegionActivity.text.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
document.getElementById('webchat')
);

// SETUP: Render 7 activities.
await pageConditions.uiConnected();
await pageConditions.numActivitiesShown(7);
await pageConditions.liveRegionStabilized();
Expand All @@ -94,30 +95,31 @@
testHelpers.getAllTextContents(child).join('\n')
);

// One of the activity contains a fallback text of empty string. It become presentational and not rendered.
// THEN: One of the activity contains a fallback text of empty string. It become presentational and not rendered.
expect(screenReaderTexts).toHaveLength(6);

// Without `webchat:fallback-text` field set, we will be narrating the "text" with best-effort.
expect(screenReaderTexts[0]).toBe(
'Bot said:\nHello, World without webchat:fallback-text field.\nSent at January 1 at 12:34 PM'
);
// THEN: Without `webchat:fallback-text` field set, we will be narrating the "text" with best-effort on removing Markdown syntax.
// Timestamp should not be narrated.
expect(screenReaderTexts[0]).toBe('Bot said:\nHello, World without webchat:fallback-text field.');

// Without valid `webchat:fallback-text` field, we will be narrating the "text" with best-effort.
expect(screenReaderTexts[1]).toBe(
'Bot said:\nHello, World with invalid webchat:fallback-text field.\nSent at January 1 at 12:34 PM'
);
// THEN: Without valid `webchat:fallback-text` field, we will be narrating the "text" with best-effort on removing Markdown syntax.
expect(screenReaderTexts[1]).toBe('Bot said:\nHello, World with invalid webchat:fallback-text field.');

expect(screenReaderTexts[2]).toBe('Bot said:\nDisplay another thing.\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[3]).toBe('You said:\nText from *MessageBack* (plain).\nSent at January 1 at 12:34 PM');
expect(screenReaderTexts[4]).toBe(
'You said:\nText from MessageBack (Markdown).\nSent at January 1 at 12:34 PM'
);
expect(screenReaderTexts[5]).toBe(
'Bot said:\nThis is *plain text*, preserve asterisks.\nSent at January 1 at 12:34 PM'
);
// THEN: With `webchat:fallback-text` field set, we will be narrating it instead of the `text` field.
expect(screenReaderTexts[2]).toBe('Bot said:\nDisplay another thing.');

// THEN: With `channelData.messageBack.displayText` field set and `textFormat` is `plain`, we will be narrating it instead of the `text` field.
expect(screenReaderTexts[3]).toBe('You said:\nText from *MessageBack* (plain).');

// THEN: With `channelData.messageBack.displayText` field set, we will be narrating it instead of the `text` field, with best-effort on removing Markdown syntax.
expect(screenReaderTexts[4]).toBe('You said:\nText from MessageBack (Markdown).');

// THEN: With `textFormat` is set to `plain`, we should narrate it as-is.
// Also note we have a preceding activity with `webchat:fallback-text` field set as an empty string. That one is not narrated and considered presentational.
expect(screenReaderTexts[5]).toBe('Bot said:\nThis is *plain text*, preserve asterisks.');

// The screenshot should show the message in Markdown format, i.e. <strong> and <code>.
// It must not show the text "This should not be displayed."
// THEN: The screenshot should show the message in Markdown format, i.e. <strong> and <code>.
// It must not show the text "This should not be displayed."
await host.snapshot();
});
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@
expect(screenReaderTexts).toHaveLength(2);

expect(screenReaderTexts[0]).toBe(
'Bot said:\nWhere are you from?\nUSA\nHong Kong\nSent at January 1 at 12:34 PM'
'Bot said:\nWhere are you from?\nUSA\nHong Kong'
);
expect(screenReaderTexts[1]).toBe('Suggested Actions Container: Has content. Press Alt + Shift + A to select.');
expect(screenReaderTexts[1]).toBe('Message has suggested actions. Press Alt Shift A to select them.');

// The screenshot should show the suggested actions as HTML <button> and verify we sent a <button> to screen reader.
await host.snapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
expect(screenReaderTexts).toHaveLength(2);

expect(screenReaderTexts[0]).toBe(
'Bot said:\nWhat can I say?\nWhat is the weather?\nSent at January 1 at 12:34 PM'
'Bot said:\nWhat can I say?\nWhat is the weather?'
);
expect(screenReaderTexts[1]).toBe('Suggested Actions Container: Has content. Press Alt + Shift + A to select.');
expect(screenReaderTexts[1]).toBe('Message has suggested actions. Press Alt Shift A to select them.');

// The screenshot should show the suggested actions as HTML <button> and verify we sent a <button> to screen reader.
await host.snapshot();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
</head>
<body>
<div id="webchat"></div>
<script>
run(async function () {
WebChat.renderWebChat(
{
directLine: testHelpers.createDirectLineWithTranscript([
{
from: {
id: 'bot',
role: 'bot'
},
suggestedActions: {
actions: [
{
title: 'What can I say?',
type: 'imBack'
},
{
title: 'What is the weather?',
type: 'imBack'
}
]
},
textFormat: 'markdown',
timestamp: new Date(2000, 0, 1, 12, 34, 56, 789).toISOString(),
type: 'message'
}
]),
store: testHelpers.createStore(),
styleOptions: {
suggestedActionLayout: 'carousel'
}
},
document.getElementById('webchat')
);

await pageConditions.uiConnected();
await pageConditions.suggestedActionsShown();

// THEN: Suggested actions container in carousel layout should be of `role="toolbar"` with `aria-orientation="horizontal"`
const suggestedActions = document.querySelector('.webchat__suggested-actions');

expect(suggestedActions.getAttribute('role')).toBe('toolbar');
expect(suggestedActions.getAttribute('aria-orientation')).toBe('horizontal');
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */

describe('accessibility requirement', () => {
describe('suggested actions of carousel layout', () => {
test('should have correct ARIA attributes', () => runHTML('accessibility.suggestedActions.carouselLayout.ariaAttributes.html'));
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
</head>
<body>
<div id="webchat"></div>
<script>
run(async function () {
WebChat.renderWebChat(
{
directLine: testHelpers.createDirectLineWithTranscript([
{
from: {
id: 'bot',
role: 'bot'
},
suggestedActions: {
actions: [
{
title: 'What can I say?',
type: 'imBack'
},
{
title: 'What is the weather?',
type: 'imBack'
}
]
},
textFormat: 'markdown',
timestamp: new Date(2000, 0, 1, 12, 34, 56, 789).toISOString(),
type: 'message'
}
]),
store: testHelpers.createStore(),
styleOptions: {
suggestedActionLayout: 'flow'
}
},
document.getElementById('webchat')
);

await pageConditions.uiConnected();
await pageConditions.suggestedActionsShown();

// THEN: Suggested actions container in flow layout should be of `role="toolbar"` with `aria-orientation="horizontal"`
const suggestedActions = document.querySelector('.webchat__suggested-actions');

expect(suggestedActions.getAttribute('role')).toBe('toolbar');
expect(suggestedActions.getAttribute('aria-orientation')).toBe('horizontal');
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */

describe('accessibility requirement', () => {
describe('suggested actions of flow layout', () => {
test('should have correct ARIA attributes', () => runHTML('accessibility.suggestedActions.flowLayout.ariaAttributes.html'));
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
</head>
<body>
<div id="webchat"></div>
<script>
run(async function () {
WebChat.renderWebChat(
{
directLine: testHelpers.createDirectLineWithTranscript([
{
from: {
id: 'bot',
role: 'bot'
},
suggestedActions: {
actions: [
{
title: 'What can I say?',
type: 'imBack'
},
{
title: 'What is the weather?',
type: 'imBack'
}
]
},
textFormat: 'markdown',
timestamp: new Date(2000, 0, 1, 12, 34, 56, 789).toISOString(),
type: 'message'
}
]),
store: testHelpers.createStore(),
styleOptions: {
suggestedActionLayout: 'stacked'
}
},
document.getElementById('webchat')
);

await pageConditions.uiConnected();
await pageConditions.suggestedActionsShown();

// THEN: Suggested actions container in stacked layout should be of `role="toolbar"` with `aria-orientation="vertical"`
const suggestedActions = document.querySelector('.webchat__suggested-actions');

expect(suggestedActions.getAttribute('role')).toBe('toolbar');
expect(suggestedActions.getAttribute('aria-orientation')).toBe('vertical');
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */

describe('accessibility requirement', () => {
describe('suggested actions of stacked layout', () => {
test('should have correct ARIA attributes', () => runHTML('accessibility.suggestedActions.stackedLayout.ariaAttributes.html'));
});
});
3 changes: 1 addition & 2 deletions __tests__/html/assets/accessibility.liveRegionAttachment.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.webchat__live-region-activity,
.webchat__live-region-transcript__interactive-note,
.webchat__live-region-transcript__suggested-actions-note,
.webchat__live-region-transcript__note,
.webchat__live-region-transcript__text-element {
color: initial !important;
height: initial !important;
Expand Down
16 changes: 7 additions & 9 deletions __tests__/html/suggestedActions.accessKey.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,20 @@
expect(screenReaderTexts).toHaveLength(3);

expect(screenReaderTexts[0]).toBe('You said:\nsuggested-actions');
expect(
screenReaderTexts[1].startsWith(
'Bot said:\nPlease select one of the actions below\nIM back as string\nPost back as string\nPost back as JSON\nMessage back as JSON with display text\nMessage back as JSON without display text\nMessage back as string with display text\nSent at'
)
).toBeTruthy();
expect(screenReaderTexts[2]).toBe('Suggested Actions Container: Has content. Press Alt + Shift + A to select.');
expect(screenReaderTexts[1]).toBe(
'Bot said:\nPlease select one of the actions below\nIM back as string\nPost back as string\nPost back as JSON\nMessage back as JSON with display text\nMessage back as JSON without display text\nMessage back as string with display text'
);
expect(screenReaderTexts[2]).toBe('Message has suggested actions. Press Alt Shift A to select them.');

expect(document.querySelector('[id^="webchat__suggested-actions--"]').textContent).toBe(
'Suggested Actions Container: '
expect(document.querySelector('.webchat__suggested-actions').getAttribute('aria-label')).toBe(
'Suggested actions'
);

expect(
[].map.call(document.querySelectorAll('[aria-keyshortcuts]'), element =>
element.getAttribute('aria-keyshortcuts')
)
).toEqual(new Array(6).fill('Alt + Shift + A'));
).toEqual(new Array(6).fill('Alt+Shift+A'));

// Access key only works when the focus is inside Web Chat.
// It will not work when the user is focusing on web page content, to prevent conflict with the hosting page.
Expand Down
Loading

0 comments on commit d972175

Please sign in to comment.