blob: 54d308da869d5af5f941a5e1e78de8a4f848bc26 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Benjamin Leipold and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Benjamin Leipold - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.tests.fieldassist;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.tests.harness.util.TestRunLogUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestWatcher;
public class ContentProposalAdapterTest {
@Rule
public TestWatcher LOG_TESTRUN = TestRunLogUtil.LOG_TESTRUN;
/**
* A shell that hosts the decorated text control
*/
private Shell controlShell;
/**
* Text control to be decorated by {@code contentProposalAdapter}
*/
private Text text;
/**
* {@code ContentProposalAdapter} to test
*/
private ContentProposalAdapter contentProposalAdapter;
/**
* Display of this test case.
*/
private Display display;
/**
* {@code true} if {@code display} has to be disposed in {@link #tearDown()}
*/
private boolean disposeDisplay;
/**
* The original number of shells at the beginning of the test.
*/
private int originalShellCount;
/**
* bug 520372: ContentProposalAdapter with autoActivationDelay pops up although
* control has already lost focus
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=520372
*
* Tests whether no proposal popup was opened if TAB was pressed within
* activation delay.
*/
@Test
public void testBug520372AutoActivationDelayTab() throws Exception {
sendKeyDownToControl('o');
sendKeyDownToControl(SWT.TAB);
ensurePopupIsUp();
assertOneShellUp();
}
/**
* bug 520372: ContentProposalAdapter with autoActivationDelay pops up although
* control has already lost focus
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=520372
*
* Tests whether no proposal popup was opened if CR was pressed within
* activation delay.
*/
@Test
public void testBug520372AutoActivationDelayCR() throws Exception {
sendKeyDownToControl('o');
sendKeyDownToControl(SWT.CR);
ensurePopupIsUp();
assertOneShellUp();
}
/**
* bug 520372: ContentProposalAdapter with autoActivationDelay pops up although
* control has already lost focus
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=520372
*
* Tests whether no proposal popup was opened if ESC was pressed within
* activation delay.
*/
@Test
public void testBug520372AutoActivationDelayESC() throws Exception {
sendKeyDownToControl('o');
sendKeyDownToControl(SWT.ESC);
ensurePopupIsUp();
assertOneShellUp();
}
// most of the following code is copied from AbstractFieldAssistTestCase
@Before
public final void setUp() throws Exception {
Display display = getDisplay();
originalShellCount = display.getShells().length;
controlShell = new Shell(display);
text = new Text(controlShell, SWT.SINGLE);
controlShell.open();
spinEventLoop();
contentProposalAdapter = createContentProposalAdapter(this.text);
assertNotNull(contentProposalAdapter);
}
@After
public final void tearDown() throws Exception {
if (controlShell != null) {
spinEventLoop();
controlShell.close();
}
if (display != null) {
if (disposeDisplay) {
display.dispose();
}
this.display = null;
}
}
private Display getDisplay() {
if (display == null) {
Display newDisplay = Display.getCurrent();
if (newDisplay == null) {
newDisplay = new Display();
disposeDisplay = true;
}
display = newDisplay;
}
return display;
}
/**
* Gives focus to the field assist control.
*/
private void sendFocusInToControl() {
text.setFocus();
spinEventLoop();
}
/**
* Sends an SWT KeyDown event for the specified character to the field assist
* control.
*
* @param character
* the character that has been pressed
*/
private void sendKeyDownToControl(char character) {
// fake a KeyDown event
sendFocusInToControl();
Event event = new Event();
event.type = SWT.KeyDown;
event.character = character;
assertTrue("unable to post event to display queue for test case", text.getDisplay().post(event));
spinEventLoop();
}
private void spinEventLoop() {
// spin the event loop again because we have some asyncExec calls in the
// ContentProposalAdapter class
Display disp = getDisplay();
while (disp.readAndDispatch()) {
}
}
private ContentProposalAdapter createContentProposalAdapter(Control control) {
ContentProposalAdapter contentProposalAdapter = new ContentProposalAdapter(control, new TextContentAdapter(),
createContentProposalProvider(), null, null);
contentProposalAdapter.setAutoActivationDelay(2000);
return contentProposalAdapter;
}
private IContentProposalProvider createContentProposalProvider() {
SimpleContentProposalProvider proposalProvider = new SimpleContentProposalProvider(getProposals());
return proposalProvider;
}
private String[] getProposals() {
return new String[] { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
}
private void ensurePopupIsUp() {
// if our autoactivation delay is zero, we use an asyncExec to get the
// popup up, hence, we need to spin the event loop
if (contentProposalAdapter.getAutoActivationDelay() == 0) {
spinEventLoop();
} else {
long time = System.currentTimeMillis();
long target = time + contentProposalAdapter.getAutoActivationDelay();
while (target > time) {
spinEventLoop(); // remain responsive
time = System.currentTimeMillis();
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// nothing to do
}
spinEventLoop();
}
}
/**
* Checks that there is only one shell up, the original field assist window.
*/
private void assertOneShellUp() {
spinEventLoop();
assertEquals("There should only be one shell up, the dialog", originalShellCount + 1,
text.getDisplay().getShells().length);
}
}