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 88d57b0b37d579293a6424bbb97ed003da29bf29..6145d7f7c3c74c9a230edb967b6ce9f82ae4ca85 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
@@ -41,8 +41,8 @@ public class Client implements EntryPoint
         if (viewContext == null)
         {
             viewContext = createViewContext();
+            loginCallback = new SessionContextCallback(viewContext);
         }
-        loginCallback = new SessionContextCallback(viewContext);
         final IGenericClientServiceAsync service = viewContext.getService();
         service.getApplicationInfo(new AbstractAsyncCallback<ApplicationInfo>(viewContext)
             {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SessionContextCallback.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SessionContextCallback.java
index 624ebccf7a97c259fa741fe23da7189624b8dc6a..da5175d660d7d6c4ab3bc17a9b74f6c5d2a78812 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SessionContextCallback.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SessionContextCallback.java
@@ -39,6 +39,7 @@ public final class SessionContextCallback extends AbstractAsyncCallback<SessionC
     @Override
     public void process(SessionContext sessionContext)
     {
+        System.out.println("SessionContextCallback.process() "+sessionContext);
         RootPanel rootPanel = RootPanel.get();
         rootPanel.clear();
         Component widget;
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 474a35dbbaf57ac491313a0031e20a69e75ca308..3efc591ab7b61ecb95a212e32ec8a386b4b01bf5 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,13 +36,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext;
  */
 public class LoginWidget extends VerticalPanel
 {
-    static final class LoginCallback extends AbstractAsyncCallback<SessionContext>
+    private static final class LoginCallback extends AbstractAsyncCallback<SessionContext>
     {
-        /**
-         *
-         *
-         * @param viewContext
-         */
         private LoginCallback(GenericViewContext viewContext)
         {
             super(viewContext);
@@ -55,17 +50,19 @@ public class LoginWidget extends VerticalPanel
         }
     }
 
-    private static final String PREFIX = GenericConstants.ID_PREFIX + "login_";
+    private static final String PREFIX = "login_";
+    private static final String ID_PREFIX = GenericConstants.ID_PREFIX + PREFIX;
 
-    static final String USER_FIELD_ID = PREFIX + "user";
-    static final String PASSWORD_FIELD_ID = PREFIX + "password";
-    static final String BUTTON_ID = PREFIX + "button";
+    static final String USER_FIELD_ID = ID_PREFIX + "user";
+    static final String PASSWORD_FIELD_ID = ID_PREFIX + "password";
+    static final String BUTTON_ID = ID_PREFIX + "button";
     
     private final TextField<String> userField;
     private final TextField<String> passwordField;
 
     public LoginWidget(final GenericViewContext viewContext)
     {
+        final LoginCallback loginCallback = new LoginCallback(viewContext);
         add(new Text(viewContext.getMessage(PREFIX + "invitation")));
         
         FormPanel formPanel = new FormPanel();
@@ -94,7 +91,9 @@ public class LoginWidget extends VerticalPanel
                 @Override
                 public void componentSelected(ComponentEvent ce)
                 {
-                    login(viewContext);
+                    String user = userField.getValue();
+                    String password = passwordField.getValue();
+                    viewContext.getService().tryToLogin(user, password, loginCallback);
                 }
             });
         formPanel.addButton(button);
@@ -102,11 +101,4 @@ public class LoginWidget extends VerticalPanel
         add(formPanel);
     }
     
-    private void login(final GenericViewContext viewContext)
-    {
-        viewContext.getService().tryToLogin(userField.getValue(), passwordField.getValue(),
-                new LoginCallback(viewContext));
-        
-    }
-    
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ClientTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthenticationTest.java
similarity index 88%
rename from openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ClientTest.java
rename to openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthenticationTest.java
index 6aa0190d106f7ff1fe9e03930af0662249bb271d..a49bb5ef9fda67cc6f1f0bb1f1049ab16dcdd101 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ClientTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthenticationTest.java
@@ -28,7 +28,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.RemoteCo
  *
  * @author Franz-Josef Elmer
  */
-public class ClientTest extends AbstractGWTTestCase
+public class AuthenticationTest extends AbstractGWTTestCase
 {
 
     private RemoteConsole remoteConsole;
@@ -38,13 +38,14 @@ public class ClientTest extends AbstractGWTTestCase
     protected void gwtSetUp() throws Exception
     {
         remoteConsole = new RemoteConsole(this);
+        System.out.println("TEST: " + getName());
     }
 
     public void testLogin() throws Exception
     {
         final Client client = new Client();
         client.onModuleLoad();
-        remoteConsole.prepare(new LoginCommand("test", "blabla")).prepare(new LogoutCommand()).finish(10000);
+        remoteConsole.prepare(new LoginCommand("test", "")).prepare(new LogoutCommand()).finish(10000);
     }
     
     public void testFailedLogin() throws Exception
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/LogoutCommand.java
index 202f85faa421839db487159e6645d8c483f33c81..3003cfdf65e5794e111af1044008c7814b408b16 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/LogoutCommand.java
@@ -20,15 +20,15 @@ import junit.framework.Assert;
 
 import com.extjs.gxt.ui.client.Events;
 import com.extjs.gxt.ui.client.widget.toolbar.TextToolItem;
-import com.google.gwt.user.client.ui.RootPanel;
 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.GWTTestUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.ITestCommandWithCondition;
 
 /**
- * 
+ * Command for logout after {@link SessionContextCallback} has finished.
  *
  * @author Franz-Josef Elmer
  */
@@ -36,12 +36,11 @@ public class LogoutCommand extends CallbackClassCondition implements ITestComman
 {
     public LogoutCommand()
     {
-        super(LoginWidget.LoginCallback.class);
+        super(SessionContextCallback.class);
     }
 
     public void execute()
     {
-        System.out.println(RootPanel.get());
         Widget w = GWTTestUtil.getWidgetWithID(TopMenu.LOGOUT_BUTTON_ID);
         Assert.assertTrue("Widget '" + TopMenu.LOGOUT_BUTTON_ID + "' is not a TextToolItem",
                 w instanceof TextToolItem);
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/GWTTestUtil.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/GWTTestUtil.java
index 8c66fde83641ca1a2bfabf5c28eff23a1fe1bfce..8f5fb007aec3927ee5e633404569758a2f1f6cba 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/GWTTestUtil.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/GWTTestUtil.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.testframework;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import junit.framework.Assert;
@@ -29,6 +30,8 @@ import com.google.gwt.user.client.ui.ComplexPanel;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.Widget;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+
 /**
  * Useful static methods for testing.
  *
@@ -43,12 +46,12 @@ public class GWTTestUtil
     /**
      * Gets the {@link Button} with specified id.
      * 
-     * @throws AssertionError if not found or isn't a text field.
+     * @throws AssertionError if not found or isn't a button.
      */
     public static Button getButtonWithID(String id)
     {
         Widget widget = tryToFindByID(id);
-        Assert.assertNotNull("Button '" + id + "' not found.", widget);
+        assertWidgetFound("Button", id, widget);
         Assert.assertTrue("Widget '" + id + "' isn't a Button: " + widget.getClass(),
                 widget instanceof Button);
         return (Button) widget;
@@ -63,7 +66,7 @@ public class GWTTestUtil
     public static <T> TextField<T> getTextFieldWithID(String id)
     {
         Widget widget = tryToFindByID(id);
-        Assert.assertNotNull("Text field '" + id + "' not found.", widget);
+        assertWidgetFound("Text field", id, widget);
         Assert.assertTrue("Widget '" + id + "' isn't a TextField: " + widget.getClass(),
                 widget instanceof TextField);
         return (TextField<T>) widget;
@@ -77,6 +80,22 @@ public class GWTTestUtil
     {
         return (T) tryToFindByID(id);
     }
+
+    /**
+     * Returns the ID of the specified widget.
+     */
+    public static String getWidgetID(Widget widget)
+    {
+        String widgetID;
+        if (widget instanceof Component)
+        {
+            widgetID = ((Component) widget).getId();
+        } else
+        {
+            widgetID = widget.getElement().getId();
+        }
+        return widgetID;
+    }
     
     public static Widget getWidgetWithID(String id)
     {
@@ -85,62 +104,136 @@ public class GWTTestUtil
         return widget;
     }
 
+    /**
+     * Tries to find the widget with specified id.
+     * 
+     * @return <code>null</code> if not found.
+     */
+    public static Widget tryToFindByID(final String id)
+    {
+        WidgetPicker widgetPicker = new WidgetPicker(id);
+        traverseRootPanel(widgetPicker);
+        return widgetPicker.tryToGetPickedWidget();
+    }
+
+    /**
+     * Traverses root panel tree with the specified widget handler. Traversal is stopped
+     * when {@link IWidgetHandler#handle(Widget)} returns <code>true</code>.
+     */
+    public static void traverseRootPanel(IWidgetHandler<Widget> handler)
+    {
+        new WidgetTreeTraverser(handler).handle(RootPanel.get());
+    }
+
     private static void assertWidgetFound(String widgetType, String id, Widget widgetOrNull)
     {
         if (widgetOrNull == null)
         {
-            Assert.fail(widgetType + " '" + id + "' not found.");
+            List<String> ids = findWidgetWithIDsStartingWith(GenericConstants.ID_PREFIX);
+            Assert.fail(widgetType + " '" + id + "' not found on page with following IDs: " + ids);
         }
     }
     
-    
-    /**
-     * Tries to find the widget with specified id.
-     * 
-     * @return <code>null</code> if not found.
-     */
-    public static Widget tryToFindByID(String id)
+    private static List<String> findWidgetWithIDsStartingWith(final String idPrefix)
     {
-        return tryToFindByID(RootPanel.get(), id);
+        final List<String> ids = new ArrayList<String>();
+        traverseRootPanel(new IWidgetHandler<Widget>()
+            {
+                public boolean handle(Widget widget)
+                {
+                    String widgetID = getWidgetID(widget);
+                    if (widgetID.startsWith(idPrefix))
+                    {
+                        ids.add(widgetID);
+                    }
+                    return false;
+                }
+            });
+        return ids;
     }
-
-    @SuppressWarnings("unchecked")
-    private static Widget tryToFindByID(Widget widget, String id)
+    
+    private static final class WidgetTreeTraverser implements IWidgetHandler<Widget>
     {
-        Widget result = null;
-        if (id.equals(widget.getElement().getId()))
+        private final IWidgetHandler<Widget> handler;
+
+        WidgetTreeTraverser(IWidgetHandler<Widget> handler)
         {
-            result = widget;
-        } else if ((widget instanceof Component) && id.equals(((Component) widget).getId()))
+            this.handler = handler;
+        }
+        
+        @SuppressWarnings("unchecked")
+        public boolean handle(Widget widget)
+        {
+            if (widget instanceof ComplexPanel)
+            {
+                return new ComplexPanelHandler(this).handle((ComplexPanel) widget);
+            } else if (widget instanceof Container)
+            {
+                return new ContainerHandler(this).handle((Container<Component>) widget);
+            } else 
+            {
+                return handler.handle(widget);
+            }
+        }
+        
+    }
+    
+    private static final class ComplexPanelHandler implements IWidgetHandler<ComplexPanel>
+    {
+        private final IWidgetHandler<Widget> handler;
+
+        ComplexPanelHandler(IWidgetHandler<Widget> handler)
         {
-            result = widget;
-        } else if (widget instanceof ComplexPanel)
+            this.handler = handler;
+        }
+
+        public boolean handle(ComplexPanel panel)
         {
-            ComplexPanel panel = (ComplexPanel) widget;
-            for (int i = 0, n = panel.getWidgetCount(); i < n && result == null; i++)
+            for (int i = 0, n = panel.getWidgetCount(); i < n; i++)
             {
-                result = tryToFindByID(panel.getWidget(i), id);
+                if (handler.handle(panel.getWidget(i)))
+                {
+                    return true;
+                }
             }
-        } else if (widget instanceof Container)
+            return false;
+        }
+    }
+    
+    private static final class ContainerHandler implements IWidgetHandler<Container<Component>>
+    {
+        private final IWidgetHandler<Widget> handler;
+
+        ContainerHandler(IWidgetHandler<Widget> handler)
+        {
+            this.handler = handler;
+        }
+
+        public boolean handle(Container<Component> container)
         {
-            Container<Component> container = (Container<Component>) widget;
             List<Component> items = container.getItems();
-            for (int i = 0, n = items.size(); i < n && result == null; i++)
+            for (int i = 0, n = items.size(); i < n; i++)
             {
-                result = tryToFindByID(items.get(i), id);
+                if (handler.handle(items.get(i)))
+                {
+                    return true;
+                }
             }
-            if (result == null && widget instanceof ContentPanel)
+            if (container instanceof ContentPanel)
             {
-                ContentPanel contentPanel = (ContentPanel) widget;
+                ContentPanel contentPanel = (ContentPanel) container;
                 List<Button> buttons = contentPanel.getButtonBar().getItems();
-                for (int i = 0, n = buttons.size(); i < n && result == null; i++)
+                for (int i = 0, n = buttons.size(); i < n; i++)
                 {
-                    result = tryToFindByID(buttons.get(i), id);
+                    if (handler.handle(buttons.get(i)))
+                    {
+                        return true;
+                    }
                 }
             }
+            return false;
         }
-        return result;
+        
     }
-
-
+    
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/IWidgetHandler.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/IWidgetHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..61e814dd47a27dbbcf8efdd1b99fcddddc192cf9
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/IWidgetHandler.java
@@ -0,0 +1,34 @@
+/*
+ * 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.ui.Widget;
+
+/**
+ * Handler of {@link Widget} objects when traversing a GWT page.
+ *
+ * @author Franz-Josef Elmer
+ */
+public interface IWidgetHandler<W extends Widget>
+{
+    /**
+     * Handles the specified widget.
+     * 
+     * @return <code>true</code> if traversing should be stopped.
+     */
+    public boolean handle(W widget);
+}
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 513218c49e7473408b120e8dcbf790bf6645cf24..45d9feda33377293891f5f463bb95a5fcc336b94 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
@@ -91,7 +91,6 @@ public class RemoteConsole
 
                 public void finishOnSuccessOf(AsyncCallback<Object> callback, Object result)
                 {
-                    System.out.println(entryIndex + "/" + entries.size() + ": " + callback);
                     if (entryIndex < entries.size()
                             && entries.get(entryIndex).condition.valid(callback, result))
                     {
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/WidgetPicker.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/WidgetPicker.java
new file mode 100644
index 0000000000000000000000000000000000000000..67b1dc5c70fef522dc96d553348e6ba9797718b1
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/WidgetPicker.java
@@ -0,0 +1,58 @@
+/*
+ * 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.ui.Widget;
+
+/**
+ * Widget handler which picks the first widget having a specified ID.
+ *
+ * @author Franz-Josef Elmer
+ */
+public class WidgetPicker implements IWidgetHandler<Widget>
+{
+    private final String id;
+    
+    private Widget pickedWidget;
+
+    /**
+     * Creates an instance for the specified widget ID.
+     */
+    public WidgetPicker(String id)
+    {
+        this.id = id;
+    }
+    
+    /**
+     * Returns the picked widget or <code>null</code>.
+     */
+    public final Widget tryToGetPickedWidget()
+    {
+        return pickedWidget;
+    }
+
+    public boolean handle(Widget widget)
+    {
+        if (id.equals(GWTTestUtil.getWidgetID(widget)))
+        {
+            pickedWidget = widget;
+            return true;
+        }
+        return false;
+    }
+
+}