From aef22185d111c085e26a03ae53b661155001494e Mon Sep 17 00:00:00 2001
From: anttil <anttil>
Date: Thu, 20 Sep 2012 08:21:49 +0000
Subject: [PATCH] SWE-2 / SP-263: Refactor Page and BrowserPage classes away.

SVN: 26694
---
 .../uitest/infra/ApplicationRunner.java       | 133 ++++++++++++---
 .../cisd/openbis/uitest/infra/Browsable.java  |   6 +-
 .../cisd/openbis/uitest/infra/Browser.java    |  30 ++++
 .../matcher/BrowserListsElementMatcher.java   |  29 ++--
 .../uitest/infra/matcher/PageMatcher.java     |   8 +-
 .../uitest/infra/webdriver/PageProxy.java     |   5 +-
 .../uitest/page/common/BrowserPage.java       | 157 ------------------
 .../openbis/uitest/page/common/LoginPage.java |   2 +-
 .../cisd/openbis/uitest/page/common/Page.java |  97 -----------
 .../cisd/openbis/uitest/page/common/Row.java  |  52 ++++++
 .../openbis/uitest/page/common/TopBar.java    |  22 +--
 .../page/dialog/AddExperimentTypeDialog.java  |  10 +-
 .../page/dialog/AddSampleTypeDialog.java      |  22 +--
 .../uitest/page/dialog/AddSpaceDialog.java    |   7 +-
 .../page/dialog/AddVocabularyDialog.java      |   7 +-
 .../page/dialog/EditSampleTypeDialog.java     |  19 +--
 .../page/dialog/InvalidPasswordDialog.java    |   7 +-
 .../openbis/uitest/page/menu/AdminMenu.java   |  20 +--
 .../uitest/page/menu/AuthorizationMenu.java   |   7 +-
 .../openbis/uitest/page/menu/BrowseMenu.java  |  15 +-
 .../uitest/page/menu/MetadataMenu.java        |  19 +--
 .../openbis/uitest/page/menu/NewMenu.java     |  15 +-
 .../openbis/uitest/page/menu/TypesMenu.java   |  11 +-
 .../openbis/uitest/page/menu/UserMenu.java    |   7 +-
 .../uitest/page/tab/AddPropertyType.java      |   6 +-
 .../page/tab/AssignSamplePropertyType.java    |   6 +-
 .../uitest/page/tab/ExperimentBrowser.java    |  24 +--
 .../page/tab/ExperimentTypeBrowser.java       |  29 ++--
 .../uitest/page/tab/ProjectBrowser.java       |  25 ++-
 .../tab/PropertyTypeAssignmentBrowser.java    |  25 ++-
 .../uitest/page/tab/PropertyTypeBrowser.java  |  25 ++-
 .../uitest/page/tab/RegisterExperiment.java   |   9 +-
 .../uitest/page/tab/RegisterProject.java      |   6 +-
 .../uitest/page/tab/RegisterSample.java       |   9 +-
 .../page/tab/RoleAssignmentBrowser.java       |  23 +--
 .../uitest/page/tab/SampleBrowser.java        |  42 ++---
 .../uitest/page/tab/SampleTypeBrowser.java    |  38 ++---
 .../openbis/uitest/page/tab/SpaceBrowser.java |  29 ++--
 .../cisd/openbis/uitest/page/tab/Trash.java   |   6 +-
 .../uitest/page/tab/VocabularyBrowser.java    |  30 ++--
 .../cisd/openbis/uitest/suite/SampleTest.java |   1 -
 .../openbis/uitest/suite/SeleniumTest.java    |  27 ++-
 .../cisd/openbis/uitest/suite/SpaceTest.java  |  10 ++
 .../{ManualTest.java => SprintTest.java}      |   6 +-
 .../cisd/openbis/uitest/type/Builder.java     |   2 +
 .../cisd/openbis/uitest/type/Experiment.java  |   4 +-
 .../uitest/type/ExperimentBuilder.java        |  14 +-
 .../openbis/uitest/type/ExperimentType.java   |   5 +-
 .../uitest/type/ExperimentTypeBuilder.java    |   8 +-
 .../cisd/openbis/uitest/type/Project.java     |   5 +-
 .../openbis/uitest/type/ProjectBuilder.java   |  12 +-
 .../openbis/uitest/type/PropertyType.java     |   5 +-
 .../uitest/type/PropertyTypeAssignment.java   |   5 +-
 .../type/PropertyTypeAssignmentBuilder.java   |  15 +-
 .../uitest/type/PropertyTypeBuilder.java      |   8 +-
 .../cisd/openbis/uitest/type/Sample.java      |   3 +-
 .../openbis/uitest/type/SampleBuilder.java    |  14 +-
 .../cisd/openbis/uitest/type/SampleType.java  |   4 +-
 .../uitest/type/SampleTypeBuilder.java        |  11 +-
 .../cisd/openbis/uitest/type/Space.java       |   5 +-
 .../openbis/uitest/type/SpaceBuilder.java     |   9 +-
 .../cisd/openbis/uitest/type/Vocabulary.java  |   4 +-
 .../uitest/type/VocabularyBuilder.java        |   8 +-
 .../cisd/openbis/uitest/widget/Button.java    |   8 +
 .../cisd/openbis/uitest/widget/Grid.java      |  58 +++++++
 65 files changed, 587 insertions(+), 703 deletions(-)
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browser.java
 delete mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/BrowserPage.java
 delete mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Page.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Row.java
 rename ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/{ManualTest.java => SprintTest.java} (98%)

diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java
index 6b347559789..47e3eccd8e3 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java
@@ -25,6 +25,13 @@ import ch.systemsx.cisd.openbis.uitest.page.dialog.AddSampleTypeDialog;
 import ch.systemsx.cisd.openbis.uitest.page.dialog.AddSpaceDialog;
 import ch.systemsx.cisd.openbis.uitest.page.dialog.AddVocabularyDialog;
 import ch.systemsx.cisd.openbis.uitest.page.dialog.EditSampleTypeDialog;
+import ch.systemsx.cisd.openbis.uitest.page.menu.AdminMenu;
+import ch.systemsx.cisd.openbis.uitest.page.menu.AuthorizationMenu;
+import ch.systemsx.cisd.openbis.uitest.page.menu.BrowseMenu;
+import ch.systemsx.cisd.openbis.uitest.page.menu.MetadataMenu;
+import ch.systemsx.cisd.openbis.uitest.page.menu.NewMenu;
+import ch.systemsx.cisd.openbis.uitest.page.menu.TypesMenu;
+import ch.systemsx.cisd.openbis.uitest.page.menu.UserMenu;
 import ch.systemsx.cisd.openbis.uitest.page.tab.AddPropertyType;
 import ch.systemsx.cisd.openbis.uitest.page.tab.AssignSamplePropertyType;
 import ch.systemsx.cisd.openbis.uitest.page.tab.ExperimentBrowser;
@@ -80,6 +87,38 @@ public class ApplicationRunner
         return space;
     }
 
+    public void delete(Space space)
+    {
+        /*
+        SpaceBrowser browser = browseToSpaceBrowser();
+
+        PagingToolBar paging = get(PagingToolBar.class);
+        paging.showFilters();
+
+        FilterToolBar bar = get(FilterToolBar.class).reset();
+        Widget filter = null;
+        for (Widget widget : bar.getFilters()) {
+            if (widget.getValue().equalsIgnoreCase("code")) {
+                filter  = widget;
+            }
+        }
+        if (filter == null) {
+            Setting settings = paging.settings();
+            settings.enableFilter("Code");
+        }
+        // then re-find filter
+        
+        filter.write(space.code();
+        
+        Row row = browser.getRow(space);
+        if (row != null)
+        {
+            row.select();
+            browser.deleteSelection();
+        }
+        */
+    }
+
     public Project create(Project project)
     {
         RegisterProject register = browseToRegisterProject();
@@ -148,8 +187,8 @@ public class ApplicationRunner
 
     public void update(SampleType sampleType)
     {
-        SampleTypeBrowser sampleTypeBrowser = browseToSampleTypeBrowser();
-        EditSampleTypeDialog dialog = sampleTypeBrowser.editSampleType(sampleType);
+        browseToSampleTypeBrowser().editSampleType(sampleType);
+        EditSampleTypeDialog dialog = proxy.get(EditSampleTypeDialog.class);
         dialog.fillWith(sampleType);
         dialog.save();
     }
@@ -168,111 +207,159 @@ public class ApplicationRunner
 
     public void logout()
     {
-        getMenus().user().logout();
+        getMenus().user();
+        load(UserMenu.class).logout();
     }
 
     public SampleTypeBrowser browseToSampleTypeBrowser()
     {
-        return getMenus().admin().types().sampleTypes();
+        getMenus().admin();
+        load(AdminMenu.class).types();
+        load(TypesMenu.class).sampleTypes();
+        return load(SampleTypeBrowser.class);
     }
 
     public ExperimentTypeBrowser browseToExperimentTypeBrowser()
     {
-        return getMenus().admin().types().experimentTypes();
+        getMenus().admin();
+        load(AdminMenu.class).types();
+        load(TypesMenu.class).experimentTypes();
+        return load(ExperimentTypeBrowser.class);
     }
 
     public Trash browseToTrash()
     {
-        return getMenus().trash();
+        getMenus().trash();
+        return load(Trash.class);
     }
 
     public AddSampleTypeDialog browseToAddSampleTypeDialog()
     {
-        return browseToSampleTypeBrowser().add();
+        browseToSampleTypeBrowser().add();
+        return load(AddSampleTypeDialog.class);
     }
 
     public AddExperimentTypeDialog browseToAddExperimentTypeDialog()
     {
-        return browseToExperimentTypeBrowser().add();
+        browseToExperimentTypeBrowser().add();
+        return load(AddExperimentTypeDialog.class);
     }
 
     public SpaceBrowser browseToSpaceBrowser()
     {
-        return getMenus().admin().spaces();
+        getMenus().admin();
+        load(AdminMenu.class).spaces();
+        return load(SpaceBrowser.class);
     }
 
     public ProjectBrowser browseToProjectBrowser()
     {
-        return getMenus().browse().projects();
+        getMenus().browse();
+        load(BrowseMenu.class).projects();
+        return load(ProjectBrowser.class);
     }
 
     public AddSpaceDialog browseToAddSpaceDialog()
     {
-        return browseToSpaceBrowser().addSpace();
+        browseToSpaceBrowser().addSpace();
+        return load(AddSpaceDialog.class);
     }
 
     public SampleBrowser browseToSampleBrowser()
     {
-        return getMenus().browse().samples();
+        getMenus().browse();
+        load(BrowseMenu.class).samples();
+        return load(SampleBrowser.class);
     }
 
     public ExperimentBrowser browseToExperimentBrowser()
     {
-        return getMenus().browse().experiments();
+        getMenus().browse();
+        load(BrowseMenu.class).experiments();
+        return load(ExperimentBrowser.class);
     }
 
     public RoleAssignmentBrowser browseToRoleAssignmentBrowser()
     {
-        return getMenus().admin().authorization().roles();
+        getMenus().admin();
+        load(AdminMenu.class).authorization();
+        load(AuthorizationMenu.class).roles();
+        return load(RoleAssignmentBrowser.class);
     }
 
     public VocabularyBrowser browseToVocabularyBrowser()
     {
-        return getMenus().admin().vocabularies();
+        getMenus().admin();
+        load(AdminMenu.class).vocabularies();
+        return load(VocabularyBrowser.class);
     }
 
     public AddVocabularyDialog browseToAddVocabularyDialog()
     {
-        return browseToVocabularyBrowser().add();
+        browseToVocabularyBrowser().add();
+        return load(AddVocabularyDialog.class);
     }
 
     public PropertyTypeBrowser browseToPropertyTypeBrowser()
     {
-        return getMenus().admin().metadata().propertyTypes();
+        getMenus().admin();
+        load(AdminMenu.class).metadata();
+        load(MetadataMenu.class).propertyTypes();
+        return load(PropertyTypeBrowser.class);
     }
 
     public AddPropertyType browseToAddPropertyType()
     {
-        return getMenus().admin().metadata().newPropertyType();
+        getMenus().admin();
+        load(AdminMenu.class).metadata();
+        load(MetadataMenu.class).newPropertyType();
+        return load(AddPropertyType.class);
     }
 
     public AssignSamplePropertyType browseToAssignSamplePropertyType()
     {
-        return getMenus().admin().metadata().assignToSampleType();
+        getMenus().admin();
+        load(AdminMenu.class).metadata();
+        load(MetadataMenu.class).assignToSampleType();
+        return load(AssignSamplePropertyType.class);
     }
 
     public PropertyTypeAssignmentBrowser browseToPropertyTypeAssignmentBrowser()
     {
-        return getMenus().admin().metadata().propertyTypeAssignments();
+        getMenus().admin();
+        load(AdminMenu.class).metadata();
+        load(MetadataMenu.class).propertyTypeAssignments();
+        return load(PropertyTypeAssignmentBrowser.class);
     }
 
     public RegisterSample browseToRegisterSample()
     {
-        return getMenus().newMenu().sample();
+        getMenus().newMenu();
+        load(NewMenu.class).sample();
+        return load(RegisterSample.class);
     }
 
     public RegisterExperiment browseToRegisterExperiment()
     {
-        return getMenus().newMenu().experiment();
+        getMenus().newMenu();
+        load(NewMenu.class).experiment();
+        return load(RegisterExperiment.class);
     }
 
     public RegisterProject browseToRegisterProject()
     {
-        return getMenus().newMenu().project();
+        getMenus().newMenu();
+        load(NewMenu.class).project();
+        return load(RegisterProject.class);
     }
 
     private TopBar getMenus()
     {
         return proxy.get(TopBar.class);
     }
+
+    private <T> T load(Class<T> clazz)
+    {
+        return proxy.get(clazz);
+    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browsable.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browsable.java
index a7984b9056f..5b91eef45fc 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browsable.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browsable.java
@@ -16,14 +16,12 @@
 
 package ch.systemsx.cisd.openbis.uitest.infra;
 
-import java.util.Map;
-
-import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
  */
 public interface Browsable
 {
-    public boolean isRepresentedBy(Map<String, Cell> row);
+    public boolean isRepresentedBy(Row row);
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browser.java
new file mode 100644
index 00000000000..013edb56a2b
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/Browser.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 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.uitest.infra;
+
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+
+/**
+ * @author anttil
+ */
+public interface Browser<T extends Browsable>
+{
+    public Row row(T browsable);
+
+    public Cell cell(T browsable, String column);
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java
index ae6be526265..0945747f61f 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java
@@ -16,24 +16,22 @@
 
 package ch.systemsx.cisd.openbis.uitest.infra.matcher;
 
-import java.util.Map;
-
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeMatcher;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
-import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
  */
-public class BrowserListsElementMatcher extends
-        TypeSafeMatcher<BrowserPage>
+public class BrowserListsElementMatcher<T extends Browsable, U extends Browser<T>> extends
+        TypeSafeMatcher<U>
 {
-    private Browsable expected;
+    private T expected;
 
-    public BrowserListsElementMatcher(Browsable expected)
+    public BrowserListsElementMatcher(T expected)
     {
         this.expected = expected;
     }
@@ -45,15 +43,16 @@ public class BrowserListsElementMatcher extends
     }
 
     @Override
-    public boolean matchesSafely(BrowserPage browser)
+    public boolean matchesSafely(U browser)
     {
-        for (Map<String, Cell> row : browser.getTableContent())
+
+        Row row = browser.row(expected);
+        if (row.exists())
+        {
+            return expected.isRepresentedBy(row);
+        } else
         {
-            if (this.expected.isRepresentedBy(row))
-            {
-                return true;
-            }
+            return false;
         }
-        return false;
     }
 }
\ No newline at end of file
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/PageMatcher.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/PageMatcher.java
index 4bc98fffc28..2f2d207970e 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/PageMatcher.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/PageMatcher.java
@@ -27,7 +27,6 @@ import org.openqa.selenium.support.FindBy;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.PageProxy;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
 
 /**
  * @author anttil
@@ -35,11 +34,11 @@ import ch.systemsx.cisd.openbis.uitest.page.common.Page;
 public class PageMatcher extends TypeSafeMatcher<WebDriver>
 {
 
-    private Class<? extends Page> pageClass;
+    private Class<?> pageClass;
 
     private PageProxy pageProxy;
 
-    public PageMatcher(Class<? extends Page> pageClass, PageProxy pageProxy)
+    public PageMatcher(Class<?> pageClass, PageProxy pageProxy)
     {
         this.pageClass = pageClass;
         this.pageProxy = pageProxy;
@@ -51,7 +50,6 @@ public class PageMatcher extends TypeSafeMatcher<WebDriver>
         description.appendText("Browser on page described by " + this.pageClass.getName());
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public boolean matchesSafely(WebDriver ignore)
     {
@@ -89,7 +87,7 @@ public class PageMatcher extends TypeSafeMatcher<WebDriver>
                 }
             }
 
-            pageClass = (Class<? extends Page>) pageClass.getSuperclass();
+            pageClass = pageClass.getSuperclass();
         }
         return true;
     }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/webdriver/PageProxy.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/webdriver/PageProxy.java
index 2c90e80ac06..087037f4c5e 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/webdriver/PageProxy.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/webdriver/PageProxy.java
@@ -30,7 +30,6 @@ import org.openqa.selenium.WebElement;
 
 import ch.systemsx.cisd.openbis.uitest.infra.screenshot.ScreenShotProxy;
 import ch.systemsx.cisd.openbis.uitest.infra.screenshot.ScreenShotter;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
 import ch.systemsx.cisd.openbis.uitest.suite.SeleniumTest;
 import ch.systemsx.cisd.openbis.uitest.widget.Widget;
 
@@ -47,7 +46,7 @@ public class PageProxy
     }
 
     @SuppressWarnings("unchecked")
-    public <T extends Page> T get(final Class<T> clazz)
+    public <T> T get(final Class<T> clazz)
     {
 
         ProxyFactory factory = new ProxyFactory();
@@ -97,8 +96,6 @@ public class PageProxy
             throw new RuntimeException(ex1);
         }
 
-        t.setPageProxy(this);
-
         initLocateFields(clazz, t);
 
         return t;
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/BrowserPage.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/BrowserPage.java
deleted file mode 100644
index 102f060b5de..00000000000
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/BrowserPage.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2012 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.uitest.page.common;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.openqa.selenium.By;
-import org.openqa.selenium.JavascriptExecutor;
-import org.openqa.selenium.WebElement;
-
-import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
-import ch.systemsx.cisd.openbis.uitest.suite.SeleniumTest;
-
-/**
- * @author anttil
- */
-public abstract class BrowserPage extends TopBar
-{
-
-    protected abstract List<WebElement> getColumns();
-
-    protected abstract List<WebElement> getData();
-
-    public Collection<Map<String, Cell>> getTableContent()
-    {
-        List<Map<String, Cell>> content = new ArrayList<Map<String, Cell>>();
-
-        List<WebElement> columnNames = getColumns();
-        List<WebElement> gridValues = getData();
-
-        List<String> columns = new ArrayList<String>();
-        for (WebElement columnName : columnNames)
-        {
-            columns.add(columnName.getText());
-        }
-
-        int index = 0;
-        Map<String, Cell> map = new HashMap<String, Cell>();
-
-        for (WebElement element : gridValues)
-        {
-            String columnName = columns.get(index % columns.size());
-            map.put(columnName, new Cell(element.getText(), element.getAttribute("href"), element));
-
-            index++;
-
-            if (index % columns.size() == 0)
-            {
-                content.add(map);
-                map = new HashMap<String, Cell>();
-            }
-        }
-        return content;
-    }
-
-    public Cell cell(Browsable browsable, String columnName)
-    {
-        for (Map<String, Cell> row : getTableContent())
-        {
-            if (browsable.isRepresentedBy(row))
-            {
-                return row.get(columnName);
-            }
-        }
-        throw new IllegalStateException("Could not find " + browsable + " from " + toString());
-    }
-
-    protected abstract WebElement getDeleteButton();
-
-    public boolean deleteIfExists(String column, String value)
-    {
-        for (Map<String, Cell> row : getTableContent())
-        {
-
-            Cell cell = row.get(column);
-            if (cell != null && cell.getText().equalsIgnoreCase(value))
-            {
-                cell.getElement().findElement(By.xpath("./..")).click();
-                waitForClickability(getDeleteButton());
-                getDeleteButton().click();
-
-                for (WebElement ellu : this.findElements(cell.getElement(),
-                        "//*[@id='deletion-confirmation-dialog']//textarea"))
-                {
-                    ellu.sendKeys("reason for deletion");
-                }
-
-                this.findElement(cell.getElement(),
-                        "//*[@id='deletion-confirmation-dialog']//button[text()='OK' or text()='Yes']")
-                        .click();
-
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString()
-    {
-        String value = getClass().getSimpleName() + "\n";
-        int numColumns = 0;
-        for (WebElement column : getColumns())
-        {
-            value += column.getText() + "\t";
-            numColumns++;
-        }
-
-        int counter = 0;
-        for (WebElement cell : getData())
-        {
-
-            if (counter % numColumns == 0)
-            {
-                value += "\n";
-            }
-            value += "-" + cell.getText() + "-\t";
-            counter++;
-        }
-
-        return value;
-
-    }
-
-    protected String getXPath(WebElement webElement)
-    {
-        String jscript = "function getPathTo(node) {" +
-                "  var stack = [];" +
-                "  while(node.parentNode !== null) {" +
-                "    stack.unshift(node.tagName);" +
-                "    node = node.parentNode;" +
-                "  }" +
-                "  return stack.join('/');" +
-                "}" +
-                "return getPathTo(arguments[0]);";
-        return (String) ((JavascriptExecutor) SeleniumTest.driver).executeScript(jscript,
-                webElement);
-    }
-}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/LoginPage.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/LoginPage.java
index 733916bf565..6c417e1c42d 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/LoginPage.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/LoginPage.java
@@ -20,7 +20,7 @@ import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 
-public class LoginPage extends Page
+public class LoginPage
 {
     @Locate("openbis_login_username")
     private Text username;
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Page.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Page.java
deleted file mode 100644
index 8c68418c565..00000000000
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Page.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012 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.uitest.page.common;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.ui.WebDriverWait;
-
-import com.google.common.base.Function;
-
-import ch.systemsx.cisd.openbis.uitest.infra.screenshot.ScreenShotProxy;
-import ch.systemsx.cisd.openbis.uitest.infra.screenshot.ScreenShotter;
-import ch.systemsx.cisd.openbis.uitest.infra.webdriver.PageProxy;
-import ch.systemsx.cisd.openbis.uitest.suite.SeleniumTest;
-
-public abstract class Page
-{
-
-    private PageProxy pageProxy;
-
-    private ScreenShotter shotter;
-
-    public void setPageProxy(PageProxy proxy)
-    {
-        this.pageProxy = proxy;
-    }
-
-    public void setScreenShotter(ScreenShotter shotter)
-    {
-        this.shotter = shotter;
-    }
-
-    public <T extends Page> T get(Class<T> clazz)
-    {
-        return this.pageProxy.get(clazz);
-    }
-
-    public WebElement findElement(WebElement element, String xpath)
-    {
-        return (WebElement) ScreenShotProxy.newInstance(element.findElement(By.xpath(xpath)),
-                shotter);
-    }
-
-    public Collection<WebElement> findElements(WebElement element, String xpath)
-    {
-        SeleniumTest.driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
-        Collection<WebElement> elements = element.findElements(By.xpath(xpath));
-        SeleniumTest.driver.manage().timeouts().implicitlyWait(SeleniumTest.IMPLICIT_WAIT,
-                TimeUnit.MILLISECONDS);
-        List<WebElement> wrapped = new ArrayList<WebElement>();
-        for (WebElement e : elements)
-        {
-            wrapped.add((WebElement) ScreenShotProxy.newInstance(e, shotter));
-        }
-        return wrapped;
-    }
-
-    public void waitForClickability(final WebElement element)
-    {
-
-        new WebDriverWait(SeleniumTest.driver, 10).until(new Function<WebDriver, Object>()
-            {
-                @Override
-                public Object apply(WebDriver arg0)
-                {
-                    if (element.isDisplayed() && element.isEnabled())
-                    {
-                        return true;
-                    } else
-                    {
-                        return null;
-                    }
-                }
-
-            });
-    }
-}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Row.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Row.java
new file mode 100644
index 00000000000..698dde00b6a
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/Row.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 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.uitest.page.common;
+
+import java.util.Map;
+
+/**
+ * @author anttil
+ */
+public class Row
+{
+
+    private Map<String, Cell> row;
+
+    private boolean exists;
+
+    public Row()
+    {
+        this.exists = false;
+    }
+
+    public Row(Map<String, Cell> row)
+    {
+        this.row = row;
+        this.exists = true;
+    }
+
+    public boolean exists()
+    {
+        return exists;
+    }
+
+    public Cell get(String columnName)
+    {
+        return this.row.get(columnName);
+    }
+
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/TopBar.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/TopBar.java
index c20b6fd517b..47f27b166a8 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/TopBar.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/common/TopBar.java
@@ -17,18 +17,13 @@
 package ch.systemsx.cisd.openbis.uitest.page.common;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.menu.AdminMenu;
-import ch.systemsx.cisd.openbis.uitest.page.menu.BrowseMenu;
-import ch.systemsx.cisd.openbis.uitest.page.menu.NewMenu;
-import ch.systemsx.cisd.openbis.uitest.page.menu.UserMenu;
-import ch.systemsx.cisd.openbis.uitest.page.tab.Trash;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 
 /**
  * @author anttil
  */
-public abstract class TopBar extends Page
+public class TopBar
 {
     @Locate("admin_menu")
     private Button adminMenu;
@@ -49,33 +44,28 @@ public abstract class TopBar extends Page
     @Locate("openbis_search-widget_text-field-input")
     private Text searchTextBox;
 
-    public AdminMenu admin()
+    public void admin()
     {
         adminMenu.click();
-        return get(AdminMenu.class);
     }
 
-    public UserMenu user()
+    public void user()
     {
         userMenu.click();
-        return get(UserMenu.class);
     }
 
-    public BrowseMenu browse()
+    public void browse()
     {
         browseMenu.click();
-        return get(BrowseMenu.class);
     }
 
-    public Trash trash()
+    public void trash()
     {
         trash.click();
-        return get(Trash.class);
     }
 
-    public NewMenu newMenu()
+    public void newMenu()
     {
         newMenu.click();
-        return get(NewMenu.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddExperimentTypeDialog.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddExperimentTypeDialog.java
index 8ee2b74cd5d..1aefd9a06a0 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddExperimentTypeDialog.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddExperimentTypeDialog.java
@@ -17,14 +17,12 @@
 package ch.systemsx.cisd.openbis.uitest.page.dialog;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.ExperimentTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.type.ExperimentType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 import ch.systemsx.cisd.openbis.uitest.widget.TextArea;
 
-public class AddExperimentTypeDialog extends Page
+public class AddExperimentTypeDialog
 {
 
     @Locate("openbis_dialog-code-field")
@@ -39,16 +37,14 @@ public class AddExperimentTypeDialog extends Page
     @Locate("openbis_dialog-cancel-button")
     private Button cancel;
 
-    public ExperimentTypeBrowser save()
+    public void save()
     {
         save.click();
-        return get(ExperimentTypeBrowser.class);
     }
 
-    public ExperimentTypeBrowser cancel()
+    public void cancel()
     {
         cancel.click();
-        return get(ExperimentTypeBrowser.class);
     }
 
     public void fillWith(ExperimentType experimentType)
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSampleTypeDialog.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSampleTypeDialog.java
index 3292cee19d6..bb09f51be8d 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSampleTypeDialog.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSampleTypeDialog.java
@@ -17,15 +17,13 @@
 package ch.systemsx.cisd.openbis.uitest.page.dialog;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.SampleTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Checkbox;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 
 @SuppressWarnings("unused")
-public class AddSampleTypeDialog extends Page
+public class AddSampleTypeDialog
 {
 
     @Locate("openbis_dialog-code-field")
@@ -61,40 +59,34 @@ public class AddSampleTypeDialog extends Page
     @Locate("openbis_dialog-cancel-button")
     private Button cancel;
 
-    public SampleTypeBrowser save()
+    public void save()
     {
         save.click();
-        return get(SampleTypeBrowser.class);
     }
 
-    public SampleTypeBrowser cancel()
+    public void cancel()
     {
         cancel.click();
-        return get(SampleTypeBrowser.class);
     }
 
-    public AddSampleTypeDialog setCode(String code)
+    public void setCode(String code)
     {
         this.code.write(code);
-        return this;
     }
 
-    public AddSampleTypeDialog setListable(boolean checked)
+    public void setListable(boolean checked)
     {
         listable.set(checked);
-        return this;
     }
 
-    public AddSampleTypeDialog setShowContainer(boolean checked)
+    public void setShowContainer(boolean checked)
     {
         showContainer.set(checked);
-        return this;
     }
 
-    public AddSampleTypeDialog setShowParents(boolean checked)
+    public void setShowParents(boolean checked)
     {
         showParents.set(checked);
-        return this;
     }
 
     public void fillWith(SampleType sampleType)
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSpaceDialog.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSpaceDialog.java
index afba7f5e4b9..d3941b475d1 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSpaceDialog.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSpaceDialog.java
@@ -17,13 +17,11 @@
 package ch.systemsx.cisd.openbis.uitest.page.dialog;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.SpaceBrowser;
 import ch.systemsx.cisd.openbis.uitest.type.Space;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 
-public class AddSpaceDialog extends Page
+public class AddSpaceDialog
 {
 
     @Locate("openbis_dialog-code-field")
@@ -37,9 +35,8 @@ public class AddSpaceDialog extends Page
         code.write(space.getCode());
     }
 
-    public SpaceBrowser save()
+    public void save()
     {
         save.click();
-        return get(SpaceBrowser.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddVocabularyDialog.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddVocabularyDialog.java
index 45a160e1b9e..172767a032f 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddVocabularyDialog.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddVocabularyDialog.java
@@ -17,14 +17,12 @@
 package ch.systemsx.cisd.openbis.uitest.page.dialog;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.VocabularyBrowser;
 import ch.systemsx.cisd.openbis.uitest.type.Vocabulary;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 import ch.systemsx.cisd.openbis.uitest.widget.TextArea;
 
-public class AddVocabularyDialog extends Page
+public class AddVocabularyDialog
 {
 
     @Locate("openbis_vocabulary-registration_formvocabulary_registration_field_set_code")
@@ -56,9 +54,8 @@ public class AddVocabularyDialog extends Page
         url.write(vocabulary.getUrl());
     }
 
-    public VocabularyBrowser save()
+    public void save()
     {
         save.click();
-        return get(VocabularyBrowser.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/EditSampleTypeDialog.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/EditSampleTypeDialog.java
index 0916bda6782..be1fc5449ca 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/EditSampleTypeDialog.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/EditSampleTypeDialog.java
@@ -17,15 +17,13 @@
 package ch.systemsx.cisd.openbis.uitest.page.dialog;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.SampleTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Checkbox;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 
 @SuppressWarnings("unused")
-public class EditSampleTypeDialog extends Page
+public class EditSampleTypeDialog
 {
 
     @Locate("openbis_edit-type-dialog-description")
@@ -58,34 +56,29 @@ public class EditSampleTypeDialog extends Page
     @Locate("openbis_dialog-cancel-button")
     private Button cancel;
 
-    public SampleTypeBrowser save()
+    public void save()
     {
         save.click();
-        return get(SampleTypeBrowser.class);
     }
 
-    public SampleTypeBrowser cancel()
+    public void cancel()
     {
         cancel.click();
-        return get(SampleTypeBrowser.class);
     }
 
-    public EditSampleTypeDialog setListable(boolean checked)
+    public void setListable(boolean checked)
     {
         listable.set(checked);
-        return this;
     }
 
-    public EditSampleTypeDialog setShowContainer(boolean checked)
+    public void setShowContainer(boolean checked)
     {
         showContainer.set(checked);
-        return this;
     }
 
-    public EditSampleTypeDialog setShowParents(boolean checked)
+    public void setShowParents(boolean checked)
     {
         showParents.set(checked);
-        return this;
     }
 
     public void fillWith(SampleType sampleType)
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/InvalidPasswordDialog.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/InvalidPasswordDialog.java
index 0c2d810e2af..4fb50d16552 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/InvalidPasswordDialog.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/InvalidPasswordDialog.java
@@ -17,18 +17,15 @@
 package ch.systemsx.cisd.openbis.uitest.page.dialog;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.LoginPage;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
 import ch.systemsx.cisd.openbis.uitest.widget.AlertMessageBox;
 
-public class InvalidPasswordDialog extends Page
+public class InvalidPasswordDialog
 {
     @Locate("login_failed_dialog")
     private AlertMessageBox errorDialog;
 
-    public LoginPage dismiss()
+    public void dismiss()
     {
         errorDialog.dismiss();
-        return get(LoginPage.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AdminMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AdminMenu.java
index 80c8ccb455b..90c2a9eae4a 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AdminMenu.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AdminMenu.java
@@ -17,12 +17,9 @@
 package ch.systemsx.cisd.openbis.uitest.page.menu;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.SpaceBrowser;
-import ch.systemsx.cisd.openbis.uitest.page.tab.VocabularyBrowser;
 import ch.systemsx.cisd.openbis.uitest.widget.Link;
 
-public class AdminMenu extends Page
+public class AdminMenu
 {
 
     @Locate("openbis_top-menu_ADMINISTRATION_MENU_MANAGE_GROUPS")
@@ -40,33 +37,28 @@ public class AdminMenu extends Page
     @Locate("ADMINISTRATION_MENU_MANAGE_AUTHORIZATION")
     private Link authorization;
 
-    public SpaceBrowser spaces()
+    public void spaces()
     {
         spaces.click();
-        return get(SpaceBrowser.class);
     }
 
-    public VocabularyBrowser vocabularies()
+    public void vocabularies()
     {
         vocabularies.click();
-        return get(VocabularyBrowser.class);
     }
 
-    public TypesMenu types()
+    public void types()
     {
         types.highlight();
-        return get(TypesMenu.class);
     }
 
-    public MetadataMenu metadata()
+    public void metadata()
     {
         metadata.highlight();
-        return get(MetadataMenu.class);
     }
 
-    public AuthorizationMenu authorization()
+    public void authorization()
     {
         authorization.highlight();
-        return get(AuthorizationMenu.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AuthorizationMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AuthorizationMenu.java
index 53c52453b2e..082721ae940 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AuthorizationMenu.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/AuthorizationMenu.java
@@ -17,19 +17,16 @@
 package ch.systemsx.cisd.openbis.uitest.page.menu;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.RoleAssignmentBrowser;
 import ch.systemsx.cisd.openbis.uitest.widget.Link;
 
-public class AuthorizationMenu extends Page
+public class AuthorizationMenu
 {
 
     @Locate("openbis_top-menu_AUTHORIZATION_MENU_ROLES")
     private Link roles;
 
-    public RoleAssignmentBrowser roles()
+    public void roles()
     {
         roles.click();
-        return get(RoleAssignmentBrowser.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/BrowseMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/BrowseMenu.java
index 4a401c974ed..638bfd41918 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/BrowseMenu.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/BrowseMenu.java
@@ -17,13 +17,9 @@
 package ch.systemsx.cisd.openbis.uitest.page.menu;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.ExperimentBrowser;
-import ch.systemsx.cisd.openbis.uitest.page.tab.ProjectBrowser;
-import ch.systemsx.cisd.openbis.uitest.page.tab.SampleBrowser;
 import ch.systemsx.cisd.openbis.uitest.widget.Link;
 
-public class BrowseMenu extends Page
+public class BrowseMenu
 {
 
     @Locate("openbis_top-menu_SAMPLE_MENU_BROWSE")
@@ -35,21 +31,18 @@ public class BrowseMenu extends Page
     @Locate("openbis_top-menu_EXPERIMENT_MENU_BROWSE")
     private Link experiments;
 
-    public SampleBrowser samples()
+    public void samples()
     {
         samples.click();
-        return get(SampleBrowser.class);
     }
 
-    public ProjectBrowser projects()
+    public void projects()
     {
         projects.click();
-        return get(ProjectBrowser.class);
     }
 
-    public ExperimentBrowser experiments()
+    public void experiments()
     {
         experiments.click();
-        return get(ExperimentBrowser.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/MetadataMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/MetadataMenu.java
index cf4f224a51d..efd30c7ec44 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/MetadataMenu.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/MetadataMenu.java
@@ -17,14 +17,9 @@
 package ch.systemsx.cisd.openbis.uitest.page.menu;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.AddPropertyType;
-import ch.systemsx.cisd.openbis.uitest.page.tab.AssignSamplePropertyType;
-import ch.systemsx.cisd.openbis.uitest.page.tab.PropertyTypeAssignmentBrowser;
-import ch.systemsx.cisd.openbis.uitest.page.tab.PropertyTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.widget.Link;
 
-public class MetadataMenu extends Page
+public class MetadataMenu
 {
 
     @Locate("openbis_top-menu_PROPERTY_TYPES_MENU_BROWSE_PROPERTY_TYPES")
@@ -39,27 +34,23 @@ public class MetadataMenu extends Page
     @Locate("openbis_top-menu_PROPERTY_TYPES_MENU_ASSIGN_TO_SAMPLE_TYPE")
     private Link assignToSampleType;
 
-    public PropertyTypeBrowser propertyTypes()
+    public void propertyTypes()
     {
         browsePropertyTypes.click();
-        return get(PropertyTypeBrowser.class);
     }
 
-    public PropertyTypeAssignmentBrowser propertyTypeAssignments()
+    public void propertyTypeAssignments()
     {
         browsePropertyTypeAssignments.click();
-        return get(PropertyTypeAssignmentBrowser.class);
     }
 
-    public AddPropertyType newPropertyType()
+    public void newPropertyType()
     {
         newPropertyType.click();
-        return get(AddPropertyType.class);
     }
 
-    public AssignSamplePropertyType assignToSampleType()
+    public void assignToSampleType()
     {
         assignToSampleType.click();
-        return get(AssignSamplePropertyType.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java
index 75f4f7256d8..6ae25ccf8a5 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java
@@ -17,13 +17,9 @@
 package ch.systemsx.cisd.openbis.uitest.page.menu;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.RegisterExperiment;
-import ch.systemsx.cisd.openbis.uitest.page.tab.RegisterProject;
-import ch.systemsx.cisd.openbis.uitest.page.tab.RegisterSample;
 import ch.systemsx.cisd.openbis.uitest.widget.Link;
 
-public class NewMenu extends Page
+public class NewMenu
 {
 
     @Locate("openbis_top-menu_SAMPLE_MENU_NEW")
@@ -35,21 +31,18 @@ public class NewMenu extends Page
     @Locate("openbis_top-menu_EXPERIMENT_MENU_NEW")
     private Link experiment;
 
-    public RegisterSample sample()
+    public void sample()
     {
         sample.click();
-        return get(RegisterSample.class);
     }
 
-    public RegisterProject project()
+    public void project()
     {
         project.click();
-        return get(RegisterProject.class);
     }
 
-    public RegisterExperiment experiment()
+    public void experiment()
     {
         experiment.click();
-        return get(RegisterExperiment.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/TypesMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/TypesMenu.java
index a3fddad6807..7fe61606590 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/TypesMenu.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/TypesMenu.java
@@ -17,12 +17,9 @@
 package ch.systemsx.cisd.openbis.uitest.page.menu;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
-import ch.systemsx.cisd.openbis.uitest.page.tab.ExperimentTypeBrowser;
-import ch.systemsx.cisd.openbis.uitest.page.tab.SampleTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.widget.Link;
 
-public class TypesMenu extends Page
+public class TypesMenu
 {
 
     @Locate("openbis_top-menu_SAMPLE_MENU_TYPES")
@@ -31,15 +28,13 @@ public class TypesMenu extends Page
     @Locate("openbis_top-menu_EXPERIMENT_MENU_TYPES")
     private Link experimentTypes;
 
-    public SampleTypeBrowser sampleTypes()
+    public void sampleTypes()
     {
         sampleTypes.click();
-        return get(SampleTypeBrowser.class);
     }
 
-    public ExperimentTypeBrowser experimentTypes()
+    public void experimentTypes()
     {
         experimentTypes.click();
-        return get(ExperimentTypeBrowser.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/UserMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/UserMenu.java
index 9c62a0730e8..490e1bb04ec 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/UserMenu.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/UserMenu.java
@@ -17,19 +17,16 @@
 package ch.systemsx.cisd.openbis.uitest.page.menu;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.LoginPage;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
 import ch.systemsx.cisd.openbis.uitest.widget.Link;
 
-public class UserMenu extends Page
+public class UserMenu
 {
 
     @Locate("openbis_top-menu_USER_MENU_LOGOUT")
     private Link logout;
 
-    public LoginPage logout()
+    public void logout()
     {
         logout.click();
-        return get(LoginPage.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AddPropertyType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AddPropertyType.java
index 7f1091b854a..3822c4429dd 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AddPropertyType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AddPropertyType.java
@@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.uitest.page.tab;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.TopBar;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyType;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeDataType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
@@ -26,7 +25,7 @@ import ch.systemsx.cisd.openbis.uitest.widget.DropDown;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 import ch.systemsx.cisd.openbis.uitest.widget.TextArea;
 
-public class AddPropertyType extends TopBar
+public class AddPropertyType
 {
 
     @Locate("openbis_property-type-registration_form_code")
@@ -61,9 +60,8 @@ public class AddPropertyType extends TopBar
         }
     }
 
-    public AddPropertyType save()
+    public void save()
     {
         save.click();
-        return get(AddPropertyType.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java
index 6b34841d3f6..4daf95aff29 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java
@@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.uitest.page.tab;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.TopBar;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeAssignment;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeDataType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
@@ -27,7 +26,7 @@ import ch.systemsx.cisd.openbis.uitest.widget.DropDown;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 import ch.systemsx.cisd.openbis.uitest.widget.Widget;
 
-public class AssignSamplePropertyType extends TopBar
+public class AssignSamplePropertyType
 {
 
     @Locate("openbis_select_property-typeopenbis_property-type-assignment_SAMPLEproperty_type")
@@ -76,9 +75,8 @@ public class AssignSamplePropertyType extends TopBar
         }
     }
 
-    public AssignSamplePropertyType save()
+    public void save()
     {
         this.save.click();
-        return get(AssignSamplePropertyType.class);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentBrowser.java
index 069ebda6e76..3545589586e 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentBrowser.java
@@ -16,18 +16,17 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.Experiment;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.DeletionConfirmationBox;
 import ch.systemsx.cisd.openbis.uitest.widget.TreeGrid;
 
-public class ExperimentBrowser extends BrowserPage
+public class ExperimentBrowser implements Browser<Experiment>
 {
     @Locate("openbis_select-project")
     private TreeGrid projectTree;
@@ -39,10 +38,9 @@ public class ExperimentBrowser extends BrowserPage
     @Locate("deletion-confirmation-dialog")
     private DeletionConfirmationBox deletionDialog;
 
-    public ExperimentBrowser space(String spaceCode)
+    public void space(String spaceCode)
     {
         projectTree.select(spaceCode);
-        return this;
     }
 
     public void deleteAll()
@@ -52,23 +50,17 @@ public class ExperimentBrowser extends BrowserPage
     }
 
     @Override
-    protected WebElement getDeleteButton()
+    public Row row(Experiment browsable)
     {
         // TODO Auto-generated method stub
         return null;
     }
 
     @Override
-    protected List<WebElement> getColumns()
+    public Cell cell(Experiment browsable, String column)
     {
         // TODO Auto-generated method stub
         return null;
     }
 
-    @Override
-    protected List<WebElement> getData()
-    {
-        // TODO Auto-generated method stub
-        return null;
-    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentTypeBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentTypeBrowser.java
index 670ba94a174..a4f64a22f52 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentTypeBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ExperimentTypeBrowser.java
@@ -16,17 +16,15 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
-import ch.systemsx.cisd.openbis.uitest.page.dialog.AddExperimentTypeDialog;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.ExperimentType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class ExperimentTypeBrowser extends BrowserPage
+public class ExperimentTypeBrowser implements Browser<ExperimentType>
 {
 
     @Locate("add-entity-type-EXPERIMENT")
@@ -36,33 +34,28 @@ public class ExperimentTypeBrowser extends BrowserPage
     @Locate("edit-entity-type-EXPERIMENT")
     private Button edit;
 
+    @SuppressWarnings("unused")
     @Locate("delete-entity-type-EXPERIMENT")
     private Button delete;
 
     @Locate("openbis_experiment-type-browser-grid")
     private Grid grid;
 
-    public AddExperimentTypeDialog add()
+    public void add()
     {
         add.click();
-        return get(AddExperimentTypeDialog.class);
     }
 
     @Override
-    protected List<WebElement> getColumns()
+    public Row row(ExperimentType experimentType)
     {
-        return grid.getColumns();
+        return grid.getRow("Code", experimentType.getCode());
     }
 
     @Override
-    protected List<WebElement> getData()
+    public Cell cell(ExperimentType experimentType, String column)
     {
-        return grid.getCells();
+        return row(experimentType).get(column);
     }
 
-    @Override
-    protected WebElement getDeleteButton()
-    {
-        return delete.getContext();
-    }
 }
\ No newline at end of file
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ProjectBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ProjectBrowser.java
index 7ee9aec9472..06854817381 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ProjectBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/ProjectBrowser.java
@@ -16,39 +16,34 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.Project;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class ProjectBrowser extends BrowserPage
+public class ProjectBrowser implements Browser<Project>
 {
 
     @Locate("openbis_project-browser-grid")
     private Grid grid;
 
+    @SuppressWarnings("unused")
     @Locate("openbis_project-browser-delete")
     private Button delete;
 
     @Override
-    protected List<WebElement> getColumns()
+    public Row row(Project project)
     {
-        return grid.getColumns();
+        return grid.getRow("Code", project.getCode());
     }
 
     @Override
-    protected List<WebElement> getData()
+    public Cell cell(Project project, String column)
     {
-        return grid.getCells();
+        return row(project).get(column);
     }
 
-    @Override
-    protected WebElement getDeleteButton()
-    {
-        return delete.getContext();
-    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeAssignmentBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeAssignmentBrowser.java
index 02dc6c2575a..2dcec5c6d1d 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeAssignmentBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeAssignmentBrowser.java
@@ -16,16 +16,15 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeAssignment;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class PropertyTypeAssignmentBrowser extends BrowserPage
+public class PropertyTypeAssignmentBrowser implements Browser<PropertyTypeAssignment>
 {
     @Locate("openbis_property-type-assignment-browser-grid")
     private Grid grid;
@@ -34,24 +33,20 @@ public class PropertyTypeAssignmentBrowser extends BrowserPage
     @Locate("openbis_property-type-assignment-browser-grid-edit")
     private Button edit;
 
+    @SuppressWarnings("unused")
     @Locate("openbis_property-type-assignment-browser-grid-release")
     private Button release;
 
     @Override
-    protected List<WebElement> getColumns()
+    public Row row(PropertyTypeAssignment assignment)
     {
-        return grid.getColumns();
+        return grid.getRow("Property Type Code", assignment.getPropertyType().getCode());
     }
 
     @Override
-    protected List<WebElement> getData()
+    public Cell cell(PropertyTypeAssignment assignment, String column)
     {
-        return grid.getCells();
+        return row(assignment).get(column);
     }
 
-    @Override
-    protected WebElement getDeleteButton()
-    {
-        return release.getContext();
-    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeBrowser.java
index c76b46302db..abbbdf47700 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/PropertyTypeBrowser.java
@@ -16,16 +16,15 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.PropertyType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class PropertyTypeBrowser extends BrowserPage
+public class PropertyTypeBrowser implements Browser<PropertyType>
 {
 
     @Locate("openbis_property-type-browser-grid")
@@ -35,24 +34,20 @@ public class PropertyTypeBrowser extends BrowserPage
     @Locate("openbis_property-type-browser-grid-add-button")
     private Button add;
 
+    @SuppressWarnings("unused")
     @Locate("openbis_property-type-browser-grid-delete-button")
     private Button delete;
 
     @Override
-    protected List<WebElement> getColumns()
+    public Row row(PropertyType type)
     {
-        return grid.getColumns();
+        return grid.getRow("Code", type.getCode());
     }
 
     @Override
-    protected List<WebElement> getData()
+    public Cell cell(PropertyType type, String column)
     {
-        return grid.getCells();
+        return row(type).get(column);
     }
 
-    @Override
-    protected WebElement getDeleteButton()
-    {
-        return delete.getContext();
-    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterExperiment.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterExperiment.java
index eca07f886ad..4a6832a0c00 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterExperiment.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterExperiment.java
@@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.uitest.page.tab;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.TopBar;
 import ch.systemsx.cisd.openbis.uitest.type.Experiment;
 import ch.systemsx.cisd.openbis.uitest.type.ExperimentType;
 import ch.systemsx.cisd.openbis.uitest.type.Sample;
@@ -27,7 +26,7 @@ import ch.systemsx.cisd.openbis.uitest.widget.DropDown;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 import ch.systemsx.cisd.openbis.uitest.widget.TextArea;
 
-public class RegisterExperiment extends TopBar
+public class RegisterExperiment
 {
 
     @Locate("openbis_select_experiment-typeopenbis_experiment-registration")
@@ -62,16 +61,14 @@ public class RegisterExperiment extends TopBar
         }
     }
 
-    public RegisterExperiment selectExperimentType(ExperimentType experimentType)
+    public void selectExperimentType(ExperimentType experimentType)
     {
         experimentTypeList.select(experimentType.getCode());
-        return get(RegisterExperiment.class);
     }
 
-    public RegisterExperiment save()
+    public void save()
     {
         this.saveButton.click();
-        return get(RegisterExperiment.class);
     }
 
     @Override
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterProject.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterProject.java
index 36aa5141589..1be87de5c36 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterProject.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterProject.java
@@ -18,13 +18,12 @@ package ch.systemsx.cisd.openbis.uitest.page.tab;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.TopBar;
 import ch.systemsx.cisd.openbis.uitest.type.Project;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.DropDown;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 
-public class RegisterProject extends TopBar
+public class RegisterProject
 {
 
     @Locate("openbis_project-register_form_code")
@@ -43,10 +42,9 @@ public class RegisterProject extends TopBar
         spaces.select(project.getSpace().getCode());
     }
 
-    public RegisterProject save()
+    public void save()
     {
         save.click();
-        return get(RegisterProject.class);
     }
 
     @Override
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java
index 5e55a71a420..be678aa3e05 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java
@@ -22,7 +22,6 @@ import java.util.Map;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.TopBar;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyType;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeDataType;
 import ch.systemsx.cisd.openbis.uitest.type.Sample;
@@ -34,7 +33,7 @@ import ch.systemsx.cisd.openbis.uitest.widget.Form;
 import ch.systemsx.cisd.openbis.uitest.widget.Text;
 import ch.systemsx.cisd.openbis.uitest.widget.Widget;
 
-public class RegisterSample extends TopBar
+public class RegisterSample
 {
 
     @Locate("openbis_select_sample-typeopenbis_sample-registration")
@@ -94,16 +93,14 @@ public class RegisterSample extends TopBar
         }
     }
 
-    public RegisterSample selectSampleType(SampleType sampleType)
+    public void selectSampleType(SampleType sampleType)
     {
         sampleTypes.select(sampleType.getCode());
-        return get(RegisterSample.class);
     }
 
-    public RegisterSample save()
+    public void save()
     {
         save.click();
-        return get(RegisterSample.class);
     }
 
     public Collection<String> getProperties()
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RoleAssignmentBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RoleAssignmentBrowser.java
index afcac1d7f60..9ddf53a4377 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RoleAssignmentBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RoleAssignmentBrowser.java
@@ -16,15 +16,14 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.Experiment;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 
-public class RoleAssignmentBrowser extends BrowserPage
+public class RoleAssignmentBrowser implements Browser<Experiment>
 {
 
     @SuppressWarnings("unused")
@@ -32,21 +31,17 @@ public class RoleAssignmentBrowser extends BrowserPage
     private Button assignRoleButton;
 
     @Override
-    protected List<WebElement> getColumns()
-    {
-        return null;
-    }
-
-    @Override
-    protected List<WebElement> getData()
+    public Row row(Experiment browsable)
     {
+        // TODO Auto-generated method stub
         return null;
     }
 
     @Override
-    protected WebElement getDeleteButton()
+    public Cell cell(Experiment browsable, String column)
     {
         // TODO Auto-generated method stub
         return null;
     }
+
 }
\ No newline at end of file
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java
index d153e2b0950..651e0874433 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java
@@ -18,16 +18,17 @@ package ch.systemsx.cisd.openbis.uitest.page.tab;
 
 import java.util.List;
 
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.Sample;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.DropDown;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class SampleBrowser extends BrowserPage
+public class SampleBrowser implements Browser<Sample>
 {
 
     @Locate("openbis_sample-browser_main-grid")
@@ -42,34 +43,19 @@ public class SampleBrowser extends BrowserPage
     @Locate("openbis_select_group-selectsample-browser-toolbar")
     private DropDown spaceList;
 
-    public RegisterSample addSample()
+    public void addSample()
     {
         addSample.click();
-        return get(RegisterSample.class);
-    }
-
-    @Override
-    protected List<WebElement> getColumns()
-    {
-        return grid.getColumns();
-    }
-
-    @Override
-    protected List<WebElement> getData()
-    {
-        return grid.getCells();
     }
 
-    public SampleBrowser selectSampleType(SampleType sampleType)
+    public void selectSampleType(SampleType sampleType)
     {
         sampleTypeList.select(sampleType.getCode());
-        return get(SampleBrowser.class);
     }
 
-    public SampleBrowser allSpaces()
+    public void allSpaces()
     {
         spaceList.select("(all)");
-        return get(SampleBrowser.class);
     }
 
     public List<String> getSampleTypes()
@@ -78,9 +64,15 @@ public class SampleBrowser extends BrowserPage
     }
 
     @Override
-    protected WebElement getDeleteButton()
+    public Row row(Sample sample)
     {
-        // TODO Auto-generated method stub
-        return null;
+        return grid.getRow("Code", sample.getCode());
     }
+
+    @Override
+    public Cell cell(Sample sample, String column)
+    {
+        return row(sample).get(column);
+    }
+
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleTypeBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleTypeBrowser.java
index 36ccc064634..55dd61db7b8 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleTypeBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleTypeBrowser.java
@@ -16,19 +16,15 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
-import ch.systemsx.cisd.openbis.uitest.page.dialog.AddSampleTypeDialog;
-import ch.systemsx.cisd.openbis.uitest.page.dialog.EditSampleTypeDialog;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class SampleTypeBrowser extends BrowserPage
+public class SampleTypeBrowser implements Browser<SampleType>
 {
     @Locate("add-entity-type-SAMPLE")
     private Button add;
@@ -36,40 +32,34 @@ public class SampleTypeBrowser extends BrowserPage
     @Locate("edit-entity-type-SAMPLE")
     private Button edit;
 
+    @SuppressWarnings("unused")
     @Locate("delete-entity-type-SAMPLE")
     private Button delete;
 
     @Locate("openbis_sample-type-browser-grid")
     private Grid grid;
 
-    public AddSampleTypeDialog add()
+    public void add()
     {
         add.click();
-        return get(AddSampleTypeDialog.class);
     }
 
-    @Override
-    protected List<WebElement> getColumns()
+    public void editSampleType(SampleType type)
     {
-        return grid.getColumns();
+        grid.select(type.getCode());
+        edit.click();
     }
 
     @Override
-    protected List<WebElement> getData()
+    public Row row(SampleType type)
     {
-        return grid.getCells();
-    }
-
-    public EditSampleTypeDialog editSampleType(SampleType type)
-    {
-        grid.select(type.getCode());
-        edit.click();
-        return get(EditSampleTypeDialog.class);
+        return grid.getRow("Code", type.getCode());
     }
 
     @Override
-    protected WebElement getDeleteButton()
+    public Cell cell(SampleType type, String column)
     {
-        return delete.getContext();
+        return row(type).get(column);
     }
+
 }
\ No newline at end of file
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SpaceBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SpaceBrowser.java
index 57166a3ead7..dbb1793df85 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SpaceBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SpaceBrowser.java
@@ -16,17 +16,15 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
-import ch.systemsx.cisd.openbis.uitest.page.dialog.AddSpaceDialog;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.Space;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class SpaceBrowser extends BrowserPage
+public class SpaceBrowser implements Browser<Space>
 {
 
     @Locate("openbis_space-browser-grid")
@@ -35,30 +33,25 @@ public class SpaceBrowser extends BrowserPage
     @Locate("openbis_space-browser_add-button")
     private Button addSpace;
 
+    @SuppressWarnings("unused")
     @Locate("openbis_space-browser_delete-button")
     private Button delete;
 
-    public AddSpaceDialog addSpace()
+    public void addSpace()
     {
         addSpace.click();
-        return get(AddSpaceDialog.class);
     }
 
     @Override
-    protected List<WebElement> getColumns()
+    public Row row(Space space)
     {
-        return this.grid.getColumns();
+        return grid.getRow("Code", space.getCode());
     }
 
     @Override
-    protected List<WebElement> getData()
+    public Cell cell(Space space, String column)
     {
-        return this.grid.getCells();
+        return row(space).get(column);
     }
 
-    @Override
-    protected WebElement getDeleteButton()
-    {
-        return this.delete.getContext();
-    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/Trash.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/Trash.java
index 77548fb4af7..d89b2e7e6a2 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/Trash.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/Trash.java
@@ -18,11 +18,10 @@ package ch.systemsx.cisd.openbis.uitest.page.tab;
 
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Lazy;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.TopBar;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.DeletionConfirmationBox;
 
-public class Trash extends TopBar
+public class Trash
 {
 
     @Locate("empty-trash-button")
@@ -32,11 +31,10 @@ public class Trash extends TopBar
     @Locate("deletion-confirmation-dialog")
     private DeletionConfirmationBox deletionDialog;
 
-    public Trash empty()
+    public void empty()
     {
         this.empty.click();
         deletionDialog.confirm();
-        return get(Trash.class);
     }
 
     @Override
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/VocabularyBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/VocabularyBrowser.java
index c436d9b183b..7314011baae 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/VocabularyBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/VocabularyBrowser.java
@@ -16,17 +16,15 @@
 
 package ch.systemsx.cisd.openbis.uitest.page.tab;
 
-import java.util.List;
-
-import org.openqa.selenium.WebElement;
-
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.Locate;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
-import ch.systemsx.cisd.openbis.uitest.page.dialog.AddVocabularyDialog;
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+import ch.systemsx.cisd.openbis.uitest.type.Vocabulary;
 import ch.systemsx.cisd.openbis.uitest.widget.Button;
 import ch.systemsx.cisd.openbis.uitest.widget.Grid;
 
-public class VocabularyBrowser extends BrowserPage
+public class VocabularyBrowser implements Browser<Vocabulary>
 {
     @Locate("openbis_vocabulary-browser-grid")
     private Grid grid;
@@ -34,30 +32,24 @@ public class VocabularyBrowser extends BrowserPage
     @Locate("openbis_vocabulary-browser_add-button")
     private Button add;
 
+    @SuppressWarnings("unused")
     @Locate("openbis_vocabulary-browser_delete-button")
     private Button delete;
 
-    public AddVocabularyDialog add()
+    public void add()
     {
         add.click();
-        return get(AddVocabularyDialog.class);
-    }
-
-    @Override
-    protected List<WebElement> getColumns()
-    {
-        return grid.getColumns();
     }
 
     @Override
-    protected List<WebElement> getData()
+    public Row row(Vocabulary vocabulary)
     {
-        return grid.getCells();
+        return grid.getRow("Code", vocabulary.getCode());
     }
 
     @Override
-    protected WebElement getDeleteButton()
+    public Cell cell(Vocabulary vocabulary, String column)
     {
-        return delete.getContext();
+        return row(vocabulary).get(column);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SampleTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SampleTest.java
index d859bf05c22..550c458cb92 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SampleTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SampleTest.java
@@ -79,7 +79,6 @@ public class SampleTest extends SeleniumTest
         assertThat(sampleBrowser().cell(sample, vocabularyType.getLabel()), displays("mouse"));
         assertThat(sampleBrowser().cell(sample, vocabularyType.getLabel()),
                 linksTo("http://www.ask.com/web?q=MOUSE"));
-
     }
 
     @Test(enabled = false)
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SeleniumTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SeleniumTest.java
index 113579611c1..8ba8fe12bef 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SeleniumTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SeleniumTest.java
@@ -36,6 +36,7 @@ import org.testng.annotations.BeforeSuite;
 
 import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
+import ch.systemsx.cisd.openbis.uitest.infra.Browser;
 import ch.systemsx.cisd.openbis.uitest.infra.User;
 import ch.systemsx.cisd.openbis.uitest.infra.matcher.BrowserListsElementMatcher;
 import ch.systemsx.cisd.openbis.uitest.infra.matcher.CellDisplaysMatcher;
@@ -48,9 +49,7 @@ import ch.systemsx.cisd.openbis.uitest.infra.screenshot.ScreenShotter;
 import ch.systemsx.cisd.openbis.uitest.infra.uid.DictionaryUidGenerator;
 import ch.systemsx.cisd.openbis.uitest.infra.uid.UidGenerator;
 import ch.systemsx.cisd.openbis.uitest.infra.webdriver.PageProxy;
-import ch.systemsx.cisd.openbis.uitest.page.common.BrowserPage;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
-import ch.systemsx.cisd.openbis.uitest.page.common.Page;
 import ch.systemsx.cisd.openbis.uitest.page.tab.ExperimentBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.ExperimentTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.ProjectBrowser;
@@ -74,6 +73,7 @@ import ch.systemsx.cisd.openbis.uitest.type.SampleBuilder;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 import ch.systemsx.cisd.openbis.uitest.type.SampleTypeBuilder;
 import ch.systemsx.cisd.openbis.uitest.type.SampleTypeUpdateBuilder;
+import ch.systemsx.cisd.openbis.uitest.type.Space;
 import ch.systemsx.cisd.openbis.uitest.type.SpaceBuilder;
 import ch.systemsx.cisd.openbis.uitest.type.UpdateBuilder;
 import ch.systemsx.cisd.openbis.uitest.type.Vocabulary;
@@ -167,7 +167,7 @@ public abstract class SeleniumTest
         shotter.screenshot();
     }
 
-    public <T extends Page> T get(Class<T> clazz)
+    public <T> T get(Class<T> clazz)
     {
         return this.pageProxy.get(clazz);
     }
@@ -234,7 +234,8 @@ public abstract class SeleniumTest
 
     protected RegisterSample sampleRegistrationPageFor(SampleType type)
     {
-        return openbis.browseToRegisterSample().selectSampleType(type);
+        openbis.browseToRegisterSample().selectSampleType(type);
+        return pageProxy.get(RegisterSample.class);
     }
 
     protected PropertyTypeAssignmentBrowser propertyTypeAssignmentBrowser()
@@ -242,7 +243,7 @@ public abstract class SeleniumTest
         return openbis.browseToPropertyTypeAssignmentBrowser();
     }
 
-    protected Matcher<WebDriver> isShowing(Class<? extends Page> pageClass)
+    protected Matcher<WebDriver> isShowing(Class<?> pageClass)
     {
         return new PageMatcher(pageClass, pageProxy);
     }
@@ -257,9 +258,14 @@ public abstract class SeleniumTest
         return not(new SampleBrowserSampleTypeDropDownMenuMatcher(sampleType));
     }
 
-    protected Matcher<BrowserPage> lists(Browsable browsable)
+    protected <T extends Browsable, U extends Browser<T>> Matcher<U> lists(T browsable)
     {
-        return new BrowserListsElementMatcher(browsable);
+        return new BrowserListsElementMatcher<T, U>(browsable);
+    }
+
+    protected <T extends Browsable, U extends Browser<T>> Matcher<U> doesNotList(T browsable)
+    {
+        return not(new BrowserListsElementMatcher<T, U>(browsable));
     }
 
     protected Matcher<RegisterSample> hasInputsForProperties(PropertyType... fields)
@@ -279,7 +285,12 @@ public abstract class SeleniumTest
 
     protected <T> T create(Builder<T> builder)
     {
-        return builder.build();
+        return builder.create();
+    }
+
+    protected void delete(Space space)
+    {
+        openbis.delete(space);
     }
 
     protected SpaceBuilder aSpace()
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SpaceTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SpaceTest.java
index 576f515ff84..f43bc9dce0a 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SpaceTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SpaceTest.java
@@ -19,4 +19,14 @@ public class SpaceTest extends SeleniumTest
         assertThat(spaceBrowser(), lists(space));
     }
 
+    @Test(enabled = false)
+    public void deletedSpaceIsRemovedFromSpaceBrowser() throws Exception
+    {
+        Space space = create(aSpace());
+
+        delete(space);
+
+        assertThat(spaceBrowser(), doesNotList(space));
+    }
+
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/ManualTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SprintTest.java
similarity index 98%
rename from ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/ManualTest.java
rename to ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SprintTest.java
index 591c5b7de9d..0b6cb262ad6 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/ManualTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/suite/SprintTest.java
@@ -36,13 +36,15 @@ import ch.systemsx.cisd.openbis.uitest.type.Vocabulary;
  */
 @Test(groups =
     { "login-admin" })
-public class ManualTest extends SeleniumTest
+public class SprintTest extends SeleniumTest
 {
 
     @Test(enabled = false)
     public void basic()
     {
+
         // 0) Cleanup
+        /*
         experimentBrowser().space("sprint-test").deleteAll();
         trash().empty();
         projectBrowser().deleteIfExists("Code", "p1");
@@ -53,7 +55,7 @@ public class ManualTest extends SeleniumTest
         propertyTypeBrowser().deleteIfExists("Code", "sprint-test.real");
         propertyTypeBrowser().deleteIfExists("Code", "sprint-test.animal");
         vocabularyBrowser().deleteIfExists("Code", "sprint-test-animal");
-
+        */
         // 1) Login and authorization
         openbis.browseToRoleAssignmentBrowser();
         assertThat(browser(), isShowing(RoleAssignmentBrowser.class));
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java
index 5d6f650c7c7..296d6ae2e4f 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java
@@ -21,5 +21,7 @@ package ch.systemsx.cisd.openbis.uitest.type;
  */
 public interface Builder<T>
 {
+    public T create();
+
     public T build();
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java
index 76889ce4679..d85acf7bc31 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java
@@ -17,11 +17,11 @@
 package ch.systemsx.cisd.openbis.uitest.type;
 
 import java.util.Collection;
-import java.util.Map;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -45,7 +45,7 @@ public class Experiment implements EntityType, Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentBuilder.java
index d6e69597e85..573acd6a870 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentBuilder.java
@@ -77,18 +77,24 @@ public class ExperimentBuilder implements Builder<Experiment>
     }
 
     @Override
-    public Experiment build()
+    public Experiment create()
     {
         if (type == null)
         {
-            type = new ExperimentTypeBuilder(openbis).build();
+            type = new ExperimentTypeBuilder(openbis).create();
         }
         if (project == null)
         {
-            project = new ProjectBuilder(openbis).build();
+            project = new ProjectBuilder(openbis).create();
         }
 
-        return openbis.create(new Experiment(type, code, project, samples));
+        return openbis.create(build());
+    }
+
+    @Override
+    public Experiment build()
+    {
+        return new Experiment(type, code, project, samples);
     }
 
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentType.java
index c444f8233fe..5b1184103de 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentType.java
@@ -16,10 +16,9 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
-import java.util.Map;
-
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -37,7 +36,7 @@ public class ExperimentType implements Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentTypeBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentTypeBuilder.java
index 3a64065db25..312b8f900ee 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentTypeBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentTypeBuilder.java
@@ -44,9 +44,15 @@ public class ExperimentTypeBuilder implements Builder<ExperimentType>
         return this;
     }
 
+    @Override
+    public ExperimentType create()
+    {
+        return openbis.create(build());
+    }
+
     @Override
     public ExperimentType build()
     {
-        return openbis.create(new ExperimentType(code, description));
+        return new ExperimentType(code, description);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java
index f6d0b7ee34f..c3aeb540329 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java
@@ -16,10 +16,9 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
-import java.util.Map;
-
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -40,7 +39,7 @@ public class Project implements Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ProjectBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ProjectBuilder.java
index 786c1cce623..ccc9ada8607 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ProjectBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ProjectBuilder.java
@@ -54,12 +54,18 @@ public class ProjectBuilder implements Builder<Project>
     }
 
     @Override
-    public Project build()
+    public Project create()
     {
         if (space == null)
         {
-            space = new SpaceBuilder(openbis).build();
+            space = new SpaceBuilder(openbis).create();
         }
-        return openbis.create(new Project(code, description, space));
+        return openbis.create(build());
+    }
+
+    @Override
+    public Project build()
+    {
+        return new Project(code, description, space);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java
index 8f45f64eed0..4df78f5c1d5 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java
@@ -16,10 +16,9 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
-import java.util.Map;
-
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -48,7 +47,7 @@ public class PropertyType implements Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java
index fdf1b6db572..d7d8d6c98a4 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java
@@ -16,11 +16,10 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
-import java.util.Map;
-
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -46,7 +45,7 @@ public class PropertyTypeAssignment implements Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell propertyTypeCode = row.get("Property Type Code");
         Cell entityTypeCode = row.get("Entity Type");
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java
index 0fc4fcd182c..6b09cc54375 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java
@@ -69,19 +69,24 @@ public class PropertyTypeAssignmentBuilder implements Builder<PropertyTypeAssign
     }
 
     @Override
-    public PropertyTypeAssignment build()
+    public PropertyTypeAssignment create()
     {
         if (propertyType == null)
         {
-            propertyType = new PropertyTypeBuilder(openbis, PropertyTypeDataType.BOOLEAN).build();
+            propertyType = new PropertyTypeBuilder(openbis, PropertyTypeDataType.BOOLEAN).create();
         }
 
         if (entityType == null)
         {
-            entityType = new SampleTypeBuilder(openbis).build();
+            entityType = new SampleTypeBuilder(openbis).create();
         }
 
-        return openbis.create(new PropertyTypeAssignment(propertyType, entityType, mandatory,
-                initialValue));
+        return openbis.create(build());
+    }
+
+    @Override
+    public PropertyTypeAssignment build()
+    {
+        return new PropertyTypeAssignment(propertyType, entityType, mandatory, initialValue);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java
index f4e0874ec9c..75f6e22c4e3 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java
@@ -71,10 +71,16 @@ public class PropertyTypeBuilder implements Builder<PropertyType>
         return this;
     }
 
+    @Override
+    public PropertyType create()
+    {
+        return openbis.create(build());
+    }
+
     @Override
     public PropertyType build()
     {
-        return openbis.create(new PropertyType(code, label, description, dataType, vocabulary));
+        return new PropertyType(code, label, description, dataType, vocabulary);
     }
 
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java
index daf3f5a8c1e..f9ba77d5b6b 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -53,7 +54,7 @@ public class Sample implements EntityType, Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java
index b6af3814eb4..25579b71c0f 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java
@@ -77,19 +77,19 @@ public class SampleBuilder implements Builder<Sample>
     }
 
     @Override
-    public Sample build()
+    public Sample create()
     {
         if (experiment != null)
         {
             space = experiment.getProject().getSpace();
         } else if (space == null)
         {
-            space = new SpaceBuilder(this.openbis).build();
+            space = new SpaceBuilder(this.openbis).create();
         }
 
         if (type == null)
         {
-            type = new SampleTypeBuilder(this.openbis).build();
+            type = new SampleTypeBuilder(this.openbis).create();
         }
 
         for (PropertyTypeAssignment assignment : type.getPropertyTypeAssignments())
@@ -101,6 +101,12 @@ public class SampleBuilder implements Builder<Sample>
             }
         }
 
-        return openbis.create(new Sample(type, code, experiment, space, parents, properties));
+        return openbis.create(build());
+    }
+
+    @Override
+    public Sample build()
+    {
+        return new Sample(type, code, experiment, space, parents, properties);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java
index af8b04b79d3..80b1277d161 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java
@@ -17,11 +17,11 @@
 package ch.systemsx.cisd.openbis.uitest.type;
 
 import java.util.Collection;
-import java.util.Map;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -67,7 +67,7 @@ public class SampleType implements Browsable, EntityType
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java
index 52657cd38f1..59dd630cd75 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java
@@ -95,12 +95,17 @@ public class SampleTypeBuilder implements Builder<SampleType>
         return this;
     }
 
+    @Override
+    public SampleType create()
+    {
+        return openbis.create(build());
+    }
+
     @Override
     public SampleType build()
     {
-        return openbis.create(new SampleType(code, description, listable, showsContainer,
-                showsParents,
+        return new SampleType(code, description, listable, showsContainer, showsParents,
                 hasUniqueSubcodes, generatesCodes, showsParentMetadata, generatedCodePrefix,
-                propertyTypeAssignments));
+                propertyTypeAssignments);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java
index 63a20d6fb00..72ae1959a30 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java
@@ -16,10 +16,9 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
-import java.util.Map;
-
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -37,7 +36,7 @@ public class Space implements Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java
index 3fbc3c207fd..66d02b52385 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java
@@ -44,9 +44,16 @@ public class SpaceBuilder implements Builder<Space>
         return this;
     }
 
+    @Override
+    public Space create()
+    {
+        return openbis.create(build());
+    }
+
     @Override
     public Space build()
     {
-        return openbis.create(new Space(code, description));
+        return new Space(code, description);
     }
+
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java
index 0ce356ab88f..d559148cc40 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java
@@ -16,11 +16,11 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
-import java.util.Map;
 import java.util.Set;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
 
 /**
  * @author anttil
@@ -44,7 +44,7 @@ public class Vocabulary implements Browsable
     }
 
     @Override
-    public boolean isRepresentedBy(Map<String, Cell> row)
+    public boolean isRepresentedBy(Row row)
     {
         Cell codeCell = row.get("Code");
         return codeCell != null && codeCell.getText().equalsIgnoreCase(this.code);
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java
index 6c9003828eb..0c299f86105 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java
@@ -70,9 +70,15 @@ public class VocabularyBuilder implements Builder<Vocabulary>
         return this;
     }
 
+    @Override
+    public Vocabulary create()
+    {
+        return openbis.create(build());
+    }
+
     @Override
     public Vocabulary build()
     {
-        return openbis.create(new Vocabulary(code, description, terms, url));
+        return new Vocabulary(code, description, terms, url);
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Button.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Button.java
index 985e6829381..f72c044e975 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Button.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Button.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.uitest.widget;
 
+import org.openqa.selenium.By;
+
 /**
  * @author anttil
  */
@@ -25,4 +27,10 @@ public class Button extends Widget
     {
         context.click();
     }
+
+    public boolean isPressed()
+    {
+        return "true".equalsIgnoreCase(context.findElement(By.xpath(".//button")).getAttribute(
+                "aria-pressed"));
+    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Grid.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Grid.java
index 9c66841b630..08bcb527a9f 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Grid.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/widget/Grid.java
@@ -18,17 +18,75 @@ package ch.systemsx.cisd.openbis.uitest.widget;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebElement;
 
+import ch.systemsx.cisd.openbis.uitest.page.common.Cell;
+import ch.systemsx.cisd.openbis.uitest.page.common.Row;
+
 /**
  * @author anttil
  */
 public class Grid extends Widget
 {
 
+    public Row getRow(String column, String value)
+    {
+
+        List<WebElement> columns = this.getColumns();
+
+        int index = 0;
+        boolean found = false;
+        for (WebElement element : columns)
+        {
+            if (element.getText().equalsIgnoreCase(column))
+            {
+                found = true;
+                break;
+            }
+            index++;
+        }
+
+        if (!found)
+        {
+            throw new IllegalArgumentException("Column " + column + " does not exist");
+        }
+
+        int numColumns = columns.size();
+
+        List<WebElement> cells = this.getCells();
+        found = false;
+        for (; index < cells.size(); index += numColumns)
+        {
+            if (cells.get(index).getText().equalsIgnoreCase(value))
+            {
+                found = true;
+                break;
+            }
+        }
+
+        if (!found)
+        {
+            throw new IllegalArgumentException("Row with value " + value + " in column " + column
+                    + " not found");
+        }
+
+        index = index - (index % numColumns);
+
+        Map<String, Cell> m = new HashMap<String, Cell>();
+        for (int i = 0; i < numColumns; i++)
+        {
+            WebElement element = cells.get(i + index);
+            m.put(columns.get(i).getText(),
+                    new Cell(element.getText(), element.getAttribute("href"), element));
+        }
+        return new Row(m);
+    }
+
     public List<WebElement> getColumns()
     {
         return context
-- 
GitLab