diff --git a/xwiki-platform-core/xwiki-platform-appwithinminutes/xwiki-platform-appwithinminutes-test/xwiki-platform-appwithinminutes-test-pageobjects/src/main/java/org/xwiki/appwithinminutes/test/po/StaticListItemsEditor.java b/xwiki-platform-core/xwiki-platform-appwithinminutes/xwiki-platform-appwithinminutes-test/xwiki-platform-appwithinminutes-test-pageobjects/src/main/java/org/xwiki/appwithinminutes/test/po/StaticListItemsEditor.java
index 66b12a187a583b79fd22f037a4bbef7b92e0ebc1..00d3d0c3e3a2ccc807904176ce91b00d4ec853bd 100644
--- a/xwiki-platform-core/xwiki-platform-appwithinminutes/xwiki-platform-appwithinminutes-test/xwiki-platform-appwithinminutes-test-pageobjects/src/main/java/org/xwiki/appwithinminutes/test/po/StaticListItemsEditor.java
+++ b/xwiki-platform-core/xwiki-platform-appwithinminutes/xwiki-platform-appwithinminutes-test/xwiki-platform-appwithinminutes-test-pageobjects/src/main/java/org/xwiki/appwithinminutes/test/po/StaticListItemsEditor.java
@@ -22,8 +22,8 @@
 import org.openqa.selenium.By;
 import org.openqa.selenium.Keys;
 import org.openqa.selenium.WebElement;
-import org.openqa.selenium.interactions.Actions;
 import org.xwiki.test.ui.po.BaseElement;
+import org.xwiki.test.ui.po.SortableElement;
 
 /**
  * Represents the static list items editor present on the configuration pane of a static list field.
@@ -53,6 +53,8 @@ public class StaticListItemsEditor extends BaseElement
      */
     private WebElement addButton;
 
