Bug 1633570 - Add setter for AXValue (incrementables only) r=morgan

This commit adds an AXValue setter to incremental accessibles, as well
as tests to validate that setter on both a range and number input.

Differential Revision: https://phabricator.services.mozilla.com/D106333
This commit is contained in:
Christian M. Macy 2021-03-16 16:17:53 +00:00
parent 2045f0c97e
commit a0adf7ccba
3 changed files with 92 additions and 20 deletions

View File

@ -69,6 +69,9 @@
*/
@interface mozIncrementableAccessible : mozAccessible
// override
- (void)moxSetValue:(id)value;
// override
- (void)moxPerformIncrement;

View File

@ -153,6 +153,10 @@ enum CheckboxValue {
@implementation mozIncrementableAccessible
- (void)moxSetValue:(id)value {
[self setValue:([value doubleValue])];
}
- (void)moxPerformIncrement {
[self changeValueBySteps:1];
}
@ -174,35 +178,52 @@ enum CheckboxValue {
}
/*
* Updates the accessible's current value by (factor * step).
* If incrementing factor should be positive, if decrementing
* factor should be negative.
* Updates the accessible's current value by factor and step.
*
* factor: A signed integer representing the number of times to
* apply step to the current value. A positive value will increment,
* while a negative one will decrement.
* step: An unsigned integer specified by the webauthor and indicating the
* amount by which to increment/decrement the current value.
*/
- (void)changeValueBySteps:(int)factor {
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
MOZ_ASSERT(!mGeckoAccessible.IsNull(), "mGeckoAccessible is null");
if (LocalAccessible* acc = mGeckoAccessible.AsAccessible()) {
double newValue = acc->CurValue() + (acc->Step() * factor);
[self setValue:(newValue)];
} else {
RemoteAccessible* proxy = mGeckoAccessible.AsProxy();
double newValue = proxy->CurValue() + (proxy->Step() * factor);
[self setValue:(newValue)];
}
}
/*
* Updates the accessible's current value to the specified value
*/
- (void)setValue:(double)value {
MOZ_ASSERT(!mGeckoAccessible.IsNull(), "mGeckoAccessible is null");
if (LocalAccessible* acc = mGeckoAccessible.AsAccessible()) {
double newVal = acc->CurValue() + (acc->Step() * factor);
double min = acc->MinValue();
double max = acc->MaxValue();
if ((IsNaN(min) || newVal >= min) && (IsNaN(max) || newVal <= max)) {
acc->SetCurValue(newVal);
}
} else if (RemoteAccessible* proxy = mGeckoAccessible.AsProxy()) {
double newVal = proxy->CurValue() + (proxy->Step() * factor);
double min = proxy->MinValue();
double max = proxy->MaxValue();
// Because min and max are not required attributes, we first check
// if the value is undefined. If this check fails,
// the value is defined, and we we verify our new value falls
// the value is defined, and we verify our new value falls
// within the bound (inclusive).
if ((IsNaN(min) || newVal >= min) && (IsNaN(max) || newVal <= max)) {
proxy->SetCurValue(newVal);
if ((IsNaN(min) || value >= min) && (IsNaN(max) || value <= max)) {
acc->SetCurValue(value);
}
} else {
RemoteAccessible* proxy = mGeckoAccessible.AsProxy();
double min = proxy->MinValue();
double max = proxy->MaxValue();
// As above, check if the value is within bounds.
if ((IsNaN(min) || value >= min) && (IsNaN(max) || value <= max)) {
proxy->SetCurValue(value);
}
}
NS_OBJC_END_TRY_IGNORE_BLOCK;
}
@end

View File

@ -12,6 +12,7 @@ loadScripts(
);
/**
* Verify that the value of a slider input can be incremented/decremented
* Test input[type=range]
*/
addAccessibleTask(
@ -50,10 +51,32 @@ addAccessibleTask(
);
/**
* Verify that the value of a slider input can be set directly
* Test input[type=range]
*/
addAccessibleTask(
`<input type="number" value="11" id="number">`,
`<input id="range" type="range" min="1" max="100" value="1" step="10">`,
async (browser, accDoc) => {
let nextValue = "21";
let range = getNativeInterface(accDoc, "range");
is(range.getAttributeValue("AXRole"), "AXSlider", "Correct AXSlider role");
is(range.getAttributeValue("AXValue"), "1", "Correct initial value");
ok(range.isAttributeSettable("AXValue"), "Range AXValue is settable.");
let evt = waitForMacEvent("AXValueChanged");
range.setAttributeValue("AXValue", nextValue);
await evt;
is(range.getAttributeValue("AXValue"), nextValue, "Correct updated value");
}
);
/**
* Verify that the value of a number input can be incremented/decremented
* Test input[type=number]
*/
addAccessibleTask(
`<input type="number" value="11" id="number" step=".05">`,
async (browser, accDoc) => {
let number = getNativeInterface(accDoc, "number");
is(
@ -70,7 +93,7 @@ addAccessibleTask(
let evt = waitForMacEvent("AXValueChanged");
number.performAction("AXIncrement");
await evt;
is(number.getAttributeValue("AXValue"), "12", "Correct increment value");
is(number.getAttributeValue("AXValue"), "11.05", "Correct increment value");
evt = waitForMacEvent("AXValueChanged");
number.performAction("AXDecrement");
@ -90,3 +113,28 @@ addAccessibleTask(
);
}
);
/**
* Verify that the value of a number input can be set directly
* Test input[type=number]
*/
addAccessibleTask(
`<input type="number" value="11" id="number">`,
async (browser, accDoc) => {
let nextValue = "21";
let number = getNativeInterface(accDoc, "number");
is(
number.getAttributeValue("AXRole"),
"AXIncrementor",
"Correct AXIncrementor role"
);
is(number.getAttributeValue("AXValue"), "11", "Correct initial value");
ok(number.isAttributeSettable("AXValue"), "Range AXValue is settable.");
let evt = waitForMacEvent("AXValueChanged");
number.setAttributeValue("AXValue", nextValue);
await evt;
is(number.getAttributeValue("AXValue"), nextValue, "Correct updated value");
}
);