Commit bd919846 authored by Akihiro Ota's avatar Akihiro Ota Committed by Commit Bot

ChromeVox Tutorial: Organize lessons based on content.

This patch changes how lessons are organized. Previously, they were
categorized by user type (new user, experienced user, developer). UXR
discovered that this method of organization could make it more difficult
for users to find the content they are looking for. The new strategy is
to organize lessons based on content, which makes finding information
easier.

This patch also adds the OOBE lessons to the main
menu; this will allow users to revisit the content whenever they
would like to. To keep the visual styling consistent, titles were
added to each of these lessons. However, this created an issue in how
initial focus is placed when interactive lessons are shown; we don't
actually want to focus the title for these lessons, rather the text
content that instructs users which keystrokes to press. To solve this
issue, this change also adds logic in tutorial_lesson.js for where to
place focus when a lesson is shown.

Lastly, this change fixes an issue where UserActionMonitor wasn't
properly destroyed, thus continuing to block ChromeVox execution even
after an interactive lesson was exited.

Bug: 1124070
Change-Id: If13952d8a7b6e954fc7292e01444a59fe6a624ef
AX-Relnotes: N/A
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412223
Commit-Queue: Akihiro Ota <akihiroota@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809193}
parent 9e7372c7
......@@ -92,14 +92,23 @@ h1 {
hidden$="[[ shouldHideMainMenu(activeScreen) ]]">
<h1 id="mainMenuHeader" tabindex="-1">[[ chooseYourExperience ]]</h1>
<div id="mainMenuButtons">
<cr-button id="newUserButton" on-click="chooseCurriculum">
[[ newUser ]]
<cr-button id="quickOrientationButton" on-click="chooseCurriculum">
[[ quickOrientation ]]
</cr-button>
<cr-button id="experiencedUserButton" on-click="chooseCurriculum">
[[ experiencedUser ]]
<cr-button id="essentialKeysButton" on-click="chooseCurriculum">
[[ essentialKeys ]]
</cr-button>
<cr-button id="developerButton" on-click="chooseCurriculum">
[[ developer ]]
<cr-button id="navigationButton" on-click="chooseCurriculum">
[[ navigation ]]
</cr-button>
<cr-button id="commandReferencesButton" on-click="chooseCurriculum">
[[ commandReferences ]]
</cr-button>
<cr-button id="soundsAndSettingsButton" on-click="chooseCurriculum">
[[ soundsAndSettings ]]
</cr-button>
<cr-button id="resourcesButton" on-click="chooseCurriculum">
[[ resources ]]
</cr-button>
</div>
</div>
......@@ -158,8 +167,9 @@ h1 {
</cr-button>
<cr-button on-click="showFirstLesson"
hidden$="[[
shouldHideRestartBasicOrientationButton(activeLessonIndex) ]]">
[[ restartBasicOrientation ]]
shouldHideRestartQuickOrientationButton(activeLessonIndex, activeScreen)
]]">
[[ restartQuickOrientation ]]
</cr-button>
<cr-button on-click="exit">[[ exitTutorial ]]</cr-button>
</div>
......
......@@ -82,11 +82,20 @@ export const TutorialLesson = Polymer({
/** @private */
show() {
this.$.container.hidden = false;
// Shorthand for Polymer.dom(this.root).querySelector(...).
const focus = this.$$('[tabindex]');
let focus;
if (this.autoInteractive) {
// Auto interactive lessons immediately initialize the UserActionMonitor,
// which will block ChromeVox execution until a desired key sequence is
// pressed. To ensure users hear instructions for these lessons, place
// focus on the first piece of text content.
// Shorthand for Polymer.dom(this.root).querySelector(...).
focus = this.$$('p');
} else {
// Otherwise, we can place focus on the lesson title.
focus = this.$$('h1');
}
if (!focus) {
throw new Error(
'A lesson must have an element which specifies tabindex.');
throw new Error('A lesson must have an element to focus.');
}
focus.focus();
if (!focus.isEqualNode(this.shadowRoot.activeElement)) {
......
......@@ -1133,7 +1133,7 @@ Panel = class {
if (!$('i-tutorial')) {
const curriculum = Panel.sessionState ===
chrome.loginState.SessionState.IN_OOBE_SCREEN ?
'oobe' :
'quick_orientation' :
null;
Panel.createITutorial(curriculum);
}
......
......@@ -103,11 +103,17 @@ TEST_F('ChromeVoxTutorialTest', 'BasicTest', function() {
await this.launchAndWaitForTutorial();
mockFeedback.expectSpeech('Choose your tutorial experience')
.call(doCmd('nextObject'))
.expectSpeech('New user', 'Button')
.expectSpeech('Quick orientation', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Experienced user', 'Button')
.expectSpeech('Essential keys', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Developer', 'Button')
.expectSpeech('Navigation', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Command references', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Sounds and settings', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Resources', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Exit tutorial', 'Button')
.replay();
......@@ -123,11 +129,11 @@ TEST_F('ChromeVoxTutorialTest', 'LessonSetTest', function() {
const tutorial = this.getPanel().iTutorial;
mockFeedback.expectSpeech('Choose your tutorial experience')
.call(doCmd('nextObject'))
.expectSpeech('New user', 'Button')
.expectSpeech('Quick orientation', 'Button')
.call(doCmd('forceClickOnCurrentItem'))
.expectSpeech(/New User Tutorial, [0-9]+ Lessons/)
.expectSpeech(/Quick Orientation Tutorial, [0-9]+ Lessons/)
.call(doCmd('nextObject'))
.expectSpeech('On, Off, and Stop')
.expectSpeech('Welcome to ChromeVox!')
.call(() => {
// Call from the tutorial directly, instead of navigating to and
// clicking on the main menu button.
......@@ -135,13 +141,13 @@ TEST_F('ChromeVoxTutorialTest', 'LessonSetTest', function() {
})
.expectSpeech('Choose your tutorial experience')
.call(doCmd('nextObject'))
.expectSpeech('New user', 'Button')
.expectSpeech('Quick orientation', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Experienced user', 'Button')
.expectSpeech('Essential keys', 'Button')
.call(doCmd('forceClickOnCurrentItem'))
.expectSpeech(/Experienced User Tutorial, [0-9]+ Lessons/)
.expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
.call(doCmd('nextObject'))
.expectSpeech('Text fields')
.expectSpeech('On, Off, and Stop')
.replay();
});
});
......@@ -154,9 +160,11 @@ TEST_F('ChromeVoxTutorialTest', 'NoPracticeAreaTest', function() {
const tutorial = this.getPanel().iTutorial;
mockFeedback.expectSpeech('Choose your tutorial experience')
.call(doCmd('nextObject'))
.expectSpeech('New user', 'Button')
.expectSpeech('Quick orientation', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Essential keys', 'Button')
.call(doCmd('forceClickOnCurrentItem'))
.expectSpeech(/New User Tutorial, [0-9]+ Lessons/)
.expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/)
.call(() => {
tutorial.showLesson(0);
})
......@@ -175,11 +183,15 @@ TEST_F('ChromeVoxTutorialTest', 'HasPracticeAreaTest', function() {
const tutorial = this.getPanel().iTutorial;
mockFeedback.expectSpeech('Choose your tutorial experience')
.call(doCmd('nextObject'))
.expectSpeech('New user', 'Button')
.expectSpeech('Quick orientation', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Essential keys', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Navigation', 'Button')
.call(doCmd('forceClickOnCurrentItem'))
.expectSpeech(/New User Tutorial, [0-9]+ Lessons/)
.expectSpeech(/Navigation Tutorial, [0-9]+ Lessons/)
.call(() => {
tutorial.showLesson(2);
tutorial.showLesson(0);
})
.expectSpeech('Basic Navigation', 'Heading 1')
.call(doCmd('nextButton'))
......@@ -230,11 +242,15 @@ TEST_F('ChromeVoxTutorialTest', 'PracticeAreaNudgesTest', function() {
};
mockFeedback.expectSpeech('Choose your tutorial experience')
.call(doCmd('nextObject'))
.expectSpeech('New user', 'Button')
.expectSpeech('Quick orientation', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Essential keys', 'Button')
.call(doCmd('nextObject'))
.expectSpeech('Navigation', 'Button')
.call(doCmd('forceClickOnCurrentItem'))
.expectSpeech(/New User Tutorial, [0-9]+ Lessons/)
.expectSpeech(/Navigation Tutorial, [0-9]+ Lessons/)
.call(() => {
tutorial.showLesson(2);
tutorial.showLesson(0);
})
.expectSpeech('Basic Navigation', 'Heading 1')
.call(doCmd('nextButton'))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment