aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrik <patrik@vaadin.com>2015-04-16 11:26:35 +0300
committerVaadin Code Review <review@vaadin.com>2015-04-16 11:40:58 +0000
commit255da01eb1208ac5b2f0994bb16f9b370d33bfab (patch)
treea578cf5ac55921ec4d1896f97b84e76d601fac51
parent522c3dd8f3b64e772f7e41205308fc24a56426f4 (diff)
downloadvaadin-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.java175
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;
+ }
+}