diff --git a/packages/main/cypress/specs/Dialog.cy.tsx b/packages/main/cypress/specs/Dialog.cy.tsx index 646b58dedf45..138984a2769a 100644 --- a/packages/main/cypress/specs/Dialog.cy.tsx +++ b/packages/main/cypress/specs/Dialog.cy.tsx @@ -13,6 +13,18 @@ import ToolbarButton from "../../src/ToolbarButton.js"; import Tokenizer from "../../src/Tokenizer.js"; import Token from "../../src/Token.js"; +const restoreViewport = () => { + const width = Cypress.config("viewportWidth"); + const height = Cypress.config("viewportHeight"); + + cy.viewport(width, height); + + cy.wrap(window).should(({ innerWidth, innerHeight }) => { + expect(innerWidth).to.equal(width); + expect(innerHeight).to.equal(height); + }); +}; + describe("Keyboard", () => { it("TAB navigation", () => { cy.mount( @@ -356,9 +368,11 @@ describe("Events", () => { }); describe("Dialog general interaction", () => { - it("tests dialog toggling", () => { - + afterEach(() => { + restoreViewport(); + }); + it("tests dialog toggling", () => { cy.mount( <> @@ -406,6 +420,60 @@ describe("Dialog general interaction", () => { .should("be.calledOnce"); }); + it.skip("dynamic dialog initial positioning", () => { + const dialog = document.createElement("ui5-dialog") as Dialog; + dialog.setAttribute("id", "dynamic-dialog"); + + const content = document.createElement("div"); + content.style.height = "600px"; + content.style.width = "600px"; + content.textContent = "Content"; + + dialog.appendChild(content); + + // Spy on Object.assign only for this dialog's style + const originalAssign = Object.assign; + const topAndLeftStyles: Array<{ top: number; left: number }> = []; + + cy.stub(Object, "assign").callsFake(function(target: any, ...sources: any[]) { + // Check if target is the dialog's style object + if (target === dialog.style) { + const styleObj = sources[0]; + if (styleObj && styleObj.top !== undefined && styleObj.left !== undefined) { + topAndLeftStyles.push({ + top: parseInt(styleObj.top), + left: parseInt(styleObj.left) + }); + } + } + return originalAssign.call(this, target, ...sources); + }).as("objectAssignStub"); + + cy.wrap(topAndLeftStyles).as("topAndLeftStyles"); + + dialog.setAttribute("open", "true"); + document.body.appendChild(dialog); + + cy.get("#dynamic-dialog").ui5DialogOpened(); + + // Assert the captured style values + cy.get>("@topAndLeftStyles") + .should((topAndLeftStyles) => { + expect(topAndLeftStyles.length).to.be.greaterThan(1, "'top' and 'left' styles should have been assigned"); + + // styles from initial call of _center method + const firstStyles = topAndLeftStyles[0]; + + expect(firstStyles.top).to.not.equal(0, "top should not start from 0"); + expect(firstStyles.left).to.not.equal(0, "left should not start from 0"); + + // styles from _center method called as resize handler callback + const secondStyles = topAndLeftStyles[1]; + + expect(secondStyles.top).to.equal(firstStyles.top, "top should remain the same after resize event"); + expect(secondStyles.left).to.equal(firstStyles.left, "left should remain the same after resize event"); + }); + }); it("dialog repositions after screen resize", () => { cy.mount( @@ -516,46 +584,52 @@ describe("Dialog general interaction", () => { cy.get("#draggable-dialog").invoke("attr", "open", true); cy.get("#draggable-dialog").ui5DialogOpened(); + let topBeforeDragging: number; + let leftBeforeDragging: number; + // Capture position before dragging cy.get("#draggable-dialog") - .then(dialog => { - const topBeforeDragging = parseInt(dialog.css("top")); - const leftBeforeDragging = parseInt(dialog.css("left")); - - // Drag dialog - cy.get("#draggable-dialog") - .find("#header-slot") - .trigger("mousedown", { which: 1 }) - .trigger("mousemove", { clientX: 150, clientY: 150 }) - .trigger("mouseup"); - - // Capture position after dragging - cy.get("#draggable-dialog") - .should(dialogAfterDragging => { - const topAfterDragging = parseInt(dialogAfterDragging.css("top")); - const leftAfterDragging = parseInt(dialogAfterDragging.css("left")); + .should(dialog => { + expect(dialog[0].style.top).to.not.be.empty; + expect(dialog[0].style.left).to.not.be.empty; - // Assert position changes - expect(topBeforeDragging).not.to.equal(topAfterDragging); - expect(leftBeforeDragging).not.to.equal(leftAfterDragging); - }); + topBeforeDragging = parseInt(dialog.css("top")); + leftBeforeDragging = parseInt(dialog.css("left")); + }); + + // Drag dialog + cy.get("#draggable-dialog") + .find("#header-slot") + .trigger("mousedown", { which: 1 }) + .trigger("mousemove", { clientX: 200, clientY: 150, }) + .trigger("mouseup"); - // Close dialog - cy.get("#draggable-dialog").invoke("attr", "open", false); + // Capture position after dragging + cy.get("#draggable-dialog") + .should(dialogAfterDragging => { + const topAfterDragging = parseInt(dialogAfterDragging.css("top")); + const leftAfterDragging = parseInt(dialogAfterDragging.css("left")); - // Reopen dialog - cy.get("#draggable-dialog").invoke("attr", "open", true); + // Assert position changes + expect(topAfterDragging).not.to.equal(topBeforeDragging); + expect(leftAfterDragging).not.to.equal(leftBeforeDragging); + }); - // Capture position after reopening - cy.get("#draggable-dialog") - .should(dialogAfterReopening => { - const topAfterReopening = parseInt(dialogAfterReopening.css("top")); - const leftAfterReopening = parseInt(dialogAfterReopening.css("left")); + // Close dialog + cy.get("#draggable-dialog").invoke("attr", "open", false); - // Assert position resets - expect(topBeforeDragging).to.equal(topAfterReopening); - expect(leftBeforeDragging).to.equal(leftAfterReopening); - }); + // Reopen dialog + cy.get("#draggable-dialog").invoke("attr", "open", true); + + // Capture position after reopening + cy.get("#draggable-dialog") + .should(dialogAfterReopening => { + const topAfterReopening = parseInt(dialogAfterReopening.css("top")); + const leftAfterReopening = parseInt(dialogAfterReopening.css("left")); + + // Assert position resets + expect(topAfterReopening).to.equal(topBeforeDragging); + expect(leftAfterReopening).to.equal(leftBeforeDragging); }); }); @@ -574,64 +648,69 @@ describe("Dialog general interaction", () => { cy.get("#draggable-dialog").invoke("attr", "open", true); cy.get("#draggable-dialog").ui5DialogOpened(); + let initialTop: number; + let initialLeft: number; + // Capture initial position cy.get("#draggable-dialog") - .then(dialog => { - const initialTop = parseInt(dialog.css("top")); - const initialLeft = parseInt(dialog.css("left")); - - // Act - Move dialog up using keyboard - cy.get("#header-slot").realClick(); - - cy.get("#header-slot").focused().realPress("{uparrow}"); - cy.get("#header-slot").focused().realPress("{uparrow}"); - - // Assert - Top position changes, left remains the same - - cy.get("#draggable-dialog").then(dialog => { - const leftAfterUp = parseInt(dialog.css("left")); - const topAfterUp = parseInt(dialog.css("top")); - cy.get("#draggable-dialog").should(() => { - expect(topAfterUp).not.to.equal(initialTop); - }) - cy.get("#draggable-dialog").should(() => { - expect(leftAfterUp).to.equal(initialLeft); - }) - - // Act - Move dialog left using keyboard - cy.get("#header-slot").realClick(); - - cy.get("#header-slot").focused().realPress("{leftarrow}"); - cy.get("#header-slot").focused().realPress("{leftarrow}"); - - // Assert - Left position changes, top remains the same - cy.get("#draggable-dialog") - .should(dialogAfterLeft => { - const topAfterLeft = parseInt(dialogAfterLeft.css("top")); - const leftAfterLeft = parseInt(dialogAfterLeft.css("left")); - expect(topAfterLeft).to.equal(topAfterUp); - expect(leftAfterLeft).not.to.equal(leftAfterUp); - }); - }); + .should(dialog => { + expect(dialog[0].style.top).to.not.be.empty; + expect(dialog[0].style.left).to.not.be.empty; + + initialTop = parseInt(dialog.css("top")); + initialLeft = parseInt(dialog.css("left")); + }); - // Close dialog - cy.get("#draggable-dialog").invoke("attr", "open", false); + // Act - Move dialog up using keyboard + cy.get("#header-slot").realClick(); + cy.get("#header-slot").focused().realPress("{uparrow}"); + cy.get("#header-slot").focused().realPress("{uparrow}"); - // Reopen dialog - cy.get("#draggable-dialog").invoke("attr", "open", true); + let topAfterUp: number; + let leftAfterUp: number; + + // Assert - Top position changes, left remains the same + cy.get("#draggable-dialog") + .should(dialog => { + leftAfterUp = parseInt(dialog.css("left")); + topAfterUp = parseInt(dialog.css("top")); + + expect(topAfterUp).not.to.equal(initialTop); + expect(leftAfterUp).to.equal(initialLeft); + }); + + // Act - Move dialog left using keyboard + cy.get("#header-slot").realClick(); + + cy.get("#header-slot").focused().realPress("{leftarrow}"); + cy.get("#header-slot").focused().realPress("{leftarrow}"); + + // Assert - Left position changes, top remains the same + cy.get("#draggable-dialog") + .should(dialogAfterLeft => { + const topAfterLeft = parseInt(dialogAfterLeft.css("top")); + const leftAfterLeft = parseInt(dialogAfterLeft.css("left")); + + expect(topAfterLeft).to.equal(topAfterUp); + expect(leftAfterLeft).not.to.equal(leftAfterUp); + }); + + // Close dialog + cy.get("#draggable-dialog").invoke("attr", "open", false); + + // Reopen dialog + cy.get("#draggable-dialog").invoke("attr", "open", true); - // Assert - Position resets to initial - cy.get("#draggable-dialog") - .should(dialogAfterReopen => { - const leftAfterReopen = parseInt(dialogAfterReopen.css("left")); + // Assert - Position resets to initial + cy.get("#draggable-dialog") + .should(dialogAfterReopen => { + const leftAfterReopen = parseInt(dialogAfterReopen.css("left")); - expect(leftAfterReopen).to.equal(initialLeft); - }); + expect(leftAfterReopen).to.equal(initialLeft); }); }); it("resizable - mouse support", () => { - cy.mount( <> @@ -645,52 +724,58 @@ describe("Dialog general interaction", () => { // Open dialog cy.get("#resizable-dialog").invoke("attr", "open", true); - // Capture dimensions before resizing - cy.get("#resizable-dialog").then(dialog => { - const widthBeforeResizing = parseInt(dialog.css("width")); - const heightBeforeResizing = parseInt(dialog.css("height")); - const topBeforeResizing = parseInt(dialog.css("top")); - const leftBeforeResizing = parseInt(dialog.css("left")); - - // Resize dialog - cy.get("#resizable-dialog") - .shadow() - .find(".ui5-popup-resize-handle") - .realMouseDown() - .realMouseMove(150, 150) - .realMouseUp(); - - // Capture dimensions after resizing - cy.get("#resizable-dialog").should(dialogAfterResizing => { - const widthAfterResizing = parseInt(dialogAfterResizing.css("width")); - const heightAfterResizing = parseInt(dialogAfterResizing.css("height")); - const leftAfterResizing = parseInt(dialogAfterResizing.css("left")); + let widthBeforeResizing: number; + let heightBeforeResizing: number; + let leftBeforeResizing: number; - // Assert dimensions change - expect(widthBeforeResizing).not.to.equal(widthAfterResizing); - expect(heightBeforeResizing).not.to.equal(heightAfterResizing); - expect(leftBeforeResizing).to.equal(leftAfterResizing); + // Capture dimensions before resizing + cy.get("#resizable-dialog") + .should(dialog => { + expect(dialog.css("width")).to.not.be.empty; + expect(dialog.css("height")).to.not.be.empty; + expect(dialog[0].style.left).to.not.be.empty; + + widthBeforeResizing = parseInt(dialog.css("width")); + heightBeforeResizing = parseInt(dialog.css("height")); + leftBeforeResizing = parseInt(dialog.css("left")); }); - // Close dialog - cy.get("#resizable-dialog").invoke("attr", "open", false); - - // Reopen dialog - cy.get("#resizable-dialog").invoke("attr", "open", true); + // Resize dialog + cy.get("#resizable-dialog") + .shadow() + .find(".ui5-popup-resize-handle") + .realMouseDown() + .realMouseMove(150, 150) + .realMouseUp(); + + // Capture dimensions after resizing + cy.get("#resizable-dialog").should(dialogAfterResizing => { + const widthAfterResizing = parseInt(dialogAfterResizing.css("width")); + const heightAfterResizing = parseInt(dialogAfterResizing.css("height")); + const leftAfterResizing = parseInt(dialogAfterResizing.css("left")); + + // Assert dimensions change + expect(widthAfterResizing).not.to.equal(widthBeforeResizing); + expect(heightAfterResizing).not.to.equal(heightBeforeResizing); + expect(leftAfterResizing).to.equal(leftBeforeResizing); + }); + // Close dialog + cy.get("#resizable-dialog").invoke("attr", "open", false); - // Capture dimensions after reopening - cy.get("#resizable-dialog").should(dialogAfterReopening => { - const widthAfterReopening = parseInt(dialogAfterReopening.css("width")); - const heightAfterReopening = parseInt(dialogAfterReopening.css("height")); - const leftAfterReopening = parseInt(dialogAfterReopening.css("left")); + // Reopen dialog + cy.get("#resizable-dialog").invoke("attr", "open", true); - // Assert dimensions reset to initial - expect(widthBeforeResizing).to.equal(widthAfterReopening); - expect(heightBeforeResizing).to.equal(heightAfterReopening); - expect(leftBeforeResizing).to.equal(leftAfterReopening); - }); + // Capture dimensions after reopening + cy.get("#resizable-dialog").should(dialogAfterReopening => { + const widthAfterReopening = parseInt(dialogAfterReopening.css("width")); + const heightAfterReopening = parseInt(dialogAfterReopening.css("height")); + const leftAfterReopening = parseInt(dialogAfterReopening.css("left")); + // Assert dimensions reset to initial + expect(widthAfterReopening).to.equal(widthBeforeResizing); + expect(heightAfterReopening).to.equal(heightBeforeResizing); + expect(leftAfterReopening).to.equal(leftBeforeResizing); }); }); @@ -711,46 +796,57 @@ describe("Dialog general interaction", () => { cy.get("#rtl-min-width-dialog").invoke("attr", "open", true); cy.get("#rtl-min-width-dialog").ui5DialogOpened(); + let initialLeft: number; + let initialWidth: number; + let initialRightEdge: number; + // Capture initial dimensions and position - cy.get("#rtl-min-width-dialog").then(dialog => { - const initialLeft = parseInt(dialog.css("left")); - const initialWidth = parseInt(dialog.css("width")); - const initialRightEdge = initialLeft + initialWidth; - - // First resize to reach minimum width - cy.get("#rtl-min-width-dialog") - .shadow() - .find(".ui5-popup-resize-handle") - .realMouseDown() - .realMouseMove(800, 0) // Large movement to ensure we hit min width - .realMouseUp(); + cy.get("#rtl-min-width-dialog").should(dialog => { + expect(dialog.css("width")).to.not.be.empty; + expect(dialog[0].style.left).to.not.be.empty; - cy.get("#rtl-min-width-dialog").then(dialogAtMinWidth => { - const leftAtMinWidth = parseInt(dialogAtMinWidth.css("left")); - const widthAtMinWidth = parseInt(dialogAtMinWidth.css("width")); - const rightEdgeAtMinWidth = leftAtMinWidth + widthAtMinWidth; + initialWidth = parseInt(dialog.css("width")); + initialLeft = parseInt(dialog.css("left")); + initialRightEdge = initialLeft + initialWidth; + }); - expect(widthAtMinWidth).to.equal(320); - expect(rightEdgeAtMinWidth).to.equal(initialRightEdge); + // First resize to reach minimum width + cy.get("#rtl-min-width-dialog") + .shadow() + .find(".ui5-popup-resize-handle") + .realMouseDown() + .realMouseMove(800, 0) // Large movement to ensure we hit min width + .realMouseUp(); + + let leftAtMinWidth: number; + let widthAtMinWidth: number; + let rightEdgeAtMinWidth: number; + + cy.get("#rtl-min-width-dialog").should(dialogAtMinWidth => { + leftAtMinWidth = parseInt(dialogAtMinWidth.css("left")); + widthAtMinWidth = parseInt(dialogAtMinWidth.css("width")); + rightEdgeAtMinWidth = leftAtMinWidth + widthAtMinWidth; + + expect(widthAtMinWidth).to.equal(320); + expect(rightEdgeAtMinWidth).to.equal(initialRightEdge); + }); - cy.get("#rtl-min-width-dialog") - .shadow() - .find(".ui5-popup-resize-handle") - .realMouseDown() - .realMouseMove(150, 0) // Additional rightward movement beyond min width - .realMouseUp(); - - cy.get("#rtl-min-width-dialog").then(dialogAfterExtraResize => { - const finalLeft = parseInt(dialogAfterExtraResize.css("left")); - const finalWidth = parseInt(dialogAfterExtraResize.css("width")); - const finalRightEdge = finalLeft + finalWidth; - - expect(finalLeft).to.equal(leftAtMinWidth, "Dialog left position should not change when at min width"); - expect(finalWidth).to.equal(widthAtMinWidth, "Dialog width should remain at min width"); - expect(finalRightEdge).to.equal(rightEdgeAtMinWidth, "Dialog right edge should remain fixed"); - expect(finalRightEdge).to.equal(initialRightEdge, "Dialog right edge should remain fixed from initial position"); - }); - }); + cy.get("#rtl-min-width-dialog") + .shadow() + .find(".ui5-popup-resize-handle") + .realMouseDown() + .realMouseMove(150, 0) // Additional rightward movement beyond min width + .realMouseUp(); + + cy.get("#rtl-min-width-dialog").should(dialogAfterExtraResize => { + const finalLeft = parseInt(dialogAfterExtraResize.css("left")); + const finalWidth = parseInt(dialogAfterExtraResize.css("width")); + const finalRightEdge = finalLeft + finalWidth; + + expect(finalLeft).to.equal(leftAtMinWidth, "Dialog left position should not change when at min width"); + expect(finalWidth).to.equal(widthAtMinWidth, "Dialog width should remain at min width"); + expect(finalRightEdge).to.equal(rightEdgeAtMinWidth, "Dialog right edge should remain fixed"); + expect(finalRightEdge).to.equal(initialRightEdge, "Dialog right edge should remain fixed from initial position"); }); }); @@ -769,59 +865,70 @@ describe("Dialog general interaction", () => { cy.get("#resizable-dialog").invoke("attr", "open", true); cy.get("#resizable-dialog").ui5DialogOpened(); + let initialWidth: number; + let initialHeight: number; + let initialLeft: number; + // Capture initial dimensions - cy.get("#resizable-dialog").then(dialog => { - const initialWidth = parseInt(dialog.css("width")); - const initialHeight = parseInt(dialog.css("height")); - const initialTop = parseInt(dialog.css("top")); - const initialLeft = parseInt(dialog.css("left")); - - // Act - Resize height using keyboard - cy.get("#resizable-dialog").shadow().find(".ui5-popup-resize-handle").click(); - cy.get("#resizable-dialog").realPress(["Shift", "ArrowDown"]); - - // Assert - Height changes, width and position remain the same - cy.get("#resizable-dialog").then(dialogAfterResizeHeight => { - const widthAfterResizeHeight = parseInt(dialogAfterResizeHeight.css("width")); - const heightAfterResizeHeight = parseInt(dialogAfterResizeHeight.css("height")); - const leftAfterResizeHeight = parseInt(dialogAfterResizeHeight.css("left")); - - expect(widthAfterResizeHeight).to.equal(initialWidth); - expect(heightAfterResizeHeight).not.to.equal(initialHeight); - expect(leftAfterResizeHeight).to.equal(initialLeft); - - // Act - Resize width using keyboard - cy.get("#resizable-dialog").shadow().find(".ui5-popup-resize-handle").click(); - cy.get("#resizable-dialog").realPress(["Shift", "ArrowRight"]); - - // Assert - Width changes, height and position remain the same - cy.get("#resizable-dialog").then(dialogAfterResizeWidth => { - const widthAfterResizeWidth = parseInt(dialogAfterResizeWidth.css("width")); - const heightAfterResizeWidth = parseInt(dialogAfterResizeWidth.css("height")); - const leftAfterResizeWidth = parseInt(dialogAfterResizeWidth.css("left")); - - expect(widthAfterResizeWidth).not.to.equal(widthAfterResizeHeight); - expect(heightAfterResizeWidth).to.equal(heightAfterResizeHeight); - expect(leftAfterResizeWidth).to.equal(leftAfterResizeHeight); - - // Close dialog - cy.get("#resizable-dialog").invoke("attr", "open", false); - - // Reopen dialog - cy.get("#resizable-dialog").invoke("attr", "open", true); - - // Assert - Dimensions reset to initial - cy.get("#resizable-dialog").then(dialogAfterReopen => { - const widthAfterReopen = parseInt(dialogAfterReopen.css("width")); - const heightAfterReopen = parseInt(dialogAfterReopen.css("height")); - const leftAfterReopen = parseInt(dialogAfterReopen.css("left")); - - expect(widthAfterReopen).to.equal(initialWidth); - expect(heightAfterReopen).to.equal(initialHeight); - expect(leftAfterReopen).to.equal(initialLeft); - }); - }); - }); + cy.get("#resizable-dialog").should(dialog => { + expect(dialog.css("width")).to.not.be.empty; + expect(dialog.css("height")).to.not.be.empty; + expect(dialog[0].style.left).to.not.be.empty; + + initialWidth = parseInt(dialog.css("width")); + initialHeight = parseInt(dialog.css("height")); + initialLeft = parseInt(dialog.css("left")); + }); + + // Act - Resize height using keyboard + cy.get("#resizable-dialog").shadow().find(".ui5-popup-resize-handle").click(); + cy.get("#resizable-dialog").realPress(["Shift", "ArrowDown"]); + + let widthAfterResizeHeight: number; + let heightAfterResizeHeight: number; + let leftAfterResizeHeight: number; + + // Assert - Height changes, width and position remain the same + cy.get("#resizable-dialog").should(dialogAfterResizeHeight => { + widthAfterResizeHeight = parseInt(dialogAfterResizeHeight.css("width")); + heightAfterResizeHeight = parseInt(dialogAfterResizeHeight.css("height")); + leftAfterResizeHeight = parseInt(dialogAfterResizeHeight.css("left")); + + expect(widthAfterResizeHeight).to.equal(initialWidth); + expect(heightAfterResizeHeight).not.to.equal(initialHeight); + expect(leftAfterResizeHeight).to.equal(initialLeft); + }); + + // Act - Resize width using keyboard + cy.get("#resizable-dialog").shadow().find(".ui5-popup-resize-handle").click(); + cy.get("#resizable-dialog").realPress(["Shift", "ArrowRight"]); + + // Assert - Width changes, height and position remain the same + cy.get("#resizable-dialog").should(dialogAfterResizeWidth => { + const widthAfterResizeWidth = parseInt(dialogAfterResizeWidth.css("width")); + const heightAfterResizeWidth = parseInt(dialogAfterResizeWidth.css("height")); + const leftAfterResizeWidth = parseInt(dialogAfterResizeWidth.css("left")); + + expect(widthAfterResizeWidth).not.to.equal(widthAfterResizeHeight); + expect(heightAfterResizeWidth).to.equal(heightAfterResizeHeight); + expect(leftAfterResizeWidth).to.equal(leftAfterResizeHeight); + }); + + // Close dialog + cy.get("#resizable-dialog").invoke("attr", "open", false); + + // Reopen dialog + cy.get("#resizable-dialog").invoke("attr", "open", true); + + // Assert - Dimensions reset to initial + cy.get("#resizable-dialog").should(dialogAfterReopen => { + const widthAfterReopen = parseInt(dialogAfterReopen.css("width")); + const heightAfterReopen = parseInt(dialogAfterReopen.css("height")); + const leftAfterReopen = parseInt(dialogAfterReopen.css("left")); + + expect(widthAfterReopen).to.equal(initialWidth); + expect(heightAfterReopen).to.equal(initialHeight); + expect(leftAfterReopen).to.equal(initialLeft); }); }); @@ -838,30 +945,41 @@ describe("Dialog general interaction", () => { cy.get("#resizable-dialog").invoke("attr", "open", true); - cy.get("#resizable-dialog").then(dialog => { - const widthBeforeResizing = parseInt(dialog.css("width")); - const heightBeforeResizing = parseInt(dialog.css("height")); - const topBeforeResizing = parseInt(dialog.css("top")); - const leftBeforeResizing = parseInt(dialog.css("left")); - - cy.get("#resizable-dialog") - .shadow() - .find(".ui5-popup-resize-handle") - .realMouseDown({ position: "left" }) - .realMouseMove(-100, 100) - .realMouseUp(); + let widthBeforeResizing: number; + let heightBeforeResizing: number; + let topBeforeResizing: number; + let leftBeforeResizing: number; - cy.get("#resizable-dialog").should(dialogAfterResizing => { - const widthAfterResizing = parseInt(dialogAfterResizing.css("width")); - const heightAfterResizing = parseInt(dialogAfterResizing.css("height")); - const topAfterResizing = parseInt(dialogAfterResizing.css("top")); - const leftAfterResizing = parseInt(dialogAfterResizing.css("left")); + // Capture initial dimensions and position + cy.get("#resizable-dialog").should(dialog => { + expect(dialog.css("width")).to.not.be.empty; + expect(dialog.css("height")).to.not.be.empty; + expect(dialog[0].style.top).to.not.be.empty; + expect(dialog[0].style.left).to.not.be.empty; + + widthBeforeResizing = parseInt(dialog.css("width")); + heightBeforeResizing = parseInt(dialog.css("height")); + topBeforeResizing = parseInt(dialog.css("top")); + leftBeforeResizing = parseInt(dialog.css("left")); + }); - expect(widthBeforeResizing).to.equal(widthAfterResizing); - expect(heightBeforeResizing).not.to.equal(heightAfterResizing); - expect(topBeforeResizing).to.equal(topAfterResizing); - expect(leftBeforeResizing).not.to.equal(leftAfterResizing + 100); - }); + cy.get("#resizable-dialog") + .shadow() + .find(".ui5-popup-resize-handle") + .realMouseDown({ position: "left" }) + .realMouseMove(-100, 100) + .realMouseUp(); + + cy.get("#resizable-dialog").should(dialogAfterResizing => { + const widthAfterResizing = parseInt(dialogAfterResizing.css("width")); + const heightAfterResizing = parseInt(dialogAfterResizing.css("height")); + const topAfterResizing = parseInt(dialogAfterResizing.css("top")); + const leftAfterResizing = parseInt(dialogAfterResizing.css("left")); + + expect(widthBeforeResizing).to.equal(widthAfterResizing); + expect(heightBeforeResizing).not.to.equal(heightAfterResizing); + expect(topBeforeResizing).to.equal(topAfterResizing); + expect(leftBeforeResizing).not.to.equal(leftAfterResizing + 100); }); }); @@ -1393,10 +1511,10 @@ describe("Page scrolling", () => { describe("Responsive paddings", () => { before(() => { cy.viewport(1000, 400); - }); + }) after(() => { - cy.viewport(Cypress.config("viewportWidth"), Cypress.config("viewportHeight")); + restoreViewport(); }); it("tests responsive paddings", () => { @@ -1583,4 +1701,4 @@ describe("Dialog initially open", () => { // Assert dialog matches :popover-open selector cy.get("#dialogOpen").should("match", ":popover-open"); }); -}); \ No newline at end of file +}); diff --git a/packages/main/cypress/specs/MultiComboBox.mobile.cy.tsx b/packages/main/cypress/specs/MultiComboBox.mobile.cy.tsx index 3de01e8e4f5b..dc5a84ee0647 100644 --- a/packages/main/cypress/specs/MultiComboBox.mobile.cy.tsx +++ b/packages/main/cypress/specs/MultiComboBox.mobile.cy.tsx @@ -191,6 +191,11 @@ describe("Typeahead", () => { cy.get("@input") .realClick(); + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); + cy.get("[ui5-multi-combobox]") .shadow() .find("[ui5-responsive-popover]") @@ -219,6 +224,11 @@ describe("Typeahead", () => { cy.get("@input") .realClick(); + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); + cy.get("[ui5-multi-combobox]") .shadow() .find("[ui5-responsive-popover]") @@ -298,6 +308,11 @@ describe("Items selection", () => { cy.get("@input") .realClick(); + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); + cy.get("[ui5-multi-combobox]") .find("[ui5-mcb-item]") .eq(0) @@ -331,6 +346,11 @@ describe("Items selection", () => { .find("input") .realClick(); + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); + cy.get("[ui5-multi-combobox]") .find("[ui5-mcb-item]") .eq(0) @@ -484,6 +504,11 @@ describe("Items selection", () => { .find("input") .realClick(); + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); + cy.get("[ui5-multi-combobox]") .shadow() .find("[ui5-responsive-popover]") @@ -628,6 +653,11 @@ describe("Eventing", () => { .find("input") .realClick(); + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); + cy.get("[ui5-multi-combobox]") .find("[ui5-mcb-item]") .eq(0) diff --git a/packages/main/cypress/specs/OpenUI5andWebCPopups.cy.tsx b/packages/main/cypress/specs/OpenUI5andWebCPopups.cy.tsx index b5e62f6e546c..1b13578f9e67 100644 --- a/packages/main/cypress/specs/OpenUI5andWebCPopups.cy.tsx +++ b/packages/main/cypress/specs/OpenUI5andWebCPopups.cy.tsx @@ -7,11 +7,20 @@ import ComboBox from "../../src/ComboBox.js"; import ComboBoxItem from "../../src/ComboBoxItem.js"; import ResponsivePopover from "../../src/ResponsivePopover.js"; +let OpenUI5Element; + function onOpenUI5InitMethod(win) { - (win as any).sap.ui.require(["sap/ui/core/HTML", "sap/m/Button", "sap/m/Dialog", "sap/m/Popover", "sap/m/Input"], async (HTML, Button, Dialog, Popover, Input) => { + (win as any).sap.ui.require([ + "sap/ui/core/Element", + "sap/ui/core/HTML", + "sap/m/Button", + "sap/m/Dialog", + "sap/m/Popover", + "sap/m/Input" + ], async (Element, HTML, Button, Dialog, Popover, Input) => { await OpenUI5Support.init(); - + OpenUI5Element = Element; new Button("openUI5Button", { text: "Open OpenUI5 Dialog", press: function () { @@ -206,6 +215,15 @@ function openUI5Popover(win, opener) { }); } +function isOpenUI5DialogOpen($dialog) { + expect(OpenUI5Element).to.exist; + + const dialogInstance = OpenUI5Element.getElementById($dialog.attr("id")); + + expect(dialogInstance).to.exist + expect(dialogInstance.isOpen()).to.be.true; +}; + describe("ui5 and web components integration", () => { beforeEach(() => { // mount the components @@ -480,6 +498,10 @@ describe("ui5 and web components integration", () => { .find('input') .focus(); + cy.get("#openUI5Combobox1") + .find('input') + .should('be.focused'); + cy.realPress("Escape"); cy.get('#dialog1') @@ -518,12 +540,11 @@ describe("ui5 and web components integration", () => { .should('be.visible') .realClick(); - cy.get("#respPopover").ui5DialogOpened(); + cy.get("#respPopover").ui5ResponsivePopoverOpened(); cy.realPress("Escape"); - cy.get("#respPopover") - .should('not.be.visible'); + cy.get("#respPopover").ui5ResponsivePopoverClosed(); cy.get("#openUI5Dialog1") .should('be.visible'); @@ -549,12 +570,12 @@ describe("ui5 and web components integration", () => { .should('be.visible') .realClick(); - cy.get("#respPopoverNoInitialFocus").ui5DialogOpened(); + cy.get("#respPopoverNoInitialFocus").ui5ResponsivePopoverOpened(); cy.realPress("Escape"); - cy.get("#respPopoverNoInitialFocus") - .should('not.be.visible'); + cy.get("#respPopoverNoInitialFocus") + .ui5ResponsivePopoverClosed(); cy.get("#openResPopoverNoInitialFocusButton") .should('be.focused'); @@ -591,8 +612,8 @@ describe("ui5 and web components integration", () => { cy.get("#webCSelect1") .shadow() - .find("[ui5-responsive-popover]") - .should('not.be.visible'); + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverClosed(); cy.get("#openUI5Dialog1") .should('be.visible'); @@ -631,8 +652,8 @@ describe("ui5 and web components integration", () => { cy.get("#webCComboBox1") .shadow() - .find("[ui5-responsive-popover]") - .should('not.be.visible'); + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverClosed(); cy.get("#openUI5Dialog1") .should('be.visible'); @@ -688,7 +709,9 @@ describe("ui5 and web components integration", () => { .realClick(); cy.get("#openUI5DialogFinal") - .should('be.visible'); + .should('be.visible') + .should(isOpenUI5DialogOpen); + cy.wait(1000); cy.get("#openUI5Dialog1") .should('not.be.visible'); @@ -706,7 +729,9 @@ describe("ui5 and web components integration", () => { .should('not.exist'); cy.get("#openUI5DialogWithButtons") - .should('be.visible'); + .should('be.visible') + .should(isOpenUI5DialogOpen); + cy.wait(100); cy.realPress("Escape"); diff --git a/packages/main/src/Dialog.ts b/packages/main/src/Dialog.ts index ecb7110ed8af..8a9625ed077d 100644 --- a/packages/main/src/Dialog.ts +++ b/packages/main/src/Dialog.ts @@ -329,7 +329,7 @@ class Dialog extends Popup { _show() { super._show(); - this._center(); + requestAnimationFrame(this._center.bind(this)); } onBeforeRendering() { diff --git a/packages/main/src/Popup.ts b/packages/main/src/Popup.ts index fda670bdff31..0023b69e30f4 100644 --- a/packages/main/src/Popup.ts +++ b/packages/main/src/Popup.ts @@ -270,9 +270,7 @@ abstract class Popup extends UI5Element { } onAfterRendering() { - renderFinished().then(() => { - this._updateMediaRange(); - }); + this._updateMediaRange(); if (this.open) { this._registerResizeHandler(); @@ -358,11 +356,6 @@ abstract class Popup extends UI5Element { this._show(); this._opened = true; - - if (this.getDomRef()) { - this._updateMediaRange(); - } - this._addOpenedPopup(); this.open = true; @@ -604,13 +597,15 @@ abstract class Popup extends UI5Element { } /** - * Sets "block" display to the popup. The property can be overriden by derivatives of Popup. + * Sets "popover=manual" to the popup. The method can be overridden by derivatives of Popup. * @protected */ _show() { if (this.isConnected) { this.setAttribute("popover", "manual"); this.showPopover(); + + requestAnimationFrame(this._updateMediaRange.bind(this)); } } diff --git a/packages/main/test/pages/Dialog.html b/packages/main/test/pages/Dialog.html index 119577f212e3..7eaa9f42e22b 100644 --- a/packages/main/test/pages/Dialog.html +++ b/packages/main/test/pages/Dialog.html @@ -95,6 +95,9 @@

Open dialog with big content +
+
+ Open dynamic dialog with big content @@ -1127,6 +1130,72 @@ document.getElementById("open-big-content").addEventListener("click", function () { window["dlgBigContent"].open = true; }); + + document.getElementById("open-big-dynamic-content").addEventListener("click", function () { + const dialog = document.createElement("ui5-dialog"); + const child1 = ` +
+

Random Title

+
+ `; + + const child2 = ` +
+
+
+
+
+ +
+
+
+
Contact RANDOM CORP
+
Some subtitle
+
+
+
+
+
+
+

Subscribe to our newsletter

+ No spam, only updates. +
+
+
+ Hint: Use a valid code +
+
Your Info
+
+
+
+
+
+
+
Company Info
+
+
+
+
+
+
+
+
+
+ + I agree to the random terms and conditions. + Read Privacy Policy. + +
+
+
+
+
+ `; + + dialog.innerHTML = child1 + child2; + document.body.appendChild(dialog); + dialog.open = true; + });