Skip to content

Content of file TableControlSWTRenderer_ITest.java

/*******************************************************************************
 * 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)); } }