/******************************************************************************* * Copyright (c) 2006-2013 The RCP Company 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: * The RCP Company - initial API and implementation *******************************************************************************/ package com.rcpcompany.uibindings.extests.observables; import static com.rcpcompany.test.utils.ui.UITestUtils.*; import static com.rcpcompany.uibindings.tests.utils.BaseUIBTestUtils.*; import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collection; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Text; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.rcpcompany.uibindings.IManager; import com.rcpcompany.uibindings.TextCommitStrategy; import com.rcpcompany.uibindings.internal.observables.DelayedChangeEvent; import com.rcpcompany.uibindings.internal.observables.IDelayedChangeListener; import com.rcpcompany.uibindings.internal.observables.TextObservableValue; import com.rcpcompany.uibindings.tests.utils.BaseUIBTestUtils; /** * Tests the {@link TextObservableValue} behaves. * * Do all tests for both single and multi line Texts. * * @author Tonny Madsen, The RCP Company * */ @RunWith(Parameterized.class) public class TextObservableValueTest<X extends Control> { private static final int DELAY = 1000; final IManager manager = IManager.Factory.getManager(); private final int myTextStyle; private final Class<X> myCls; private final boolean mySingleLine; private final static String NL = System.getProperty("line.separator"); @Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][] { // Class<X> cls, int style, boolean singleLine { Text.class, SWT.SINGLE, true }, { Text.class, SWT.MULTI, false }, { StyledText.class, SWT.NONE, false }, { Combo.class, SWT.NONE, true }, { CCombo.class, SWT.NONE, true }, }); } public TextObservableValueTest(Class<X> cls, int style, boolean singleLine) { myCls = cls; myTextStyle = style; mySingleLine = singleLine; } private X w1; private TextObservableValue ov1; /* * Used for focus out */ private Text w2; public String getText() { if (w1 instanceof Text) return ((Text) w1).getText(); if (w1 instanceof StyledText) return ((StyledText) w1).getText(); if (w1 instanceof Combo) return ((Combo) w1).getText(); if (w1 instanceof CCombo) return ((CCombo) w1).getText(); return null; } public void setText(String string) { if (w1 instanceof Text) { ((Text) w1).setText(string); } if (w1 instanceof StyledText) { ((StyledText) w1).setText(string); } if (w1 instanceof Combo) { ((Combo) w1).setText(string); } if (w1 instanceof CCombo) { ((CCombo) w1).setText(string); } } public void selectAll() { if (w1 instanceof Text) { ((Text) w1).selectAll(); } if (w1 instanceof StyledText) { ((StyledText) w1).selectAll(); } if (w1 instanceof Combo) { final Combo c = (Combo) w1; c.setSelection(new Point(0, c.getText().length())); } if (w1 instanceof CCombo) { final CCombo c = (CCombo) w1; c.setSelection(new Point(0, c.getText().length())); } } /** * Executes the specified runnable and monitors whether the specified value change occurs and * whether the value changes. * <p> * <em>NOTE:</em> There are a special case with multi-line Text widgets: when the complete * selected text is changed, it happens in two parts: First the text of the widget is changed to * "" and then it is changed to the new text. * * @param changeFromValue the from value expect in a change event * @param changeToValue the to value expect in a change event * @param expectDelayChangeEvents <code>true</code> if a {@link DelayedChangeEvent} event is * expected * @param getValue the expected value of the ov1 after the change * @param change the {@link Runnable} to execute */ public void performChange(final String changeFromValue, final String changeToValue, final boolean expectDelayChangeEvents, String getValue, Runnable change) { final boolean[] changeExpected = new boolean[] { !(changeToValue.equals(changeFromValue)) }; final boolean[] dceExpected = new boolean[] { expectDelayChangeEvents }; final IValueChangeListener valueListener = new IValueChangeListener() { String fromValue = changeFromValue; String toValue = changeToValue; @Override public void handleValueChange(ValueChangeEvent event) { // LogUtils.debug(this, "'" + event.diff.getOldValue() + "' -> '" + // event.diff.getNewValue() + "'"); assertTrue("No value change expected", changeExpected[0]); assertEquals(fromValue, event.diff.getOldValue()); if (event.diff.getNewValue().equals("")) { fromValue = ""; return; } assertEquals(toValue, event.diff.getNewValue()); changeExpected[0] = false; } }; final IDelayedChangeListener dcListener = new IDelayedChangeListener() { @Override public void handleDelayedChange(DelayedChangeEvent event) { // LogUtils.debug(this, ""); assertTrue("No delayed change expected", dceExpected[0]); dceExpected[0] = false; } }; try { ov1.addValueChangeListener(valueListener); ov1.addDelayedChangeListener(dcListener); if (change != null) { change.run(); } yield(); } finally { ov1.removeValueChangeListener(valueListener); ov1.removeDelayedChangeListener(dcListener); } assertEquals(getValue, ov1.getValue()); assertEquals(false, changeExpected[0]); assertEquals(false, dceExpected[0]); } @Before public void before() { BaseUIBTestUtils.resetAll(); w1 = createWidget(myCls, myTextStyle); if (w1 instanceof Text) { ov1 = new TextObservableValue((Text) w1); } if (w1 instanceof StyledText) { ov1 = new TextObservableValue((StyledText) w1); } if (w1 instanceof Combo) { ov1 = new TextObservableValue((Combo) w1); } if (w1 instanceof CCombo) { ov1 = new TextObservableValue((CCombo) w1); } w2 = createWidget(Text.class, SWT.None); } @After public void tearDown() { ov1.dispose(); manager.setTextCommitStrategy(TextCommitStrategy.ON_MODIFY); manager.setTextCommitStrategyDelay(400); w1.dispose(); w2.dispose(); } /** * Tests that getDelayedChange and getValue is correct for all strategies for the sequence * <nl> * <li>set iov value to "a" (reset)</li> * <li>set value to "b"</li> * <li>wait DELAY/5</li> * <li>set value to "c"</li> * <li>wait 2*DELAY</li> * <li>focus out</li> * </nl> * * @param strategy the strategy to test * @param b1 expected value change after setting the value to "b" * @param b2 expected value change after DELAY/5 * @param b3 expected value change after setting the value to "c" * @param b4 expected value change after 2*DELAY * @param b5 expected value change after focus out */ public void testAStrategy(TextCommitStrategy strategy, String b1, String b2, String b3, String b4, String b5) { manager.setTextCommitStrategy(strategy); manager.setTextCommitStrategyDelay(DELAY); w1.setFocus(); ov1.setValue("a"); assertEquals("a", getText()); performChange("a", b1, strategy != TextCommitStrategy.ON_MODIFY, "b", new Runnable() { @Override public void run() { setText("b"); } }); performChange(b1, b2, false, "b", new Runnable() { public void run() { sleep(DELAY / 5); } }); performChange(b2, b3, strategy != TextCommitStrategy.ON_MODIFY, "c", new Runnable() { @Override public void run() { setText("c"); } }); performChange(b3, b4, false, "c", new Runnable() { @Override public void run() { sleep(2 * DELAY); } }); performChange(b4, b5, false, "c", new Runnable() { @Override public void run() { w2.setFocus(); } }); } @Test public void testModifyStrategy() { testAStrategy(TextCommitStrategy.ON_MODIFY, "b", "b", "c", "c", "c"); } @Test public void testModifyDelayStrategy() { testAStrategy(TextCommitStrategy.ON_MODIFY_DELAY, "a", "a", "a", "c", "c"); } @Test public void testFocusOutStrategy() { testAStrategy(TextCommitStrategy.ON_FOCUS_OUT, "a", "a", "a", "a", "c"); } /** * Tests that getDelayedChange and getValue is correct for all strategies for the sequence * <nl> * <li>set iov value to "a" (reset)</li> * <li>select all text (programatically) and enter "b"</li> * <li>wait DELAY/5</li> * <li>select all text (programatically) and enter "c"</li> * <li>wait 2*DELAY</li> * <li>focus out</li> * </nl> * * @param strategy the strategy to test * @param b1 expected value change after entering "b" * @param b2 expected value change after DELAY/5 * @param b3 expected value change after entering "c" * @param b4 expected value change after 2*DELAY * @param b5 expected value change after focus out */ public void testAKeyStrategy(TextCommitStrategy strategy, String b1, String b2, String b3, String b4, String b5) { manager.setTextCommitStrategy(strategy); manager.setTextCommitStrategyDelay(DELAY); w1.setFocus(); ov1.setValue("a"); assertEquals("a", getText()); yield(); performChange("a", b1, strategy != TextCommitStrategy.ON_MODIFY, "b", new Runnable() { public void run() { selectAll(); // postKeyDown(w1, "M1+A"); postKeyStroke(w1, "b"); } }); performChange(b1, b2, false, "b", new Runnable() { public void run() { sleep(DELAY / 5); } }); performChange(b2, b3, strategy != TextCommitStrategy.ON_MODIFY, "c", new Runnable() { public void run() { selectAll(); // postKeyDown(w1, "M1+A"); postKeyStroke(w1, "c"); } }); performChange(b3, b4, false, "c", new Runnable() { public void run() { sleep(2 * DELAY); } }); performChange(b4, b5, false, "c", new Runnable() { public void run() { w2.setFocus(); } }); } @Test public void testModifyKeyStrategy() { try { testAKeyStrategy(TextCommitStrategy.ON_MODIFY, "b", "b", "c", "c", "c"); } finally { sleep(DELAY); } } @Test public void testModifyDelayKeyStrategy() { testAKeyStrategy(TextCommitStrategy.ON_MODIFY_DELAY, "a", "a", "a", "c", "c"); } @Test public void testFocusOutKeyStrategy() { testAKeyStrategy(TextCommitStrategy.ON_FOCUS_OUT, "a", "a", "a", "a", "c"); } /** * Tests that getDelayedChange and getValue is correct for all strategies for the sequence * <nl> * <li>set iov value to "a" (reset)</li> * <li>set value to "b"</li> * <li>do stroke</li> * </nl> * * @param strategy the strategy to test * @param b1 expected value after setting the value * @param stroke the key to press * @param b2 expected value after 2*DELAY * @param expectDelayChangeEvents <code>true</code> if a {@link DelayedChangeEvent} event is * expected * @param getValue the value of the observable value after the operation */ public void testKeyStrategy(TextCommitStrategy strategy, String b1, final String stroke, String b2, boolean expectDelayChangeEvents, String getValue) { manager.setTextCommitStrategy(strategy); manager.setTextCommitStrategyDelay(DELAY); w1.setFocus(); final String initial = "a"; ov1.setValue(initial); performChange(initial, b1, strategy != TextCommitStrategy.ON_MODIFY, "b", new Runnable() { public void run() { setText("b"); } }); performChange(b1, b1, false, "b", new Runnable() { public void run() { sleep(DELAY / 2); } }); performChange(b1, b2, expectDelayChangeEvents, getValue, new Runnable() { public void run() { postKeyStroke(w1, stroke); } }); } @Test public void testModifyEnterStrategy() { testKeyStrategy(TextCommitStrategy.ON_MODIFY, "b", "ENTER", mySingleLine ? "b" : NL + "b", false, mySingleLine ? "b" : NL + "b"); } @Test public void testModifyDelayEnterStrategy() { testKeyStrategy(TextCommitStrategy.ON_MODIFY_DELAY, "a", "ENTER", mySingleLine ? "b" : "a", !mySingleLine, mySingleLine ? "b" : NL + "b"); } @Test public void testFocusOutEnterStrategy() { testKeyStrategy(TextCommitStrategy.ON_FOCUS_OUT, "a", "ENTER", mySingleLine ? "b" : "a", !mySingleLine, mySingleLine ? "b" : NL + "b"); } @Test public void testModifyEscapeStrategy() { testKeyStrategy(TextCommitStrategy.ON_MODIFY, "b", "ESCAPE", "b", false, "b"); } @Test public void testModifyDelayEscapeStrategy() { testKeyStrategy(TextCommitStrategy.ON_MODIFY_DELAY, "a", "ESCAPE", "a", false, "a"); } @Test public void testFocusOutEscapeStrategy() { testKeyStrategy(TextCommitStrategy.ON_FOCUS_OUT, "a", "ESCAPE", "a", false, "a"); } /** * Tests that getDelayedChange and getValue is correct for all strategies for the sequence * <nl> * <li>set iov value to "a" (reset)</li> * <li>do stroke</li> * <li>wait DELAY/2</li> * <li>focus out</li> * </nl> * * @param strategy the strategy to test * @param b1 expected value after setting the value * @param stroke the key to press */ public void testKeyStrategyFocusOut(TextCommitStrategy strategy, String b1, final String stroke) { manager.setTextCommitStrategy(strategy); manager.setTextCommitStrategyDelay(DELAY); w1.setFocus(); final String initial = "a"; ov1.setValue(initial); performChange(initial, b1, strategy != TextCommitStrategy.ON_MODIFY, b1, new Runnable() { public void run() { postKeyStroke(w1, "ARROW_LEFT"); // LogUtils.debug(this, "next: " + stroke); postKeyStroke(w1, stroke); sleep(DELAY / 2); w2.setFocus(); } }); } @Test public void testModifyFocusOutStrategy() { testKeyStrategyFocusOut(TextCommitStrategy.ON_MODIFY, "ba", "b"); } @Test public void testModifyDelayFocusOutStrategy() { testKeyStrategyFocusOut(TextCommitStrategy.ON_MODIFY_DELAY, "ba", "b"); } @Test public void testFocusOutFocusOutStrategy() { testKeyStrategyFocusOut(TextCommitStrategy.ON_FOCUS_OUT, "ba", "b"); } /** * Tests that getDelayedChange and getValue are correct when the strategy is changed for the * sequence * <nl> * <li>set iov value to "a" (reset)</li> * <li>wait DELAY/2</li> * <li>change strategy</li> * </nl> * * @param fromStrategy original strategy * @param expectDelayChangeEvents <code>true</code> if a {@link DelayedChangeEvent} event is * expected * @param b1 the new value * @param toStrategy new strategy */ protected void testA2BStrategy(TextCommitStrategy fromStrategy, boolean expectDelayChangeEvents, String b1, final TextCommitStrategy toStrategy) { manager.setTextCommitStrategy(fromStrategy); manager.setTextCommitStrategyDelay(DELAY); w1.setFocus(); ov1.setValue("a"); performChange("a", b1, expectDelayChangeEvents, "b", new Runnable() { public void run() { setText("b"); } }); performChange(b1, b1, false, "b", new Runnable() { public void run() { sleep(DELAY / 2); } }); performChange(b1, "b", false, "b", new Runnable() { public void run() { manager.setTextCommitStrategy(toStrategy); } }); } @Test public void testModify2FocusOutStrategy() { testA2BStrategy(TextCommitStrategy.ON_MODIFY, false, "b", TextCommitStrategy.ON_FOCUS_OUT); } @Test public void testModify2ModifyDelayStrategy() { testA2BStrategy(TextCommitStrategy.ON_MODIFY, false, "b", TextCommitStrategy.ON_MODIFY_DELAY); } @Test public void testFocusOut2ModifyStrategy() { testA2BStrategy(TextCommitStrategy.ON_FOCUS_OUT, true, "a", TextCommitStrategy.ON_MODIFY); } @Test public void testFocusOut2ModifyDelayStrategy() { testA2BStrategy(TextCommitStrategy.ON_FOCUS_OUT, true, "a", TextCommitStrategy.ON_MODIFY_DELAY); } @Test public void testModifyDelay2ModifyStrategy() { testA2BStrategy(TextCommitStrategy.ON_MODIFY_DELAY, true, "a", TextCommitStrategy.ON_MODIFY); } @Test public void testModifyDelay2FocusOutStrategy() { testA2BStrategy(TextCommitStrategy.ON_MODIFY_DELAY, true, "a", TextCommitStrategy.ON_FOCUS_OUT); } /** * Tests that getDelayedChange and getValue is correct for all strategies for the sequence * <nl> * <li>set iov value to "a" (reset)</li> * <li>set value to "b"</li> * <li>wait 2*DELAY</li> * <li>set iov to new value "c"</li> * </nl> * * @param fromStrategy the strategy to test * @param expectDelayChangeEvents <code>true</code> if a {@link DelayedChangeEvent} event is * expected */ private void testASetValueStrategy(TextCommitStrategy fromStrategy, boolean expectDelayChangeEvents, String b1) { manager.setTextCommitStrategy(fromStrategy); manager.setTextCommitStrategyDelay(1000); w1.setFocus(); ov1.setValue("a"); performChange("a", b1, expectDelayChangeEvents, "b", new Runnable() { public void run() { setText("b"); } }); performChange(b1, b1, false, "b", new Runnable() { public void run() { sleep(DELAY / 2); } }); performChange(b1, "c", false, "c", new Runnable() { public void run() { ov1.setValue("c"); } }); } @Test public void testModifySetValueStrategy() { testASetValueStrategy(TextCommitStrategy.ON_MODIFY, false, "b"); } @Test public void testFocusOutSetValueStrategy() { testASetValueStrategy(TextCommitStrategy.ON_FOCUS_OUT, true, "a"); } @Test public void testModifyDelaySetValueStrategy() { testASetValueStrategy(TextCommitStrategy.ON_MODIFY_DELAY, true, "a"); } }