xy.ui.testing.Tester Maven / Gradle / Ivy
package xy.ui.testing;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeModel;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
import xy.ui.testing.action.TestAction;
import xy.ui.testing.editor.TesterEditor;
import xy.ui.testing.util.Listener;
import xy.ui.testing.util.TestFailure;
import xy.ui.testing.util.TestingUtils;
public class Tester {
public static final Color HIGHLIGHT_FOREGROUND = TestingUtils.stringToColor(
System.getProperty(Tester.class.getPackage().getName() + ".highlightForeground", "235,48,33"));
public static final Color HIGHLIGHT_BACKGROUND = TestingUtils.stringToColor(
System.getProperty(Tester.class.getPackage().getName() + ".highlightBackground", "245,216,214"));
protected final Object CURRENT_COMPONENT_MUTEX = new Object() {
@Override
public String toString() {
return Tester.class.getName() + ".CURRENT_COMPONENT_MUTEX";
}
};
protected List testActions = new ArrayList();
protected int minimumSecondsToWaitBetwneenActions = 2;
protected int maximumSecondsToWaitBetwneenActions = 15;
protected Component currentComponent;
protected Color currentComponentBackground;
protected Color currentComponentForeground;
protected MouseListener[] currentComponentMouseListeners;
protected Border currentComponentBorder;
public Tester() {
}
public int getMinimumSecondsToWaitBetwneenActions() {
return minimumSecondsToWaitBetwneenActions;
}
public void setMinimumSecondsToWaitBetwneenActions(int minimumSecondsToWaitBetwneenActions) {
this.minimumSecondsToWaitBetwneenActions = minimumSecondsToWaitBetwneenActions;
}
public int getMaximumSecondsToWaitBetwneenActions() {
return maximumSecondsToWaitBetwneenActions;
}
public void setMaximumSecondsToWaitBetwneenActions(int maximumSecondsToWaitBetwneenActions) {
this.maximumSecondsToWaitBetwneenActions = maximumSecondsToWaitBetwneenActions;
}
public TestAction[] getTestActions() {
return testActions.toArray(new TestAction[testActions.size()]);
}
public void setTestActions(TestAction[] testActions) {
this.testActions.clear();
this.testActions.addAll(Arrays.asList(testActions));
}
public void replayAll() {
replayAll(null);
}
public void replayAll(Listener beforeEachAction) {
replay(testActions, beforeEachAction);
}
public void replay(final List toReplay, Listener beforeEachAction) {
for (int i = 0; i < toReplay.size(); i++) {
if (Thread.currentThread().isInterrupted()) {
break;
}
final TestAction testAction = toReplay.get(i);
try {
if (beforeEachAction != null) {
beforeEachAction.handle(testAction);
}
Thread.sleep(minimumSecondsToWaitBetwneenActions * 1000);
testAction.validate();
Component c = findComponentImmediatelyOrRetry(testAction);
if (c != null) {
currentComponent = c;
highlightCurrentComponent();
try {
Thread.sleep(1000);
} finally {
unhighlightCurrentComponent();
currentComponent = null;
}
}
testAction.execute(c, this);
} catch (Throwable t) {
if (t instanceof InterruptedException) {
break;
}
throw new TestFailure("Test Action n?" + (testActions.indexOf(testAction) + 1) + ": " + t.toString(),
t);
}
}
try {
Thread.sleep(minimumSecondsToWaitBetwneenActions * 1000);
} catch (InterruptedException ignore) {
}
}
protected Component findComponentImmediatelyOrRetry(TestAction testAction) {
Component result = null;
int remainingSeconds = maximumSecondsToWaitBetwneenActions - minimumSecondsToWaitBetwneenActions;
while (true) {
try {
result = testAction.findComponent(this);
break;
} catch (TestFailure e) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
throw e;
}
remainingSeconds--;
if (remainingSeconds == 0) {
throw e;
}
}
}
return result;
}
protected String getComponentSelectionActionTitle() {
return "Left Click";
}
protected void restoreCurrentComponentListeners() {
for (MouseListener l : currentComponentMouseListeners) {
currentComponent.addMouseListener(l);
}
}
protected void disableCurrentComponentListeners() {
currentComponentMouseListeners = currentComponent.getMouseListeners();
for (int i = 0; i < currentComponentMouseListeners.length; i++) {
currentComponent.removeMouseListener(currentComponentMouseListeners[i]);
}
}
protected void unhighlightCurrentComponent() {
currentComponent.setBackground(currentComponentBackground);
currentComponent.setForeground(currentComponentForeground);
if (currentComponent instanceof JComponent) {
try {
((JComponent) currentComponent).setBorder(currentComponentBorder);
} catch (Throwable ignore) {
}
}
}
protected void highlightCurrentComponent() {
currentComponentBackground = currentComponent.getBackground();
currentComponent.setBackground(HIGHLIGHT_BACKGROUND);
currentComponentForeground = currentComponent.getForeground();
currentComponent.setForeground(HIGHLIGHT_FOREGROUND);
if (currentComponent instanceof JComponent) {
currentComponentBorder = ((JComponent) currentComponent).getBorder();
try {
((JComponent) currentComponent).setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(HIGHLIGHT_FOREGROUND, 1), currentComponentBorder));
} catch (Throwable ignore) {
}
}
}
public void loadFromFile(File input) throws IOException {
FileInputStream stream = new FileInputStream(input);
try {
loadFromStream(stream);
} finally {
try {
stream.close();
} catch (Exception ignore) {
}
}
}
public void loadFromStream(InputStream input) {
XStream xstream = getXStream();
Tester loaded = (Tester) xstream.fromXML(input);
testActions = loaded.testActions;
minimumSecondsToWaitBetwneenActions = loaded.minimumSecondsToWaitBetwneenActions;
maximumSecondsToWaitBetwneenActions = loaded.maximumSecondsToWaitBetwneenActions;
}
public void saveToFile(File output) throws IOException {
FileOutputStream stream = new FileOutputStream(output);
try {
saveToStream(stream);
} finally {
try {
stream.close();
} catch (Exception ignore) {
}
}
}
public void saveToStream(OutputStream output) throws IOException {
XStream xstream = getXStream();
xstream.toXML(this, output);
}
protected XStream getXStream() {
XStream result = new XStream();
result.registerConverter(new JavaBeanConverter(result.getMapper()), -20);
return result;
}
public void handleCurrentComponentChange(Component c) {
synchronized (CURRENT_COMPONENT_MUTEX) {
if (currentComponent != null) {
unhighlightCurrentComponent();
restoreCurrentComponentListeners();
currentComponent = null;
}
if (c == null) {
return;
}
currentComponent = c;
highlightCurrentComponent();
disableCurrentComponentListeners();
}
}
public List getChildrenComponents(Container container) {
List result = Arrays.asList(container.getComponents());
result = new ArrayList(result);
Collections.sort(result, getComponentPositionBasedComparator());
return result;
}
protected Comparator getComponentPositionBasedComparator() {
return new Comparator() {
@Override
public int compare(Component c1, Component c2) {
Point location1 = c1.getLocation();
Point location2 = c2.getLocation();
int result = new Integer(location1.y).compareTo(new Integer(location2.y));
if (result == 0) {
result = new Integer(location1.x).compareTo(new Integer(location2.x));
}
return result;
}
};
}
public boolean isTestableWindow(Window window) {
for (TesterEditor testerEditor : TestingUtils.getTesterEditors(this)) {
if (TestingUtils.isTesterEditorComponent(testerEditor, window)) {
return false;
}
}
if (!window.isVisible()) {
return false;
}
return true;
}
public File getSavedImagesDirectory() {
return new File(Tester.class.getSimpleName().toLowerCase() + "-saved-images");
}
public List extractVisibleStrings(Component c) {
List result = new ArrayList();
String s;
s = extractVisibleStringThroughMethod(c, "getTitle");
if (s != null) {
result.add(s);
}
s = extractVisibleStringThroughMethod(c, "getText");
if (s != null) {
result.add(s);
}
s = extractVisibleStringThroughMethod(c, "getToolTipText");
if (s != null) {
result.add(s);
}
if (c instanceof JComponent) {
Border border = ((JComponent) c).getBorder();
if (border != null) {
s = extractVisibleStringFromBorder(border);
if ((s != null) && (s.trim().length() > 0)) {
result.add(s);
}
}
}
if (c instanceof JTable) {
JTable table = (JTable) c;
result.addAll(extractVisibleStringsFromTable(table));
}
if (c instanceof JTree) {
JTree tree = (JTree) c;
result.addAll(extractVisibleStringsFromTree(tree));
}
if (c instanceof JList) {
JList list = (JList) c;
result.addAll(extractVisibleStringsFromList(list));
}
return result;
}
protected String extractVisibleStringFromBorder(Border border) {
if (border instanceof TitledBorder) {
String s = ((TitledBorder) border).getTitle();
if ((s != null) && (s.trim().length() > 0)) {
return s;
}
}
return null;
}
protected Collection extractVisibleStringsFromList(JList list) {
List result = new ArrayList();
ListModel model = list.getModel();
ListCellRenderer cellRenderer = list.getCellRenderer();
for (int i = 0; i < model.getSize(); i++) {
try {
Object item = model.getElementAt(i);
Component cellComponent = cellRenderer.getListCellRendererComponent(list, item, i, false, false);
result.addAll(extractVisibleStrings(cellComponent));
} catch (Exception ignore) {
}
}
return result;
}
protected List extractVisibleStringsFromTable(JTable table) {
List result = new ArrayList();
TableModel model = table.getModel();
String s;
for (int i = 0; i < model.getColumnCount(); i++) {
s = model.getColumnName(i);
if ((s != null) && (s.trim().length() > 0)) {
result.add(s);
}
}
for (int iRow = 0; iRow < model.getRowCount(); iRow++) {
for (int iCol = 0; iCol < model.getColumnCount(); iCol++) {
try {
Object cellValue = model.getValueAt(iRow, iCol);
TableCellRenderer cellRenderer = table.getCellRenderer(iRow, iCol);
Component cellComponent = cellRenderer.getTableCellRendererComponent(table, cellValue, false, false,
iRow, iCol);
List cellVisibleStrings = extractVisibleStrings(cellComponent);
result.addAll(cellVisibleStrings);
} catch (Exception ignore) {
}
}
}
return result;
}
protected Collection extends String> extractVisibleStringsFromTree(JTree tree) {
List result = new ArrayList();
result.addAll(extractVisibleStringsFromTree(0, tree.getModel().getRoot(), tree));
return result;
}
protected List extractVisibleStringsFromTree(int currentRow, Object currentNode, JTree tree) {
List result = new ArrayList();
TreeModel model = tree.getModel();
try {
String s = tree.convertValueToText(currentNode, false, true, model.isLeaf(currentNode), currentRow, false);
if ((s != null) && (s.trim().length() > 0)) {
result.add(s);
}
} catch (Exception ignore) {
}
for (int i = 0; i < model.getChildCount(currentNode); i++) {
Object childNode = model.getChild(currentNode, i);
result.addAll(extractVisibleStringsFromTree(currentRow + 1, childNode, tree));
}
return result;
}
protected String extractVisibleStringThroughMethod(Component c, String methodName) {
try {
Method method = c.getClass().getMethod(methodName);
String result = (String) method.invoke(c);
if (result == null) {
return null;
}
if (result.trim().length() == 0) {
return null;
}
return result;
} catch (Exception e) {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy