From 4860b3c05253ea21be0f4d65bb63b737bb97feba Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Thu, 2 Oct 2008 09:23:38 +0000
Subject: [PATCH] LMS-597 testing framework extended and modified

SVN: 8519
---
 openbis/build/build.xml                       |   1 +
 openbis/etc/passwd                            |   7 ++
 ...S System Tests (Hosted Mode, Linux).launch |   2 +-
 ...BIS System Tests (Hosted Mode, Mac).launch |   2 +-
 ...System Tests (Hosted Mode, Windows).launch |   2 +-
 .../web/client/IGenericClientService.java     |   2 +-
 .../application/AbstractAsyncCallback.java    |  11 +-
 .../client/web/client/application/Client.java |   5 +
 .../client/application/ICallbackListener.java |  16 +--
 .../client/application/ui/LoginWidget.java    |   2 +-
 .../web/server/GenericClientService.java      |  24 ++--
 .../server/GenericClientServiceServlet.java   |   2 +-
 .../application/AuthenticationTest.java       |  38 +++---
 .../AuthorizationManagementConsolTest.java    |  25 ++--
 ...CheckGroupCommand.java => CheckGroup.java} |   7 +-
 ...eateGroupCommand.java => CreateGroup.java} |   7 +-
 .../ui/{LoginCommand.java => Login.java}      |   8 +-
 .../ui/{LogoutCommand.java => Logout.java}    |   7 +-
 ...n.java => AbstractDefaultTestCommand.java} |  20 +++-
 .../testframework/AbstractGWTTestCase.java    |  45 ++++++++
 .../testframework/FailureExpectation.java     |  96 +++++++++++++++
 ...hCondition.java => IMessageValidator.java} |   6 +-
 .../client/testframework/ITestCommand.java    |   6 +-
 .../client/testframework/RemoteConsole.java   | 109 ++++++------------
 .../{ICallbackCondition.java => WaitFor.java} |  28 +++--
 25 files changed, 301 insertions(+), 177 deletions(-)
 create mode 100644 openbis/etc/passwd
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{CheckGroupCommand.java => CheckGroup.java} (86%)
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{CreateGroupCommand.java => CreateGroup.java} (81%)
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{LoginCommand.java => Login.java} (82%)
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/{LogoutCommand.java => Logout.java} (86%)
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/{CallbackClassCondition.java => AbstractDefaultTestCommand.java} (63%)
 create mode 100644 openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/FailureExpectation.java
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/{ITestCommandWithCondition.java => IMessageValidator.java} (80%)
 rename openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/{ICallbackCondition.java => WaitFor.java} (65%)

diff --git a/openbis/build/build.xml b/openbis/build/build.xml
index f6982aee5e3..c6db3750911 100644
--- a/openbis/build/build.xml
+++ b/openbis/build/build.xml
@@ -51,6 +51,7 @@
       	<pathelement location="${gwt.lib}/linux/gwt-dev-linux.jar"/>
       </classpath>
       <jvmarg value="-ea"/>
+      <sysproperty key="authentication-service" value="file-authentication-service"/>
       <sysproperty key="log4j.configuration" value="etc/log.xml"/>
       <sysproperty key="database.create-from-scratch" value="true"/>
       <sysproperty key="database.kind" value="system_test"/>
diff --git a/openbis/etc/passwd b/openbis/etc/passwd
new file mode 100644
index 00000000000..5d69fd92abf
--- /dev/null
+++ b/openbis/etc/passwd
@@ -0,0 +1,7 @@
+admin:admin@admins.com:Adam:The Admin:uCpOu7yTuErc/Z6lzh0SRKGiEw9YKSVg
+test:a@admins.com:A:The Admin:J3fII6Pex7jnCBwF+uXz2mFuB1QVhPUi
+user:user@users.com:Ulf:The User:6NyK/Sheyr6qro8idEY2gNj2oCB0PAkm
+u:u@users.com:U:The User:dmbGKaGRmbX8YKfslMxUHObmYfjywkuT
+observer:observer@observers.com:ObiWan:The Observer:I1D4AjdNDa/adKc0vbEdW/QCzwuhIRZM
+o:o@observers.com:O:The Observer:t53ADCnFnEFhBvHB7FPoHhbHeW2O1KJc
+etlserver::::SHGHSPawL/B3NKXD5nsu4fSrj5LwR2MX
diff --git a/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Linux).launch b/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Linux).launch
index bbe55b98c3d..1d7b0ddebce 100644
--- a/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Linux).launch	
+++ b/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Linux).launch	
@@ -22,5 +22,5 @@
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
 <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-out targets/www-test"/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="openbis"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Ddatabase.create-from-scratch=true&#13;&#10;-Ddatabase.kind=system_test&#13;&#10;-Dscript-folder=sourceTest&#13;&#10;-Dmass-upload-folder=sourceTest/sql/postgresql&#13;&#10;-Dlog4j.configuration=etc/log.xml&#13;&#10;-Xmx512M&#13;&#10;-ea"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dauthentication-service=file-authentication-service&#13;&#10;-Ddatabase.create-from-scratch=true&#13;&#10;-Ddatabase.kind=system_test&#13;&#10;-Dscript-folder=sourceTest&#13;&#10;-Dmass-upload-folder=sourceTest/sql/postgresql&#13;&#10;-Dlog4j.configuration=etc/log.xml&#13;&#10;-Xmx512M&#13;&#10;-ea"/>
 </launchConfiguration>
diff --git a/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Mac).launch b/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Mac).launch
index f70540fc164..8487bb1a1ca 100644
--- a/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Mac).launch	
+++ b/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Mac).launch	
@@ -25,5 +25,5 @@
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
 <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-out targets/www-test"/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="openbis"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread&#13;&#10;-Ddatabase.create-from-scratch=true&#13;&#10;-Ddatabase.kind=system_test&#13;&#10;-Dscript-folder=sourceTest&#13;&#10;-Dmass-upload-folder=sourceTest/sql/postgresql&#13;&#10;-Dlog4j.configuration=etc/log.xml&#13;&#10;-Xmx512M&#13;&#10;-ea"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread&#13;&#10;-Dauthentication-service=file-authentication-service&#13;&#10;-Ddatabase.create-from-scratch=true&#13;&#10;-Ddatabase.kind=system_test&#13;&#10;-Dscript-folder=sourceTest&#13;&#10;-Dmass-upload-folder=sourceTest/sql/postgresql&#13;&#10;-Dlog4j.configuration=etc/log.xml&#13;&#10;-Xmx512M&#13;&#10;-ea"/>
 </launchConfiguration>
diff --git a/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Windows).launch b/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Windows).launch
index c0dbce5b366..09898ca1762 100644
--- a/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Windows).launch	
+++ b/openbis/resource/eclipse/openBIS System Tests (Hosted Mode, Windows).launch	
@@ -22,5 +22,5 @@
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
 <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-out targets/www-test"/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="openbis"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Ddatabase.create-from-scratch=true&#13;&#10;-Ddatabase.kind=system_test&#13;&#10;-Dscript-folder=sourceTest&#13;&#10;-Dmass-upload-folder=sourceTest/sql/postgresql&#13;&#10;-Dlog4j.configuration=etc/log.xml&#13;&#10;-Xmx512M&#13;&#10;-ea"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dauthentication-service=file-authentication-service&#13;&#10;-Ddatabase.create-from-scratch=true&#13;&#10;-Ddatabase.kind=system_test&#13;&#10;-Dscript-folder=sourceTest&#13;&#10;-Dmass-upload-folder=sourceTest/sql/postgresql&#13;&#10;-Dlog4j.configuration=etc/log.xml&#13;&#10;-Xmx512M&#13;&#10;-ea"/>
 </launchConfiguration>
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java
index 7d4aef75e12..61a1876d1c1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java
@@ -48,7 +48,7 @@ public interface IGenericClientService extends RemoteService
      * Tries to login with specified user ID and password. If failed <code>null</code> is
      * returned.
      */
-    public SessionContext tryToLogin(String userID, String password);
+    public SessionContext tryToLogin(String userID, String password) throws UserFailureException;
 
     /**
      * Logs out.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java
index 355aa03c677..6a5d0487158 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java
@@ -34,11 +34,7 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T>
 {
     private static final ICallbackListener DUMMY_LISTENER = new ICallbackListener()
         {
-            public void onFailureOf(AsyncCallback<Object> callback, Throwable throwable)
-            {
-            }
-
-            public void startOnSuccessOf(AsyncCallback<Object> callback, Object result)
+            public void onFailureOf(AsyncCallback<Object> callback, String failureMessage, Throwable throwable)
             {
             }
 
@@ -77,7 +73,6 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T>
     
     public void onFailure(Throwable caught)
     {
-        callbackListener.onFailureOf(getThis(), caught);
         final String msg;
         if (caught instanceof InvocationException)
         {
@@ -99,8 +94,9 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T>
                 msg = message;
             }
         }
-        IPageController pageController = viewContext.getPageController();
+        callbackListener.onFailureOf(getThis(), msg, caught);
         MessageBox.alert("Error", msg, null);
+        IPageController pageController = viewContext.getPageController();
         if (caught instanceof InvalidSessionException)
         {
             pageController.reload();
@@ -109,7 +105,6 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T>
 
     public final void onSuccess(T result)
     {
-        callbackListener.startOnSuccessOf(getThis(), result);
         process(result);
         callbackListener.finishOnSuccessOf(getThis(), result);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java
index 6145d7f7c3c..e5fdeebea67 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java
@@ -36,6 +36,11 @@ public class Client implements EntryPoint
     private GenericViewContext viewContext;
     private AbstractAsyncCallback<SessionContext> loginCallback;
     
+    public final GenericViewContext tryToGetViewContext()
+    {
+        return viewContext;
+    }
+
     public void onModuleLoad()
     {
         if (viewContext == null)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ICallbackListener.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ICallbackListener.java
index f2420e6a85a..19b8eb64502 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ICallbackListener.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ICallbackListener.java
@@ -26,18 +26,12 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
 public interface ICallbackListener
 {
     /**
-     * Handles invocations of {@link AsyncCallback#onFailure(Throwable)} of the specified
-     * callback object with the specified throwable. This method will be invoked before
-     * the callback object is actually handling the failure.
+     * Handles invocations of {@link AsyncCallback#onFailure(Throwable)} of the specified callback
+     * object with the specified failure message and throwable. This method will be invoked before
+     * the callback object is showing the failure message in a popup dialog.
      */
-    public void onFailureOf(AsyncCallback<Object> callback, Throwable throwable);
-    
-    /**
-     * Handles invocations of {@link AsyncCallback#onSuccess(Object)} of the specified
-     * callback object with the specified result object. This method will be invoked before
-     * the callback object is actually processing the result object.
-     */
-    public void startOnSuccessOf(AsyncCallback<Object> callback, Object result);
+    public void onFailureOf(AsyncCallback<Object> callback, String failureMessage,
+            Throwable throwable);
     
     /**
      * Handles invocations of {@link AsyncCallback#onSuccess(Object)} of the specified
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java
index 3efc591ab7b..fb956e76a58 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java
@@ -36,7 +36,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext;
  */
 public class LoginWidget extends VerticalPanel
 {
-    private static final class LoginCallback extends AbstractAsyncCallback<SessionContext>
+    public static final class LoginCallback extends AbstractAsyncCallback<SessionContext>
     {
         private LoginCallback(GenericViewContext viewContext)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java
index 86b50c28f15..25e7ba4eef2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java
@@ -160,17 +160,23 @@ public class GenericClientService implements IGenericClientService
 
     public SessionContext tryToLogin(String userID, String password)
     {
-        Session session = server.tryToAuthenticate(userID, password);
-        if (session == null)
+        try
         {
-            return null;
+            Session session = server.tryToAuthenticate(userID, password);
+            if (session == null)
+            {
+                return null;
+            }
+            HttpSession httpSession = creatHttpSession();
+            // Expiration time of httpSession is 10 seconds less than of session
+            httpSession.setMaxInactiveInterval(session.getSessionExpirationTime() / 1000 - 10);
+            httpSession.setAttribute(SESSION_KEY, session);
+            httpSession.setAttribute(SERVER_KEY, server);
+            return createSessionContext(session);
+        } catch (UserFailureException e)
+        {
+            throw UserFailureExceptionTranslater.translate(e);
         }
-        HttpSession httpSession = creatHttpSession();
-        // Expiration time of httpSession is 10 seconds less than of session
-        httpSession.setMaxInactiveInterval(session.getSessionExpirationTime() / 1000 - 10);
-        httpSession.setAttribute(SESSION_KEY, session);
-        httpSession.setAttribute(SERVER_KEY, server);
-        return createSessionContext(session);
     }
 
     public void logout()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java
index bb4f2cd9927..34ce42764d4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java
@@ -70,7 +70,7 @@ public class GenericClientServiceServlet extends GWTSpringController implements
             }
         } catch (final Exception ex)
         {
-            notificationLog.fatal("Failure during servlet initialization.", ex);
+            notificationLog.fatal("FailureExpectation during servlet initialization.", ex);
             throw new ServletException(ex);
         }
     }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthenticationTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthenticationTest.java
index a4a3dada807..2995fddf7b1 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthenticationTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthenticationTest.java
@@ -17,10 +17,12 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application;
 
 
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.LoginCommand;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.LogoutCommand;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.Login;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.LoginWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.Logout;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractGWTTestCase;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.RemoteConsole;
+import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.FailureExpectation;
+import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.WaitFor;
 
 
 /**
@@ -30,29 +32,29 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.RemoteCo
  */
 public class AuthenticationTest extends AbstractGWTTestCase
 {
-    private RemoteConsole remoteConsole;
-    
-    @Override
-    protected void gwtSetUp() throws Exception
+    public void testLogin() throws Exception
     {
-        remoteConsole = new RemoteConsole(this);
-        System.out.println("TEST: " + getName());
+        remoteConsole.prepare(new Login("test", "a"));
+        remoteConsole.prepare(new WaitFor(LoginWidget.LoginCallback.class));
+        remoteConsole.finish(10000);
+        
+        client.onModuleLoad();
     }
-
-    public void testLogin() throws Exception
+    
+    public void testLogout() throws Exception
     {
-        final Client client = new Client();
+        remoteConsole.prepare(new Login("test", "a"));
+        remoteConsole.prepare(new Logout()).finish(10000);
+        
         client.onModuleLoad();
-        remoteConsole.prepare(new LoginCommand("a", "a"));
-        remoteConsole.prepare(new LogoutCommand()).finish(10000);
     }
     
-    public void testFailedLogin() throws Exception
+    public void testFailedLoginBecauseOfEmptyPassword() throws Exception
     {
-        final Client client = new Client();
+        remoteConsole.prepare(new Login("u", ""));
+        remoteConsole.prepare(new FailureExpectation(LoginWidget.LoginCallback.class)).finish(10000);
+        
         client.onModuleLoad();
-        remoteConsole.prepare(new LoginCommand("u", ""));
-        remoteConsole.prepare(new LogoutCommand()).finish(10000);
     }
     
     
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java
index 301068ae089..cb0ce331513 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java
@@ -16,11 +16,10 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application;
 
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.CheckGroupCommand;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.CreateGroupCommand;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.LoginCommand;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.CheckGroup;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.CreateGroup;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.Login;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractGWTTestCase;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.RemoteConsole;
 
 /**
  * 
@@ -29,24 +28,14 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.RemoteCo
  */
 public class AuthorizationManagementConsolTest extends AbstractGWTTestCase
 {
-    private RemoteConsole remoteConsole;
-    
-    @Override
-    protected void gwtSetUp() throws Exception
-    {
-        remoteConsole = new RemoteConsole(this);
-        System.out.println("TEST: " + getName());
-    }
-    
     public void testCreateGroup()
     {
-        final Client client = new Client();
-        client.onModuleLoad();
-        remoteConsole.prepare(new LoginCommand("a", "a"));
+        remoteConsole.prepare(new Login("test", "a"));
         String groupCode = "test-group";
-        remoteConsole.prepare(new CreateGroupCommand(groupCode));
-        remoteConsole.prepare(new CheckGroupCommand(groupCode.toUpperCase())).finish(10000);
+        remoteConsole.prepare(new CreateGroup(groupCode));
+        remoteConsole.prepare(new CheckGroup(groupCode.toUpperCase())).finish(10000);
         
+        client.onModuleLoad();
     }
 
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CheckGroupCommand.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CheckGroup.java
similarity index 86%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CheckGroupCommand.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CheckGroup.java
index 23bb6ff09fb..60339f5d4d0 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CheckGroupCommand.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CheckGroup.java
@@ -22,21 +22,20 @@ import com.extjs.gxt.ui.client.store.ListStore;
 import com.extjs.gxt.ui.client.widget.grid.Grid;
 import com.google.gwt.user.client.ui.Widget;
 
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.CallbackClassCondition;
+import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractDefaultTestCommand;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.GWTTestUtil;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.ITestCommandWithCondition;
 
 /**
  * 
  *
  * @author Franz-Josef Elmer
  */
-public class CheckGroupCommand extends CallbackClassCondition implements ITestCommandWithCondition<Object>
+public class CheckGroup extends AbstractDefaultTestCommand
 {
 
     private final String groupCode;
 
-    public CheckGroupCommand(String groupCode)
+    public CheckGroup(String groupCode)
     {
         super(GroupsView.ListGroupsCallback.class);
         this.groupCode = groupCode;
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CreateGroupCommand.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CreateGroup.java
similarity index 81%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CreateGroupCommand.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CreateGroup.java
index fcb864f2359..12f77e42599 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CreateGroupCommand.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CreateGroup.java
@@ -16,21 +16,20 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.CallbackClassCondition;
+import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractDefaultTestCommand;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.GWTTestUtil;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.ITestCommandWithCondition;
 
 /**
  * 
  *
  * @author Franz-Josef Elmer
  */
-public class CreateGroupCommand extends CallbackClassCondition implements ITestCommandWithCondition<Object>
+public class CreateGroup extends AbstractDefaultTestCommand
 {
 
     private final String groupCode;
 
-    public CreateGroupCommand(String groupCode)
+    public CreateGroup(String groupCode)
     {
         super(GroupsView.ListGroupsCallback.class);
         this.groupCode = groupCode;
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginCommand.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/Login.java
similarity index 82%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginCommand.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/Login.java
index f3b5d6523f4..d6a3471b13a 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginCommand.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/Login.java
@@ -17,28 +17,26 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.SessionContextCallback;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.CallbackClassCondition;
+import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractDefaultTestCommand;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.GWTTestUtil;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.ITestCommandWithCondition;
 
 /**
  * Command for login after {@link SessionContextCallback} has finished.
  *
  * @author Franz-Josef Elmer
  */
-public class LoginCommand extends CallbackClassCondition implements ITestCommandWithCondition<Object>
+public class Login extends AbstractDefaultTestCommand
 {
     private final String user;
     private final String password;
 
-    public LoginCommand(String user, String password)
+    public Login(String user, String password)
     {
         super(SessionContextCallback.class);
         this.user = user;
         this.password = password;
     }
 
-    @SuppressWarnings("unchecked")
     public void execute()
     {
         GWTTestUtil.<String>getTextFieldWithID(LoginWidget.USER_FIELD_ID).setValue(user);
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LogoutCommand.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/Logout.java
similarity index 86%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LogoutCommand.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/Logout.java
index 3003cfdf65e..00d9209180f 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LogoutCommand.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/Logout.java
@@ -23,18 +23,17 @@ import com.extjs.gxt.ui.client.widget.toolbar.TextToolItem;
 import com.google.gwt.user.client.ui.Widget;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.SessionContextCallback;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.CallbackClassCondition;
+import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractDefaultTestCommand;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.GWTTestUtil;
-import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.ITestCommandWithCondition;
 
 /**
  * Command for logout after {@link SessionContextCallback} has finished.
  *
  * @author Franz-Josef Elmer
  */
-public class LogoutCommand extends CallbackClassCondition implements ITestCommandWithCondition<Object>
+public class Logout extends AbstractDefaultTestCommand
 {
-    public LogoutCommand()
+    public Logout()
     {
         super(SessionContextCallback.class);
     }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/CallbackClassCondition.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/AbstractDefaultTestCommand.java
similarity index 63%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/CallbackClassCondition.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/AbstractDefaultTestCommand.java
index 3041e182c69..669195178ab 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/CallbackClassCondition.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/AbstractDefaultTestCommand.java
@@ -23,19 +23,33 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
  *
  * @author Franz-Josef Elmer
  */
-public class CallbackClassCondition implements ICallbackCondition<Object>
+public abstract class AbstractDefaultTestCommand implements ITestCommand
 {
     private final Class<?> callbackClass;
 
     /**
      * Creates an instance for the specified callback class.
      */
-    public CallbackClassCondition(Class<? extends AsyncCallback<?>> callbackClass)
+    public AbstractDefaultTestCommand(Class<? extends AsyncCallback<?>> callbackClass)
     {
         this.callbackClass = callbackClass;
     }
     
-    public boolean valid(AsyncCallback<Object> callback, Object result)
+    public boolean validOnFailure(AsyncCallback<Object> callback, String failureMessage,
+            Throwable throwable)
+    {
+        return false;
+    }
+
+    public boolean validOnSucess(AsyncCallback<Object> callback, Object result)
+    {
+        return equalsExpectedCallback(callback);
+    }
+
+    /**
+     * Returns <code>true</code> if the specified callback object is of expected type. 
+     */
+    protected boolean equalsExpectedCallback(AsyncCallback<Object> callback)
     {
         return callbackClass.equals(callback.getClass());
     }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/AbstractGWTTestCase.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/AbstractGWTTestCase.java
index 51a268ff279..85f7a7ed8f8 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/AbstractGWTTestCase.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/AbstractGWTTestCase.java
@@ -17,6 +17,10 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.testframework;
 
 import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Client;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericViewContext;
 
 /**
  * Abstract super class of all GWT System Tests.
@@ -25,6 +29,8 @@ import com.google.gwt.junit.client.GWTTestCase;
  */
 public abstract class AbstractGWTTestCase extends GWTTestCase
 {
+    protected RemoteConsole remoteConsole;
+    protected Client client;
     
     @Override
     public String getModuleName()
@@ -48,5 +54,44 @@ public abstract class AbstractGWTTestCase extends GWTTestCase
     {
         delayTestFinish(timeoutMillis);
     }
+
+    @Override
+    protected final void gwtSetUp() throws Exception
+    {
+        System.out.println("TEST: " + getName());
+        remoteConsole = new RemoteConsole(this);
+        client = new Client();
+        setUpTest();
+    }
+    
+    protected void setUpTest() throws Exception
+    {
+    }
+
+    @Override
+    protected final void gwtTearDown() throws Exception
+    {
+        GenericViewContext viewContext = client.tryToGetViewContext();
+        if (viewContext != null)
+        {
+            viewContext.getService().logout(new AsyncCallback<Void>()
+                {
+                    public void onSuccess(Void result)
+                    {
+                    }
+            
+                    public void onFailure(Throwable caught)
+                    {
+                        System.out.println("LOGOUT FAILED: " + caught);
+                    }
+                });
+        }
+        tearDownTest();
+    }
+    
+    protected void tearDownTest() throws Exception
+    {
+    }
+    
     
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/FailureExpectation.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/FailureExpectation.java
new file mode 100644
index 00000000000..cfd9c68b78e
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/FailureExpectation.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.testframework;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+/**
+ * Failure expectation.
+ *
+ * @author Franz-Josef Elmer
+ */
+public class FailureExpectation extends AbstractDefaultTestCommand
+{
+
+    private IMessageValidator messageValidator = new IMessageValidator()
+        {
+            public boolean valid(String message)
+            {
+                return true;
+            }
+        };
+        
+    private Class<? extends Throwable> expectedThrowableClassOrNull;
+
+    public FailureExpectation(Class<? extends AsyncCallback<?>> callbackClass)
+    {
+        super(callbackClass);
+    }
+    
+    public FailureExpectation with(final String failureMessage)
+    {
+        return with(new IMessageValidator()
+            {
+                public boolean valid(String message)
+                {
+                    return failureMessage.equals(message);
+                }
+            });
+    }
+    
+    public FailureExpectation with(IMessageValidator validator)
+    {
+        messageValidator = validator;
+        return this;
+    }
+    
+    public FailureExpectation ofType(Class<? extends Throwable> throwableClass)
+    {
+        expectedThrowableClassOrNull = throwableClass;
+        return this;
+    }
+    
+    @Override
+    public boolean validOnFailure(AsyncCallback<Object> callback, String failureMessage,
+            Throwable throwable)
+    {
+        if (equalsExpectedCallback(callback) == false)
+        {
+            return false;
+        }
+        if (messageValidator.valid(failureMessage) == false)
+        {
+            return false;
+        }
+        if (expectedThrowableClassOrNull == null)
+        {
+            return true;
+        }
+        return expectedThrowableClassOrNull.equals(throwable.getClass());
+    }
+
+    @Override
+    public boolean validOnSucess(AsyncCallback<Object> callback, Object result)
+    {
+        return false;
+    }
+
+    public void execute()
+    {
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ITestCommandWithCondition.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/IMessageValidator.java
similarity index 80%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ITestCommandWithCondition.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/IMessageValidator.java
index 1e1093d76bd..1df6f5fa9c0 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ITestCommandWithCondition.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/IMessageValidator.java
@@ -17,11 +17,11 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.testframework;
 
 /**
- * Interface of all test commands which knows also their condition for execution.
+ * 
  *
  * @author Franz-Josef Elmer
  */
-public interface ITestCommandWithCondition<T> extends ITestCommand, ICallbackCondition<T>
+public interface IMessageValidator
 {
-
+    public boolean valid(String message);
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ITestCommand.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ITestCommand.java
index 604b18af55f..c7fc45cf278 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ITestCommand.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ITestCommand.java
@@ -21,13 +21,17 @@ import org.aopalliance.intercept.Invocation;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
 /**
- * A commad which will be executed after a successful {@link Invocation} of
+ * A command which will be executed after a successful {@link Invocation} of
  * {@link AsyncCallback#onSuccess(Object)}.
  * 
  * @author Franz-Josef Elmer
  */
 public interface ITestCommand
 {
+    public boolean validOnFailure(AsyncCallback<Object> callback, String failureMessage, Throwable throwable);
+    
+    public boolean validOnSucess(AsyncCallback<Object> callback, Object result);
+
     /**
      * Executes this command.
      */
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java
index 45d9feda333..b9830eb3398 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java
@@ -29,45 +29,17 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ICallbackL
 
 /**
  * A class which allows to execute a sequence of {@link ITestCommand} instances. The commands are
- * executed in the order they have been added by the various prepare methods. A
- * {@link ICallbackCondition} has to be fulfilled before the next command is executed. This
- * condition is checked after each successful invocation of
- * {@link AsyncCallback#onSuccess(Object)}. With the method {@link #finish(int)} a timeout
- * will be specified after which the test will be terminated independent whether all commands have
- * been executed or not. In the later case the test fails.
+ * executed in the order they have been added by {@link #prepare(ITestCommand)}. In order to be
+ * executed a command has to be valid for the kind of {@link AsyncCallback} invocation. With the
+ * method {@link #finish(int)} a timeout will be specified after which the test will be terminated
+ * independent whether all commands have been executed or not. In the later case the test fails.
  * 
  * @author Franz-Josef Elmer
  */
 public class RemoteConsole
 {
-    private static final class CommandEntry 
-    {
-        private final ICallbackCondition<Object> condition;
-        private final ITestCommand command;
-        CommandEntry(ICallbackCondition<Object> condition, ITestCommand command)
-        {
-            this.condition = condition;
-            this.command = command;
-        }
-    }
-    
-    private class EqualsCallback implements ICallbackCondition<Object>
-    {
-        private final AsyncCallback<?> callbackToCheck;
-        
-        public EqualsCallback(AsyncCallback<?> callback)
-        {
-            this.callbackToCheck = callback;
-        }
-        
-        public boolean valid(AsyncCallback<Object> callback, Object result)
-        {
-            return callbackToCheck.equals(callback);
-        }
-    }
-    
     private final AbstractGWTTestCase testCase;
-    private final List<CommandEntry> entries;
+    private final List<ITestCommand> commands;
     
     private int entryIndex;
     
@@ -77,68 +49,53 @@ public class RemoteConsole
     public RemoteConsole(final AbstractGWTTestCase testCase)
     {
         this.testCase = testCase;
-        entries = new ArrayList<CommandEntry>();
+        commands = new ArrayList<ITestCommand>();
         AbstractAsyncCallback.setCallbackListener(new ICallbackListener()
             {
-                public void onFailureOf(AsyncCallback<Object> callback, Throwable throwable)
+                public void onFailureOf(AsyncCallback<Object> callback, String failureMessage,
+                        Throwable throwable)
                 {
-                    Assert.fail("Failed condition " + callback + ": " + throwable);
+                    if (entryIndex < commands.size()
+                            && commands.get(entryIndex).validOnFailure(callback, failureMessage, throwable))
+                    {
+                        executeCommand();
+                    } else
+                    {
+                        Assert.fail("Failed callback " + callback + ": " + failureMessage + "["
+                                + throwable.getClass() + "]");
+                    }
                 }
 
-                public void startOnSuccessOf(AsyncCallback<Object> callback, Object result)
+                public void finishOnSuccessOf(AsyncCallback<Object> callback, Object result)
                 {
+                    if (entryIndex < commands.size()
+                            && commands.get(entryIndex).validOnSucess(callback, result))
+                    {
+                        executeCommand();
+                    }
                 }
-
-                public void finishOnSuccessOf(AsyncCallback<Object> callback, Object result)
+                
+                private void executeCommand()
                 {
-                    if (entryIndex < entries.size()
-                            && entries.get(entryIndex).condition.valid(callback, result))
+                    ITestCommand testCommand = commands.get(entryIndex++);
+                    System.out.println("EXECUTE: " + testCommand);
+                    testCommand.execute();
+                    if (entryIndex == commands.size())
                     {
-                        CommandEntry commandEntry = entries.get(entryIndex++);
-                        commandEntry.command.execute();
-                        if (entryIndex == entries.size())
-                        {
-                            testCase.terminateTest();
-                        }
+                        testCase.terminateTest();
                     }
                 }
 
             });
     }
 
-    /**
-     * Prepares the console with the specified command.
-     */
-    public RemoteConsole prepare(ITestCommandWithCondition<Object> command)
-    {
-        return prepare(command, command);
-    }
-    
-    /**
-     * Prepares the console with the specified command which will be executed if the
-     * class of the callback object is as specified. 
-     */
-    public RemoteConsole prepare(Class<? extends AsyncCallback<?>> clazz, ITestCommand command)
-    {
-        return prepare(new CallbackClassCondition(clazz), command);
-    }
-    
-    /**
-     * Prepares the console with the specified command which will be executed if the
-     * callback object equals the specified one. 
-     */
-    public RemoteConsole prepare(AsyncCallback<?> callback, ITestCommand command)
-    {
-        return prepare(new EqualsCallback(callback), command);
-    }
-
     /**
      * Prepares the console with the specified command which will be executed if the
      * specified condition is fulfilled. 
      */
-    public RemoteConsole prepare(ICallbackCondition<Object> condition, ITestCommand command)
+    public RemoteConsole prepare(ITestCommand command)
     {
-        entries.add(new CommandEntry(condition, command));
+        commands.add(command);
         return this;
     }
     
@@ -155,7 +112,7 @@ public class RemoteConsole
                 public void run()
                 {
                     AbstractAsyncCallback.setCallbackListener(null);
-                    int numberOfUnexcutedCommands = entries.size() - entryIndex;
+                    int numberOfUnexcutedCommands = commands.size() - entryIndex;
                     if (numberOfUnexcutedCommands > 0)
                     {
                         Assert.fail("Console not finished. Last "
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ICallbackCondition.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/WaitFor.java
similarity index 65%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ICallbackCondition.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/WaitFor.java
index d4f4db070dc..381f5638339 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/ICallbackCondition.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/WaitFor.java
@@ -19,15 +19,29 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.testframework;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
 /**
- * Condition a callback object and/or the result delivered by the callback object have
- * to fulfilled in order to execute a {@link ITestCommand} in {@link RemoteConsole}.
+ * 
  *
  * @author Franz-Josef Elmer
  */
-public interface ICallbackCondition<T>
+public class WaitFor extends AbstractDefaultTestCommand
 {
-    /**
-     * Returns <code>true</code> if the condition is fulfilled.
-     */
-    public boolean valid(AsyncCallback<T> callback, T result);
+    private final String callbackClassName;
+
+    public WaitFor(Class<? extends AsyncCallback<?>> callbackClass)
+    {
+        super(callbackClass);
+        callbackClassName = callbackClass.getName();
+    }
+
+    public void execute()
+    {
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Wait for " + callbackClassName;
+    }
+
+    
 }
-- 
GitLab