mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 10:42:45 +00:00
8384940: Open source accessibility tests
Reviewed-by: prr, kizune
This commit is contained in:
parent
05a198af2f
commit
a73097f9fb
115
test/jdk/javax/accessibility/awt/ButtonTest.java
Normal file
115
test/jdk/javax/accessibility/awt/ButtonTest.java
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
123
test/jdk/javax/accessibility/awt/ChoiceTest.java
Normal file
123
test/jdk/javax/accessibility/awt/ChoiceTest.java
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
158
test/jdk/javax/accessibility/awt/ScrollbarTest.java
Normal file
158
test/jdk/javax/accessibility/awt/ScrollbarTest.java
Normal 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"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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() {
|
||||
}
|
||||
}
|
||||
@ -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 + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user