+    private final SortableElement sortable;
+
     /**
      * Creates a new instance.
      * 
@@ -62,6 +64,8 @@ public StaticListItemsEditor(WebElement container)
     {
         this.container = container;
 
+        this.sortable = new SortableElement(container);
+
         By xpath = By.xpath(".//*[@class = 'xHint' and . = 'ID']/following-sibling::input[@type = 'text']");
         valueInput = getDriver().findElementWithoutWaiting(container, xpath);
 
@@ -134,16 +138,7 @@ public void setLabel(String value, String newLabel)
      */
     public void moveBefore(String valueToMove, String beforeValue)
     {
-        WebElement itemToMove = getItem(valueToMove);
-        WebElement itemBefore = getItem(beforeValue);
-
-        Actions actions = getDriver().createActions().clickAndHold(itemToMove);
-
-        // We move the item from the center, so we need to ensure that we actually move it with an offset of half its
-        // width to be sure it's before the other item element.
-        int offsetX = - (itemToMove.getSize().getWidth() / 2);
-        int offsetY = 2;
-        getDriver().moveToTopLeftCornerOfTargetWithOffset(itemBefore, offsetX, offsetY, actions).release().perform();
+        this.sortable.moveBefore(getSelectorForItem(valueToMove), getSelectorForItem(beforeValue));
     }
 
     /**
@@ -152,8 +147,12 @@ public void moveBefore(String valueToMove, String beforeValue)
      */
     public WebElement getItem(String valueOrLabel)
     {
-        By xpath = By.xpath("ul/li/*[@title = '" + valueOrLabel + "' or . = '" + valueOrLabel + "']");
-        return getDriver().findElementWithoutWaiting(container, xpath);
+        return getDriver().findElementWithoutWaiting(this.container, getSelectorForItem(valueOrLabel));
+    }
+
+    private By getSelectorForItem(String valueOrLabel)
+    {
+        return By.xpath("ul/li/*[@title = '" + valueOrLabel + "' or . = '" + valueOrLabel + "']");
     }
 
     /**
diff --git a/xwiki-platform-core/xwiki-platform-panels/xwiki-platform-panels-test/xwiki-platform-panels-test-pageobjects/src/main/java/org/xwiki/panels/test/po/ApplicationsPanelAdministrationPage.java b/xwiki-platform-core/xwiki-platform-panels/xwiki-platform-panels-test/xwiki-platform-panels-test-pageobjects/src/main/java/org/xwiki/panels/test/po/ApplicationsPanelAdministrationPage.java
index 0312cf375a07776a797bd66473a6461793c9ec8e..4e6de555aec4e344ac3714845781e7b0ccf49ab9 100644
--- a/xwiki-platform-core/xwiki-platform-panels/xwiki-platform-panels-test/xwiki-platform-panels-test-pageobjects/src/main/java/org/xwiki/panels/test/po/ApplicationsPanelAdministrationPage.java
+++ b/xwiki-platform-core/xwiki-platform-panels/xwiki-platform-panels-test/xwiki-platform-panels-test-pageobjects/src/main/java/org/xwiki/panels/test/po/ApplicationsPanelAdministrationPage.java
@@ -23,13 +23,10 @@
 import java.util.List;
 
 import org.openqa.selenium.By;
-import org.openqa.selenium.Point;
-import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
-import org.openqa.selenium.interactions.Actions;
 import org.openqa.selenium.support.FindBy;
-import org.openqa.selenium.support.ui.ExpectedCondition;
 import org.xwiki.administration.test.po.AdministrationPage;
+import org.xwiki.test.ui.po.SortableElement;
 import org.xwiki.test.ui.po.ViewPage;
 
 import static org.junit.Assert.assertTrue;
@@ -56,6 +53,8 @@ public class ApplicationsPanelAdministrationPage extends ViewPage
     @FindBy(id = "bt-save")
     private WebElement saveButton;
 
+    private final SortableElement sortableDisplayedPanels = new SortableElement(this.displayedPanels);
+
     public static ApplicationsPanelAdministrationPage gotoPage()
     {
         AdministrationPage administrationPage = AdministrationPage.gotoPage();
@@ -116,40 +115,7 @@ public void moveAppBefore(String appName, String appBeforeName)
             return;
         }
 
-        WebElement app = displayedPanels.findElement(By.linkText(appName));
-        WebElement appBefore = displayedPanels.findElement(By.linkText(appBeforeName));
-        Point target = appBefore.getLocation();
-        Point source = app.getLocation();
-
-        // The drag & drop of the "sortable" plugin of "jquery-ui" is very sensitive so we need to script the
-        // moves of the mouse precisely if we don't want to have flickers.
-        Actions actions = new Actions(getDriver().getWrappedDriver());
-        // First we hold the app
-        actions.clickAndHold(app);
-        // Then we move into the position of the targeted app so jquery-ui can register we want to take its place.
-        actions.moveByOffset(target.getX() - source.getX(), target.getY() - source.getY());
-        // Now we do a little move on top left so jquery-ui understand we want to be *before* the other app and
-        // put a blank place instead of the other app.
-        actions.moveByOffset(-5, -5);
-        // Do it
-        actions.perform();
-
-        // Before releasing the click, check that jquery-ui has moved the other app to let the place free.
-        getDriver().waitUntilCondition(new ExpectedCondition<Object>()
-        {
-            @Override
-            public Object apply(WebDriver webDriver)
-            {
-                Point newTarget = appBefore.getLocation();
-                Point newSource = app.getLocation();
-                return newTarget.getX() > newSource.getX() + 5 || newTarget.getY() > newSource.getY() + 5;
-            }
-        });
-
-        // Now we can release the selection
-        actions = new Actions(getDriver().getWrappedDriver());
-        actions.release();
-        actions.perform();
+        this.sortableDisplayedPanels.moveBefore(By.linkText(appName), By.linkText(appBeforeName));
     }
 
     public void revert()
diff --git a/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/SortableElement.java b/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/SortableElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ceb8c610d67a3ab9bef119408d4ed295aee2fe8
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-ui/src/main/java/org/xwiki/test/ui/po/SortableElement.java
@@ -0,0 +1,89 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.test.ui.po;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.Point;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+
+/**
+ * Represents a sortable element that is using, e.g., the "sortable" plugin of "jquery-ui".
+ *
+ * @version $Id$
+ * @since 15.6RC1
+ * @since 15.5.1
+ * @since 14.10.15
+ */
+public class SortableElement extends BaseElement
+{
+    private final WebElement container;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param container the element that wraps the sortable elements
+     */
+    public SortableElement(WebElement container)
+    {
+        super();
+
+        this.container = container;
+    }
+
+    /**
+     * Move a given element before another one.
+     *
+     * @param toMove the selector for the element to move inside the sortable
+     * @param before the selector for the element before which the element to move should be moved
+     */
+    public void moveBefore(By toMove, By before)
+    {
+        WebElement elementToMove = this.container.findElement(toMove);
+        WebElement elementBefore = this.container.findElement(before);
+        Point target = elementBefore.getLocation();
+        Point source = elementToMove.getLocation();
+
+        // The drag & drop of the "sortable" plugin of "jquery-ui" is very sensitive so we need to script the
+        // moves of the mouse precisely if we don't want to have flickers.
+
+        // First, we click and hold the item we want to move.
+        Actions actions = getDriver().createActions().clickAndHold(elementToMove);
+        // Then we move into the position of the targeted item so jquery-ui can register we want to take its place.
+        actions.moveByOffset(target.getX() - source.getX(), target.getY() - source.getY());
+        // Now we do a little move on top left so jquery-ui understand we want to be *before* the other item and
+        // put a blank place instead of the other app.
+        actions.moveByOffset(-4, -4);
+        actions.perform();
+
+        // Before releasing the click, check that jquery-ui has moved the other item to let the place free.
+        getDriver().waitUntilCondition((ExpectedCondition<Object>) webDriver -> {
+            Point newTarget = elementBefore.getLocation();
+            Point newSource = elementToMove.getLocation();
+            return newTarget.getX() > newSource.getX() + 5 || newTarget.getY() > newSource.getY() + 5;
+        });
+
+        // Now we can release the selection
+        actions = new Actions(getDriver().getWrappedDriver());
+        actions.release();
+        actions.perform();
+    }
+}