diff options
author | patrik <patrik@vaadin.com> | 2015-04-16 11:26:35 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2015-04-16 11:40:58 +0000 |
commit | 255da01eb1208ac5b2f0994bb16f9b370d33bfab (patch) | |
tree | a578cf5ac55921ec4d1896f97b84e76d601fac51 | |
parent | 522c3dd8f3b64e772f7e41205308fc24a56426f4 (diff) | |
download | vaadin-framework-255da01eb1208ac5b2f0994bb16f9b370d33bfab.tar.gz vaadin-framework-255da01eb1208ac5b2f0994bb16f9b370d33bfab.zip |
Create declarative UI test harness (#17484)
Change-Id: I8d83830f897b50a73f2fa125d297457f7a90888c
-rw-r--r-- | uitest/src/com/vaadin/tests/components/DeclarativeTestUI.java | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/uitest/src/com/vaadin/tests/components/DeclarativeTestUI.java b/uitest/src/com/vaadin/tests/components/DeclarativeTestUI.java new file mode 100644 index 0000000000..568c484760 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/DeclarativeTestUI.java @@ -0,0 +1,175 @@ +/* + * Copyright 2000-2014 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.components; + +import java.io.File; +import java.io.FileInputStream; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.Component; +import com.vaadin.ui.declarative.Design; + +/** + * Declarative test UI. Provides simple instantiation of HTML designs located + * under {@code uitest/src}. Also provides {@link OnLoad} annotation that lets + * you easily hook up methods to run after the UI has been created. Note: you + * <i>must</i> add the {@link DeclarativeUI} annotation to your subclass; not + * doing this will result in program failure. + */ +@SuppressWarnings("serial") +public class DeclarativeTestUI extends AbstractTestUI { + + private Logger logger; + private Component component; + + /** + * Class marker indicating the design .html file to load + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public static @interface DeclarativeUI { + String value(); + + /** + * Set this property to true if you provide an absolute path to your + * design; otherwise, the DeclarativeTestUI logic will look for the HTML + * design file under {@code vaadin_project/uitest/src/<package path>/}. + */ + boolean absolutePath() default false; + } + + /** + * Method marker interface indicating that a method should be run after the + * declarative UI has been created + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public static @interface OnLoad { + + } + + /** + * Figure out the proper path for the HTML design file + */ + private String getDesignPath() { + Class<?> clazz = getClass(); + String designFilePath = null; + if (clazz.getAnnotation(DeclarativeUI.class).absolutePath()) { + designFilePath = ""; + } else { + // This is rather nasty.. but it works well enough for now. + String userDir = System.getProperty("user.dir"); + designFilePath = userDir + "/uitest/src/" + + clazz.getPackage().getName().replace('.', '/') + "/"; + } + + String designFileName = clazz.getAnnotation(DeclarativeUI.class) + .value(); + + return designFilePath + designFileName; + } + + private Component readDesign() throws Exception { + String path = getDesignPath(); + getLogger().log(Level.INFO, "Reading design from " + path); + + File file = new File(path); + return Design.read(new FileInputStream(file)); + } + + @Override + protected void setup(VaadinRequest request) { + Class<?> clazz = getClass(); + + if (clazz.isAnnotationPresent(DeclarativeUI.class)) { + + // Create component + try { + component = readDesign(); + } catch (Exception e1) { + getLogger().log(Level.SEVERE, "Error reading design", e1); + return; + } + + addComponent(component); + + // Call on-load methods (if applicable) + Method[] methods = clazz.getMethods(); + for (Method m : methods) { + if (m.isAnnotationPresent(OnLoad.class)) { + try { + m.invoke(this, (Object[]) null); + } catch (IllegalAccessException e) { + getLogger().log(Level.SEVERE, + "Error invoking @OnLoad method", e); + return; + } catch (IllegalArgumentException e) { + getLogger().log(Level.SEVERE, + "Error invoking @OnLoad method", e); + return; + } catch (InvocationTargetException e) { + getLogger().log(Level.SEVERE, + "Error invoking @OnLoad method", e); + return; + } + } + } + + } else { + throw new IllegalStateException( + "Cannot find declarative UI annotation"); + } + } + + /** + * Get access to the declaratively created component. This method typecasts + * the component to the receiving type; if there's a mismatch between what + * you expect and what's written in the design, this will fail with a + * ClassCastException. + * + * @return a Vaadin component + */ + @SuppressWarnings("unchecked") + public <T extends Component> T getComponent() { + try { + return (T) component; + } catch (ClassCastException ex) { + getLogger().log(Level.SEVERE, + "Component code/design type mismatch", ex); + } + return null; + } + + /** + * Get access to the logger of this class + * + * @return a Logger instance + */ + protected Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(getClass().getName()); + } + return logger; + } +} |