8384940: Open source accessibility tests

Reviewed-by: prr, kizune
This commit is contained in:
lawrence.andrews 2026-05-21 17:31:30 +00:00 committed by Phil Race
parent 05a198af2f
commit a73097f9fb
6 changed files with 1246 additions and 0 deletions

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @key headful
* @summary Regression Test: javax.accessibility, Button
* @library ../../swing/regtesthelpers/accessibility/
* @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester
* @run main ButtonTest
*/
import java.awt.AWTException;
import java.awt.Button;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Robot;
import java.lang.reflect.InvocationTargetException;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleStateSet;
public class ButtonTest {
static Button button;
final String accName = "Button Test";
final String accDesc = "Regression Test: javax.accessibility, Button";
final AccessibleRole role = AccessibleRole.PUSH_BUTTON;
static Frame frame;
public void createGUI() {
frame = new Frame("ButtonTest");
button = new Button("This is a Button!");
AccessibleContext ac = button.getAccessibleContext();
ac.setAccessibleName(accName);
ac.setAccessibleDescription(accDesc);
frame.add(button);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args)
throws InterruptedException, InvocationTargetException, AWTException {
ButtonTest buttonTest = new ButtonTest();
EventQueue.invokeAndWait(buttonTest::createGUI);
Robot rbt = new Robot();
rbt.waitForIdle();
rbt.delay(5000);
try {
EventQueue.invokeAndWait(buttonTest::test);
} finally {
buttonTest.dispose();
}
}
private void dispose()
throws InterruptedException, InvocationTargetException {
EventQueue.invokeAndWait(() -> {
if (frame != null) {
frame.dispose();
}
});
}
public Component getComponent() {
return button;
}
public void test() {
Button b = (Button) getComponent();
AccessibleContext ac = b.getAccessibleContext();
AccessibleStateSet aset = ac.getAccessibleStateSet();
if (aset == null) {
throw new RuntimeException("getAccessibleStateSet should not return null");
}
AccessibleStateSetTester astr =
new AccessibleStateSetTester(b, aset);
astr.testAll();
AccessibleTestUtils.verifyButtonAccessibility(
b,
accName,
accDesc
);
}
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @key headful
* @summary Regression Test: javax.accessibility, Choice
* @library ../../swing/regtesthelpers/accessibility/
* @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester
* @run main ChoiceTest
*/
import java.awt.AWTException;
import java.awt.Choice;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Robot;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleStateSet;
public class ChoiceTest {
static Choice choice;
final String accName = "Choice Test";
final String accDesc = "Regression Test: javax.accessibility, Choice";
final AccessibleRole role = AccessibleRole.COMBO_BOX;
static Frame frame;
public void createGUI() {
frame = new Frame("Choice Test");
choice = new Choice();
choice.add("One");
choice.add("Two");
choice.add("Three");
AccessibleContext ac = choice.getAccessibleContext();
ac.setAccessibleName(accName);
ac.setAccessibleDescription(accDesc);
frame.add(choice);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args)
throws InterruptedException, InvocationTargetException, AWTException {
ChoiceTest choiceTest = new ChoiceTest();
EventQueue.invokeAndWait(choiceTest::createGUI);
Robot rbt = new Robot();
rbt.waitForIdle();
rbt.delay(5000);
try {
EventQueue.invokeAndWait(choiceTest::test);
} finally {
choiceTest.dispose();
}
}
private void dispose()
throws InterruptedException, InvocationTargetException {
EventQueue.invokeAndWait(() -> {
if (frame != null) {
frame.dispose();
}
});
}
public Component getComponent() {
return choice;
}
public void test() {
Choice c = (Choice) getComponent();
// If you want to keep using AccessibleStateSetTester explicitly:
AccessibleContext ac = c.getAccessibleContext();
AccessibleStateSet aset = ac.getAccessibleStateSet();
if (aset == null) {
throw new RuntimeException(
"getAccessibleStateSet should not return a null value");
}
AccessibleStateSetTester astr =
new AccessibleStateSetTester(c, aset);
astr.testAll();
// All remaining checks (name, desc, role, locale, AccessibleAction,
// AccessibleComponent, selection/text/value) are in one place:
AccessibleTestUtils.verifyChoiceAccessibility(
c,
accName,
accDesc
);
}
}

View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @key headful
* @summary Scrollbar Accessibility test.
* @library ../../swing/regtesthelpers/accessibility/
* @build AccessibleTestUtils AccessibleComponentTester AccessibleStateSetTester
* @run main ScrollbarTest
*/
import java.awt.AWTException;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Robot;
import java.awt.Scrollbar;
import java.lang.reflect.InvocationTargetException;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
public final class ScrollbarTest {
private static Scrollbar scrollbar;
private static Frame frame;
private static final String ACCESSIBLE_NAME = "Scrollbar Test";
private static final String ACCESSIBLE_DESCRIPTION =
"Regression Test: javax.accessibility, Scrollbar";
public static void main(String[] args)
throws InterruptedException, InvocationTargetException, AWTException {
ScrollbarTest test = new ScrollbarTest();
EventQueue.invokeAndWait(test::createGui);
Robot robot = new Robot();
robot.waitForIdle();
robot.delay(5000);
try {
EventQueue.invokeAndWait(test::testAccessibility);
} finally {
test.dispose();
}
}
private void createGui() {
frame = new Frame("ScrollbarTest");
scrollbar = new Scrollbar(Scrollbar.VERTICAL, 0, 60, 0, 300);
AccessibleContext context = scrollbar.getAccessibleContext();
context.setAccessibleName(ACCESSIBLE_NAME);
context.setAccessibleDescription(ACCESSIBLE_DESCRIPTION);
frame.add(scrollbar);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void dispose() throws InterruptedException, InvocationTargetException {
EventQueue.invokeAndWait(() -> {
if (frame != null) {
frame.dispose();
}
});
}
private Scrollbar getComponent() {
return scrollbar;
}
private void testAccessibility() {
Scrollbar component = getComponent();
AccessibleTestUtils.verifyScrollbarAccessibility(
component,
ACCESSIBLE_NAME,
ACCESSIBLE_DESCRIPTION
);
AccessibleStateSet stateSet = component.getAccessibleContext().getAccessibleStateSet();
if (stateSet == null) {
throw new RuntimeException("getAccessibleStateSet returned null");
}
new ScrollAccessibleStateSetTester(component, stateSet).testAll();
}
private static final class ScrollAccessibleStateSetTester extends AccessibleStateSetTester {
private final Scrollbar scrollbar;
private final AccessibleStateSet stateSet;
private ScrollAccessibleStateSetTester(Scrollbar scrollbar, AccessibleStateSet stateSet) {
super(scrollbar, stateSet);
this.scrollbar = scrollbar;
this.stateSet = stateSet;
}
@Override
public void testHorizontal() {
if (scrollbar.getOrientation() == Scrollbar.HORIZONTAL) {
if (!stateSet.contains(AccessibleState.HORIZONTAL)) {
throw new RuntimeException(
"Scrollbar is horizontal but AccessibleStateSet does not contain HORIZONTAL"
);
}
if (stateSet.contains(AccessibleState.VERTICAL)) {
throw new RuntimeException(
"Scrollbar is horizontal but AccessibleStateSet contains both HORIZONTAL and VERTICAL"
);
}
}
}
@Override
public void testVertical() {
if (scrollbar.getOrientation() == Scrollbar.VERTICAL) {
if (!stateSet.contains(AccessibleState.VERTICAL)) {
throw new RuntimeException(
"Scrollbar is vertical but AccessibleStateSet does not contain VERTICAL"
);
}
if (stateSet.contains(AccessibleState.HORIZONTAL)) {
throw new RuntimeException(
"Scrollbar is vertical but AccessibleStateSet contains both VERTICAL and HORIZONTAL"
);
}
}
}
}
}

View File

@ -0,0 +1,198 @@
/*
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Objects;
import java.util.function.Supplier;
import javax.accessibility.AccessibleComponent;
public final class AccessibleComponentTester {
private final AccessibleComponent accessibleComponent;
private final Component component;
public AccessibleComponentTester(Component component, AccessibleComponent accessibleComponent) {
this.component = Objects.requireNonNull(component, "component must not be null");
this.accessibleComponent = Objects.requireNonNull(accessibleComponent, "accessibleComponent must not be null");
}
public void test() {
testGetBackground();
testGetBounds();
testGetCursor();
testGetFont();
testGetForeground();
testGetLocation();
testGetLocationOnScreen();
testGetSize();
testIsEnabled();
testIsFocusTraversable();
testIsShowing();
testIsVisible();
}
public void testGetBackground() {
assertEqual(
"getBackground",
component.getBackground(),
accessibleComponent.getBackground()
);
}
public void testGetBounds() {
assertEqual(
"getBounds",
component.getBounds(),
accessibleComponent.getBounds()
);
}
public void testGetCursor() {
assertEqual(
"getCursor",
component.getCursor(),
accessibleComponent.getCursor()
);
}
public void testGetFont() {
assertEqual(
"getFont",
component.getFont(),
accessibleComponent.getFont()
);
}
public void testGetForeground() {
assertEqual(
"getForeground",
component.getForeground(),
accessibleComponent.getForeground()
);
}
public void testGetLocation() {
assertEqualWithStateHandling(
"getLocation",
component::getLocation,
accessibleComponent::getLocation
);
}
public void testGetLocationOnScreen() {
assertEqualWithStateHandling(
"getLocationOnScreen",
component::getLocationOnScreen,
accessibleComponent::getLocationOnScreen
);
}
public void testGetSize() {
assertEqual(
"getSize",
component.getSize(),
accessibleComponent.getSize()
);
}
public void testIsEnabled() {
assertBooleanEqual(
"isEnabled",
component.isEnabled(),
accessibleComponent.isEnabled()
);
}
public void testIsFocusTraversable() {
assertBooleanEqual(
"isFocusTraversable",
component.isFocusTraversable(),
accessibleComponent.isFocusTraversable()
);
}
public void testIsShowing() {
assertBooleanEqual(
"isShowing",
component.isShowing(),
accessibleComponent.isShowing()
);
}
public void testIsVisible() {
assertBooleanEqual(
"isVisible",
component.isVisible(),
accessibleComponent.isVisible()
);
}
private void assertEqual(String methodName, Object componentValue, Object accessibleValue) {
if (!Objects.equals(componentValue, accessibleValue)) {
throw new RuntimeException(buildMismatchMessage(methodName, componentValue, accessibleValue));
}
}
private void assertBooleanEqual(String methodName, boolean componentValue, boolean accessibleValue) {
if (componentValue != accessibleValue) {
throw new RuntimeException(
String.format(
"Mismatch in %s: Component returned [%s], AccessibleComponent returned [%s]",
methodName, componentValue, accessibleValue
)
);
}
}
private <T> void assertEqualWithStateHandling(
String methodName,
Supplier<T> componentSupplier,
Supplier<T> accessibleSupplier
) {
try {
T componentValue = componentSupplier.get();
T accessibleValue = accessibleSupplier.get();
assertEqual(methodName, componentValue, accessibleValue);
} catch (java.awt.IllegalComponentStateException ex) {
throw new RuntimeException(
"Component was not in a valid state when " + methodName + " was called. " +
"This is not necessarily an accessibility issue.",
ex
);
}
}
private String buildMismatchMessage(String methodName, Object componentValue, Object accessibleValue) {
return String.format(
"Mismatch in %s: Component returned [%s], AccessibleComponent returned [%s]",
methodName, componentValue, accessibleValue
);
}
}

View File

@ -0,0 +1,318 @@
/*
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.Component;
import java.util.Objects;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleSelection;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import javax.swing.JComponent;
/**
* Validates an {@link AccessibleStateSet} against the state of a component.
*
* <p>This class provides generic validation for common accessibility states.
* Subclasses can extend it to add component-specific checks.</p>
*
* <p>This works for both Swing and AWT components that implement
* {@link Accessible}.</p>
*/
public class AccessibleStateSetTester {
private final AccessibleStateSet stateSet;
private final Component component;
public AccessibleStateSetTester(Component component, AccessibleStateSet stateSet) {
this.component = Objects.requireNonNull(component, "component must not be null");
this.stateSet = Objects.requireNonNull(stateSet, "stateSet must not be null");
}
/**
* Runs all generic state validations plus component-specific hooks.
*/
public void testAll() {
testActive();
testArmed();
testBusy();
testChecked();
testCollapsed();
testEditable();
testEnabled();
testExpandable();
testExpanded();
testFocusable();
testFocused();
testHorizontal();
testIconified();
testModal();
testMultiLine();
testMultiSelectable();
testOpaque();
testPressed();
testResizable();
testSelectable();
testSelected();
testShowing();
testSingleLine();
testTransient();
testVertical();
testVisible();
}
public void testEnabled() {
assertStateMatches(
AccessibleState.ENABLED,
component.isEnabled(),
"component is enabled",
"component is not enabled"
);
}
public void testFocusable() {
assertStateMatches(
AccessibleState.FOCUSABLE,
component.isFocusable(),
"component is focusable",
"component is not focusable"
);
}
public void testFocused() {
boolean focused = isFocused();
if (stateSet.contains(AccessibleState.FOCUSED)) {
if (!stateSet.contains(AccessibleState.FOCUSABLE)) {
throw new RuntimeException(
"AccessibleStateSet contains FOCUSED but not FOCUSABLE"
);
}
if (!focused) {
throw new RuntimeException(
"AccessibleStateSet contains FOCUSED but the component does not have focus"
);
}
} else if (focused) {
throw new RuntimeException(
"AccessibleStateSet does not contain FOCUSED but the component has focus"
);
}
}
public void testShowing() {
assertStateMatches(
AccessibleState.SHOWING,
component.isShowing(),
"component is showing",
"component is not showing"
);
}
public void testVisible() {
assertStateMatches(
AccessibleState.VISIBLE,
component.isVisible(),
"component is visible",
"component is not visible"
);
}
public void testSelectable() {
AccessibleState selectionStatus = getSelectionStatus();
if (stateSet.contains(AccessibleState.SELECTABLE)) {
if (selectionStatus != AccessibleState.SELECTABLE
&& selectionStatus != AccessibleState.SELECTED) {
throw new RuntimeException(
"AccessibleStateSet contains SELECTABLE but the component is not selectable"
);
}
} else if (selectionStatus == AccessibleState.SELECTABLE) {
throw new RuntimeException(
"AccessibleStateSet does not contain SELECTABLE but the component is selectable"
);
}
}
public void testSelected() {
AccessibleState selectionStatus = getSelectionStatus();
if (stateSet.contains(AccessibleState.SELECTED)) {
if (!stateSet.contains(AccessibleState.SELECTABLE)) {
throw new RuntimeException(
"AccessibleStateSet contains SELECTED but not SELECTABLE"
);
}
if (selectionStatus != AccessibleState.SELECTED) {
throw new RuntimeException(
"AccessibleStateSet contains SELECTED but the component is not selected"
);
}
} else if (selectionStatus == AccessibleState.SELECTED) {
throw new RuntimeException(
"AccessibleStateSet does not contain SELECTED but the component is selected"
);
}
}
public void testOpaque() {
if (!(component instanceof JComponent jComponent)) {
return;
}
assertStateMatches(
AccessibleState.OPAQUE,
jComponent.isOpaque(),
"component is opaque",
"component is not opaque"
);
}
/**
* Returns true if the component currently has focus.
*/
public boolean isFocused() {
return component.hasFocus();
}
/**
* Determines whether the component is selectable or selected.
*
* @return {@link AccessibleState#SELECTED} if selected,
* {@link AccessibleState#SELECTABLE} if selectable but not selected,
* or {@code null} if neither applies
*/
public AccessibleState getSelectionStatus() {
if (!(component instanceof Accessible accessible)) {
return null;
}
AccessibleContext context = accessible.getAccessibleContext();
if (context == null) {
return null;
}
Accessible parent = context.getAccessibleParent();
if (parent == null) {
return null;
}
AccessibleContext parentContext = parent.getAccessibleContext();
if (parentContext == null) {
return null;
}
AccessibleSelection selection = parentContext.getAccessibleSelection();
if (selection == null) {
return null;
}
int index = context.getAccessibleIndexInParent();
if (index < 0) {
return AccessibleState.SELECTABLE;
}
return selection.isAccessibleChildSelected(index)
? AccessibleState.SELECTED
: AccessibleState.SELECTABLE;
}
private void assertStateMatches(
AccessibleState state,
boolean actualCondition,
String presentMessage,
String absentMessage) {
boolean presentInStateSet = stateSet.contains(state);
if (presentInStateSet && !actualCondition) {
throw new RuntimeException(
"AccessibleStateSet contains " + state + " but " + absentMessage
);
}
if (!presentInStateSet && actualCondition) {
throw new RuntimeException(
"AccessibleStateSet does not contain " + state + " but " + presentMessage
);
}
}
// Component-specific hooks (intentionally empty by default)
public void testActive() {
}
public void testArmed() {
}
public void testBusy() {
}
public void testChecked() {
}
public void testCollapsed() {
}
public void testEditable() {
}
public void testExpandable() {
}
public void testExpanded() {
}
public void testHorizontal() {
}
public void testIconified() {
}
public void testModal() {
}
public void testMultiLine() {
}
public void testMultiSelectable() {
}
public void testPressed() {
}
public void testResizable() {
}
public void testSingleLine() {
}
public void testTransient() {
}
public void testVertical() {
}
}

View File

@ -0,0 +1,334 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.Button;
import java.awt.Choice;
import java.awt.Component;
import java.awt.Scrollbar;
import java.util.Locale;
import java.util.Objects;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleComponent;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleSelection;
import javax.accessibility.AccessibleStateSet;
import javax.accessibility.AccessibleText;
import javax.accessibility.AccessibleValue;
public final class AccessibleTestUtils {
private AccessibleTestUtils() {
}
public static void verifyAccessibleContextCommon(
AccessibleContext context,
String expectedName,
String expectedDescription,
AccessibleRole expectedRole,
boolean expectAction,
boolean expectSelection,
boolean expectText,
boolean expectValue) {
Objects.requireNonNull(context, "AccessibleContext must not be null");
assertExpectedString(
"getAccessibleName",
expectedName,
context.getAccessibleName()
);
assertExpectedString(
"getAccessibleDescription",
expectedDescription,
context.getAccessibleDescription()
);
if (expectedRole != null) {
AccessibleRole actualRole = context.getAccessibleRole();
if (actualRole == null) {
throw new RuntimeException("getAccessibleRole returned null");
}
if (!expectedRole.equals(actualRole)) {
throw new RuntimeException(String.format(
"getAccessibleRole returned [%s]; expected [%s]",
actualRole, expectedRole
));
}
}
AccessibleStateSet stateSet = context.getAccessibleStateSet();
if (stateSet == null) {
throw new RuntimeException("getAccessibleStateSet returned null");
}
assertPresence("getAccessibleAction", expectAction, context.getAccessibleAction());
assertPresence("getAccessibleSelection", expectSelection, context.getAccessibleSelection());
assertPresence("getAccessibleText", expectText, context.getAccessibleText());
assertPresence("getAccessibleValue", expectValue, context.getAccessibleValue());
}
public static void verifyAWTComponentAccessibility(
Component component,
String expectedName,
String expectedDescription,
AccessibleRole expectedRole,
boolean expectAction,
boolean expectSelection,
boolean expectText,
boolean expectValue) {
Objects.requireNonNull(component, "Component under test must not be null");
AccessibleContext context = component.getAccessibleContext();
verifyAccessibleContextCommon(
context,
expectedName,
expectedDescription,
expectedRole,
expectAction,
expectSelection,
expectText,
expectValue
);
assertLocaleMatches(component, context);
AccessibleComponent accessibleComponent = context.getAccessibleComponent();
if (accessibleComponent == null) {
throw new RuntimeException("getAccessibleComponent returned null");
}
new AccessibleComponentTester(component, accessibleComponent).test();
}
public static void verifyChoiceAccessibility(
Choice choice,
String expectedName,
String expectedDescription) {
Objects.requireNonNull(choice, "Choice must not be null");
verifyAWTComponentAccessibility(
choice,
expectedName,
expectedDescription,
AccessibleRole.COMBO_BOX,
true,
false,
false,
false
);
AccessibleContext context = choice.getAccessibleContext();
AccessibleAction action = context.getAccessibleAction();
if (action == null) {
throw new RuntimeException("getAccessibleAction should not return null for Choice");
}
AccessibleValue value = context.getAccessibleValue();
if (value != null) {
throw new RuntimeException("getAccessibleValue should return null for Choice");
}
}
public static void verifyScrollbarAccessibility(
Scrollbar scrollbar,
String expectedName,
String expectedDescription) {
Objects.requireNonNull(scrollbar, "Scrollbar must not be null");
verifyAWTComponentAccessibility(
scrollbar,
expectedName,
expectedDescription,
AccessibleRole.SCROLL_BAR,
false,
false,
false,
true
);
AccessibleValue value = scrollbar.getAccessibleContext().getAccessibleValue();
if (value == null) {
throw new RuntimeException("getAccessibleValue should not return null for Scrollbar");
}
assertIntValueEquals(
"getCurrentAccessibleValue",
scrollbar.getValue(),
value.getCurrentAccessibleValue()
);
assertIntValueEquals(
"getMinimumAccessibleValue",
scrollbar.getMinimum(),
value.getMinimumAccessibleValue()
);
assertIntValueEquals(
"getMaximumAccessibleValue",
scrollbar.getMaximum(),
value.getMaximumAccessibleValue()
);
if (!value.setCurrentAccessibleValue(Integer.valueOf(5))) {
throw new RuntimeException("setCurrentAccessibleValue(5) returned false for Scrollbar");
}
assertIntValueEquals(
"getCurrentAccessibleValue after setCurrentAccessibleValue(5)",
5,
value.getCurrentAccessibleValue()
);
if (scrollbar.getValue() != 5) {
throw new RuntimeException(
"setCurrentAccessibleValue(5) did not update Scrollbar.getValue(); actual value: "
+ scrollbar.getValue()
);
}
}
public static void verifyButtonAccessibility(
Button button,
String expectedName,
String expectedDescription) {
Objects.requireNonNull(button, "Button must not be null");
verifyAWTComponentAccessibility(
button,
expectedName,
expectedDescription,
AccessibleRole.PUSH_BUTTON,
true,
false,
false,
true
);
AccessibleContext context = button.getAccessibleContext();
AccessibleAction action = context.getAccessibleAction();
if (action == null) {
throw new RuntimeException("getAccessibleAction should not return null for Button");
}
int actionCount = action.getAccessibleActionCount();
if (actionCount != 1) {
throw new RuntimeException(
"getAccessibleActionCount should return 1 for Button; got " + actionCount
);
}
String actionDescription = action.getAccessibleActionDescription(0);
if (!"click".equals(actionDescription)) {
throw new RuntimeException(
"getAccessibleActionDescription(0) should return \"click\" for Button; got ["
+ actionDescription + "]"
);
}
AccessibleValue value = context.getAccessibleValue();
if (value == null) {
throw new RuntimeException("getAccessibleValue should not return null for Button");
}
assertIntValueEquals("getCurrentAccessibleValue", 0, value.getCurrentAccessibleValue());
assertIntValueEquals("getMinimumAccessibleValue", 0, value.getMinimumAccessibleValue());
assertIntValueEquals("getMaximumAccessibleValue", 0, value.getMaximumAccessibleValue());
if (value.setCurrentAccessibleValue(Integer.valueOf(5))) {
throw new RuntimeException(
"setCurrentAccessibleValue(5) should return false for Button"
);
}
assertIntValueEquals(
"getCurrentAccessibleValue after setCurrentAccessibleValue(5)",
0,
value.getCurrentAccessibleValue()
);
}
private static void assertExpectedString(String methodName, String expected, String actual) {
if (expected == null) {
throw new RuntimeException("Excepted value is null. Provide " +
"excepted value");
}
if (actual == null) {
throw new RuntimeException(methodName + " returned null; expected" +
" [" + expected + "]");
}
if (!expected.equals(actual)) {
throw new RuntimeException(methodName + " returned [" + actual +
"]; expected [" + expected + "]");
}
}
private static void assertPresence(String methodName, boolean expectedPresent, Object value) {
if (expectedPresent && value == null) {
throw new RuntimeException(methodName + " returned null but was expected");
}
if (!expectedPresent && value != null) {
throw new RuntimeException(methodName + " returned non-null but " +
"was expected to be null");
}
}
private static void assertLocaleMatches(Component component, AccessibleContext context) {
Locale componentLocale = component.getLocale();
Locale accessibleLocale = context.getLocale();
if (componentLocale == null) {
throw new RuntimeException("Component.getLocale returned null");
}
if (accessibleLocale == null) {
throw new RuntimeException("AccessibleContext.getLocale returned null");
}
if (!componentLocale.equals(accessibleLocale)) {
throw new RuntimeException(String.format(
"AccessibleContext.getLocale returned [%s], but Component" +
".getLocale returned [%s]",
accessibleLocale, componentLocale
));
}
}
private static void assertIntValueEquals(String methodName, int expected, Number actual) {
if (actual == null) {
throw new RuntimeException(methodName + " returned null; expected [" + expected + "]");
}
if (actual.intValue() != expected) {
throw new RuntimeException(
methodName + " returned [" + actual + "]; expected [" + expected + "]"
);
}
}
}