All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 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