diff --git a/accessible/jsat/AccessFu.jsm b/accessible/jsat/AccessFu.jsm index 7c80d7580b76..0a8f73151961 100644 --- a/accessible/jsat/AccessFu.jsm +++ b/accessible/jsat/AccessFu.jsm @@ -12,7 +12,6 @@ const Cr = Components.results; this.EXPORTED_SYMBOLS = ['AccessFu']; Cu.import('resource://gre/modules/Services.jsm'); - Cu.import('resource://gre/modules/accessibility/Utils.jsm'); const ACCESSFU_DISABLE = 0; @@ -135,8 +134,7 @@ this.AccessFu = { } if (Utils.MozBuildApp !== 'mobile/android') { - this.announce( - Utils.stringBundle.GetStringFromName('screenReaderStarted')); + this.announce('screenReaderStarted'); } }, @@ -154,8 +152,7 @@ this.AccessFu = { Utils.win.document.removeChild(this.stylesheet.get()); if (Utils.MozBuildApp !== 'mobile/android') { - this.announce( - Utils.stringBundle.GetStringFromName('screenReaderStopped')); + this.announce('screenReaderStopped'); } for each (let mm in Utils.AllMessageManagers) { @@ -509,97 +506,8 @@ var Output = { } }, - speechHelper: { - EARCONS: ['virtual_cursor_move.ogg', - 'virtual_cursor_key.ogg', - 'clicked.ogg'], - - earconBuffers: {}, - - inited: false, - - webspeechEnabled: false, - - deferredOutputs: [], - - init: function init() { - let window = Utils.win; - this.webspeechEnabled = !!window.speechSynthesis && - !!window.SpeechSynthesisUtterance; - - let settingsToGet = 2; - let settingsCallback = (aName, aSetting) => { - if (--settingsToGet > 0) { - return; - } - - this.inited = true; - - for (let actions of this.deferredOutputs) { - this.output(actions); - } - }; - - this._volumeSetting = new SettingCache( - 'accessibility.screenreader-volume', settingsCallback, - { defaultValue: 1, callbackNow: true, callbackOnce: true }); - this._rateSetting = new SettingCache( - 'accessibility.screenreader-rate', settingsCallback, - { defaultValue: 0, callbackNow: true, callbackOnce: true }); - - for (let earcon of this.EARCONS) { - let earconName = /(^.*)\..*$/.exec(earcon)[1]; - this.earconBuffers[earconName] = new WeakMap(); - this.earconBuffers[earconName].set( - window, new window.Audio('chrome://global/content/accessibility/' + earcon)); - } - }, - - uninit: function uninit() { - if (this.inited) { - delete this._volumeSetting; - delete this._rateSetting; - } - this.inited = false; - }, - - output: function output(aActions) { - if (!this.inited) { - this.deferredOutputs.push(aActions); - return; - } - - for (let action of aActions) { - let window = Utils.win; - Logger.debug('tts.' + action.method, '"' + action.data + '"', - JSON.stringify(action.options)); - - if (!action.options.enqueue && this.webspeechEnabled) { - window.speechSynthesis.cancel(); - } - - if (action.method === 'speak' && this.webspeechEnabled) { - let utterance = new window.SpeechSynthesisUtterance(action.data); - let requestedRate = this._rateSetting.value; - utterance.volume = this._volumeSetting.value; - utterance.rate = requestedRate >= 0 ? - requestedRate + 1 : 1 / (Math.abs(requestedRate) + 1); - window.speechSynthesis.speak(utterance); - } else if (action.method === 'playEarcon') { - let audioBufferWeakMap = this.earconBuffers[action.data]; - if (audioBufferWeakMap) { - let node = audioBufferWeakMap.get(window).cloneNode(false); - node.volume = this._volumeSetting.value; - node.play(); - } - } - } - } - }, - start: function start() { Cu.import('resource://gre/modules/Geometry.jsm'); - this.speechHelper.init(); }, stop: function stop() { @@ -607,22 +515,32 @@ var Output = { Utils.win.document.documentElement.removeChild(this.highlightBox.get()); delete this.highlightBox; } + }, - if (this.announceBox) { - Utils.win.document.documentElement.removeChild(this.announceBox.get()); - delete this.announceBox; + B2G: function B2G(aDetails) { + let details = { + type: 'accessfu-output', + details: JSON.stringify(aDetails) + }; + let window = Utils.win; + if (window.shell) { + // On B2G device. + window.shell.sendChromeEvent(details); + } else { + // Dispatch custom event to have support for desktop and screen reader + // emulator add-on. + window.dispatchEvent(new window.CustomEvent(details.type, { + bubbles: true, + cancelable: true, + detail: details + })); } - - this.speechHelper.uninit(); }, - Speech: function Speech(aDetails, aBrowser) { - this.speechHelper.output(aDetails.actions); - }, - - Visual: function Visual(aDetails, aBrowser) { - switch (aDetails.method) { - case 'showBounds': + Visual: function Visual(aDetail, aBrowser) { + switch (aDetail.eventType) { + case 'viewport-change': + case 'vc-change': { let highlightBox = null; if (!this.highlightBox) { @@ -643,8 +561,8 @@ var Output = { highlightBox = this.highlightBox.get(); } - let padding = aDetails.padding; - let r = AccessFu.adjustContentBounds(aDetails.bounds, aBrowser, true); + let padding = aDetail.padding; + let r = AccessFu.adjustContentBounds(aDetail.bounds, aBrowser, true); // First hide it to avoid flickering when changing the style. highlightBox.style.display = 'none'; @@ -656,45 +574,13 @@ var Output = { break; } - case 'hideBounds': + case 'tabstate-change': { let highlightBox = this.highlightBox ? this.highlightBox.get() : null; if (highlightBox) highlightBox.style.display = 'none'; break; } - case 'showAnnouncement': - { - let announceBox = this.announceBox ? this.announceBox.get() : null; - if (!announceBox) { - announceBox = Utils.win.document. - createElementNS('http://www.w3.org/1999/xhtml', 'div'); - announceBox.id = 'announce-box'; - Utils.win.document.documentElement.appendChild(announceBox); - this.announceBox = Cu.getWeakReference(announceBox); - } - - announceBox.innerHTML = '
' + aDetails.text + '
'; - announceBox.classList.add('showing'); - - if (this._announceHideTimeout) - Utils.win.clearTimeout(this._announceHideTimeout); - - if (aDetails.duration > 0) - this._announceHideTimeout = Utils.win.setTimeout( - function () { - announceBox.classList.remove('showing'); - this._announceHideTimeout = 0; - }.bind(this), aDetails.duration); - break; - } - case 'hideAnnouncement': - { - let announceBox = this.announceBox ? this.announceBox.get() : null; - if (announceBox) - announceBox.classList.remove('showing'); - break; - } } }, @@ -736,12 +622,8 @@ var Output = { } }, - Haptic: function Haptic(aDetails, aBrowser) { - Utils.win.navigator.vibrate(aDetails.pattern); - }, - - Braille: function Braille(aDetails, aBrowser) { - Logger.debug('Braille output: ' + aDetails.text); + Braille: function Braille(aDetails) { + Logger.debug('Braille output: ' + aDetails.output); } }; diff --git a/accessible/jsat/OutputGenerator.jsm b/accessible/jsat/OutputGenerator.jsm index f606aebf8e88..5f04717ace24 100644 --- a/accessible/jsat/OutputGenerator.jsm +++ b/accessible/jsat/OutputGenerator.jsm @@ -26,8 +26,6 @@ XPCOMUtils.defineLazyModuleGetter(this, 'PrefCache', 'resource://gre/modules/accessibility/Utils.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'Logger', 'resource://gre/modules/accessibility/Utils.jsm'); -XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm', - 'resource://gre/modules/PluralForm.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'Roles', 'resource://gre/modules/accessibility/Constants.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'States', @@ -44,12 +42,9 @@ this.OutputGenerator = { * @param {PivotContext} aContext object that generates and caches * context information for a given accessible and its relationship with * another accessible. - * @return {Object} An object that neccessarily has an output property which - * is an array of strings. Depending on the utterance order, - * the strings describe the context for an accessible object either + * @return {Object} An array of speech data. Depending on the utterance order, + * the data describes the context for an accessible object either * starting from the accessible's ancestry or accessible's subtree. - * The object may also have properties specific to the type of output - * generated. */ genForContext: function genForContext(aContext) { let output = []; @@ -82,10 +77,7 @@ this.OutputGenerator = { contextStart.reverse().forEach(addOutput); } - // Clean up the white space. - let trimmed; - output = [trimmed for (word of output) if (trimmed = word.trim())]; - return {output: output}; + return output; }, @@ -96,10 +88,10 @@ this.OutputGenerator = { * @param {PivotContext} aContext object that generates and caches * context information for a given accessible and its relationship with * another accessible. - * @return {Array} Two string array. The first string describes the object - * and its state. The second string is the object's name. Whether the - * object's description or it's role is included is determined by - * {@link roleRuleMap}. + * @return {Array} A 2 element array of speech data. The first element + * describes the object and its state. The second element is the object's + * name. Whether the object's description or it's role is included is + * determined by {@link roleRuleMap}. */ genForObject: function genForObject(aAccessible, aContext) { let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role); @@ -122,15 +114,14 @@ this.OutputGenerator = { * invoked in. * @param {string} aActionName the name of the action, one of the keys in * {@link gActionMap}. - * @return {Array} A one string array with the action. + * @return {Array} A one element array with action data. */ genForAction: function genForAction(aObject, aActionName) {}, /** - * Generates output for an announcement. Basically attempts to localize - * the announcement string. + * Generates output for an announcement. * @param {string} aAnnouncement unlocalized announcement. - * @return {Array} A one string array with the announcement. + * @return {Array} An announcement speech data to be localized. */ genForAnnouncement: function genForAnnouncement(aAnnouncement) {}, @@ -153,6 +144,12 @@ this.OutputGenerator = { _getContextStart: function getContextStart(aContext) {}, + /** + * Adds an accessible name and description to the output if available. + * @param {Array} aOutput Output array. + * @param {nsIAccessible} aAccessible current accessible object. + * @param {Number} aFlags output flags. + */ _addName: function _addName(aOutput, aAccessible, aFlags) { let name; if ((Utils.getAttributes(aAccessible)['explicit-name'] === 'true' && @@ -173,10 +170,10 @@ this.OutputGenerator = { } } - if (name) { - aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? - 'push' : 'unshift'](name); + if (!name || !name.trim()) { + return; } + aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift'](name); }, /** @@ -189,23 +186,18 @@ this.OutputGenerator = { if (!landmarkName) { return; } - - let landmark = Utils.stringBundle.GetStringFromName(landmarkName); - if (!landmark) { - return; - } - - aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'unshift' : 'push']( - landmark); + aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'unshift' : 'push']({ + string: landmarkName + }); }, /** * Adds an entry type attribute to the description if available. - * @param {Array} aDesc Description array. + * @param {Array} aOutput Output array. * @param {nsIAccessible} aAccessible current accessible object. * @param {String} aRoleStr aAccessible's role string. */ - _addType: function _addType(aDesc, aAccessible, aRoleStr) { + _addType: function _addType(aOutput, aAccessible, aRoleStr) { if (aRoleStr !== 'entry') { return; } @@ -215,14 +207,13 @@ this.OutputGenerator = { if (!typeName || typeName === 'text') { return; } - typeName = 'textInputType_' + typeName; - try { - aDesc.push(Utils.stringBundle.GetStringFromName(typeName)); - } catch (x) { - Logger.warning('Failed to get a string from a bundle for', typeName); - } + aOutput.push({string: 'textInputType_' + typeName}); }, + _addState: function _addState(aOutput, aState) {}, + + _addRole: function _addRole(aOutput, aRoleStr) {}, + get outputOrder() { if (!this._utteranceOrder) { this._utteranceOrder = new PrefCache('accessibility.accessfu.utterance'); @@ -235,16 +226,6 @@ this.OutputGenerator = { return aName.replace(' ', ''); }, - _getLocalizedRole: function _getLocalizedRole(aRoleStr) {}, - - _getLocalizedState: function _getLocalizedState(aState) {}, - - _getPluralFormString: function _getPluralFormString(aString, aCount) { - let str = Utils.stringBundle.GetStringFromName(this._getOutputName(aString)); - str = PluralForm.get(aCount, str); - return str.replace('#1', aCount); - }, - roleRuleMap: { 'menubar': INCLUDE_DESC, 'scrollbar': INCLUDE_DESC, @@ -326,21 +307,14 @@ this.OutputGenerator = { let output = []; if (aFlags & INCLUDE_DESC) { - let desc = this._getLocalizedState(aState); - let roleStr = this._getLocalizedRole(aRoleStr); - if (roleStr) { - this._addType(desc, aAccessible, aRoleStr); - desc.push(roleStr); - } - output.push(desc.join(' ')); + this._addState(output, aState); + this._addType(output, aAccessible, aRoleStr); + this._addRole(output, aRoleStr); } - if (aFlags & INCLUDE_VALUE) { - let value = aAccessible.value; - if (value) { - output[this.outputOrder === OUTPUT_DESC_FIRST ? - 'push' : 'unshift'](value); - } + if (aFlags & INCLUDE_VALUE && aAccessible.value.trim()) { + output[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift']( + aAccessible.value); } this._addName(output, aAccessible, aFlags); @@ -367,16 +341,16 @@ this.OutputGenerator = { }, pagetab: function pagetab(aAccessible, aRoleStr, aState, aFlags) { - let localizedRole = this._getLocalizedRole(aRoleStr); let itemno = {}; let itemof = {}; aAccessible.groupPosition({}, itemof, itemno); let output = []; - let desc = this._getLocalizedState(aState); - desc.push( - Utils.stringBundle.formatStringFromName( - 'objItemOf', [localizedRole, itemno.value, itemof.value], 3)); - output.push(desc.join(' ')); + this._addState(output, aState); + this._addRole(output, aRoleStr); + output.push({ + string: 'objItemOfN', + args: [itemno.value, itemof.value] + }); this._addName(output, aAccessible, aFlags); this._addLandmark(output, aAccessible); @@ -398,13 +372,14 @@ this.OutputGenerator = { if (table.isProbablyForLayout()) { return output; } - let tableColumnInfo = this._getPluralFormString('tableColumnInfo', - table.columnCount); - let tableRowInfo = this._getPluralFormString('tableRowInfo', - table.rowCount); - output.push(Utils.stringBundle.formatStringFromName( - this._getOutputName('tableInfo'), [this._getLocalizedRole(aRoleStr), - tableColumnInfo, tableRowInfo], 3)); + this._addRole(output, aRoleStr); + output.push.call(output, { + string: this._getOutputName('tblColumnInfo'), + count: table.columnCount + }, { + string: this._getOutputName('tblRowInfo'), + count: table.rowCount + }); this._addName(output, aAccessible, aFlags); this._addLandmark(output, aAccessible); return output; @@ -415,7 +390,7 @@ this.OutputGenerator = { /** * Generates speech utterances from objects, actions and state changes. - * An utterance is an array of strings. + * An utterance is an array of speech data. * * It should not be assumed that flattening an utterance array would create a * gramatically correct sentence. For example, {@link genForObject} might @@ -451,47 +426,42 @@ this.UtteranceGenerator = { //TODO: May become more verbose in the future. genForAction: function genForAction(aObject, aActionName) { - return [Utils.stringBundle.GetStringFromName(this.gActionMap[aActionName])]; + return [{string: this.gActionMap[aActionName]}]; }, genForLiveRegion: function genForLiveRegion(aContext, aIsHide, aModifiedText) { let utterance = []; if (aIsHide) { - utterance.push(Utils.stringBundle.GetStringFromName('hidden')); + utterance.push({string: 'hidden'}); } - return utterance.concat( - aModifiedText || this.genForContext(aContext).output); + return utterance.concat(aModifiedText || this.genForContext(aContext)); }, genForAnnouncement: function genForAnnouncement(aAnnouncement) { - try { - return [Utils.stringBundle.GetStringFromName(aAnnouncement)]; - } catch (x) { - return [aAnnouncement]; - } + return [{ + string: aAnnouncement + }]; }, genForTabStateChange: function genForTabStateChange(aObject, aTabState) { switch (aTabState) { case 'newtab': - return [Utils.stringBundle.GetStringFromName('tabNew')]; + return [{string: 'tabNew'}]; case 'loading': - return [Utils.stringBundle.GetStringFromName('tabLoading')]; + return [{string: 'tabLoading'}]; case 'loaded': - return [aObject.name || '', - Utils.stringBundle.GetStringFromName('tabLoaded')]; + return [aObject.name, {string: 'tabLoaded'}]; case 'loadstopped': - return [Utils.stringBundle.GetStringFromName('tabLoadStopped')]; + return [{string: 'tabLoadStopped'}]; case 'reload': - return [Utils.stringBundle.GetStringFromName('tabReload')]; + return [{string: 'tabReload'}]; default: return []; } }, genForEditingMode: function genForEditingMode(aIsEditing) { - return [Utils.stringBundle.GetStringFromName( - aIsEditing ? 'editingMode' : 'navigationMode')]; + return [{string: aIsEditing ? 'editingMode' : 'navigationMode'}]; }, objectOutputFunctions: { @@ -505,9 +475,7 @@ this.UtteranceGenerator = { heading: function heading(aAccessible, aRoleStr, aState, aFlags) { let level = {}; aAccessible.groupPosition(level, {}, {}); - let utterance = - [Utils.stringBundle.formatStringFromName( - 'headingLevel', [level.value], 1)]; + let utterance = [{string: 'headingLevel', args: [level.value]}]; this._addName(utterance, aAccessible, aFlags); this._addLandmark(utterance, aAccessible); @@ -520,10 +488,14 @@ this.UtteranceGenerator = { let itemof = {}; aAccessible.groupPosition({}, itemof, itemno); let utterance = []; - if (itemno.value == 1) // Start of list - utterance.push(Utils.stringBundle.GetStringFromName('listStart')); - else if (itemno.value == itemof.value) // last item - utterance.push(Utils.stringBundle.GetStringFromName('listEnd')); + if (itemno.value == 1) { + // Start of list + utterance.push({string: 'listStart'}); + } + else if (itemno.value == itemof.value) { + // last item + utterance.push({string: 'listEnd'}); + } this._addName(utterance, aAccessible, aFlags); this._addLandmark(utterance, aAccessible); @@ -554,35 +526,32 @@ this.UtteranceGenerator = { let utterance = []; let cell = aContext.getCellInfo(aAccessible); if (cell) { - let desc = []; - let addCellChanged = function addCellChanged(aDesc, aChanged, aString, aIndex) { - if (aChanged) { - aDesc.push(Utils.stringBundle.formatStringFromName(aString, - [aIndex + 1], 1)); - } - }; - let addExtent = function addExtent(aDesc, aExtent, aString) { + let addCellChanged = + function addCellChanged(aUtterance, aChanged, aString, aIndex) { + if (aChanged) { + aUtterance.push({string: aString, args: [aIndex + 1]}); + } + }; + let addExtent = function addExtent(aUtterance, aExtent, aString) { if (aExtent > 1) { - aDesc.push(Utils.stringBundle.formatStringFromName(aString, - [aExtent], 1)); + aUtterance.push({string: aString, args: [aExtent]}); } }; - let addHeaders = function addHeaders(aDesc, aHeaders) { + let addHeaders = function addHeaders(aUtterance, aHeaders) { if (aHeaders.length > 0) { - aDesc.push.apply(aDesc, aHeaders); + aUtterance.push.apply(aUtterance, aHeaders); } }; - addCellChanged(desc, cell.columnChanged, 'columnInfo', cell.columnIndex); - addCellChanged(desc, cell.rowChanged, 'rowInfo', cell.rowIndex); + addCellChanged(utterance, cell.columnChanged, 'columnInfo', + cell.columnIndex); + addCellChanged(utterance, cell.rowChanged, 'rowInfo', cell.rowIndex); - addExtent(desc, cell.columnExtent, 'spansColumns'); - addExtent(desc, cell.rowExtent, 'spansRows'); + addExtent(utterance, cell.columnExtent, 'spansColumns'); + addExtent(utterance, cell.rowExtent, 'spansRows'); - addHeaders(desc, cell.columnHeaders); - addHeaders(desc, cell.rowHeaders); - - utterance.push(desc.join(' ')); + addHeaders(utterance, cell.columnHeaders); + addHeaders(utterance, cell.rowHeaders); } this._addName(utterance, aAccessible, aFlags); @@ -612,76 +581,61 @@ this.UtteranceGenerator = { return aContext.newAncestry; }, - _getLocalizedRole: function _getLocalizedRole(aRoleStr) { - try { - return Utils.stringBundle.GetStringFromName( - this._getOutputName(aRoleStr)); - } catch (x) { - return ''; - } + _addRole: function _addRole(aOutput, aRoleStr) { + aOutput.push({string: this._getOutputName(aRoleStr)}); }, - _getLocalizedState: function _getLocalizedState(aState) { - let stateUtterances = []; + _addState: function _addState(aOutput, aState) { if (aState.contains(States.UNAVAILABLE)) { - stateUtterances.push( - Utils.stringBundle.GetStringFromName('stateUnavailable')); + aOutput.push({string: 'stateUnavailable'}); } // Don't utter this in Jelly Bean, we let TalkBack do it for us there. // This is because we expose the checked information on the node itself. - // XXX: this means the checked state is always appended to the end, regardless - // of the utterance ordering preference. + // XXX: this means the checked state is always appended to the end, + // regardless of the utterance ordering preference. if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === 'browser') && aState.contains(States.CHECKABLE)) { let statetr = aState.contains(States.CHECKED) ? 'stateChecked' : 'stateNotChecked'; - stateUtterances.push(Utils.stringBundle.GetStringFromName(statetr)); + aOutput.push({string: statetr}); } if (aState.contains(States.PRESSED)) { - stateUtterances.push( - Utils.stringBundle.GetStringFromName('statePressed')); + aOutput.push({string: 'statePressed'}); } if (aState.contains(States.EXPANDABLE)) { let statetr = aState.contains(States.EXPANDED) ? 'stateExpanded' : 'stateCollapsed'; - stateUtterances.push(Utils.stringBundle.GetStringFromName(statetr)); + aOutput.push({string: statetr}); } if (aState.contains(States.REQUIRED)) { - stateUtterances.push( - Utils.stringBundle.GetStringFromName('stateRequired')); + aOutput.push({string: 'stateRequired'}); } if (aState.contains(States.TRAVERSED)) { - stateUtterances.push( - Utils.stringBundle.GetStringFromName('stateTraversed')); + aOutput.push({string: 'stateTraversed'}); } if (aState.contains(States.HASPOPUP)) { - stateUtterances.push( - Utils.stringBundle.GetStringFromName('stateHasPopup')); + aOutput.push({string: 'stateHasPopup'}); } if (aState.contains(States.SELECTED)) { - stateUtterances.push( - Utils.stringBundle.GetStringFromName('stateSelected')); + aOutput.push({string: 'stateSelected'}); } - - return stateUtterances; }, _getListUtterance: function _getListUtterance(aAccessible, aRoleStr, aFlags, aItemCount) { - let desc = []; - let roleStr = this._getLocalizedRole(aRoleStr); - if (roleStr) { - desc.push(roleStr); - } - desc.push(this._getPluralFormString('listItemsCount', aItemCount)); - let utterance = [desc.join(' ')]; + let utterance = []; + this._addRole(utterance, aRoleStr); + utterance.push({ + string: this._getOutputName('listItemsCount'), + count: aItemCount + }); this._addName(utterance, aAccessible, aFlags); this._addLandmark(utterance, aAccessible); @@ -690,7 +644,6 @@ this.UtteranceGenerator = { } }; - this.BrailleGenerator = { __proto__: OutputGenerator, @@ -703,7 +656,7 @@ this.BrailleGenerator = { // direct first children of listitems, because these are both common browsing // scenarios let addListitemIndicator = function addListitemIndicator(indicator = '*') { - output.output.unshift(indicator); + output.unshift(indicator); }; if (acc.indexInParent === 1 && @@ -724,12 +677,6 @@ this.BrailleGenerator = { } } - if (acc instanceof Ci.nsIAccessibleText) { - output.endOffset = this.outputOrder === OUTPUT_DESC_FIRST ? - output.output.join(' ').length : acc.characterCount; - output.startOffset = output.endOffset - acc.characterCount; - } - return output; }, @@ -754,20 +701,19 @@ this.BrailleGenerator = { let braille = []; let cell = aContext.getCellInfo(aAccessible); if (cell) { - let desc = []; - let addHeaders = function addHeaders(aDesc, aHeaders) { + let addHeaders = function addHeaders(aBraille, aHeaders) { if (aHeaders.length > 0) { - aDesc.push.apply(aDesc, aHeaders); + aBraille.push.apply(aBraille, aHeaders); } }; - desc.push(Utils.stringBundle.formatStringFromName( - this._getOutputName('cellInfo'), [cell.columnIndex + 1, - cell.rowIndex + 1], 2)); + braille.push({ + string: this._getOutputName('cellInfo'), + args: [cell.columnIndex + 1, cell.rowIndex + 1] + }); - addHeaders(desc, cell.columnHeaders); - addHeaders(desc, cell.rowHeaders); - braille.push(desc.join(' ')); + addHeaders(braille, cell.columnHeaders); + addHeaders(braille, cell.rowHeaders); } this._addName(braille, aAccessible, aFlags); @@ -795,10 +741,7 @@ this.BrailleGenerator = { _useStateNotRole: function _useStateNotRole(aAccessible, aRoleStr, aState, aFlags) { let braille = []; - - let desc = this._getLocalizedState(aState, aAccessible.role); - braille.push(desc.join(' ')); - + this._addState(braille, aState, aAccessible.role); this._addName(braille, aAccessible, aFlags); this._addLandmark(braille, aAccessible); @@ -813,7 +756,7 @@ this.BrailleGenerator = { return this.objectOutputFunctions._useStateNotRole.apply(this, arguments); }, - togglebutton: function radiobutton(aAccessible, aRoleStr, aState, aFlags) { + togglebutton: function togglebutton(aAccessible, aRoleStr, aState, aFlags) { return this.objectOutputFunctions._useStateNotRole.apply(this, arguments); } }, @@ -830,42 +773,24 @@ this.BrailleGenerator = { return OutputGenerator._getOutputName(aName) + 'Abbr'; }, - _getLocalizedRole: function _getLocalizedRole(aRoleStr) { - try { - return Utils.stringBundle.GetStringFromName( - this._getOutputName(aRoleStr)); - } catch (x) { - try { - return Utils.stringBundle.GetStringFromName( - OutputGenerator._getOutputName(aRoleStr)); - } catch (y) { - return ''; - } - } + _addRole: function _addRole(aBraille, aRoleStr) { + aBraille.push({string: this._getOutputName(aRoleStr)}); }, - _getLocalizedState: function _getLocalizedState(aState, aRole) { - let stateBraille = []; - - let getResultMarker = function getResultMarker(aMarker) { - // aMarker is a simple boolean. - let resultMarker = []; - resultMarker.push('('); - resultMarker.push(aMarker ? 'x' : ' '); - resultMarker.push(')'); - - return resultMarker.join(''); - }; - + _addState: function _addState(aBraille, aState, aRole) { if (aState.contains(States.CHECKABLE)) { - stateBraille.push(getResultMarker(aState.contains(States.CHECKED))); + aBraille.push({ + string: aState.contains(States.CHECKED) ? + this._getOutputName('stateChecked') : + this._getOutputName('stateUnchecked') + }); } - if (aRole === Roles.TOGGLE_BUTTON) { - stateBraille.push(getResultMarker(aState.contains(States.PRESSED))); + aBraille.push({ + string: aState.contains(States.PRESSED) ? + this._getOutputName('statePressed') : + this._getOutputName('stateUnpressed') + }); } - - return stateBraille; } - }; diff --git a/accessible/jsat/Presentation.jsm b/accessible/jsat/Presentation.jsm index 0797031a7b8c..a586729b5e04 100644 --- a/accessible/jsat/Presentation.jsm +++ b/accessible/jsat/Presentation.jsm @@ -130,7 +130,6 @@ Presenter.prototype = { /** * Visual presenter. Draws a box around the virtual cursor's position. */ - this.VisualPresenter = function VisualPresenter() { this._displayedAccessibles = new WeakMap(); }; @@ -161,7 +160,7 @@ VisualPresenter.prototype = { return { type: this.type, details: { - method: 'showBounds', + eventType: 'viewport-change', bounds: bounds, padding: this.BORDER_PADDING } @@ -194,7 +193,7 @@ VisualPresenter.prototype = { return { type: this.type, details: { - method: 'showBounds', + eventType: 'vc-change', bounds: bounds, padding: this.BORDER_PADDING } @@ -212,20 +211,9 @@ VisualPresenter.prototype = { tabStateChanged: function VisualPresenter_tabStateChanged(aDocObj, aPageState) { if (aPageState == 'newdoc') - return {type: this.type, details: {method: 'hideBounds'}}; + return {type: this.type, details: {eventType: 'tabstate-change'}}; return null; - }, - - announce: function VisualPresenter_announce(aAnnouncement) { - return { - type: this.type, - details: { - method: 'showAnnouncement', - text: aAnnouncement, - duration: 1000 - } - }; } }; @@ -297,7 +285,8 @@ AndroidPresenter.prototype = { let state = Utils.getState(aContext.accessible); androidEvents.push({eventType: (isExploreByTouch) ? this.ANDROID_VIEW_HOVER_ENTER : focusEventType, - text: UtteranceGenerator.genForContext(aContext).output, + text: Utils.localize(UtteranceGenerator.genForContext( + aContext)), bounds: aContext.bounds, clickable: aContext.accessible.actionCount > 0, checkable: state.contains(States.CHECKABLE), @@ -323,7 +312,8 @@ AndroidPresenter.prototype = { type: this.type, details: [{ eventType: this.ANDROID_VIEW_CLICKED, - text: UtteranceGenerator.genForAction(aObject, aActionName), + text: Utils.localize(UtteranceGenerator.genForAction(aObject, + aActionName)), checked: state.contains(States.CHECKED) }] }; @@ -337,7 +327,7 @@ AndroidPresenter.prototype = { tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj, aPageState) { return this.announce( - UtteranceGenerator.genForTabStateChange(aDocObj, aPageState).join(' ')); + UtteranceGenerator.genForTabStateChange(aDocObj, aPageState)); }, textChanged: function AndroidPresenter_textChanged(aIsInserted, aStart, @@ -421,18 +411,18 @@ AndroidPresenter.prototype = { }, editingModeChanged: function AndroidPresenter_editingModeChanged(aIsEditing) { - return this.announce( - UtteranceGenerator.genForEditingMode(aIsEditing).join(' ')); + return this.announce(UtteranceGenerator.genForEditingMode(aIsEditing)); }, announce: function AndroidPresenter_announce(aAnnouncement) { + let localizedAnnouncement = Utils.localize(aAnnouncement).join(' '); return { type: this.type, details: [{ eventType: (Utils.AndroidSdkVersion >= 16) ? this.ANDROID_ANNOUNCEMENT : this.ANDROID_VIEW_TEXT_CHANGED, - text: [aAnnouncement], - addedCount: aAnnouncement.length, + text: [localizedAnnouncement], + addedCount: localizedAnnouncement.length, removedCount: 0, fromIndex: 0 }] @@ -442,118 +432,99 @@ AndroidPresenter.prototype = { liveRegion: function AndroidPresenter_liveRegion(aContext, aIsPolite, aIsHide, aModifiedText) { return this.announce( - UtteranceGenerator.genForLiveRegion(aContext, aIsHide, - aModifiedText).join(' ')); + UtteranceGenerator.genForLiveRegion(aContext, aIsHide, aModifiedText)); } }; /** - * A speech presenter for direct TTS output + * A B2G presenter for Gaia. */ +this.B2GPresenter = function B2GPresenter() {}; -this.SpeechPresenter = function SpeechPresenter() {}; - -SpeechPresenter.prototype = { +B2GPresenter.prototype = { __proto__: Presenter.prototype, - type: 'Speech', + type: 'B2G', - pivotChanged: function SpeechPresenter_pivotChanged(aContext, aReason) { - if (!aContext.accessible) + /** + * A pattern used for haptic feedback. + * @type {Array} + */ + PIVOT_CHANGE_HAPTIC_PATTERN: [40], + + /** + * Pivot move reasons. + * @type {Array} + */ + pivotChangedReasons: ['none', 'next', 'prev', 'first', 'last', 'text', + 'point'], + + pivotChanged: function B2GPresenter_pivotChanged(aContext, aReason) { + if (!aContext.accessible) { return null; + } return { type: this.type, details: { - actions: [ - {method: 'playEarcon', - data: aContext.accessible.role === Roles.KEY ? - 'virtual_cursor_key' : 'virtual_cursor_move', - options: {}}, - {method: 'speak', - data: UtteranceGenerator.genForContext(aContext).output.join(' '), - options: {enqueue: true}} - ] + eventType: 'vc-change', + data: UtteranceGenerator.genForContext(aContext), + options: { + pattern: this.PIVOT_CHANGE_HAPTIC_PATTERN, + isKey: aContext.accessible.role === Roles.KEY, + reason: this.pivotChangedReasons[aReason] + } } }; }, - valueChanged: function SpeechPresenter_valueChanged(aAccessible) { + valueChanged: function B2GPresenter_valueChanged(aAccessible) { return { type: this.type, details: { - actions: [ - { method: 'speak', - data: aAccessible.value, - options: { enqueue: false } } - ] + eventType: 'value-change', + data: aAccessible.value } - } + }; }, - actionInvoked: function SpeechPresenter_actionInvoked(aObject, aActionName) { - let actions = []; - if (aActionName === 'click') { - actions.push({method: 'playEarcon', - data: 'clicked', - options: {}}); - } else { - actions.push({method: 'speak', - data: UtteranceGenerator.genForAction(aObject, aActionName).join(' '), - options: {enqueue: false}}); - } - return { type: this.type, details: { actions: actions } }; - }, - - liveRegion: function SpeechPresenter_liveRegion(aContext, aIsPolite, aIsHide, - aModifiedText) { + actionInvoked: function B2GPresenter_actionInvoked(aObject, aActionName) { return { type: this.type, details: { - actions: [{ - method: 'speak', + eventType: 'action', + data: UtteranceGenerator.genForAction(aObject, aActionName) + } + }; + }, + + liveRegion: function + B2GPresenter_liveRegion(aContext, aIsPolite, aIsHide, aModifiedText) { + return { + type: this.type, + details: { + eventType: 'liveregion-change', data: UtteranceGenerator.genForLiveRegion(aContext, aIsHide, - aModifiedText).join(' '), + aModifiedText), options: {enqueue: aIsPolite} - }] - } - }; - }, + } + }; + }, - announce: function SpeechPresenter_announce(aAnnouncement) { + announce: function B2GPresenter_announce(aAnnouncement) { return { type: this.type, details: { - actions: [{ - method: 'speak', data: aAnnouncement, options: { enqueue: false } - }] + eventType: 'announcement', + data: aAnnouncement } }; } }; -/** - * A haptic presenter - */ - -this.HapticPresenter = function HapticPresenter() {}; - -HapticPresenter.prototype = { - __proto__: Presenter.prototype, - - type: 'Haptic', - - PIVOT_CHANGE_PATTERN: [40], - - pivotChanged: function HapticPresenter_pivotChanged(aContext, aReason) { - return { type: this.type, details: { pattern: this.PIVOT_CHANGE_PATTERN } }; - } -}; - /** * A braille presenter */ - this.BraillePresenter = function BraillePresenter() {}; BraillePresenter.prototype = { @@ -566,23 +537,28 @@ BraillePresenter.prototype = { return null; } - let brailleOutput = BrailleGenerator.genForContext(aContext); - brailleOutput.output = brailleOutput.output.join(' '); - brailleOutput.selectionStart = 0; - brailleOutput.selectionEnd = 0; - - return { type: this.type, details: brailleOutput }; + return { + type: this.type, + details: { + output: Utils.localize(BrailleGenerator.genForContext(aContext)).join( + ' '), + selectionStart: 0, + selectionEnd: 0 + } + }; }, textSelectionChanged: function BraillePresenter_textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd, aIsFromUser) { - return { type: this.type, - details: { selectionStart: aStart, - selectionEnd: aEnd } }; - }, - - + return { + type: this.type, + details: { + selectionStart: aStart, + selectionEnd: aEnd + } + }; + } }; this.Presentation = { @@ -590,9 +566,8 @@ this.Presentation = { delete this.presenters; let presenterMap = { 'mobile/android': [VisualPresenter, AndroidPresenter], - 'b2g': [VisualPresenter, SpeechPresenter, HapticPresenter], - 'browser': [VisualPresenter, SpeechPresenter, HapticPresenter, - AndroidPresenter] + 'b2g': [VisualPresenter, B2GPresenter], + 'browser': [VisualPresenter, B2GPresenter, AndroidPresenter] }; this.presenters = [new P() for (P of presenterMap[Utils.MozBuildApp])]; return this.presenters; @@ -648,7 +623,7 @@ this.Presentation = { announce: function Presentation_announce(aAnnouncement) { // XXX: Typically each presenter uses the UtteranceGenerator, // but there really isn't a point here. - return [p.announce(UtteranceGenerator.genForAnnouncement(aAnnouncement)[0]) + return [p.announce(UtteranceGenerator.genForAnnouncement(aAnnouncement)) for each (p in this.presenters)]; }, diff --git a/accessible/jsat/Utils.jsm b/accessible/jsat/Utils.jsm index 65f81877d6bf..9d30dd315cb2 100644 --- a/accessible/jsat/Utils.jsm +++ b/accessible/jsat/Utils.jsm @@ -21,6 +21,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Relations', 'resource://gre/modules/accessibility/Constants.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'States', 'resource://gre/modules/accessibility/Constants.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm', + 'resource://gre/modules/PluralForm.jsm'); this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache', 'SettingCache']; @@ -189,10 +191,49 @@ this.Utils = { return this.isContentProcess; }, + localize: function localize(aOutput) { + let outputArray = Array.isArray(aOutput) ? aOutput : [aOutput]; + let localized = + [this.stringBundle.get(details) for (details of outputArray)]; // jshint ignore:line + // Clean up the white space. + let trimmed; + return [trimmed for (word of localized) if (word && // jshint ignore:line + (trimmed = word.trim()))]; // jshint ignore:line + }, + get stringBundle() { delete this.stringBundle; - this.stringBundle = Services.strings.createBundle( + let bundle = Services.strings.createBundle( 'chrome://global/locale/AccessFu.properties'); + this.stringBundle = { + get: function stringBundle_get(aDetails = {}) { + if (!aDetails || typeof aDetails === 'string') { + return aDetails; + } + let str = ''; + let string = aDetails.string; + if (!string) { + return str; + } + try { + let args = aDetails.args; + let count = aDetails.count; + if (args) { + str = bundle.formatStringFromName(string, args, args.length); + } else { + str = bundle.GetStringFromName(string); + } + if (count) { + str = PluralForm.get(count, str); + str = str.replace('#1', count); + } + } catch (e) { + Logger.debug('Failed to get a string from a bundle for', string); + } finally { + return str; + } + } + }; return this.stringBundle; }, diff --git a/accessible/tests/mochitest/jsat/jsatcommon.js b/accessible/tests/mochitest/jsat/jsatcommon.js index f6b4a0ae08ce..97c566bb9fe4 100644 --- a/accessible/tests/mochitest/jsat/jsatcommon.js +++ b/accessible/tests/mochitest/jsat/jsatcommon.js @@ -78,7 +78,7 @@ var AccessFuTest = { if (!data) { return; } - isDeeply(data.details.actions, aWaitForData, "Data is correct"); + isDeeply(data.details, aWaitForData, "Data is correct"); aListener.apply(listener); }; Services.obs.addObserver(listener, 'accessfu-output', false); @@ -288,8 +288,9 @@ AccessFuContentTest.prototype = { var android = this.extractAndroid(aMessage.json, expected.android); if ((speech && expected.speak) || (android && expected.android)) { if (expected.speak) { - (SimpleTest[expected.speak_checkFunc] || is)(speech, expected.speak, - '"' + speech + '" spoken'); + var checkFunc = SimpleTest[expected.speak_checkFunc] || isDeeply; + checkFunc.apply(SimpleTest, [speech, expected.speak, + '"' + JSON.stringify(speech) + '" spoken']); } if (expected.android) { @@ -332,11 +333,9 @@ AccessFuContentTest.prototype = { } for (var output of aData) { - if (output && output.type === 'Speech') { - for (var action of output.details.actions) { - if (action && action.method == 'speak') { - return action.data; - } + if (output && output.type === 'B2G') { + if (output.details && output.details.data[0].string !== 'clickAction') { + return output.details.data; } } } @@ -345,6 +344,10 @@ AccessFuContentTest.prototype = { }, extractAndroid: function(aData, aExpectedEvents) { + if (!aData) { + return null; + } + for (var output of aData) { if (output && output.type === 'Android') { for (var i in output.details) { diff --git a/accessible/tests/mochitest/jsat/output.js b/accessible/tests/mochitest/jsat/output.js index 6ab2d2e3cd02..406432caaf98 100644 --- a/accessible/tests/mochitest/jsat/output.js +++ b/accessible/tests/mochitest/jsat/output.js @@ -22,7 +22,7 @@ function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator var oldAccessible = aOldAccOrElmOrID !== null ? getAccessible(aOldAccOrElmOrID || 'root') : null; var context = new PivotContext(accessible, oldAccessible); - var output = aGenerator.genForContext(context).output; + var output = aGenerator.genForContext(context); // Create a version of the output that has null members where we have // null members in the expected output. Those are indexes that are not testable @@ -33,14 +33,15 @@ function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator if (expected[i] === null) { masked_output.push(null); } else { - masked_output[i] = output[i]; + masked_output[i] = typeof output[i] === "string" ? output[i].trim() : + output[i]; } } isDeeply(masked_output, expected, "Context output is correct for " + aAccOrElmOrID + - " (output: " + output.join(", ") + ") ==" + - " (expected: " + expected.join(", ") + ")"); + " (output: " + JSON.stringify(output) + ") ==" + + " (expected: " + JSON.stringify(expected) + ")"); } /** @@ -53,6 +54,9 @@ function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator */ function testObjectOutput(aAccOrElmOrID, aGenerator) { var accessible = getAccessible(aAccOrElmOrID); + if (!accessible.name || !accessible.name.trim()) { + return; + } var context = new PivotContext(accessible); var output = aGenerator.genForObject(accessible, context); var outputOrder; diff --git a/accessible/tests/mochitest/jsat/test_alive.html b/accessible/tests/mochitest/jsat/test_alive.html index 2ae2b214733c..922289f669ea 100644 --- a/accessible/tests/mochitest/jsat/test_alive.html +++ b/accessible/tests/mochitest/jsat/test_alive.html @@ -23,13 +23,10 @@ function settingsStart() { ok(true, "EventManager was stopped."); isnot(AccessFu._enabled, true, "AccessFu was disabled."); - AccessFuTest.once([{ - "method": "speak", - "data": "Screen reader started", - "options": { - "enqueue": false - } - }], AccessFuTest.nextTest); + AccessFuTest.once({ + "eventType": "announcement", + "data": [{string: "screenReaderStarted"}] + }, AccessFuTest.nextTest); // XXX: Bug 978076 - test start with SettingsManager. //navigator.mozSettings.createLock().set( // {'accessibility.screenreader': false}); @@ -39,13 +36,10 @@ // Make sure EventManager is started again. function settingsStop() { ok(AccessFu._enabled, "AccessFu was enabled again."); - AccessFuTest.once([{ - "method": "speak", - "data": "Screen reader stopped", - "options": { - "enqueue": false - } - }], AccessFuTest.finish); + AccessFuTest.once({ + "eventType": "announcement", + "data": [{string: "screenReaderStopped"}] + }, AccessFuTest.finish); // XXX: Bug 978076 - test stop with SettingsManager. //navigator.mozSettings.createLock().set( // {'accessibility.screenreader': false}); diff --git a/accessible/tests/mochitest/jsat/test_content_integration.html b/accessible/tests/mochitest/jsat/test_content_integration.html index 350bba13e7ce..5bbac658c195 100644 --- a/accessible/tests/mochitest/jsat/test_content_integration.html +++ b/accessible/tests/mochitest/jsat/test_content_integration.html @@ -23,68 +23,72 @@ diff --git a/accessible/tests/mochitest/jsat/test_content_text.html b/accessible/tests/mochitest/jsat/test_content_text.html index 4b9189647b0a..ee85a9cb5ff1 100644 --- a/accessible/tests/mochitest/jsat/test_content_text.html +++ b/accessible/tests/mochitest/jsat/test_content_text.html @@ -27,9 +27,9 @@ [ // Read-only text tests [ContentMessages.simpleMoveFirst, { - speak: 'These are my awards, Mother. From Army. ' + + speak: ['These are my awards, Mother. From Army. ' + 'The seal is for marksmanship, and the gorilla is ' + - 'for sand racing. Text content test document' + 'for sand racing.', 'Text content test document'] }], [ContentMessages.moveNextBy('word'), { speak: 'These', @@ -142,8 +142,8 @@ // Editable text tests. [ContentMessages.focusSelector('textarea'), { - speak: 'Please refrain from Mayoneggs during this ' + - 'salmonella scare. text area' + speak: ['Please refrain from Mayoneggs during this ' + + 'salmonella scare.', {string: 'textarea'}] }], [null, { // When we first focus, caret is at 0. android: [{ diff --git a/accessible/tests/mochitest/jsat/test_explicit_names.html b/accessible/tests/mochitest/jsat/test_explicit_names.html index 40fbcc2f0096..73bf05aa30d9 100644 --- a/accessible/tests/mochitest/jsat/test_explicit_names.html +++ b/accessible/tests/mochitest/jsat/test_explicit_names.html @@ -16,80 +16,99 @@ // Test the following accOrElmOrID. var tests = [{ accOrElmOrID: "anchor1", - expected: ["link", "title"] + expected: [{"string": "link"}, "title"] }, { accOrElmOrID: "anchor2", - expected: ["link", "This is a link"] + expected: [{"string": "link"}, "This is a link"] }, { accOrElmOrID: "button1", - expected: ["button", "Press me"] + expected: [{"string": "pushbutton"}, "Press me"] }, { accOrElmOrID: "button2", - expected: ["button", "Press me"] + expected: [{"string": "pushbutton"}, "Press me"] }, { accOrElmOrID: "textarea1", - expected: ["text area", "This is the text area text.", "Test Text Area"] + expected: [{"string": "textarea"}, "This is the text area text.", + "Test Text Area"] }, { accOrElmOrID: "textarea2", - expected: ["text area", "This is the text area text."] + expected: [{"string": "textarea"}, "This is the text area text."] }, { accOrElmOrID: "heading1", - expected: ["heading level 1", "Test heading", "This is the heading."] + expected: [{"string": "headingLevel", "args": [1]}, "Test heading", + "This is the heading."] }, { accOrElmOrID: "heading1", oldAccOrElmOrID: null, expected: [null /* parent doc title */, document.title, - "heading level 1", "Test heading", "This is the heading."] + {"string": "headingLevel", "args": [1]}, "Test heading", + "This is the heading."] }, { accOrElmOrID: "heading2", - expected: ["heading level 1", "This is the heading."] + expected: [{"string": "headingLevel", "args": [1]}, + "This is the heading."] }, { accOrElmOrID: "list", - expected: ["list 2 items", "Test List", "First item", "Top of the list", - "Last item", "2.", "list two"] + expected: [{"string": "list"}, {"string": "listItemsCount", "count": 2}, + "Test List", {"string": "listStart"}, "Top of the list", + {"string": "listEnd"}, "2.", "list two"] }, { accOrElmOrID: "dlist", - expected: ["definition list 0.5 items", "Test Definition List", + expected: [{"string": "definitionlist"}, + {"string": "listItemsCount", "count": 0.5}, "Test Definition List", "dd one"] }, { accOrElmOrID: "li_one", - expected: ["list 2 items", "Test List", "First item", "Top of the list"] + expected: [{"string": "list"}, {"string": "listItemsCount", "count": 2}, + "Test List", {"string": "listStart"}, "Top of the list"] }, { accOrElmOrID: "li_two", - expected: ["list 2 items", "Test List", "Last item", "2.", "list two"] + expected: [{"string": "list"}, {"string": "listItemsCount", "count": 2}, + "Test List", {"string": "listEnd"}, "2.", "list two"] }, { accOrElmOrID: "cell", - expected: ["table with 1 column and 1 row", "Fruits and vegetables", - "Column 1 Row 1", "List of Fruits", "list 4 items", "First item", - "link", "Apples", "link", "Bananas", "link", "Peaches", "Last item", - "link", "Plums"] + expected: [{"string": "table"}, + {"string": "tblColumnInfo", "count": 1}, + {"string": "tblRowInfo", "count": 1}, "Fruits and vegetables", + {"string": "columnInfo", "args": [1]}, + {"string": "rowInfo", "args": [1]}, "List of Fruits", + {"string": "list"}, {"string": "listItemsCount", "count": 4}, + {"string": "listStart"}, {"string": "link"}, "Apples", + {"string": "link"}, "Bananas", + {"string": "link"}, "Peaches", {"string": "listEnd"}, + {"string": "link"}, "Plums"] }, { accOrElmOrID: "app.net", - expected: ["list 2 items", "First item", "link", "star", "Last item", - "link", "repost"] + expected: [{"string": "list"}, {"string": "listItemsCount", "count": 2}, + {"string": "listStart"}, {"string": "link"}, "star", + {"string": "listEnd"}, {"string": "link"}, "repost"] }, { // Test pivot to list from li_one. accOrElmOrID: "list", oldAccOrElmOrID: "li_one", - expected: ["list 2 items", "Test List", "First item", "Top of the list", - "Last item", "2.", "list two"] + expected: [{"string": "list"}, {"string": "listItemsCount", "count": 2}, + "Test List", {"string": "listStart"}, "Top of the list", + {"string": "listEnd"}, "2.", "list two"] }, { // Test pivot to li_one from list. accOrElmOrID: "li_one", oldAccOrElmOrID: "list", - expected: ["First item", "Top of the list"] + expected: [{"string": "listStart"}, "Top of the list"] }, { // Test pivot to "apples" link from the table cell. accOrElmOrID: "apples", oldAccOrElmOrID: "cell", - expected: ["list 4 items", "First item", "link", "Apples"] + expected: [{"string": "list"}, {"string": "listItemsCount", "count": 4}, + {"string": "listStart"}, {"string": "link"}, "Apples"] }, { // Test pivot to the table cell from the "apples" link. accOrElmOrID: "cell", oldAccOrElmOrID: "apples", - expected: ["List of Fruits", "list 4 items", "First item", "link", - "Apples", "link", "Bananas", "link", "Peaches", "Last item", "link", - "Plums"] + expected: ["List of Fruits", {"string": "list"}, + {"string": "listItemsCount", "count": 4}, {"string": "listStart"}, + {"string": "link"}, "Apples", {"string": "link"}, "Bananas", + {"string": "link"}, "Peaches", {"string": "listEnd"}, + {"string": "link"}, "Plums"] }]; SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, 0); diff --git a/accessible/tests/mochitest/jsat/test_landmarks.html b/accessible/tests/mochitest/jsat/test_landmarks.html index 5b591e5ead68..d0982bb31809 100644 --- a/accessible/tests/mochitest/jsat/test_landmarks.html +++ b/accessible/tests/mochitest/jsat/test_landmarks.html @@ -16,81 +16,104 @@ // Test the following accOrElmOrID. var tests = [{ accOrElmOrID: "nav", - expectedUtterance: [["navigation", "a nav"], ["a nav", "navigation"]], - expectedBraille: [["navigation", "a nav"], ["a nav", "navigation"]] + expectedUtterance: [[{"string": "navigation"}, "a nav"], + ["a nav", {"string": "navigation"}]], + expectedBraille: [[{"string": "navigation"}, "a nav"], + ["a nav", {"string": "navigation"}]] }, { accOrElmOrID: "main", - expectedUtterance: [["main", "a main area"], ["a main area", "main"]], - expectedBraille: [["main", "a main area"], ["a main area", "main"]] + expectedUtterance: [[{"string": "main"}, "a main area"], + ["a main area", {"string": "main"}]], + expectedBraille: [[{"string": "main"}, "a main area"], + ["a main area", {"string": "main"}]] }, { accOrElmOrID: "header", - expectedUtterance: [["banner", "header", "a header"], ["a header", - "header", "banner"]], - expectedBraille: [["banner", "header", "a header"], ["a header", - "header", "banner"]] + expectedUtterance: [ + [{"string": "banner"}, {"string": "header"}, "a header"], + ["a header", {"string": "header"}, {"string": "banner"}]], + expectedBraille: [ + [{"string": "banner"}, {"string": "headerAbbr"}, "a header"], + ["a header", {"string": "headerAbbr"}, {"string": "banner"}]] }, { accOrElmOrID: "footer", - expectedUtterance: [["content info", "footer", "a footer"], [ - "a footer", "footer", "content info"]], - expectedBraille: [["content info", "footer", "a footer"], ["a footer", - "footer", "content info"]] + expectedUtterance: [ + [{"string": "contentinfo"}, {"string": "footer"}, "a footer"], + ["a footer", {"string": "footer"}, {"string": "contentinfo"}]], + expectedBraille: [ + [{"string": "contentinfo"}, {"string": "footerAbbr"}, "a footer"], + ["a footer", {"string": "footerAbbr"}, {"string": "contentinfo"}]] }, { accOrElmOrID: "article_header", - expectedUtterance: [["header", "a header within an article"], [ - "a header within an article", "header"]], - expectedBraille: [["header", "a header within an article"], [ - "a header within an article", "header"]], + expectedUtterance: [ + [{"string": "header"}, "a header within an article"], + ["a header within an article", {"string": "header"}]], + expectedBraille: [ + [{"string": "headerAbbr"}, "a header within an article"], + ["a header within an article", {"string": "headerAbbr"}]], }, { accOrElmOrID: "article_footer", - expectedUtterance: [["footer", "a footer within an article"], [ - "a footer within an article", "footer"]], - expectedBraille: [["footer", "a footer within an article"], [ - "a footer within an article", "footer"]] + expectedUtterance: [ + [{"string": "footer"}, "a footer within an article"], + ["a footer within an article", {"string": "footer"}]], + expectedBraille: [ + [{"string": "footerAbbr"}, "a footer within an article"], + ["a footer within an article", {"string": "footerAbbr"}]] }, { accOrElmOrID: "section_header", - expectedUtterance: [["header", "a header within a section"], [ - "a header within a section", "header"]], - expectedBraille: [["header", "a header within a section"], [ - "a header within a section", "header"]] + expectedUtterance: [[{"string":"header"}, "a header within a section"], + ["a header within a section", {"string":"header"}]], + expectedBraille: [ + [{"string":"headerAbbr"}, "a header within a section"], + ["a header within a section", {"string":"headerAbbr"}]] }, { accOrElmOrID: "section_footer", - expectedUtterance: [["footer", "a footer within a section"], [ - "a footer within a section", "footer"]], - expectedBraille: [["footer", "a footer within a section"], [ - "a footer within a section", "footer"]] + expectedUtterance: [ + [{"string": "footer"}, "a footer within a section"], + ["a footer within a section", {"string": "footer"}]], + expectedBraille: [ + [{"string": "footerAbbr"}, "a footer within a section"], + ["a footer within a section", {"string": "footerAbbr"}]] }, { accOrElmOrID: "aside", - expectedUtterance: [["complementary", "by the way I am an aside"], [ - "by the way I am an aside", "complementary"]], - expectedBraille: [["complementary", "by the way I am an aside"], [ - "by the way I am an aside", "complementary"]] + expectedUtterance: [ + [{"string": "complementary"}, "by the way I am an aside"], + ["by the way I am an aside", {"string": "complementary"}]], + expectedBraille: [ + [{"string": "complementary"}, "by the way I am an aside"], + ["by the way I am an aside", {"string": "complementary"}]] }, { accOrElmOrID: "main_element", - expectedUtterance: [["main", "another main area"], [ - "another main area", "main"]], - expectedBraille: [["main", "another main area"], ["another main area", - "main"]] + expectedUtterance: [[{"string": "main"}, "another main area"], + ["another main area", {"string": "main"}]], + expectedBraille: [[{"string": "main"}, "another main area"], + ["another main area", {"string": "main"}]] }, { accOrElmOrID: "complementary", - expectedUtterance: [["list 1 item", "complementary", "First item", - "A complementary"], ["A complementary", "First item", - "complementary", "list 1 item"]], - expectedBraille: [["*", "complementary", "A complementary"], ["*", - "A complementary", "complementary"]] + expectedUtterance: [[{"string": "list"}, + {"string": "listItemsCount", "count": 1}, {"string": "complementary"}, + {"string": "listStart"}, "A complementary"], ["A complementary", + {"string": "listStart"}, {"string": "complementary"}, + {"string": "list"}, {"string": "listItemsCount", "count": 1}]], + expectedBraille: [["*", {"string": "complementary"}, "A complementary"], + ["*", "A complementary", {"string": "complementary"}]] }, { accOrElmOrID: "parent_main", - expectedUtterance: [["main", "a parent main", "complementary", - "a child complementary"], ["a parent main", "a child complementary", - "complementary", "main"]], - expectedBraille: [["main", "a parent main", "complementary", - "a child complementary"], ["a parent main", "a child complementary", - "complementary", "main"]] + expectedUtterance: [[{"string": "main"}, "a parent main", + {"string": "complementary"}, "a child complementary"], + ["a parent main", "a child complementary", + {"string": "complementary"}, {"string": "main"}]], + expectedBraille: [[{"string": "main"}, "a parent main", + {"string": "complementary"}, "a child complementary"], + ["a parent main", "a child complementary", + {"string": "complementary"}, {"string": "main"}]] }, { accOrElmOrID: "child_complementary", - expectedUtterance: [["main", "complementary", "a child complementary"], - ["a child complementary", "complementary", "main"]], - expectedBraille: [["complementary", "a child complementary"], - ["a child complementary", "complementary"]] + expectedUtterance: [[{"string": "main"}, {"string": "complementary"}, + "a child complementary"], ["a child complementary", + {"string": "complementary"}, {"string": "main"}]], + expectedBraille: [[{"string": "complementary"}, + "a child complementary"], ["a child complementary", + {"string": "complementary"}]] }]; // Test outputs (utterance and braille) for landmarks. diff --git a/accessible/tests/mochitest/jsat/test_live_regions.html b/accessible/tests/mochitest/jsat/test_live_regions.html index f8be880095e8..a7e0e9671b3c 100644 --- a/accessible/tests/mochitest/jsat/test_live_regions.html +++ b/accessible/tests/mochitest/jsat/test_live_regions.html @@ -47,204 +47,204 @@ } var tests = [{ - expected: [{ - "method": "speak", - "data": "hidden I will be hidden", + expected: { + "eventType": "liveregion-change", + "data": [{"string": "hidden"}, "I will be hidden"], "options": { "enqueue": true } - }], + }, action: function action() { [hide(id) for (id of ["to_hide1", "to_hide2", "to_hide3", "to_hide4"])]; } }, { - expected: [{ - "method": "speak", - "data": "hidden I will be hidden", + expected: { + "eventType": "liveregion-change", + "data": [{"string": "hidden"},"I will be hidden"], "options": { "enqueue": true } - }], + }, action: function action() { [hide(id) for (id of ["to_hide_descendant1", "to_hide_descendant2", "to_hide_descendant3", "to_hide_descendant4"])]; } }, { - expected: [{ - "method": "speak", - "data": "I will be shown", + expected: { + "eventType": "liveregion-change", + "data": ["I will be shown"], "options": { "enqueue": true } - }], + }, action: function action() { [show(id) for (id of ["to_show1", "to_show2", "to_show3", "to_show4"])]; } }, { - expected: [{ - "method": "speak", - "data": "I will be shown", + expected: { + "eventType": "liveregion-change", + "data": ["I will be shown"], "options": { "enqueue": true } - }], + }, action: function action() { [show(id) for (id of ["to_show_descendant1", "to_show_descendant2", "to_show_descendant3", "to_show_descendant4"])]; } }, { - expected: [{ - "method": "speak", - "data": "hidden I will be hidden", + expected: { + "eventType": "liveregion-change", + "data": [{"string": "hidden"}, "I will be hidden"], "options": { "enqueue": false } - }], + }, action: function action() { hide("to_hide_live_assertive"); } }, { - expected: [{ - "method": "speak", - "data": "I will be shown", + expected: { + "eventType": "liveregion-change", + "data": ["I will be shown"], "options": { "enqueue": false } - }], + }, action: function action() { [show(id) for (id of ["to_show_live_off", "to_show_live_assertive"])]; } }, { - expected: [{ - "method": "speak", - "data": "Text Added", + expected: { + "eventType": "liveregion-change", + "data": ["Text Added"], "options": { "enqueue": false } - }], + }, action: function action() { updateText("text_add", "Text Added"); } }, { - expected: [{ - "method": "speak", - "data": "Text Added", + expected: { + "eventType": "liveregion-change", + "data": ["Text Added"], "options": { "enqueue": false } - }], + }, action: function action() { updateHTML("text_add", "Text Added"); } }, { - expected: [{ - "method": "speak", - "data": "hidden Text Removed", + expected: { + "eventType": "liveregion-change", + "data": [{"string": "hidden"}, "Text Removed"], "options": { "enqueue": true } - }], + }, action: function action() { updateText("text_remove", ""); } }, { - expected: [{ - "method": "speak", - "data": "Descendant Text Added", + expected: { + "eventType": "liveregion-change", + "data": ["Descendant Text Added"], "options": { "enqueue": false } - }], + }, action: function action() { updateText("text_add_descendant", "Descendant Text Added"); } }, { - expected: [{ - "method": "speak", - "data": "Descendant Text Added", + expected: { + "eventType": "liveregion-change", + "data": ["Descendant Text Added"], "options": { "enqueue": false } - }], + }, action: function action() { updateHTML("text_add_descendant", "Descendant Text Added"); } }, { - expected: [{ - "method": "speak", - "data": "hidden Descendant Text Removed", + expected: { + "eventType": "liveregion-change", + "data": [{"string": "hidden"}, "Descendant Text Removed"], "options": { "enqueue": true } - }], + }, action: function action() { updateText("text_remove_descendant", ""); } }, { - expected: [{ - "method": "speak", - "data": "Descendant Text Added", + expected: { + "eventType": "liveregion-change", + "data": ["Descendant Text Added"], "options": { "enqueue": false } - }], + }, action: function action() { updateText("text_add_descendant2", "Descendant Text Added"); } }, { - expected: [{ - "method": "speak", - "data": "Descendant Text Added", + expected: { + "eventType": "liveregion-change", + "data": ["Descendant Text Added"], "options": { "enqueue": false } - }], + }, action: function action() { updateHTML("text_add_descendant2", "Descendant Text Added"); } }, { - expected: [{ - "method": "speak", - "data": "hidden Descendant Text Removed", + expected: { + "eventType": "liveregion-change", + "data": [{"string": "hidden"}, "Descendant Text Removed"], "options": { "enqueue": true } - }], + }, action: function action() { updateText("text_remove_descendant2", ""); } }, { - expected: [{ - "method": "speak", - "data": "I am replaced main", + expected: { + "eventType": "liveregion-change", + "data": ["I am replaced", {"string": "main"}], "options": { "enqueue": true } - }], + }, action: function action() { var region = document.getElementById("to_replace_region"); var child = document.getElementById("to_replace"); child.setAttribute("role", "main"); } }, { - expected: [{ - "method": "speak", - "data": "I am a replaced text", + expected: { + "eventType": "liveregion-change", + "data": ["I am a replaced text"], "options": { "enqueue": false } - }], + }, action: function action() { updateText("to_replace_text", "I am a replaced text"); } }, { - expected: [{ - "method": "speak", - "data": "I am a replaced text", + expected: { + "eventType": "liveregion-change", + "data": ["I am a replaced text"], "options": { "enqueue": false } - }], + }, action: function action() { updateHTML("to_replace_text", "I am a replaced text"); } diff --git a/accessible/tests/mochitest/jsat/test_output.html b/accessible/tests/mochitest/jsat/test_output.html index f9cc5aa126e3..5c1e4e9c0e05 100644 --- a/accessible/tests/mochitest/jsat/test_output.html +++ b/accessible/tests/mochitest/jsat/test_output.html @@ -22,340 +22,372 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 // generator function within the UtteranceGenerator. var tests = [{ accOrElmOrID: "anchor", - expectedUtterance: [["link", "title"], ["title", "link"]], - expectedBraille: [["lnk", "title"], ["title", "lnk"]] + expectedUtterance: [[{"string": "link"}, "title"], + ["title", {"string": "link"}]], + expectedBraille: [[{"string": "linkAbbr"}, "title"], + ["title", {"string": "linkAbbr"}]] }, { accOrElmOrID: "anchor_titleandtext", - expectedUtterance: [["link", "goes to the tests -", "Tests"], - ["Tests", "- goes to the tests", "link"]], - expectedBraille: [["lnk", "goes to the tests -", "Tests"], - ["Tests", "- goes to the tests", "lnk"]], + expectedUtterance: [[{"string": "link"}, "goes to the tests -", + "Tests"], ["Tests", "- goes to the tests", {"string": "link"}]], + expectedBraille: [[{"string": "linkAbbr"}, "goes to the tests -", + "Tests"], ["Tests", "- goes to the tests", {"string": "linkAbbr"}]], }, { accOrElmOrID: "anchor_duplicatedtitleandtext", - expectedUtterance: [["link", "Tests"], ["Tests", "link"]], - expectedBraille: [["lnk", "Tests"], ["Tests", "lnk"]] + expectedUtterance: [[{"string": "link"}, "Tests"], + ["Tests", {"string": "link"}]], + expectedBraille: [[{"string": "linkAbbr"}, "Tests"], + ["Tests", {"string": "linkAbbr"}]] }, { accOrElmOrID: "anchor_arialabelandtext", - expectedUtterance: [["link", "goes to the tests - Tests"], - ["Tests - goes to the tests", "link"]], - expectedBraille: [["lnk", "goes to the tests - Tests"], - ["Tests - goes to the tests", "lnk"]], + expectedUtterance: [[{"string": "link"}, "goes to the tests - Tests"], + ["Tests - goes to the tests", {"string": "link"}]], + expectedBraille: [[{"string": "linkAbbr"}, + "goes to the tests - Tests"], ["Tests - goes to the tests", + {"string": "linkAbbr"}]], }, { accOrElmOrID: "textarea", - expectedUtterance: [[ - "text area", "This is the text area text." - ], [ - "This is the text area text.", "text area" - ],], - expectedBraille: [[ - "txtarea", "This is the text area text." - ], [ - "This is the text area text.", "txtarea" - ],], + expectedUtterance: [[{"string": "textarea"}, + "This is the text area text."], ["This is the text area text.", + {"string": "textarea"}]], + expectedBraille: [[{"string": "textareaAbbr"}, + "This is the text area text."], ["This is the text area text.", + {"string": "textareaAbbr"}]], }, { accOrElmOrID: "heading", - expectedUtterance: [ - ["heading level 1", "Test heading"], - ["Test heading", "heading level 1"] - ], - expectedBraille: [ - ["heading", "Test heading"], - ["Test heading", "heading"] - ] + expectedUtterance: [[{"string": "headingLevel", "args": [1]}, + "Test heading"], ["Test heading", + {"string": "headingLevel", "args": [1]}]], + expectedBraille: [[{"string": "headingAbbr"}, "Test heading"], + ["Test heading", {"string": "headingAbbr"}]] }, { accOrElmOrID: "list", - expectedUtterance: [ - ["list 1 item", "First item", "1.", "list one"], - ["1.", "list one", "First item", "list 1 item"] + expectedUtterance: [[{"string": "list"}, + {"string": "listItemsCount", "count":1}, {"string": "listStart"}, + "1.", "list one"], ["1.", "list one", {"string": "listStart"}, + {"string": "list"}, {"string": "listItemsCount", "count":1}] ], - expectedBraille: [ - ["list", "list one"], - ["list one", "list"] - ] + expectedBraille: [[{"string": "listAbbr"}, "list one"], + ["list one", {"string": "listAbbr"}]] }, { accOrElmOrID: "dlist", - expectedUtterance: [ - ["definition list 0.5 items", "dd one"], - ["dd one", "definition list 0.5 items"] + expectedUtterance: [[{"string": "definitionlist"}, + {"string": "listItemsCount", "count": 0.5}, "dd one"], ["dd one", + {"string": "definitionlist"}, + {"string": "listItemsCount", "count": 0.5}] ], - expectedBraille: [ - ["definition list", "dd one"], - ["dd one", "definition list"] - ] + expectedBraille: [[{"string": "definitionlistAbbr"}, "dd one"], + ["dd one", {"string": "definitionlistAbbr"}]] }, { accOrElmOrID: "li_one", - expectedUtterance: [ - ["list 1 item", "First item", "1.", "list one"], - ["1.", "list one", "First item", "list 1 item"] + expectedUtterance: [[{"string": "list"}, + {"string": "listItemsCount", "count": 1}, {"string": "listStart"}, + "1.", "list one"], ["1.", "list one", {"string": "listStart"}, + {"string": "list"}, {"string": "listItemsCount", "count": 1}] ], - expectedBraille: [ - ["1.", "list one"], - ["1.", "list one"] - ] + expectedBraille: [["1.", "list one"], ["1.", "list one"]] }, { accOrElmOrID: "li_two", - expectedUtterance: [ - ["list 1 item", "First item", "list two"], - ["list two", "First item", "list 1 item"] + expectedUtterance: [[{"string": "list"}, + {"string": "listItemsCount", "count": 1}, {"string": "listStart"}, + "list two"], ["list two", {"string": "listStart"}, + {"string": "list"}, {"string": "listItemsCount", "count": 1}] ], - expectedBraille: [ - ["*", "list two"], - ["*", "list two"] - ] + expectedBraille: [["*", "list two"], ["*", "list two"]] }, { accOrElmOrID: "cell", - expectedUtterance: [[ - "table with 1 column and 1 row", "Fruits and vegetables", - "Column 1 Row 1", "list 4 items", "First item", "link", "Apples", - "link", "Bananas", "link", "Peaches", "Last item", "link", "Plums" - ], [ - "Apples", "link", "First item", "Bananas", "link", "Peaches", - "link", "Plums", "link", "Last item", "list 4 items", - "Column 1 Row 1", "Fruits and vegetables", - "table with 1 column and 1 row" - ]], - expectedBraille: [[ - "c1r1", "list", "lnk", "Apples", "lnk", "Bananas", "lnk", - "Peaches", "lnk", "Plums" - ], [ - "Apples", "lnk", "Bananas", "lnk", "Peaches", "lnk", "Plums", - "lnk", "list", "c1r1" - ]] + expectedUtterance: [[{"string":"table"}, + {"string": "tblColumnInfo", "count": 1}, + {"string": "tblRowInfo", "count": 1}, "Fruits and vegetables", + {"string": "columnInfo", "args": [1]}, + {"string": "rowInfo", "args": [1]}, {"string": "list"}, + {"string": "listItemsCount", "count": 4}, {"string": "listStart"}, + {"string": "link"}, "Apples", {"string": "link"}, "Bananas", + {"string": "link"}, "Peaches", {"string": "listEnd"}, + {"string": "link"}, "Plums"], ["Apples", {"string": "link"}, + {"string": "listStart"}, "Bananas", {"string": "link"}, "Peaches", + {"string": "link"}, "Plums", {"string": "link"}, + {"string": "listEnd"}, {"string": "list"}, + {"string": "listItemsCount", "count": 4}, + {"string": "columnInfo", "args": [1]}, + {"string": "rowInfo", "args": [1]}, "Fruits and vegetables", + {"string":"table"}, {"string": "tblColumnInfo", "count": 1}, + {"string": "tblRowInfo", "count": 1}]], + expectedBraille: [[{"string": "cellInfoAbbr", "args": [ 1, 1]}, + {"string": "listAbbr"}, {"string": "linkAbbr"}, "Apples", + {"string": "linkAbbr"}, "Bananas", {"string": "linkAbbr"}, + "Peaches", {"string": "linkAbbr"}, "Plums"], ["Apples", + {"string": "linkAbbr"}, "Bananas", {"string": "linkAbbr"}, + "Peaches", {"string": "linkAbbr"}, "Plums", {"string": "linkAbbr"}, + {"string": "listAbbr"}, + {"string": "cellInfoAbbr", "args": [ 1, 1]}]] }, { accOrElmOrID: "date", - expectedUtterance: [["date entry", "2011-09-29"], ["2011-09-29", "date entry"]], - expectedBraille: [["date entry", "2011-09-29"], ["2011-09-29", "date entry"]] + expectedUtterance: [[{"string": "textInputType_date"}, + {"string": "entry"}, "2011-09-29"], ["2011-09-29", + {"string": "textInputType_date"}, {"string": "entry"}]], + expectedBraille: [[{"string": "textInputType_date"}, + {"string": "entryAbbr"}, "2011-09-29"], ["2011-09-29", + {"string": "textInputType_date"}, {"string": "entryAbbr"}]] }, { accOrElmOrID: "email", - expectedUtterance: [ - ["e-mail entry", "test@example.com"], - ["test@example.com", "e-mail entry"] - ], - expectedBraille: [ - ["e-mail entry", "test@example.com"], - ["test@example.com", "e-mail entry"] - ] + expectedUtterance: [[{"string": "textInputType_email"}, + {"string": "entry"}, "test@example.com"], ["test@example.com", + {"string": "textInputType_email"}, {"string": "entry"}]], + expectedBraille: [[{"string": "textInputType_email"}, + {"string": "entryAbbr"}, "test@example.com"], ["test@example.com", + {"string": "textInputType_email"}, {"string": "entryAbbr"}]] }, { accOrElmOrID: "search", - expectedUtterance: [ - ["search entry", "This is a search"], - ["This is a search", "search entry"] - ], - expectedBraille: [ - ["search entry", "This is a search"], - ["This is a search", "search entry"] - ] + expectedUtterance: [[{"string": "textInputType_search"}, + {"string": "entry"}, "This is a search"], ["This is a search", + {"string": "textInputType_search"}, {"string": "entry"}]], + expectedBraille: [[{"string": "textInputType_search"}, + {"string": "entryAbbr"}, "This is a search"], ["This is a search", + {"string": "textInputType_search"}, {"string": "entryAbbr"}]] }, { accOrElmOrID: "tel", - expectedUtterance: [ - ["telephone entry", "555-5555"], ["555-5555", "telephone entry"] - ], - expectedBraille: [ - ["telephone entry", "555-5555"], ["555-5555", "telephone entry"] - ] + expectedUtterance: [[{"string": "textInputType_tel"}, + {"string": "entry"}, "555-5555"], ["555-5555", + {"string": "textInputType_tel"}, {"string": "entry"}]], + expectedBraille: [[{"string": "textInputType_tel"}, + {"string": "entryAbbr"}, "555-5555"], ["555-5555", + {"string": "textInputType_tel"}, {"string": "entryAbbr"}]] }, { accOrElmOrID: "url", - expectedUtterance: [ - ["URL entry", "http://example.com"], - ["http://example.com", "URL entry"] - ], - expectedBraille: [ - ["URL entry", "http://example.com"], - ["http://example.com", "URL entry"] - ] + expectedUtterance: [[{"string": "textInputType_url"}, + {"string": "entry"}, "http://example.com"], ["http://example.com", + {"string": "textInputType_url"}, {"string": "entry"}]], + expectedBraille: [[{"string": "textInputType_url"}, + {"string": "entryAbbr"}, "http://example.com"], + ["http://example.com", {"string": "textInputType_url"}, + {"string": "entryAbbr"}]] }, { accOrElmOrID: "textInput", - expectedUtterance: [["entry", "This is text."], ["This is text.", "entry"]], - expectedBraille: [["entry", "This is text."], ["This is text.", "entry"]] + expectedUtterance: [[{"string": "entry"}, "This is text."], + ["This is text.", {"string": "entry"}]], + expectedBraille: [[{"string": "entryAbbr"}, "This is text."], + ["This is text.", {"string": "entryAbbr"}]] }, { // Test pivot to list from li_one. accOrElmOrID: "list", oldAccOrElmOrID: "li_one", - expectedUtterance: [ - ["list 1 item", "First item", "1.", "list one"], - ["1.", "list one", "First item", "list 1 item"] + expectedUtterance: [[{"string": "list"}, + {"string": "listItemsCount", "count": 1}, {"string": "listStart"}, + "1.", "list one"], ["1.", "list one", {"string": "listStart"}, + {"string": "list"}, {"string": "listItemsCount", "count": 1}] ], - expectedBraille: [ - ["list", "list one"], - ["list one", "list"] - ] + expectedBraille: [[{"string": "listAbbr"}, "list one"], + ["list one", {"string": "listAbbr"}]] }, { // Test pivot to "apples" link from the table cell. accOrElmOrID: "apples", oldAccOrElmOrID: "cell", - expectedUtterance: [ - ["list 4 items", "First item", "link", "Apples"], - ["Apples", "link", "First item", "list 4 items"] + expectedUtterance: [[{"string": "list"}, + {"string": "listItemsCount", "count": 4}, {"string": "listStart"}, + {"string": "link"}, "Apples"], ["Apples", {"string": "link"}, + {"string": "listStart"}, {"string": "list"}, + {"string": "listItemsCount", "count": 4}] ], - expectedBraille: [ - ["*", "lnk", "Apples"], - ["*", "Apples", "lnk"] - ] + expectedBraille: [["*", {"string": "linkAbbr"}, "Apples"], + ["*", "Apples", {"string": "linkAbbr"}]] }, { - // Test pivot to 'bananas' link from 'apples' link. + // Test pivot to "bananas" link from "apples" link. accOrElmOrID: "bananas", oldAccOrElmOrID: "apples", - expectedUtterance: [["link", "Bananas"], ["Bananas", "link"]], - expectedBraille: [["*", "lnk", "Bananas"], ["*", "Bananas", "lnk"]] + expectedUtterance: [[{"string": "link"}, "Bananas"], + ["Bananas", {"string": "link"}]], + expectedBraille: [["*", {"string": "linkAbbr"}, "Bananas"], + ["*", "Bananas", {"string": "linkAbbr"}]] }, { // test unavailable state utterance - accOrElmOrID: 'unavailableButton', - expectedUtterance: [["unavailable button", "I am unavailable"], - ["I am unavailable", "unavailable button"]], - expectedBraille: [["btn", "I am unavailable"], - ["I am unavailable", "btn"]] + accOrElmOrID: "unavailableButton", + expectedUtterance: [[{"string": "stateUnavailable"}, + {"string": "pushbutton"}, "I am unavailable"], ["I am unavailable", + {"string": "stateUnavailable"}, {"string": "pushbutton"}]], + expectedBraille: [[{"string": "pushbuttonAbbr"}, "I am unavailable"], + ["I am unavailable", {"string": "pushbuttonAbbr"}]] }, { // test expanded state utterance - accOrElmOrID: 'expandedButton', - expectedUtterance: [["expanded button", "I am expanded"], - ["I am expanded", "expanded button"]], - expectedBraille: [["btn", "I am expanded"], - ["I am expanded", "btn"]] + accOrElmOrID: "expandedButton", + expectedUtterance: [[{"string": "stateExpanded"}, + {"string": "pushbutton"}, "I am expanded"], ["I am expanded", + {"string": "stateExpanded"}, {"string": "pushbutton"}]], + expectedBraille: [[{"string": "pushbuttonAbbr"}, "I am expanded"], + ["I am expanded", {"string": "pushbuttonAbbr"}]] }, { // test collapsed state utterance - accOrElmOrID: 'collapsedButton', - expectedUtterance: [["collapsed button", "I am collapsed"], - ["I am collapsed", "collapsed button"]], - expectedBraille: [["btn", "I am collapsed"], - ["I am collapsed", "btn"]] + accOrElmOrID: "collapsedButton", + expectedUtterance: [[{"string": "stateCollapsed"}, + {"string": "pushbutton"}, "I am collapsed"], ["I am collapsed", + {"string": "stateCollapsed"}, {"string": "pushbutton"}]], + expectedBraille: [[{"string": "pushbuttonAbbr"}, "I am collapsed"], + ["I am collapsed", {"string": "pushbuttonAbbr"}]] }, { // test required state utterance - accOrElmOrID: 'requiredInput', - expectedUtterance: [["required entry", "I am required"], - ["I am required", "required entry"]], - expectedBraille: [["entry", "I am required"], - ["I am required", "entry"]] + accOrElmOrID: "requiredInput", + expectedUtterance: [[{"string": "stateRequired"}, {"string": "entry"}, + "I am required"], ["I am required", {"string": "stateRequired"}, + {"string": "entry"}]], + expectedBraille: [[{"string": "entryAbbr"}, "I am required"], + ["I am required", {"string": "entryAbbr"}]] }, { // test has popup state utterance - accOrElmOrID: 'hasPopupButton', - expectedUtterance: [["has pop up button menu", "I have a popup"], - ["I have a popup", "has pop up button menu"]], - expectedBraille: [["button menu", "I have a popup"], - ["I have a popup", "button menu"]] + accOrElmOrID: "hasPopupButton", + expectedUtterance: [[{"string": "stateHasPopup"}, + {"string": "buttonmenu"}, "I have a popup"], ["I have a popup", + {"string": "stateHasPopup"}, {"string": "buttonmenu"}]], + expectedBraille: [[{"string": "buttonmenuAbbr"}, "I have a popup"], + ["I have a popup", {"string": "buttonmenuAbbr"}]] }, { // Test selected tab - accOrElmOrID: 'tab1', - expectedUtterance: [['tab list', 'selected tab 1 of 2', 'Account'], - ['Account', 'selected tab 1 of 2', 'tab list']], - expectedBraille: [['tab 1 of 2', 'Account'], - ['Account', 'tab 1 of 2']] + accOrElmOrID: "tab1", + expectedUtterance: [[{"string": "pagetablist"}, + {"string": "stateSelected"}, {"string": "pagetab"}, + {"string": "objItemOfN", "args": [1, 2]}, "Account"], ["Account", + {"string": "stateSelected"}, {"string": "pagetab"}, + {"string": "objItemOfN", "args": [1, 2]}, {"string": "pagetablist"}] + ], + expectedBraille: [[{"string": "pagetabAbbr"}, + {"string": "objItemOfN", "args": [1, 2]}, "Account"], ["Account", + {"string": "pagetabAbbr"}, + {"string": "objItemOfN", "args": [1, 2]}]] }, { // Test unselected tab - accOrElmOrID: 'tab2', - expectedUtterance: [['tab list', 'tab 2 of 2', 'Advanced'], - ['Advanced', 'tab 2 of 2', 'tab list']], - expectedBraille: [['tab 2 of 2', 'Advanced'], - ['Advanced', 'tab 2 of 2']] - }, - - { + accOrElmOrID: "tab2", + expectedUtterance: [[{"string": "pagetablist"}, {"string": "pagetab"}, + {"string": "objItemOfN", "args": [2, 2]}, "Advanced"], ["Advanced", + {"string": "pagetab"}, {"string": "objItemOfN", "args": [2, 2]}, + {"string": "pagetablist"}]], + expectedBraille: [[{"string": "pagetabAbbr"}, + {"string": "objItemOfN", "args": [2, 2]}, "Advanced"], ["Advanced", + {"string": "pagetabAbbr"}, + {"string": "objItemOfN", "args": [2, 2]}]] + }, { // Landing on this label should mimic landing on the checkbox. accOrElmOrID: "label1", - expectedUtterance: [['not checked check button', 'Orange'], - ['Orange', 'not checked check button']], - expectedBraille: [['( )', 'Orange'], - ['Orange', '( )']] - }, - { + expectedUtterance: [[{"string": "stateNotChecked"}, + {"string": "checkbutton"}, "Orange"], ["Orange", + {"string": "stateNotChecked"}, {"string": "checkbutton"}]], + expectedBraille: [[{"string": "stateUncheckedAbbr"}, "Orange"], + ["Orange", {"string": "stateUncheckedAbbr"}]] + }, { // Here we get a top-level view of the form. accOrElmOrID: "form1", - expectedUtterance: [['label', 'not checked check button', 'Orange', 'Orange', - 'not checked check button', 'Blue', 'label', 'Blue'], - ['Orange', 'not checked check button', 'Orange', 'label', - 'Blue', 'not checked check button', 'Blue', 'label']], - expectedBraille: [['label', '( )', 'Orange', 'Orange', - '( )', 'Blue', 'label', 'Blue'], - ['Orange', '( )', 'Orange', 'label', - 'Blue', '( )', 'Blue', 'label']] - }, - { + expectedUtterance: [[{"string": "label"}, + {"string": "stateNotChecked"}, {"string": "checkbutton"}, "Orange", + "Orange", {"string": "stateNotChecked"}, {"string": "checkbutton"}, + "Blue", {"string": "label"}, "Blue"], ["Orange", + {"string": "stateNotChecked"}, {"string": "checkbutton"}, "Orange", + {"string": "label"}, "Blue", {"string": "stateNotChecked"}, + {"string": "checkbutton"}, "Blue", {"string": "label"}]], + expectedBraille: [[{"string": "labelAbbr"}, + {"string": "stateUncheckedAbbr"}, "Orange", "Orange", + {"string": "stateUncheckedAbbr"}, "Blue", {"string": "labelAbbr"}, + "Blue"], ["Orange", {"string": "stateUncheckedAbbr"}, "Orange", + {"string": "labelAbbr"}, "Blue", {"string": "stateUncheckedAbbr"}, + "Blue", {"string": "labelAbbr"}]] + }, { // This is a non-nesting label. accOrElmOrID: "label2", - expectedUtterance: [['label', 'Blue'], ['Blue', 'label']], - expectedBraille: [['label', 'Blue'], ['Blue', 'label']] - }, - { + expectedUtterance: [[{"string": "label"}, "Blue"], + ["Blue", {"string": "label"}]], + expectedBraille: [[{"string": "labelAbbr"}, "Blue"], + ["Blue", {"string": "labelAbbr"}]] + }, { // This is a distinct control. accOrElmOrID: "input2", - expectedUtterance: [['not checked check button', 'Blue'], - ['Blue', 'not checked check button']], - expectedBraille: [['( )', 'Blue'], - ['Blue', '( )']] - }, - { + expectedUtterance: [[{"string": "stateNotChecked"}, + {"string": "checkbutton"}, "Blue"], ["Blue", + {"string": "stateNotChecked"}, {"string": "checkbutton"}]], + expectedBraille: [[{"string": "stateUncheckedAbbr"}, "Blue"], ["Blue", + {"string": "stateUncheckedAbbr"}]] + }, { // This is a nested control. accOrElmOrID: "input1", - expectedUtterance: [['not checked check button', 'Orange'], - ['Orange', 'not checked check button']], - expectedBraille: [['( )', 'Orange'], - ['Orange', '( )']] - }, - { + expectedUtterance: [[{"string": "stateNotChecked"}, + {"string": "checkbutton"}, "Orange"], ["Orange", + {"string": "stateNotChecked"}, {"string": "checkbutton"}]], + expectedBraille: [[{"string": "stateUncheckedAbbr"}, "Orange"], + ["Orange", {"string": "stateUncheckedAbbr"}]] + }, { // Landing on this label should mimic landing on the entry. accOrElmOrID: "label3", - expectedUtterance: [['entry', 'Joe', 'First name:'], - ['First name:', 'Joe', 'entry']], - expectedBraille: [['entry', 'Joe', 'First name:'], - ['First name:', 'Joe', 'entry']] - }, - { + expectedUtterance: [[{"string": "entry"}, "Joe", "First name:"], + ["First name:", "Joe", {"string": "entry"}]], + expectedBraille: [[{"string": "entryAbbr"}, "Joe", "First name:"], + ["First name:", "Joe", {"string": "entryAbbr"}]] + }, { // This is a nested control with a value. accOrElmOrID: "input3", - expectedUtterance: [['entry', 'Joe', 'First name:'], - ['First name:', 'Joe', 'entry']], - expectedBraille: [['entry', 'Joe', 'First name:'], - ['First name:', 'Joe', 'entry']] - }, - { + expectedUtterance: [[{"string": "entry"}, "Joe", "First name:"], + ["First name:", "Joe", {"string": "entry"}]], + expectedBraille: [[{"string": "entryAbbr"}, "Joe", "First name:"], + ["First name:", "Joe", {"string": "entryAbbr"}]] + }, { // This is a nested control with a value. accOrElmOrID: "input4", - expectedUtterance: [['slider', '3', 'Points:'], - ['Points:', '3', 'slider']], - expectedBraille: [['slider', '3', 'Points:'], - ['Points:', '3', 'slider']] - },{ + expectedUtterance: [[{"string": "slider"}, "3", "Points:"], + ["Points:", "3", {"string": "slider"}]], + expectedBraille: [[{"string": "sliderAbbr"}, "3", "Points:"], + ["Points:", "3", {"string": "sliderAbbr"}]] + }, { accOrElmOrID: "password", - expectedUtterance: [["password text", "Secret Password"], - ["Secret Password", "password text"]], - expectedBraille: [["passwdtxt", "Secret Password"], - ["Secret Password", "passwdtxt"]] - },{ + expectedUtterance: [[{"string": "passwordtext"}, "Secret Password"], + ["Secret Password", {"string": "passwordtext"}]], + expectedBraille: [[{"string": "passwordtextAbbr"}, "Secret Password"], + ["Secret Password", {"string": "passwordtextAbbr"}]] + }, { accOrElmOrID: "input5", - expectedUtterance: [["checked check button", "Boring label"], - ["Boring label", "checked check button"]], - expectedBraille: [["(x)", "Boring label"], - ["Boring label", "(x)"]] - },{ + expectedUtterance: [[{"string": "stateChecked"}, + {"string": "checkbutton"}, "Boring label"], ["Boring label", + {"string": "stateChecked"}, {"string": "checkbutton"}]], + expectedBraille: [[{"string": "stateCheckedAbbr"}, "Boring label"], + ["Boring label", {"string": "stateCheckedAbbr"}]] + }, { accOrElmOrID: "radio_unselected", - expectedUtterance: [["not checked radio button", "any old radio button"], - ["any old radio button", "not checked radio button"]], - expectedBraille: [["( )", "any old radio button"], - ["any old radio button", "( )"]] - },{ + expectedUtterance: [[{"string": "stateNotChecked"}, + {"string": "radiobutton"}, "any old radio button"], + ["any old radio button", {"string": "stateNotChecked"}, + {"string": "radiobutton"}] + ], + expectedBraille: [ + [{"string": "stateUncheckedAbbr"}, "any old radio button"], + ["any old radio button", {"string": "stateUncheckedAbbr"}]] + }, { accOrElmOrID: "radio_selected", - expectedUtterance: [["checked radio button", "a unique radio button"], - ["a unique radio button", "checked radio button"]], - expectedBraille: [["(x)", "a unique radio button"], - ["a unique radio button", "(x)"]] - },{ + expectedUtterance: [[{"string": "stateChecked"}, + {"string": "radiobutton"}, "a unique radio button"], + ["a unique radio button", {"string": "stateChecked"}, + {"string": "radiobutton"}]], + expectedBraille: [ + [{"string": "stateCheckedAbbr"}, "a unique radio button"], + ["a unique radio button", {"string": "stateCheckedAbbr"}]] + }, { accOrElmOrID: "togglebutton_notpressed", - expectedUtterance: [["toggle button", "I ain't pressed"], - ["I ain't pressed", "toggle button"]], - expectedBraille: [["( )", "I ain't pressed"], - ["I ain't pressed", "( )"]] - },{ + expectedUtterance: [[{"string": "togglebutton"}, "I am not pressed"], + ["I am not pressed", {"string": "togglebutton"}]], + expectedBraille: [ + [{"string": "stateUnpressedAbbr"}, "I am not pressed"], + ["I am not pressed", {"string": "stateUnpressedAbbr"}]] + }, { accOrElmOrID: "togglebutton_pressed", - expectedUtterance: [["pressed toggle button", "I am pressed!"], - ["I am pressed!", "pressed toggle button"]], - expectedBraille: [["(x)", "I am pressed!"], - ["I am pressed!", "(x)"]] + expectedUtterance: [[{"string": "statePressed"}, + {"string": "togglebutton"}, "I am pressed!"], ["I am pressed!", + {"string": "statePressed"}, {"string": "togglebutton"}]], + expectedBraille: [[{"string": "statePressedAbbr"}, "I am pressed!"], + ["I am pressed!", {"string": "statePressedAbbr"}]] }, { accOrElmOrID: "listbox-option", - expectedUtterance: [["list box", "option", "Search suggestion"], - ["Search suggestion", "option", "list box"]], - expectedBraille: [["option", "Search suggestion"], - ["Search suggestion", "option"]] + expectedUtterance: [[{"string": "listbox"}, + {"string": "listboxoption"}, "Search suggestion"], + ["Search suggestion", {"string": "listboxoption"}, + {"string": "listbox"}] + ], + expectedBraille: [ + [{"string": "listboxoptionAbbr"}, "Search suggestion"], + ["Search suggestion", {"string": "listboxoptionAbbr"}]] }]; // Test all possible utterance order preference values. @@ -471,7 +503,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 -
I ain't pressed
+
I am not pressed
I am pressed!