001 /*
002 * Copyright 2008-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package griffon.javafx.test;
017
018 import griffon.core.ApplicationEvent;
019 import griffon.core.RunnableWithArgs;
020 import griffon.core.env.Environment;
021 import griffon.exceptions.GriffonException;
022 import griffon.javafx.JavaFXGriffonApplication;
023 import javafx.stage.Window;
024 import org.awaitility.Duration;
025 import org.codehaus.griffon.runtime.core.DefaultGriffonApplication;
026 import org.codehaus.griffon.runtime.javafx.TestJavaFXGriffonApplication;
027 import org.junit.rules.MethodRule;
028 import org.junit.runners.model.FrameworkMethod;
029 import org.junit.runners.model.Statement;
030 import org.testfx.api.FxToolkit;
031
032 import javax.annotation.Nonnull;
033 import javax.annotation.Nullable;
034 import java.util.concurrent.TimeoutException;
035
036 import static griffon.javafx.test.TestContext.getTestContext;
037 import static griffon.util.GriffonNameUtils.requireNonBlank;
038 import static java.util.Objects.requireNonNull;
039 import static java.util.concurrent.TimeUnit.SECONDS;
040 import static org.awaitility.Awaitility.await;
041
042 /**
043 * A JUnit Rule that starts an application for each test method.
044 *
045 * @author Andres Almiray
046 * @since 2.3.0
047 */
048 public class GriffonTestFXRule extends TestFX implements MethodRule {
049 protected String windowName;
050 protected Duration timeout;
051 protected String[] startupArgs;
052 protected Class<? extends TestJavaFXGriffonApplication> applicationClass;
053 protected JavaFXGriffonApplication application;
054
055 public GriffonTestFXRule(@Nonnull String windowName) {
056 this(TestJavaFXGriffonApplication.class, windowName, new Duration(10, SECONDS), DefaultGriffonApplication.EMPTY_ARGS);
057 }
058
059 public GriffonTestFXRule(@Nonnull String windowName, @Nonnull Duration timeout) {
060 this(TestJavaFXGriffonApplication.class, windowName, timeout, DefaultGriffonApplication.EMPTY_ARGS);
061 }
062
063 public GriffonTestFXRule(@Nonnull Class<? extends TestJavaFXGriffonApplication> applicationClass, @Nonnull String windowName) {
064 this(applicationClass, windowName, new Duration(10, SECONDS), DefaultGriffonApplication.EMPTY_ARGS);
065 }
066
067 public GriffonTestFXRule(@Nonnull Class<? extends TestJavaFXGriffonApplication> applicationClass, @Nonnull String windowName, @Nonnull Duration timeout) {
068 this(applicationClass, windowName, timeout, DefaultGriffonApplication.EMPTY_ARGS);
069 }
070
071 public GriffonTestFXRule(@Nonnull Class<? extends TestJavaFXGriffonApplication> applicationClass, @Nonnull String windowName, @Nonnull String[] startupArgs) {
072 this(applicationClass, windowName, new Duration(10, SECONDS), startupArgs);
073 }
074
075 public GriffonTestFXRule(@Nonnull Class<? extends TestJavaFXGriffonApplication> applicationClass, @Nonnull String windowName, @Nonnull Duration timeout, @Nonnull String[] startupArgs) {
076 this.applicationClass = requireNonNull(applicationClass, "Argument 'applicationClass' must not be null");
077 this.windowName = requireNonBlank(windowName, "Argument 'windowName' cannot be blank");
078 this.timeout = requireNonNull(timeout, "Argument 'timeout' cannot be blank");
079 requireNonNull(startupArgs, "Argument 'startupArgs' must not be null");
080 this.startupArgs = new String[startupArgs.length];
081 System.arraycopy(startupArgs, 0, this.startupArgs, 0, startupArgs.length);
082 if (!Environment.isSystemSet()) {
083 System.setProperty(Environment.KEY, Environment.TEST.getName());
084 }
085 }
086
087 @Override
088 public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
089 initialize(target);
090
091 return new Statement() {
092 @Override
093 public void evaluate() throws Throwable {
094 FxToolkit.registerPrimaryStage();
095
096 application = (JavaFXGriffonApplication) FxToolkit.setupApplication(applicationClass);
097 WindowShownHandler startingWindow = new WindowShownHandler(windowName);
098 application.getEventRouter().addEventListener(ApplicationEvent.WINDOW_SHOWN.getName(), startingWindow);
099 application.getInjector().injectMembers(target);
100
101 await().timeout(timeout).until(startingWindow::isShowing);
102
103 before(application, target);
104 try {
105 base.evaluate();
106 } finally {
107 after(application, target);
108 }
109 }
110 };
111 }
112
113 protected void initialize(Object target) {
114 getTestContext().setTestCase(target);
115 getTestContext().setWindowName(windowName);
116 }
117
118 protected void before(@Nonnull JavaFXGriffonApplication application, @Nonnull Object target) throws Throwable {
119
120 }
121
122 protected void after(@Nonnull JavaFXGriffonApplication application, @Nonnull Object target) throws TimeoutException {
123 if (application != null) {
124 application.shutdown();
125 try {
126 FxToolkit.cleanupApplication(application);
127 } catch (TimeoutException e) {
128 throw new GriffonException("An error occurred while shutting down the application", e);
129 } finally {
130 this.application = null;
131 }
132 }
133 }
134
135 @Nullable
136 public <W extends Window> W managedWindow(@Nonnull String name) {
137 return (W) application.getWindowManager().findWindow(name);
138 }
139
140 private static class WindowShownHandler implements RunnableWithArgs {
141 private final String windowName;
142 private boolean showing;
143
144 private WindowShownHandler(String windowName) {
145 this.windowName = windowName;
146 }
147
148 public boolean isShowing() {
149 return showing;
150 }
151
152 @Override
153 public void run(Object... args) {
154 if (args != null && args.length > 0 && args[0] instanceof CharSequence) {
155 showing = windowName.equals(String.valueOf(args[0]));
156 }
157 }
158 }
159 }
|