diff --git a/packages/main/cypress/specs/ListItemGroup.cy.tsx b/packages/main/cypress/specs/ListItemGroup.cy.tsx
new file mode 100644
index 000000000000..22021757f477
--- /dev/null
+++ b/packages/main/cypress/specs/ListItemGroup.cy.tsx
@@ -0,0 +1,218 @@
+import ListItemGroup from "../../src/ListItemGroup.js";
+
+describe("ListItemGroup Tests", () => {
+ it("ListGroup is rendered", () => {
+ cy.mount();
+
+ cy.get("[ui5-li-group]").should("exist");
+
+ cy.get("[ui5-li-group]")
+ .shadow()
+ .find("ui5-li-group-header")
+ .should("exist");
+ });
+
+ it("ListGroup renders header-text property correctly", () => {
+ cy.mount();
+
+ cy.get("[ui5-li-group]")
+ .shadow()
+ .find("ui5-li-group-header")
+ .should("contain.text", "New Items");
+ });
+
+ it("ListGroup propagates focused property to header item", () => {
+ cy.mount();
+
+ cy.get("[ui5-li-group]")
+ .invoke("prop", "focused", true);
+
+ cy.get("[ui5-li-group]")
+ .shadow()
+ .find("ui5-li-group-header")
+ .should("have.prop", "focused", true);
+
+ cy.get("[ui5-li-group]")
+ .invoke("prop", "focused", false);
+
+ cy.get("[ui5-li-group]")
+ .shadow()
+ .find("ui5-li-group-header")
+ .should("have.prop", "focused", false);
+ });
+});
+
+describe("List drag and drop tests", () => {
+ const setupDragAndDrop = (listId: string, acceptExternal = false) => {
+ cy.get(`#${listId}`).then(($list) => {
+ const list = $list[0];
+
+ list.addEventListener("ui5-move-over", (e: CustomEvent) => {
+ const { destination, source } = e.detail;
+
+ if (!acceptExternal && !list.contains(source.element)) {
+ return;
+ }
+
+ if (destination.placement === "Before" || destination.placement === "After") {
+ e.preventDefault();
+ }
+
+ if (destination.placement === "On" && "allowsNesting" in destination.element.dataset) {
+ e.preventDefault();
+ }
+ });
+
+ list.addEventListener("ui5-move", (e: CustomEvent) => {
+ const { destination, source } = e.detail;
+
+ if (source.element === destination.element) return;
+
+ const parent = destination.element.closest("[ui5-li-group]");
+
+ if (destination.placement === "Before") {
+ parent.insertBefore(source.element, destination.element);
+ } else if (destination.placement === "After") {
+ const nextElement = Array.from(parent.children).at(
+ Array.from(parent.children).indexOf(destination.element) + 1
+ );
+ parent.insertBefore(source.element, nextElement);
+ } else if (destination.placement === "On") {
+ destination.element.prepend(source.element);
+ }
+ });
+ });
+ };
+
+ const dispatchMoveEvent = (sourceAlias: string, targetAlias: string, placement: string) => {
+ cy.get(sourceAlias).then($source => {
+ cy.get(targetAlias).then($target => {
+ const moveEvent = new CustomEvent("ui5-move", {
+ detail: {
+ source: { element: $source[0] },
+ destination: { element: $target[0], placement }
+ }
+ });
+
+ const listElement = $target[0].closest("[ui5-li-group]");
+ if (listElement) {
+ listElement.dispatchEvent(moveEvent);
+ }
+ });
+ });
+ };
+
+ beforeEach(() => {
+ cy.mount(
+
+ );
+
+ // Set up both lists
+ setupDragAndDrop("listDnd1", false);
+ setupDragAndDrop("listDnd2", true);
+
+ // Create items for list1
+ cy.get("#listDnd1").then($list => {
+ $list[0].innerHTML = `
+ 1. Bulgaria
+ 1. Germany
+ 1. Spain
+ `;
+ });
+
+ // Create items for list2
+ cy.get("#listDnd2").then($list => {
+ $list[0].innerHTML = `
+ 2. Bulgaria
+ 2. Germany (Allows nesting)
+ 2. Spain
+ `;
+ });
+
+ cy.get("#listDnd1 ui5-li").should("have.length", 3);
+ cy.get("#listDnd2 ui5-li").should("have.length", 3);
+ });
+
+ it("Moving item After another", () => {
+ cy.get("#listDnd1 ui5-li").eq(0).as("first");
+ cy.get("#listDnd1 ui5-li").eq(1).as("second");
+
+ dispatchMoveEvent("@first", "@second", "After");
+
+ cy.get("#listDnd1 ui5-li").eq(0).should("contain.text", "1. Germany");
+ cy.get("#listDnd1 ui5-li").eq(1).should("contain.text", "1. Bulgaria");
+
+ cy.get("#listDnd1 ui5-li").eq(1).as("currentFirst");
+ cy.get("#listDnd1 ui5-li").eq(2).as("currentThird");
+
+ dispatchMoveEvent("@currentFirst", "@currentThird", "After");
+
+ cy.get("#listDnd1 ui5-li").eq(0).should("contain.text", "1. Germany");
+ cy.get("#listDnd1 ui5-li").eq(1).should("contain.text", "1. Spain");
+ cy.get("#listDnd1 ui5-li").eq(2).should("contain.text", "1. Bulgaria");
+ });
+
+ it("Moving item Before another", () => {
+ cy.get("#listDnd1 ui5-li").eq(0).as("first");
+ cy.get("#listDnd1 ui5-li").eq(2).as("third");
+
+ dispatchMoveEvent("@first", "@third", "Before");
+
+ cy.get("#listDnd1 ui5-li").eq(0).should("contain.text", "1. Germany");
+ cy.get("#listDnd1 ui5-li").eq(1).should("contain.text", "1. Bulgaria");
+ cy.get("#listDnd1 ui5-li").eq(2).should("contain.text", "1. Spain");
+
+ cy.get("#listDnd1 ui5-li").eq(1).as("currentFirst");
+ cy.get("#listDnd1 ui5-li").eq(0).as("currentSecond");
+
+ dispatchMoveEvent("@currentFirst", "@currentSecond", "Before");
+
+ cy.get("#listDnd1 ui5-li").eq(0).should("contain.text", "1. Bulgaria");
+ cy.get("#listDnd1 ui5-li").eq(1).should("contain.text", "1. Germany");
+ cy.get("#listDnd1 ui5-li").eq(2).should("contain.text", "1. Spain");
+ });
+
+ it("Moving item ON another", () => {
+ cy.get("#listDnd2 ui5-li").eq(0).as("first");
+ cy.get("#listDnd2 ui5-li").eq(1).as("second");
+
+ dispatchMoveEvent("@first", "@second", "On");
+
+ cy.get("#listDnd2 > ui5-li").should("have.length", 2);
+ cy.get("#listDnd2 > ui5-li").eq(0).find("ui5-li").should("contain.text", "2. Bulgaria");
+ });
+
+ it("Moving item from one list to another", () => {
+ cy.get("#bg2").as("listTwoItem");
+ cy.get("#listDnd1 ui5-li").eq(0).as("listOneFirst");
+
+ dispatchMoveEvent("@listTwoItem", "@listOneFirst", "After");
+
+ cy.get("#listDnd1 ui5-li").should("have.length", 4);
+ cy.get("#listDnd2 ui5-li").should("have.length", 2);
+ });
+
+ it("Moving link to list that doesn't accept it", () => {
+ cy.get("#link").as("link");
+ cy.get("#listDnd1 ui5-li").eq(0).as("first");
+
+ dispatchMoveEvent("@link", "@first", "After");
+
+ cy.get("#listDnd1 ui5-li").should("have.length", 3);
+ cy.get("#link").should("exist");
+ });
+
+ it("Moving link to list that accepts it", () => {
+ cy.get("#link").as("link");
+ cy.get("#listDnd2 ui5-li").eq(1).as("second");
+
+ dispatchMoveEvent("@link", "@second", "Before");
+
+ cy.get("#listDnd2").children().should("have.length", 4);
+ cy.get("#listDnd2 #link").should("exist");
+ });
+});
\ No newline at end of file
diff --git a/packages/main/test/specs/ListItemGroup.spec.js b/packages/main/test/specs/ListItemGroup.spec.js
deleted file mode 100644
index fadf1eecb6c2..000000000000
--- a/packages/main/test/specs/ListItemGroup.spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import { assert } from "chai";
-
-describe("ListItemGroup Tests", () => {
- before(async () => {
- await browser.url(`test/pages/List_test_page.html`);
- });
-
- it("ListGroup is rendered", async () => {
- const listItemGroup = await browser.$("#list1 [ui5-li-group]");
- const listItemGroupHeader = await listItemGroup.shadow$("ui5-li-group-header");
-
- assert.ok(listItemGroup.isExisting(), true, "ListGroup is rendered");
- assert.ok(listItemGroupHeader.isExisting(), true, "ListGroup header is rendered");
- });
-
- it("ListGroup renders header-text property correctly", async () => {
- const listItemGroup = await browser.$("#list1 [ui5-li-group]");
- const listItemGroupHeader = await listItemGroup.shadow$("ui5-li-group-header");
-
- assert.strictEqual(await listItemGroupHeader.getText(), "New Items", "List's group header is correctly displayed");
- });
-
- it("ListGroup propagates focused property to header item", async () => {
- const listItemGroup = await browser.$("#list1 [ui5-li-group]");
- const listItemGroupHeader = await listItemGroup.shadow$("ui5-li-group-header");
-
- await listItemGroup.setProperty("focused", true);
- assert.strictEqual(await listItemGroupHeader.getProperty("focused"), true, "List's group header is focused");
- await listItemGroup.setProperty("focused", false);
- });
-});
-
-describe("List drag and drop tests", () => {
- const getDragOffset = async (draggedElement, dropTargetElement, targetPosition) => {
- const EXTRA_OFFSET = 5;
- const draggedRectangle = {
- ...await draggedElement.getLocation(),
- ...await draggedElement.getSize()
- };
-
- const dropTargetElementRectangle = {
- ...await dropTargetElement.getLocation(),
- ...await dropTargetElement.getSize()
- }
-
- const draggedElementCenter = (draggedRectangle.y + draggedRectangle.height / 2);
- const droppedElementCenter = (dropTargetElementRectangle.y + dropTargetElementRectangle.height / 2);
-
- let offsetToCenter = Math.round(droppedElementCenter - draggedElementCenter);
-
- if (targetPosition === "Before") {
- offsetToCenter -= EXTRA_OFFSET
- } else if (targetPosition === "After") {
- offsetToCenter += EXTRA_OFFSET;
- }
-
- return offsetToCenter;
- };
-
- const compareItemsOrder = async (listId, expectedItems) => {
- const listItems = await browser.$$(`#${listId} > *`);
- const results = await Promise.all(expectedItems.map((item, i) => item.isEqual(listItems[i])));
-
- return results.every(value => value);
- }
-
- before(async () => {
- await browser.url(`test/pages/ListItemGroupDragAndDrop.html`);
- });
-
- it("Moving item After another", async () => {
- const [firstItem, secondItem, thirdItem] = await browser.$$("#listDnd1 [ui5-li]");
-
- let dragOffset = await getDragOffset(firstItem, secondItem, "After");
- await firstItem.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd1", [secondItem, firstItem, thirdItem]), "Items order has changed");
-
- dragOffset = await getDragOffset(firstItem, thirdItem, "After");
- await firstItem.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd1", [secondItem, thirdItem, firstItem]), "Items order has changed");
- });
-
- it("Moving item Before another", async () => {
- const [secondItem, thirdItem, firstItem] = await browser.$$("#listDnd1 [ui5-li]");
-
- let dragOffset = await getDragOffset(firstItem, thirdItem, "Before");
- await firstItem.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd1", [secondItem, firstItem, thirdItem]), "Items order has changed");
-
- dragOffset = await getDragOffset(firstItem, secondItem, "Before")
- await firstItem.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd1", [firstItem, secondItem, thirdItem]), "Items order has changed");
- });
-
- it("Moving item ON another", async () => {
- const [firstItem, secondItem, thirdItem] = await browser.$$("#listDnd2 [ui5-li]");
-
- await firstItem.dragAndDrop({ x: 0, y: 0 });
- assert.ok(await compareItemsOrder("listDnd2", [firstItem, secondItem, thirdItem]), "Items order has NOT changed");
-
- const dragOffset = await getDragOffset(firstItem, secondItem);
- await firstItem.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd2", [secondItem, thirdItem]), "Items order has changed");
- assert.ok(await secondItem.$("[ui5-li]").isEqual(firstItem), "First item is nested in second item");
- });
-
- it("Moving item from one list to another", async () => {
- const [listOneFirstItem, listOneSecondItem, listOneThirdItem] = await browser.$$("#listDnd1 [ui5-li]");
- const listTwoItem = await browser.$("#bg2")
-
- const dragOffset = await getDragOffset(listTwoItem, listOneFirstItem, "After");
- await listTwoItem.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd1", [listOneFirstItem, listTwoItem, listOneSecondItem, listOneThirdItem]), "Items order has changed");
- });
-
- it("Moving link to list that doesn't accept it", async () => {
- const [firstItem, secondItem, thirdItem] = await browser.$$("#listDnd1 [ui5-li]");
- const link = await browser.$("#link")
-
- const dragOffset = await getDragOffset(link, firstItem, "After");
- await link.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd1", [firstItem, secondItem, thirdItem]), "Items order has NOT changed");
- });
-
- it("Moving link to list that accepts it", async () => {
- const [firstItem, secondItem] = await browser.$$("#listDnd2 [ui5-li]");
- const link = await browser.$("#link")
-
- const dragOffset = await getDragOffset(link, secondItem, "Before");
- await link.dragAndDrop({ x: 0, y: dragOffset});
- assert.ok(await compareItemsOrder("listDnd2", [firstItem, link, secondItem]), "Items order has changed");
- });
-});
\ No newline at end of file