/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.internal.ui.swt.utils;
import java.text.DecimalFormatSymbols;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;
import junit.framework.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.riena.core.marker.IMarkable;
import org.eclipse.riena.core.marker.IMarker;
import org.eclipse.riena.internal.ui.swt.test.UITestHelper;
import org.eclipse.riena.ui.core.marker.IMessageMarker;
import org.eclipse.riena.ui.core.marker.MandatoryMarker;
import org.eclipse.riena.ui.ridgets.IMarkableRidget;
import org.eclipse.riena.ui.swt.facades.SWTFacade;
/**
* Utility class for tests.
*/
public final class TestUtils {
private TestUtils() {
// utility class
}
/**
* For a given Tree or Table, tests that the layouting results in correctly-calculated column widths.
*
* @param control
* the Tree or Table widget to check
* @param numberOfCols
* the number of columns that the widget displays
*/
public static void assertColumnWidths(final Control control, final int numberOfCols) {
final int expected = control.getSize().x / numberOfCols;
Assert.assertTrue(String.valueOf(expected), expected > 0);
for (int column = 0; column < numberOfCols; column++) {
final int actual = getColumnWidth(control, column);
// take into account rounding errors, e.g. total width 85 => col widths (29, 28, 28)
final String message = String.format("col %d, expected %d <= x <= %d but was %d", column, expected, (expected + 1), actual); //$NON-NLS-1$
Assert.assertTrue(message, (expected <= actual && actual <= expected + 1));
}
}
/**
* Asserts that the given ridget has {@code expectedCount} mandatory markers with the given {@code disabledState}.
*
* @param ridget
* never null
* @param expectedCount
* the expected count of markers
* @param disabledState
* the expected disabled state value
*/
public static void assertMandatoryMarker(final IMarkableRidget ridget, final int expectedCount, final boolean disabledState) {
final Collection<MandatoryMarker> markers = ridget.getMarkersOfType(MandatoryMarker.class);
Assert.assertEquals(expectedCount, markers.size());
final Iterator<MandatoryMarker> iter = markers.iterator();
while (iter.hasNext()) {
final boolean isDisabled = iter.next().isDisabled();
Assert.assertEquals(disabledState, isDisabled);
}
}
/**
* Asserts that given ridget has a certain number of markers of the given type
*
* @param ridget
* a IMarkable ridget; never null
* @param markerType
* a marker type implementing IMessageMarker
* @param count
* the expected count; 0 or greater
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void assertMessageCount(final IMarkable ridget, final Class markerType, final int count) {
final Collection<IMessageMarker> collection = ridget.getMarkersOfType(markerType);
if (count != collection.size()) {
System.out.println(String.format("assertion failed on message count -- expected %d, got %d:", count, //$NON-NLS-1$
collection.size()));
for (final IMessageMarker messageMarker : collection) {
System.out.println("\t" + messageMarker.getMessage()); //$NON-NLS-1$
}
}
Assert.assertEquals(count, collection.size());
}
/**
* Asserts that an IMessageMarker with the given message is contained in the ridget.
*
* @param ridget
* a IMarkable ridget; never null
* @param markerType
* a marker type implementing IMessageMarker
* @param message
* the message to find
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void assertMessage(final IMarkable ridget, final Class markerType, final String message) {
final Collection<IMessageMarker> collection = ridget.getMarkersOfType(markerType);
boolean wasFound = false;
final Iterator<IMessageMarker> iter = collection.iterator();
while (!wasFound && iter.hasNext()) {
final IMessageMarker marker = iter.next();
wasFound = message.equals(marker.getMessage());
}
Assert.assertEquals(String.format("Message '%s'", message), true, wasFound); //$NON-NLS-1$
}
/**
* Asserts that in the given {@code control} the text and cursor position match the expected {@code before} value. It then applies the given key sequence
* and asserts that the resulting text and cursor position matches the expected {@code after} value.
* <p>
* One can use one '^' character to denote the expected cursor position, or two '^' characters to denote the expected selection.
* <p>
* Example:
*
* <pre>
* assertText(" ˆ. .2008", "1208", "12.08ˆ.2008");
* </pre>
*
* @param control
* a non-null Text control
* @param before
* the expected before value
* @param keySeq
* a String with the characters to type
* @param after
* the expected after value
*/
public static void assertText(final Text control, final String before, final String keySeq, final String after) {
forceText(control, before);
checkText(control, before);
checkSelection(control, before);
checkCaret(control, before);
control.setFocus();
UITestHelper.sendString(control.getDisplay(), keySeq);
checkText(control, after);
checkCaret(control, after);
}
/**
* Asserts that in the given {@code control} the text and cursor position match the expected {@code before} value. It then applies the given keyCode and
* asserts that the resulting text and cursor position matches the expected {@code after} value.
* <p>
* One can use one '^' character to denote the expected cursor position, or two '^' characters to denote the expected selection.
* <p>
* Example:
*
* <pre>
* assertText(" ˆ. .2008", "1208", "12.08ˆ.2008");
* </pre>
*
* @param control
* a non-null Text control
* @param before
* the expected before value
* @param keySeq
* the keyCode to type
* @param after
* the expected after value
*/
public static void assertText(final Text control, final String before, final int keyCode, final String after) {
forceText(control, before);
checkText(control, before);
checkSelection(control, before);
checkCaret(control, before);
control.setFocus();
UITestHelper.sendKeyAction(control.getDisplay(), keyCode);
checkText(control, after);
checkCaret(control, after);
}
/**
* Returns true if the Arab locale ("ar_AE") is available.
*/
public static boolean isArabLocaleAvailable() {
final Locale arabLocale = new Locale("ar", "AE"); //$NON-NLS-1$ //$NON-NLS-2$
for (final Locale availableLocale : Locale.getAvailableLocales()) {
if (availableLocale.equals(arabLocale)) {
return true;
}
}
return false;
}
/**
* Return a localized version of a String representation of a number. The returned string will use the grouping separator and decimal separator for the
* current locale.
* <p>
* Examples:
* <ul>
* <li>DE - "1.234,56" -> "1.234,56"</li>
* <li>US - "1.234,56" -> "1,234.56"</li>
* </ul>
*
* @param number
* a String representation of a number, where '.' is used as the grouping separator and ',' is used as the decimal separator.
* @return a localized String representation of a number
*/
public static String getLocalizedNumber(final String number) {
final DecimalFormatSymbols dfs = new DecimalFormatSymbols();
final char decimalSep = dfs.getDecimalSeparator();
final char groupingSep = dfs.getGroupingSeparator();
final String result = number.replace('.', '_').replace(',', decimalSep).replace('_', groupingSep);
return result;
}
/**
* Print all markers in this markable.
*/
public static void printMarkers(final IMarkable markable) {
final Collection<IMarker> markers = (Collection<IMarker>) markable.getMarkers();
System.out.println(String.format("Have %d markers::", markers.size())); //$NON-NLS-1$
for (final IMarker m : markers) {
System.out.println(m.toString());
}
}
// helping methods
//////////////////
private static void checkText(final Text control, final String input) {
final String expected = removePositionMarkers(input);
Assert.assertEquals(expected, control.getText());
}
private static void checkSelection(final Text control, final String input) {
final int start = input.indexOf('^');
final int end = input.lastIndexOf('^');
String expected = ""; //$NON-NLS-1$
if (start < end) {
expected = input.substring(start + 1, end);
}
// System.out.println("exp sel: " + expected);
Assert.assertEquals(expected, control.getSelectionText());
}
private static void checkCaret(final Text control, final String input) {
final int start = input.indexOf('^');
if (start != -1) {
final int end = input.lastIndexOf('^');
final int expected = start < end ? end - 1 : end;
// System.out.println("exp car: " + expected);
Assert.assertEquals(expected, control.getCaretPosition());
}
}
private static int getColumnWidth(final Control control, final int colIndex) {
if (control instanceof Tree) {
return ((Tree) control).getColumn(colIndex).getWidth();
} else if (control instanceof Table) {
return ((Table) control).getColumn(colIndex).getWidth();
}
throw new IllegalArgumentException("unsupported control: " + control); //$NON-NLS-1$
}
private static String removePositionMarkers(final String input) {
final StringBuilder result = new StringBuilder(input.length());
for (int i = 0; i < input.length(); i++) {
final char ch = input.charAt(i);
if (ch != '^') {
result.append(ch);
}
}
return result.toString();
}
private static void forceText(final Text control, final String text) {
final int start = text.indexOf('^');
final int end = text.lastIndexOf('^');
final SWTFacade facade = SWTFacade.getDefault();
final Object[] listeners = facade.removeListeners(control, SWT.Verify);
control.setText(removePositionMarkers(text));
facade.addListeners(control, SWT.Verify, listeners);
control.setFocus();
if (start == end) {
control.setSelection(start, start);
} else {
control.setSelection(start, end - 1);
}
}
}