Bug 1473690 - add selectable ingegration tests. r=eeejay, jchen

MozReview-Commit-ID: 9ka7CjOJcew
This commit is contained in:
Yura Zenevich 2018-07-18 15:58:01 -04:00
parent f970fc3e21
commit bb4b5de6ed
6 changed files with 87 additions and 61 deletions

View File

@ -219,8 +219,9 @@ this.ContentControl.prototype = {
}
}
// Action invoked will be presented on checkable state change.
if (!Utils.getState(aAccessible).contains(States.CHECKABLE)) {
// Action invoked will be presented on checked/selected state change.
if (!Utils.getState(aAccessible).contains(States.CHECKABLE) &&
!Utils.getState(aAccessible).contains(States.SELECTABLE)) {
this._contentScope.get().sendAsyncMessage("AccessFu:Present",
Presentation.actionInvoked(aAccessible, "click"));
}

View File

@ -163,25 +163,13 @@ this.EventManager.prototype = {
}
case Events.STATE_CHANGE:
{
let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
let state = Utils.getState(event);
const event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
const state = Utils.getState(event);
if (state.contains(States.CHECKED)) {
if (aEvent.accessible.role === Roles.SWITCH) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? "on" : "off"));
} else {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? "check" : "uncheck"));
}
this.present(Presentation.checked(aEvent.accessible));
} else if (state.contains(States.SELECTED)) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? "select" : "unselect"));
this.present(Presentation.selected(aEvent.accessible,
event.isEnabled ? "select" : "unselect"));
}
break;
}

View File

@ -770,8 +770,12 @@ var UtteranceGenerator = { // jshint ignore:line
}
},
/**
* Add localized state information to output data.
* Note: We do not expose checked and selected states, we let TalkBack do it for us
* there. This is because we expose the checked information on the node info itself.
*/
_addState: function _addState(aOutput, aState, aRoleStr) {
if (aState.contains(States.UNAVAILABLE)) {
aOutput.push({string: "stateUnavailable"});
}
@ -780,22 +784,6 @@ var UtteranceGenerator = { // jshint ignore:line
aOutput.push({string: "stateReadonly"});
}
// 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.
if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === "browser") &&
aState.contains(States.CHECKABLE)) {
let checked = aState.contains(States.CHECKED);
let statetr;
if (aRoleStr === "switch") {
statetr = checked ? "stateOn" : "stateOff";
} else {
statetr = checked ? "stateChecked" : "stateNotChecked";
}
aOutput.push({string: statetr});
}
if (aState.contains(States.PRESSED)) {
aOutput.push({string: "statePressed"});
}
@ -817,10 +805,6 @@ var UtteranceGenerator = { // jshint ignore:line
if (aState.contains(States.HASPOPUP)) {
aOutput.push({string: "stateHasPopup"});
}
if (aState.contains(States.SELECTED)) {
aOutput.push({string: "stateSelected"});
}
},
_getListUtterance:

View File

@ -98,25 +98,38 @@ class AndroidPresentor {
}
/**
* An object's action has been invoked.
* @param {nsIAccessible} aObject the object that has been invoked.
* @param {string} aActionName the name of the action.
* An object's check action has been invoked.
* Note: Checkable objects use TalkBack's text derived from the event state, so we don't
* populate the text here.
* @param {nsIAccessible} aAccessible the object that has been invoked.
*/
actionInvoked(aObject, aActionName) {
let state = Utils.getState(aObject);
// Checkable objects use TalkBack's text derived from the event state,
// so we don't populate the text here.
let text = null;
if (!state.contains(States.CHECKABLE)) {
text = Utils.localize(UtteranceGenerator.genForAction(aObject,
aActionName));
}
checked(aAccessible) {
return [{
eventType: AndroidEvents.VIEW_CLICKED,
text,
checked: state.contains(States.CHECKED)
checked: Utils.getState(aAccessible).contains(States.CHECKED)
}];
}
/**
* An object's select action has been invoked.
* @param {nsIAccessible} aAccessible the object that has been invoked.
*/
selected(aAccessible, aActionName) {
return [{
eventType: AndroidEvents.VIEW_CLICKED,
selected: Utils.getState(aAccessible).contains(States.SELECTED)
}];
}
/**
* An object's action has been invoked.
* @param {nsIAccessible} aAccessible the object that has been invoked.
* @param {string} aActionName the name of the action.
*/
actionInvoked(aAccessible, aActionName) {
return [{
eventType: AndroidEvents.VIEW_CLICKED,
text: Utils.localize(UtteranceGenerator.genForAction(aAccessible, aActionName))
}];
}
@ -292,6 +305,7 @@ class AndroidPresentor {
checkable: state.contains(States.CHECKABLE),
checked: state.contains(States.CHECKED),
editable: state.contains(States.EDITABLE),
selected: state.contains(States.SELECTED)
};
if (EDIT_TEXT_ROLES.has(aContext.accessible.role)) {

View File

@ -197,14 +197,21 @@ class AccessibilityTest : BaseSessionTest() {
})
}
private fun waitUntilClick(checked: Boolean) {
private fun waitUntilClick(checked: Boolean? = null, selected: Boolean? = null) {
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1)
override fun onClicked(event: AccessibilityEvent) {
assertThat("Checked state matches", event.isChecked, equalTo(checked))
var nodeId = getSourceId(event)
var node = provider.createAccessibilityNodeInfo(nodeId)
assertThat("Checkbox node is checked", node.isChecked, equalTo(checked))
if (checked != null) {
assertThat("Event's checked state matches", event.isChecked, equalTo(checked))
assertThat("Checkbox node has correct checked state", node.isChecked, equalTo(checked))
}
if (selected != null) {
assertThat("Selectable node has correct selected state", node.isSelected, equalTo(selected))
}
}
})
}
@ -393,9 +400,37 @@ class AccessibilityTest : BaseSessionTest() {
})
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(true);
waitUntilClick(checked = true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(false);
waitUntilClick(checked = false)
}
@Test fun testSelectable() {
var nodeId = View.NO_ID
sessionRule.session.loadString(
"""<ul style="list-style-type: none;" role="listbox">
<li id="li" role="option" onclick="this.setAttribute('aria-selected',
this.getAttribute('aria-selected') == 'true' ? 'false' : 'true')">1</li>
</ul>""","text/html")
sessionRule.waitForPageStop()
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1)
override fun onAccessibilityFocused(event: AccessibilityEvent) {
nodeId = getSourceId(event)
var node = provider.createAccessibilityNodeInfo(nodeId)
assertThat("Selectable node is clickable", node.isClickable, equalTo(true))
assertThat("Selectable node is not selected", node.isSelected, equalTo(false))
assertThat("Selectable node has correct role", node.text.toString(), equalTo("1 option list box"))
}
})
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(selected = true)
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
waitUntilClick(selected = false)
}
}

View File

@ -379,6 +379,7 @@ public class SessionAccessibility {
node.setPassword(message.getBoolean("password"));
node.setFocusable(message.getBoolean("focusable"));
node.setFocused(message.getBoolean("focused"));
node.setSelected(message.getBoolean("selected"));
node.setClassName(message.getString("className", "android.view.View"));
@ -435,6 +436,9 @@ public class SessionAccessibility {
if (message.containsKey("checked")) {
node.setChecked(message.getBoolean("checked"));
}
if (message.containsKey("selected")) {
node.setSelected(message.getBoolean("selected"));
}
}
private void sendAccessibilityEvent(final GeckoBundle message) {