blob: 70d44b83067bb714fa5c440c7d08b8cbf619a3c0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2017 Red Hat Inc. 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:
* Mickael Istria, Sopot Cela (Red Hat Inc.)
*******************************************************************************/
package org.eclipse.ui.genericeditor.tests;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Collections;
import java.util.Map;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.resources.IMarker;
import org.eclipse.text.tests.Accessor;
import org.eclipse.jface.text.AbstractInformationControl;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.tests.util.DisplayHelper;
import org.eclipse.ui.genericeditor.tests.contributions.AlrightyHoverProvider;
import org.eclipse.ui.genericeditor.tests.contributions.EnabledPropertyTester;
import org.eclipse.ui.genericeditor.tests.contributions.HelloHoverProvider;
import org.eclipse.ui.genericeditor.tests.contributions.MarkerResolutionGenerator;
import org.eclipse.ui.genericeditor.tests.contributions.WorldHoverProvider;
import org.eclipse.ui.workbench.texteditor.tests.ScreenshotTest;
import org.eclipse.ui.texteditor.AbstractTextEditor;
/**
* @since 1.0
*/
public class HoverTest extends AbstratGenericEditorTest {
@Rule
public TestName testName= new TestName();
@Before
public void skipOnNonLinux() {
Assume.assumeFalse("This test currently always fail on Windows (bug 505842), skipping", Platform.OS_WIN32.equals(Platform.getOS()));
Assume.assumeFalse("This test currently always fail on macOS (bug 505842), skipping", Platform.OS_MACOSX.equals(Platform.getOS()));
}
@Test
public void testSingleHover() throws Exception {
Shell shell= getHoverShell(triggerCompletionAndRetrieveInformationControlManager(), true);
assertNotNull(findControl(shell, StyledText.class, AlrightyHoverProvider.LABEL));
assertNull(findControl(shell, StyledText.class, HelloHoverProvider.LABEL));
assertNull(findControl(shell, StyledText.class, WorldHoverProvider.LABEL));
}
@Test
public void testEnabledWhenHover() throws Exception {
cleanFileAndEditor();
EnabledPropertyTester.setEnabled(true);
createAndOpenFile("enabledWhen.txt", "bar 'bar'");
Shell shell= getHoverShell(triggerCompletionAndRetrieveInformationControlManager(), true);
assertNotNull(findControl(shell, StyledText.class, AlrightyHoverProvider.LABEL));
assertNull(findControl(shell, StyledText.class, WorldHoverProvider.LABEL));
cleanFileAndEditor();
EnabledPropertyTester.setEnabled(false);
createAndOpenFile("enabledWhen.txt", "bar 'bar'");
shell= getHoverShell(triggerCompletionAndRetrieveInformationControlManager(), true);
assertNull(findControl(shell, StyledText.class, AlrightyHoverProvider.LABEL));
assertNotNull(findControl(shell, StyledText.class, WorldHoverProvider.LABEL));
}
/**
* @throws Exception ex
* @since 1.1
*/
@Test
public void testMultipleHover() throws Exception {
cleanFileAndEditor();
createAndOpenFile("bar.txt", "Hi");
Shell shell= getHoverShell(triggerCompletionAndRetrieveInformationControlManager(), true);
assertNull(findControl(shell, StyledText.class, AlrightyHoverProvider.LABEL));
assertNotNull(findControl(shell, StyledText.class, WorldHoverProvider.LABEL));
assertNotNull(findControl(shell, StyledText.class, HelloHoverProvider.LABEL));
}
@Test
public void testProblemHover() throws Exception {
String problemMessage= "Huston...";
IMarker marker= null;
try {
marker= this.file.createMarker(IMarker.PROBLEM);
marker.setAttribute(IMarker.LINE_NUMBER, 1);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
marker.setAttribute(IMarker.CHAR_START, 0);
marker.setAttribute(IMarker.CHAR_END, 5);
marker.setAttribute(IMarker.MESSAGE, problemMessage);
marker.setAttribute(MarkerResolutionGenerator.FIXME, true);
AbstractInformationControlManager manager= triggerCompletionAndRetrieveInformationControlManager();
Object hoverData= getHoverData(manager);
assertTrue(hoverData instanceof Map);
assertTrue(((Map<?, ?>) hoverData).containsValue(Collections.singletonList(marker)));
assertTrue(((Map<?, ?>) hoverData).containsValue(AlrightyHoverProvider.LABEL));
assertFalse(((Map<?, ?>) hoverData).containsValue(HelloHoverProvider.LABEL));
// check dialog content
Shell shell= getHoverShell(manager, true);
assertNotNull(findControl(shell, Label.class, marker.getAttribute(IMarker.MESSAGE, "NONE")));
assertNotNull(findControl(shell, StyledText.class, AlrightyHoverProvider.LABEL));
assertNull(findControl(shell, StyledText.class, HelloHoverProvider.LABEL));
// check quick-fix works
Link link= findControl(shell, Link.class, MarkerResolutionGenerator.FIXME);
assertNotNull(link);
Event event= new Event();
event.widget= link;
event.display= link.getDisplay();
event.doit= true;
event.type= SWT.Selection;
link.notifyListeners(SWT.Selection, event);
final IMarker m= marker;
new DisplayHelper() {
@Override
protected boolean condition() {
return !m.exists();
}
}.waitForCondition(event.display, 1000);
assertFalse(marker.exists());
} finally {
if (marker != null && marker.exists()) {
marker.delete();
}
}
}
private Shell getHoverShell(AbstractInformationControlManager manager, boolean failOnError) {
AbstractInformationControl[] control= { null };
new DisplayHelper() {
@Override
protected boolean condition() {
control[0]= (AbstractInformationControl) new Accessor(manager, AbstractInformationControlManager.class).get("fInformationControl");
return control[0] != null;
}
}.waitForCondition(this.editor.getSite().getShell().getDisplay(), 5000);
if (control[0] == null) {
if (failOnError) {
ScreenshotTest.takeScreenshot(getClass(), testName.getMethodName(), System.out);
fail();
} else {
return null;
}
}
Shell shell= (Shell) new Accessor(control[0], AbstractInformationControl.class).get("fShell");
new DisplayHelper() {
@Override
protected boolean condition() {
return shell.isVisible();
}
}.waitForCondition(this.editor.getSite().getShell().getDisplay(), 2000);
if (failOnError) {
assertTrue(shell.isVisible());
}
return shell;
}
private <T extends Control> T findControl(Control control, Class<T> controlType, String label) {
if (control.getClass() == controlType) {
@SuppressWarnings("unchecked")
T res= (T) control;
if (label == null) {
return res;
}
String controlLabel= null;
if (control instanceof Label) {
controlLabel= ((Label) control).getText();
} else if (control instanceof Link) {
controlLabel= ((Link) control).getText();
} else if (control instanceof Text) {
controlLabel= ((Text) control).getText();
} else if (control instanceof StyledText) {
controlLabel= ((StyledText) control).getText();
}
if (controlLabel != null && controlLabel.contains(label)) {
return res;
}
} else if (control instanceof Composite) {
for (Control child : ((Composite) control).getChildren()) {
T res= findControl(child, controlType, label);
if (res != null) {
return res;
}
}
}
return null;
}
private Object getHoverData(AbstractInformationControlManager manager) {
Object hoverData= new Accessor(manager, AbstractInformationControlManager.class).get("fInformation");
return hoverData;
}
private AbstractInformationControlManager triggerCompletionAndRetrieveInformationControlManager() {
final int caretLocation= 2;
this.editor.selectAndReveal(caretLocation, 0);
final StyledText editorTextWidget= (StyledText) this.editor.getAdapter(Control.class);
new DisplayHelper() {
@Override
protected boolean condition() {
return editorTextWidget.isFocusControl() && editorTextWidget.getSelection().x == caretLocation;
}
}.waitForCondition(editorTextWidget.getDisplay(), 3000);
// sending event to trigger hover computation
editorTextWidget.getShell().forceActive();
editorTextWidget.getShell().setActive();
editorTextWidget.getShell().setFocus();
editorTextWidget.getShell().getDisplay().wake();
Event hoverEvent= new Event();
hoverEvent.widget= editorTextWidget;
hoverEvent.type= SWT.MouseHover;
hoverEvent.x= editorTextWidget.getClientArea().x + 5;
hoverEvent.y= editorTextWidget.getClientArea().y + 5;
hoverEvent.display= editorTextWidget.getDisplay();
hoverEvent.doit= true;
editorTextWidget.getDisplay().setCursorLocation(editorTextWidget.toDisplay(hoverEvent.x, hoverEvent.y));
editorTextWidget.notifyListeners(SWT.MouseHover, hoverEvent);
ITextViewer viewer= (ITextViewer) new Accessor(editor, AbstractTextEditor.class).invoke("getSourceViewer", new Object[0]);
AbstractInformationControlManager textHoverManager= (AbstractInformationControlManager) new Accessor(viewer, TextViewer.class).get("fTextHoverManager");
// retrieving hover content
new DisplayHelper() {
@Override
protected boolean condition() {
return getHoverData(textHoverManager) != null;
}
}.waitForCondition(hoverEvent.display, 6000);
return textHoverManager;
}
}