/* * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.vaadin.tests.server.component.abstractlisting; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.function.Consumer; import org.junit.Assert; import org.junit.Test; import com.vaadin.data.provider.Query; import com.vaadin.server.ExternalResource; import com.vaadin.server.FileResource; import com.vaadin.server.Resource; import com.vaadin.server.SerializablePredicate; import com.vaadin.server.ThemeResource; import com.vaadin.tests.design.DeclarativeTestBaseBase; import com.vaadin.tests.server.component.abstractcomponent.AbstractComponentDeclarativeTestBase; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.AbstractListing; import com.vaadin.ui.IconGenerator; import com.vaadin.ui.ItemCaptionGenerator; import com.vaadin.ui.declarative.DesignContext; /** * {@link AbstractListing} component declarative test. * <p> * Test ignores comparison for {@link ItemCaptionGenerator}, * {@link IconGenerator} and {@link SerializablePredicate} "properties" since * they are functions and it doesn't matter which implementation is chosen. But * test checks generated item captions, item icon generation and enabled items * generations if they are available in the component as public methods. * <p> * Common {@link AbstractComponent} properties are tested in * {@link AbstractComponentDeclarativeTestBase} * * @see AbstractComponentDeclarativeTestBase * * @author Vaadin Ltd * * * @param <T> * a component type */ @SuppressWarnings({ "unchecked", "rawtypes" }) public abstract class AbstractListingDeclarativeTest<T extends AbstractListing> extends AbstractComponentDeclarativeTestBase<T> { private static final String EXTERNAL_URL = "http://example.com/example.gif"; private static final String FILE_PATH = "img/example.gif"; private static final String THEME_PATH = "example.gif"; @Test public abstract void dataSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException; @Test public abstract void valueSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException; @Test public void itemIconsSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException { T component = getComponentClass().newInstance(); Method setIconGenerator = getIconGeneratorMethod(component); if (setIconGenerator == null) { return; } List<String> items = Arrays.asList("foo", "bar", "foobar", "barfoo"); String design = String.format( "<%s>\n" + "<option item='foo' icon='%s'>foo</option>\n" + "<option item='bar' icon='%s'>bar</option>" + "<option item='foobar' icon='theme://%s'>foobar</option>" + "<option item='barfoo'>barfoo</option>" + "</%s>", getComponentTag(), EXTERNAL_URL, FILE_PATH, THEME_PATH, getComponentTag()); component.setItems(items); IconGenerator generator = item -> generateIcons(item, items); setIconGenerator.invoke(component, generator); testRead(design, component); testWrite(design, component, true); } @Test public void enabledItemsSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException { T component = getComponentClass().newInstance(); Method setEnabledITemsGenerator = getEnabledItemsProviderMethod( component); if (setEnabledITemsGenerator == null) { return; } List<String> items = Arrays.asList("foo", "bar", "foobar"); String design = String.format( "<%s>\n" + "<option item='foo'>foo</option>\n" + "<option item='bar' disabled>bar</option>" + "<option item='foobar'>foobar</option>", getComponentTag(), getComponentTag()); component.setItems(items); SerializablePredicate predicate = item -> !item.equals("bar"); setEnabledITemsGenerator.invoke(component, predicate); testRead(design, component); testWrite(design, component, true); } @Test public abstract void readOnlySelection() throws InstantiationException, IllegalAccessException, InvocationTargetException; @Override protected boolean acceptProperty(Class<?> clazz, Method readMethod, Method writeMethod) { if (readMethod != null) { Class<?> returnType = readMethod.getReturnType(); if (ItemCaptionGenerator.class.equals(returnType) || IconGenerator.class.equals(returnType) || SerializablePredicate.class.equals(returnType)) { return false; } } return super.acceptProperty(clazz, readMethod, writeMethod); } public DesignContext readComponentAndCompare(String design, T expected, Consumer<DesignContext> configureContext) { DesignContext context = super.readComponentAndCompare(design, expected); configureContext.accept(context); T read = (T) context.getRootComponent(); testReadData(design, expected, read, context); return context; } public T testRead(String design, T expected, boolean testWrite) { T read = testRead(design, expected); if (testWrite) { DesignContext context = new DesignContext(); context.setShouldWriteDataDelegate( DeclarativeTestBaseBase.ALWAYS_WRITE_DATA); testReadData(design, expected, read, context); } return read; } private void testReadData(String design, T expected, T read, DesignContext context) { Assert.assertEquals( read.getDataCommunicator().getDataProvider() .size(new Query<>()), expected.getDataCommunicator().getDataProvider() .size(new Query<>())); testWrite(read, design, context); } private Method getIconGeneratorMethod(T component) throws IllegalAccessException, InvocationTargetException { try { return component.getClass().getMethod("setItemIconGenerator", new Class[] { IconGenerator.class }); } catch (NoSuchMethodException ignore) { // ignore if there is no such method return null; } } private Method getEnabledItemsProviderMethod(T component) throws IllegalAccessException, InvocationTargetException { try { return component.getClass().getMethod("setItemEnabledProvider", new Class[] { SerializablePredicate.class }); } catch (NoSuchMethodException ignore) { // ignore if there is no such method return null; } } private Resource generateIcons(Object item, List<String> items) { int index = items.indexOf(item); switch (index) { case 0: return new ExternalResource(EXTERNAL_URL); case 1: return new FileResource(new File(FILE_PATH)); case 2: return new ThemeResource(THEME_PATH); } return null; } }