blob: 5f49af0149116ae589bb2c4117e74dcfcb8e4938 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2019 EclipseSource Muenchen GmbH and others.
*
* All rights reserved. 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:
* remi - initial API and implementation
* Christian W. Damus - add test for null inputs to applyValidation(...)
******************************************************************************/
package org.eclipse.emf.ecp.view.spi.table.swt;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.databinding.EObjectObservableValue;
import org.eclipse.emf.databinding.IEMFValueProperty;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecp.view.model.common.AbstractGridCell.Alignment;
import org.eclipse.emf.ecp.view.model.common.AbstractRenderer;
import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
import org.eclipse.emf.ecp.view.spi.model.LabelAlignment;
import org.eclipse.emf.ecp.view.spi.model.VDiagnostic;
import org.eclipse.emf.ecp.view.spi.model.VElement;
import org.eclipse.emf.ecp.view.spi.model.VFeaturePathDomainModelReference;
import org.eclipse.emf.ecp.view.spi.model.VViewFactory;
import org.eclipse.emf.ecp.view.spi.table.model.VTableControl;
import org.eclipse.emf.ecp.view.spi.table.swt.TableControlSWTRenderer.ECPTableEditingSupport;
import org.eclipse.emf.ecp.view.spi.table.swt.TableControlSWTRenderer.ECPTableEditingSupport.EditingState;
import org.eclipse.emf.ecp.view.spi.util.swt.ImageRegistryService;
import org.eclipse.emf.ecp.view.template.model.VTStyleProperty;
import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
import org.eclipse.emf.ecp.view.template.style.tableStyleProperty.model.RenderMode;
import org.eclipse.emf.ecp.view.template.style.tableStyleProperty.model.VTTableStyleProperty;
import org.eclipse.emf.ecp.view.template.style.tableStyleProperty.model.VTTableStylePropertyFactory;
import org.eclipse.emfforms.common.Optional;
import org.eclipse.emfforms.internal.core.services.databinding.DefaultRealm;
import org.eclipse.emfforms.spi.common.report.ReportService;
import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
import org.eclipse.emfforms.spi.core.services.databinding.emf.EMFFormsDatabindingEMF;
import org.eclipse.emfforms.spi.core.services.editsupport.EMFFormsEditSupport;
import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider;
import org.eclipse.emfforms.spi.swt.core.layout.SWTGridCell;
import org.eclipse.emfforms.spi.swt.core.layout.SWTGridDescription;
import org.eclipse.jface.viewers.TableViewer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
/**
* Basic tests around {@link TableControlSWTRenderer}.
*/
@SuppressWarnings("restriction")
public class TableControlSWTRenderer_ITest {
private EPackage ePackage;
private EClass eClass1;
private DefaultRealm realm;
private VTableControl vElement;
private ViewModelContext viewContext;
private ReportService reportService;
private EMFFormsDatabindingEMF emfFormsDatabinding;
private EMFFormsLabelProvider emfFormsLabelProvider;
private VTViewTemplateProvider vtViewTemplateProvider;
private ImageRegistryService imageRegistryService;
private EMFFormsEditSupport emfFormsEditSupport;
@Before
public void before() {
ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("pack1");
eClass1 = EcoreFactory.eINSTANCE.createEClass();
ePackage.getEClassifiers().add(eClass1);
realm = new DefaultRealm();
vElement = mock(VTableControl.class);
viewContext = mock(ViewModelContext.class);
reportService = mock(ReportService.class);
emfFormsDatabinding = mock(EMFFormsDatabindingEMF.class);
emfFormsLabelProvider = mock(EMFFormsLabelProvider.class);
vtViewTemplateProvider = mock(VTViewTemplateProvider.class);
imageRegistryService = mock(ImageRegistryService.class);
emfFormsEditSupport = mock(EMFFormsEditSupport.class);
}
@After
public void after() {
realm.dispose();
}
private void setupCompact() {
final Set<VTStyleProperty> properties = new HashSet<VTStyleProperty>();
final VTTableStyleProperty tableStyleProperty = VTTableStylePropertyFactory.eINSTANCE
.createTableStyleProperty();
tableStyleProperty.setRenderMode(RenderMode.COMPACT_VERTICALLY);
properties.add(tableStyleProperty);
Mockito.when(vtViewTemplateProvider.getStyleProperties(Matchers.any(VElement.class),
Matchers.any(ViewModelContext.class))).thenReturn(properties);
}
@Test
public void getSettingFromObservable_simple() throws DatabindingFailedException {
final EStructuralFeature feature = EcorePackage.Literals.ENAMED_ELEMENT__NAME;
final Optional<Setting> result = doGetSettingFromObservable(feature, ePackage, ePackage);
assertThat(result.isPresent(), is(true));
assertThat(ePackage, equalTo(result.get().getEObject()));
assertThat(feature, equalTo(result.get().getEStructuralFeature()));
}
protected Optional<Setting> doGetSettingFromObservable(EStructuralFeature feature, EObject mainObject,
EObject observed) throws DatabindingFailedException {
final TableControlSWTRenderer renderer = mock(TableControlSWTRenderer.class);
final VFeaturePathDomainModelReference dmr = VViewFactory.eINSTANCE.createFeaturePathDomainModelReference();
dmr.setDomainModelEFeature(feature);
final IEMFValueProperty valueProperty = EMFProperties.value(feature);
final EObjectObservableValue observableValue = (EObjectObservableValue) EMFObservables.observeValue(
realm, observed,
feature);
final EMFFormsDatabindingEMF db = mock(EMFFormsDatabindingEMF.class);
Mockito.when(renderer.getEMFFormsDatabinding()).thenReturn(db);
when(db.getValueProperty(dmr, mainObject)).thenReturn(valueProperty);
when(db.getObservableValue(dmr, mainObject)).thenReturn(observableValue);
Mockito.when(renderer.getSettingFromObservable(dmr, mainObject)).thenCallRealMethod();
return renderer.getSettingFromObservable(dmr, mainObject);
}
protected TableControlSWTRenderer createNonMockRenderer() {
return new TableControlSWTRenderer(vElement, viewContext, reportService, emfFormsDatabinding,
emfFormsLabelProvider, vtViewTemplateProvider, imageRegistryService, emfFormsEditSupport);
}
@Test
public void getSettingFromObservable_noFeature() throws DatabindingFailedException {
final EStructuralFeature feature = EcorePackage.Literals.ECLASS__ABSTRACT;
final Optional<Setting> result = doGetSettingFromObservable(feature, ePackage, ePackage);
assertThat(result.isPresent(), is(false));
}
@Test
public void getSettingFromObservable_differentObserved() throws DatabindingFailedException {
final EStructuralFeature feature = EcorePackage.Literals.ECLASS__EOPERATIONS;
final Optional<Setting> result = doGetSettingFromObservable(feature, ePackage, eClass1);
assertThat(result.isPresent(), is(true));
assertThat(eClass1, equalTo(result.get().getEObject()));
assertThat(feature, equalTo(result.get().getEStructuralFeature()));
}
@Test
public void getSettingFromObservable_differentObservedNoFeature() throws DatabindingFailedException {
final EStructuralFeature feature = EcorePackage.Literals.EPACKAGE__ESUBPACKAGES;
final Optional<Setting> result = doGetSettingFromObservable(feature, ePackage, eClass1);
assertThat(result.isPresent(), is(false));
}
@Test
public void getSettingFromObservable_observedNull() throws DatabindingFailedException {
final EStructuralFeature feature = EcorePackage.Literals.EPACKAGE__ESUBPACKAGES;
final Optional<Setting> result = doGetSettingFromObservable(feature, ePackage, null);
assertThat(result.isPresent(), is(false));
}
@Test
public void getSettingFromObservable_databindingException()
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException,
DatabindingFailedException {
final EStructuralFeature feature = EcorePackage.Literals.EPACKAGE__ESUBPACKAGES;
final TableControlSWTRenderer renderer = mock(TableControlSWTRenderer.class);
final DatabindingFailedException dbfe = new DatabindingFailedException("testing");
final ReportService reportService = mock(ReportService.class);
final Field field = AbstractRenderer.class.getDeclaredField("reportService");
field.setAccessible(true);
field.set(renderer, reportService);
final VFeaturePathDomainModelReference dmr = VViewFactory.eINSTANCE.createFeaturePathDomainModelReference();
dmr.setDomainModelEFeature(feature);
final EMFFormsDatabindingEMF db = mock(EMFFormsDatabindingEMF.class);
Mockito.when(renderer.getEMFFormsDatabinding()).thenReturn(db);
when(db.getObservableValue(dmr, ePackage)).thenThrow(dbfe);
Mockito.when(renderer.getSettingFromObservable(dmr, ePackage)).thenCallRealMethod();
final Optional<Setting> result = renderer.getSettingFromObservable(dmr, ePackage);
assertThat(result.isPresent(), is(false));
}
@Test
public void getGridDescription_WithLabel() {
setupCompact();
when(vElement.getLabelAlignment()).thenReturn(LabelAlignment.DEFAULT);
final TableControlSWTRenderer renderer = createNonMockRenderer();
final SWTGridDescription gridDescription = renderer.getGridDescription(null);
assertThat(gridDescription.getColumns(), is(equalTo(3)));
assertLabelCell(gridDescription.getGrid().get(0));
assertValidationCell(gridDescription.getGrid().get(1));
assertMainCell(gridDescription.getGrid().get(2));
}
@Test
public void getGridDescription_WithoutLabel() {
setupCompact();
when(vElement.getLabelAlignment()).thenReturn(LabelAlignment.NONE);
final TableControlSWTRenderer renderer = createNonMockRenderer();
final SWTGridDescription gridDescription = renderer.getGridDescription(null);
assertThat(gridDescription.getColumns(), is(equalTo(2)));
assertValidationCell(gridDescription.getGrid().get(0));
assertMainCell(gridDescription.getGrid().get(1));
}
@Test
public void isUpdateNeeded_BothNull_ReturnFalse() {
/* setup */
final TableViewer tblViewer = mock(TableViewer.class);
final TableControlSWTRenderer renderer = mock(TableControlSWTRenderer.class);
final IObservableValue<?> target = mock(IObservableValue.class);
when(target.getValue()).thenReturn(null);
final IObservableValue<?> model = mock(IObservableValue.class);
when(model.getValue()).thenReturn(null);
final ECPTableEditingSupport editingSupport = renderer.new ECPTableEditingSupport(tblViewer, null, null, null);
final EditingState state = editingSupport.new EditingState(null, target, model);
/* act */
final boolean updateNeeded = state.isUpdateNeeded();
/* assert */
assertFalse(updateNeeded);
}
@Test
public void isUpdateNeeded_OnlyModelNull_ReturnTrue() {
/* setup */
final TableViewer tblViewer = mock(TableViewer.class);
final TableControlSWTRenderer renderer = mock(TableControlSWTRenderer.class);
@SuppressWarnings("unchecked")
final IObservableValue<Object> target = mock(IObservableValue.class);
when(target.getValue()).thenReturn(new Object());
final IObservableValue<?> model = mock(IObservableValue.class);
when(model.getValue()).thenReturn(null);
final ECPTableEditingSupport editingSupport = renderer.new ECPTableEditingSupport(tblViewer, null, null, null);
final EditingState state = editingSupport.new EditingState(null, target, model);
/* act */
final boolean updateNeeded = state.isUpdateNeeded();
/* assert */
assertTrue(updateNeeded);
}
@Test
public void isUpdateNeeded_TargetModelNull_ReturnTrue() {
/* setup */
final TableViewer tblViewer = mock(TableViewer.class);
final TableControlSWTRenderer renderer = mock(TableControlSWTRenderer.class);
@SuppressWarnings("unchecked")
final IObservableValue<Object> target = mock(IObservableValue.class);
when(target.getValue()).thenReturn(null);
@SuppressWarnings("unchecked")
final IObservableValue<Object> model = mock(IObservableValue.class);
when(model.getValue()).thenReturn(new Object());
final ECPTableEditingSupport editingSupport = renderer.new ECPTableEditingSupport(tblViewer, null, null, null);
final EditingState state = editingSupport.new EditingState(null, target, model);
/* act */
final boolean updateNeeded = state.isUpdateNeeded();
/* assert */
assertTrue(updateNeeded);
}
@Test
public void isUpdateNeeded_Same_ReturnFalse() {
/* setup */
final TableViewer tblViewer = mock(TableViewer.class);
final TableControlSWTRenderer renderer = mock(TableControlSWTRenderer.class);
@SuppressWarnings("unchecked")
final IObservableValue<String> target = mock(IObservableValue.class);
when(target.getValue()).thenReturn("VALUE");
@SuppressWarnings("unchecked")
final IObservableValue<String> model = mock(IObservableValue.class);
when(model.getValue()).thenReturn("VALUE");
final ECPTableEditingSupport editingSupport = renderer.new ECPTableEditingSupport(tblViewer, null, null, null);
final EditingState state = editingSupport.new EditingState(null, target, model);
/* act */
final boolean updateNeeded = state.isUpdateNeeded();
/* assert */
assertFalse(updateNeeded);
}
/**
* Simple test to verify that the {@link TableControlSWTRenderer#applyValidation(VDiagnostic, VDiagnostic)}
* method does not NPE on {@code null} inputs.
*/
@Test
public void applyValidation_VDiagnostic_VDiagnostic() {
final TableControlSWTRenderer fixture = spy(
new TableControlSWTRenderer(vElement, viewContext, reportService, emfFormsDatabinding,
emfFormsLabelProvider, vtViewTemplateProvider, imageRegistryService, emfFormsEditSupport));
doCallRealMethod().when(fixture).applyValidation(any(), any());
final Function<Boolean, VDiagnostic> diagnosticFactory = isNull -> {
VDiagnostic result = null;
if (!isNull) {
result = mock(VDiagnostic.class);
when(result.getDiagnostics()).thenReturn(ECollections.emptyEList());
}
return result;
};
final BiConsumer<Boolean, Boolean> testScenario = (oldIsNull, newIsNull) -> {
final VDiagnostic oldDiagnostic = diagnosticFactory.apply(oldIsNull);
final VDiagnostic newDiagnostic = diagnosticFactory.apply(newIsNull);
try {
fixture.applyValidation(oldDiagnostic, newDiagnostic);
if (oldDiagnostic != null) {
verify(oldDiagnostic).getDiagnostics();
}
if (newDiagnostic != null) {
verify(newDiagnostic).getDiagnostics();
}
} catch (final NullPointerException e) {
e.printStackTrace();
fail("Should not have got NPE");
}
};
// Case of old is not null, new is not null
testScenario.accept(false, false);
// Case of old is null, new is not null
testScenario.accept(true, false);
// Case of old is not null, new is null
testScenario.accept(false, true);
// Case of old is null, new is null
testScenario.accept(true, true);
}
private void assertLabelCell(SWTGridCell labelCell) {
assertThat(labelCell.getPreferredSize(), nullValue());
assertThat(labelCell.isHorizontalGrab(), is(false));
assertThat(labelCell.getVerticalAlignment(), is(Alignment.BEGINNING));
}
private void assertValidationCell(SWTGridCell validationCell) {
assertThat(validationCell.getPreferredSize(), notNullValue());
assertThat(validationCell.isHorizontalGrab(), is(false));
assertThat(validationCell.getVerticalAlignment(), is(Alignment.BEGINNING));
}
private void assertMainCell(SWTGridCell mainCell) {
assertThat(mainCell.getPreferredSize(), nullValue());
assertThat(mainCell.isHorizontalGrab(), is(true));
assertThat(mainCell.isVerticalGrab(), is(true));
}
}