blob: 16ed173974c54cef7b5fc53d8e15c62e7cf1d929 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 RCP Vision (http://www.rcp-vision.com) 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:
* Lorenzo Bettini - Initial contribution and API
*******************************************************************************/
package org.eclipse.emf.parsley.tests;
import static org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable.syncExec;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.allOf;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType;
import static org.eclipse.swtbot.swt.finder.waits.Conditions.shellCloses;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swtbot.eclipse.finder.exceptions.QuickFixNotFoundException;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.forms.finder.SWTFormsBot;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
import org.eclipse.swtbot.swt.finder.matchers.AbstractMatcher;
import org.eclipse.swtbot.swt.finder.results.Result;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.results.WidgetResult;
import org.eclipse.swtbot.swt.finder.utils.MessageFormat;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.waits.WaitForObjectCondition;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* @author Lorenzo Bettini
*
*/
@RunWith(SWTBotJunit4ClassRunner.class)
public class EmfParsleyFormTests extends EmfParsleySWTBotAbstractTests {
protected final Logger log = Logger.getLogger(getClass());
public EmfParsleyFormTests() {
log.setLevel(Level.DEBUG);
}
@Test
public void detailViewShowsDetailsOnSelection() throws Exception {
boolean editable = true;
SWTBotView detailView = openTestView(EMF_DETAIL_VIEW);
// select on the editor's tree
SWTBotTreeItem rootOfEditorTree = openEditorAndGetTreeRoot(EMF_TREE_EDITOR,
MY_EXTLIBRARY, MY_EXT_LIBRARY_PLATFORM_URI);
getLibraryWriterNode(rootOfEditorTree).select();
SWTFormsBot formbot = formBotFromView(detailView);
assertFormControlsOfWriterNode(formbot, editable);
// select on the outline view
getLibraryNode(getRootOfOutlineViewTree()).select();
assertFormControlsOfLibraryNode(formbot, editable);
// select the book
getLibraryBookNode(rootOfEditorTree).select();
assertFormControlsOfBookNode(formbot);
// select the damaged video cassette node
getLibraryDamagedVideoCassetteNode(rootOfEditorTree).select();
assertCheckBoxComponent(formbot, 0, true, true);
// now select again on the editor's tree
getLibraryWriterNode(rootOfEditorTree).select();
formbot.label(ADDRESS_LABEL);
assertTextComponent(formbot, WRITER_S_ADDRESS_TEXT, editable);
// detailView.close();
}
@Test
public void checkFormDatabinding() throws Exception {
SWTBotView detailView = openTestView(EMF_DETAIL_VIEW);
// select on the editor's tree
getLibraryNode(openEditorAndGetTreeRoot(EMF_TREE_EDITOR,
MY_EXTLIBRARY, MY_EXT_LIBRARY_PLATFORM_URI)).select();
modifyFormText(formBotFromView(detailView), LIBRARY_NAME);
assertEditorDirty(EMF_TREE_EDITOR);
getEditor(EMF_TREE_EDITOR).close();
}
@Test
public void checkSetReferenceToNull() throws Exception {
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=490463
SWTBotView detailView = openTestView(EMF_DETAIL_VIEW);
SWTFormsBot formbot = formBotFromView(detailView);
// select on the editor's tree
final SWTBotTreeItem rootOfEditorTree = openEditorAndGetTreeRoot(EMF_TREE_EDITOR,
MY_EXTLIBRARY, MY_EXT_LIBRARY_PLATFORM_URI);
getLibraryNode(rootOfEditorTree).select();
// select the book
getLibraryBookNode(rootOfEditorTree).select();
formbot.comboBox(WRITER_LABEL).setSelection("");
assertEditorDirty(EMF_TREE_EDITOR);
getEditor(EMF_TREE_EDITOR).close();
}
@Test
public void detailReadOnlyViewShowsDetailsOnSelection() throws Exception {
boolean editable = false;
SWTBotView detailView = openTestView(EMF_DETAIL_READONLY_VIEW);
// select on the editor's tree
SWTBotTreeItem rootOfEditorTree = openEditorAndGetTreeRoot(EMF_TREE_EDITOR,
MY_EXTLIBRARY, MY_EXT_LIBRARY_PLATFORM_URI);
getLibraryWriterNode(rootOfEditorTree).select();
SWTFormsBot formbot = formBotFromView(detailView);
formbot.label(ADDRESS_LABEL);
assertTextComponent(formbot, WRITER_S_ADDRESS_TEXT, editable);
formbot.label(FIRSTNAME_LABEL);
// Button "..." must not be present in readonly mode
assertNoButton(formbot, detailView);
// select on the outline view
getLibraryNode(getRootOfOutlineViewTree()).select();
formbot.label(ADDRESS_LABEL);
assertTextComponent(formbot, LIBRARY_S_ADDRESS_TEXT, editable);
// the label for 'people'
formbot.label(PEOPLE_LABEL);
// the inner label listing all the people, before the button "..."
formbot.label(PEOPLE_TEXT);
// select the book
getLibraryBookNode(rootOfEditorTree).select();
formbot.label(AUTHOR_LABEL);
// in readonly mode it is a Text component
assertTextComponent(formbot, WRITER_LABEL, editable);
// select the damaged video cassette node
getLibraryDamagedVideoCassetteNode(rootOfEditorTree).select();
// in readonly mode the checkbox must not be enabled
assertCheckBoxComponent(formbot, 0, true, false);
// now select again on the editor's tree
getLibraryWriterNode(rootOfEditorTree).select();
formbot.label(ADDRESS_LABEL);
assertTextComponent(formbot, WRITER_S_ADDRESS_TEXT, editable);
// detailView.close();
}
@SuppressWarnings({ "unchecked" })
protected void assertNoButton(SWTFormsBot formbot, SWTBotView view) {
Matcher<Control> allOf = allOf(widgetOfType(Control.class));
List<? extends Control> controls = formbot.widgets(allOf,
view.getWidget());
for (Control c : controls) {
Assert.assertFalse("Expected no Button!", c instanceof Button);
}
}
@Test
public void treeFormViewShowsOnSelection() throws Exception {
SWTBotView view = openTestView(EMF_TREE_FORM_DETAIL_VIEW);
// select on the editor's tree
SWTBotTreeItem rootOfEditorTree = openEditorAndGetTreeRoot(EMF_TREE_EDITOR,
MY_EXTLIBRARY, MY_EXT_LIBRARY_PLATFORM_URI);
// select on the editor
getLibraryNode(rootOfEditorTree).select();
// now select on the tree inside the view
view.bot().tree().getTreeItem(WRITER_LABEL).select();
SWTFormsBot formbot = formBotFromView(view);
formbot.label(ADDRESS_LABEL);
formbot.text(WRITER_S_ADDRESS_TEXT);
formbot.label(FIRSTNAME_LABEL);
}
@Test
public void testMultipleFeatureControlDialog() throws Exception {
SWTBotView detailView = openTestView(LIBRARY_CUSTOM_DETAIL_VIEW);
// select on the editor's tree
SWTBotTreeItem rootOfEditorTree = openEditorAndGetTreeRoot(EMF_TREE_EDITOR,
MY_EXTLIBRARY, MY_EXT_LIBRARY_PLATFORM_URI);
getLibraryBookNode(rootOfEditorTree).select();
SWTFormsBot formbot = formBotFromView(detailView);
formbot.button("...").click();
SWTBotShell shell = bot.shell("Select -- Book: Lorenzo's Book");
shell.activate();
// simulate the addition of a borrower in the dialog
bot.table(0).select("Borrower: Foo"); // left table
bot.button("Add").click();
// is the additional proposal there?
bot.table(0).select("Borrower: Fake Borrower"); // left table
// now the borrower should be in the right table
bot.table(1).select("Borrower: Foo"); // right table
bot.button("OK").click();
bot.waitUntil(shellCloses(shell), SWTBotPreferences.TIMEOUT);
// check that the selected borrower has been added
formbot.label("Borrower: Foo");
getEditor(EMF_TREE_EDITOR).close();
}
// @Test This test fails too often probably due to some missed
// synchronization... however, the interesting one is
// testContentAssistInFormAndSelect
// so I'll comment this out (Lorenzo)
public void testContentAssistInFormContainsProposals() throws Exception {
SWTFormsBot formbot = setupFormForContentAssistTest();
SWTBotText text = formbot.textWithLabel(STRING_FEATURE_LABEL);
List<String> proposals = getContentAssistProposals(text);
assertEquals("[First Proposal, Second Proposal]", proposals.toString());
getEditor(EMF_TREE_EDITOR).close();
}
@Test
public void testContentAssistInFormAndSelect() throws Exception {
if (!isIndigo()) {
SWTFormsBot formbot = setupFormForContentAssistTest();
SWTBotText text = formbot.textWithLabel(STRING_FEATURE_LABEL);
// select the content assist proposal
selectContentAssistProposal(text, "Second Proposal");
// and check that the text has changed
formbot.text("Second Proposal");
getEditor(EMF_TREE_EDITOR).saveAndClose();
}
}
private SWTFormsBot setupFormForContentAssistTest() throws CoreException,
InvocationTargetException, InterruptedException, IOException {
SWTBotView detailView = openTestView(CUSTOM_PROPOSALS_FORM_VIEW);
// select on the editor's tree
SWTBotTreeItem rootOfEditorTree = openEditorAndGetTreeRoot(EMF_TREE_EDITOR,
TEST_CONTAINER, TEST_CONTAINER_PLATFORM_URI);
getClassForControlsNode(rootOfEditorTree).select();
SWTFormsBot formbot = formBotFromView(detailView);
return formbot;
}
public List<String> getContentAssistProposals(SWTBotText text) {
WaitForObjectCondition<SWTBotTable> autoCompleteAppears = autoCompleteAppears(text, tableWithRows());
waitUntil(autoCompleteAppears);
final SWTBotTable autoCompleteTable = autoCompleteAppears.get(0);
List<String> proposals = getRows(autoCompleteTable);
makeProposalsDisappear(text);
return proposals;
}
public void selectContentAssistProposal(SWTBotText text, String proposalText) {
WaitForObjectCondition<SWTBotTable> autoCompleteTable = autoCompleteAppears(text, tableWithRows());
waitUntil(autoCompleteTable);
selectProposal(autoCompleteTable.get(0), proposalText);
}
private WaitForObjectCondition<SWTBotTable> autoCompleteAppears(final SWTBotText text, Matcher<SWTBotTable> tableMatcher) {
return new WaitForObjectCondition<SWTBotTable>(tableMatcher) {
@Override
protected List<SWTBotTable> findMatches() {
try {
text.pressShortcut(SWT.CTRL, 0, ' ');
SWTBotTable autoCompleteTable = getProposalTable(text);
if (matcher.matches(autoCompleteTable)) {
log.debug("matched table, returning");
return Arrays.asList(autoCompleteTable);
}
} catch (Throwable e) {
makeProposalsDisappear(text);
}
return null;
}
@Override
public String getFailureMessage() {
return "Could not find auto complete proposal using matcher " + matcher;
}
};
}
private SWTBotTable getProposalTable(SWTBotText text) {
log.debug("Finding table containing proposals.");
try {
Table table = bot.widget(widgetOfType(Table.class), activatePopupShell(text).widget);
SWTBotTable swtBotTable = new SWTBotTable(table);
log.debug(MessageFormat.format("Found table containing proposals -- {0}", getRows(swtBotTable)));
return swtBotTable;
} catch (Exception e) {
throw new QuickFixNotFoundException("Quickfix options not found. Giving up.", e); //$NON-NLS-1$
}
}
private Matcher<SWTBotTable> tableWithRows() {
return new AbstractMatcher<SWTBotTable>() {
@Override
protected boolean doMatch(Object item) {
List<String> rows = getRows((SWTBotTable) item);
return !rows.isEmpty();
}
@Override
public void describeTo(Description description) {
description.appendText("table with rows");
}
};
}
private SWTBotShell activatePopupShell(final SWTBotText text) {
log.debug("Activating quickfix shell."); //$NON-NLS-1$
try {
Shell mainWindow = syncExec(new WidgetResult<Shell>() {
@Override
public Shell run() {
return text.widget.getShell();
}
});
final List<Shell> shells = bot.shells("", mainWindow);
log.debug(MessageFormat.format("Obtained shells: {0}",
syncExec(new Result<String>() {
@Override
public String run() {
return shells.toString();
}
}))); //$NON-NLS-1$
Shell widgetShell = syncExec(new WidgetResult<Shell>() {
@Override
public Shell run() {
for(int j=0; j<shells.size(); j++) {
Shell s = shells.get(j);
Control[] children = s.getChildren();
for (int i = 0; i < children.length; i++) {
//Select shell which has content assist table
log.debug(MessageFormat.format("Examining shell: {0}",
children[i].getClass().getName()));
if(children[i] instanceof Composite) {
log.debug("Found Composite");
return s;
}
}
}
return shells.get(0);
}
});
SWTBotShell shell = new SWTBotShell(widgetShell);
shell.activate();
log.debug("Activated quickfix shell."); //$NON-NLS-1$
return shell;
} catch (Exception e) {
throw new QuickFixNotFoundException("Quickfix popup not found. Giving up.", e); //$NON-NLS-1$
}
}
private List<String> getRows(SWTBotTable table) {
int rowCount = table.rowCount();
List<String> result = new ArrayList<String>();
for (int i = 0; i < rowCount; i++)
result.add(table.cell(i, 0));
return result;
}
private void selectProposal(SWTBotTable proposalTable, String proposalText) {
log.debug(MessageFormat.format("Trying to select proposal {0}", proposalText)); //$NON-NLS-1$
if (proposalTable.containsItem(proposalText)) {
selectProposal(proposalTable, proposalTable.indexOf(proposalText));
return;
}
throw new QuickFixNotFoundException("Quickfix options not found. Giving up."); //$NON-NLS-1$
}
private void selectProposal(final SWTBotTable proposalTable, final int proposalIndex) {
log.debug(MessageFormat.format("Trying to select proposal with index {0}", proposalIndex)); //$NON-NLS-1$
UIThreadRunnable.syncExec(new VoidResult() {
@Override
public void run() {
Table table = proposalTable.widget;
log.debug(MessageFormat.format("Selecting row [{0}] {1} in {2}", proposalIndex, table.getItem(proposalIndex).getText(), //$NON-NLS-1$
table));
table.setSelection(proposalIndex);
Event event = new Event();
event.type = SWT.Selection;
event.widget = table;
event.item = table.getItem(proposalIndex);
table.notifyListeners(SWT.Selection, event);
table.notifyListeners(SWT.DefaultSelection, event);
}
});
}
private void makeProposalsDisappear(SWTBotText text) {
// clear away all content assists for next retry.
log.debug("Making proposals disappear.");
text.setFocus();
}
private void waitUntil(WaitForObjectCondition<SWTBotTable> table) {
bot.waitUntil(table, SWTBotPreferences.TIMEOUT);
}
}