/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * 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 org.uberfire.wbtest.gwttest; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import com.google.common.base.Predicate; import com.google.gwt.user.client.Timer; import org.gwtbootstrap3.client.GwtBootstrap3EntryPoint; import org.jboss.errai.enterprise.client.cdi.AbstractErraiCDITest; import org.uberfire.wbtest.client.api.UncaughtExceptionAlerter; public abstract class AbstractUberFireGwtTest extends AbstractErraiCDITest { /** * If set to true (eg. by a subclass) then the async polling logic in the {@link #pollWhile(Predicate)} system will * log status updates to System.out. */ protected boolean debugAsyncTesting = false; @Override public String getModuleName() { return "org.uberfire.wbtest.UberFireClientGwtTest"; } @Override protected void gwtSetUp() throws Exception { UncaughtExceptionAlerter.disable(); disableBus = true; // let GwtBootstrap inject its scripts (otherwise, its widgets will blow up during the test) //new Bootstrap().onModuleLoad(); new GwtBootstrap3EntryPoint().onModuleLoad(); super.gwtSetUp(); } /** * Entry point for building step-by-step asynchronous tests. Use the initial predicate to test for workbench startup * completion, then chain an arbitrary number of additional actions to execute afterward: JUnit assertions, * framework actions such as {@code PlaceManager.goTo()}, and even additional predicates to poll on. * <p> * The async processing will log its progress on stdout if the field {@link #debugAsyncTesting} is set to * {@code true}. * @param predicate the predicate to test. Must not be null. Will be called over and over (every 500 ms) until it returns * false. * @return a builder object for chaining the additional actions that will be executed once {@code predicate} returns * false. */ protected AfterPolling pollWhile(final Predicate<Void> predicate) { final List<Object> chainedActions = new ArrayList<Object>(); delayTestFinish(15000); new Timer() { private final long startTime = System.currentTimeMillis(); @Override public void run() { debugPrint("Testing predicate"); if (!predicate.apply(null)) { final ListIterator<Object> chain = chainedActions.listIterator(); new Timer() { @Override public void run() { if (chain.hasNext()) { Object next = chain.next(); if (next instanceof Runnable) { debugPrint("Running supplied task"); ((Runnable) next).run(); schedule(0); } else if (next instanceof Predicate) { debugPrint("Testing intermediate predicate"); if (((Predicate<?>) next).apply(null)) { debugPrint("Intermediate predicate is true. Will try again in 500ms."); chain.previous(); schedule(500); } else { debugPrint("Intermediate predicate became false. Continuing."); schedule(0); } } else if (next instanceof Integer) { debugPrint("Delaying " + next + " ms"); schedule((Integer) next); } else { throw new AssertionError("Unknown entry in doAfter list: " + next); } } else { debugPrint("Test passed!"); finishTest(); } } }.schedule(0); } else { if (System.currentTimeMillis() - startTime > 5000) { debugPrint("Still waiting on pollWhile() condition..."); } schedule(500); } } }.schedule(500); return new AfterPolling() { @Override public AfterPolling thenDo(Runnable runnable) { chainedActions.add(runnable); return this; } @Override public AfterPolling thenPollWhile(Predicate<Void> isTrue) { chainedActions.add(isTrue); return this; } @Override public AfterPolling thenDelay(int delayMillis) { chainedActions.add(delayMillis); return this; } }; } private void debugPrint(String msg) { if (debugAsyncTesting) { System.out.println(msg); } } /** * Builder for chaining additional tasks to perform after a {@link AbstractUberFireGwtTest#pollWhile(Predicate)} * condition has been satisfied. */ public interface AfterPolling { /** * Adds the given arbitrary code to be executed after all previous steps in the chain have been satisfied. * This is a good place to put JUnit assertions. * @param runnable the code to run. Must not be null. * @return this object again, for chaining more steps. */ AfterPolling thenDo(Runnable runnable); /** * Adds a new predicate to test every 500 ms. The next step in the chain will not be executed until the given * predicate returns false. * @param isTrue the predicate to poll every 500ms. Not null. * @return this object again, for chaining more steps. */ AfterPolling thenPollWhile(Predicate<Void> isTrue); /** * Adds a delay of the given length to the chain. The next step in the chain will be executed after the given * time has elapsed. * @param delayMillis the amount of time to delay (in milliseconds). Must be a nonnegative number. * @return this object again, for chaining more steps. */ AfterPolling thenDelay(int delayMillis); } }