diff --git a/packages/main/cypress/specs/TableNavigationFixedHeader.cy.tsx b/packages/main/cypress/specs/TableNavigationFixedHeader.cy.tsx new file mode 100644 index 000000000000..da18e0fee502 --- /dev/null +++ b/packages/main/cypress/specs/TableNavigationFixedHeader.cy.tsx @@ -0,0 +1,199 @@ +import Table from "../../src/Table.js"; +import TableHeaderRow from "../../src/TableHeaderRow.js"; +import TableHeaderCell from "../../src/TableHeaderCell.js"; +import TableRow from "../../src/TableRow.js"; +import TableCell from "../../src/TableCell.js"; +import Label from "../../src/Label.js"; +import Bar from "../../src/Bar.js"; +import Title from "../../src/Title.js"; +import Slider from "../../src/Slider.js"; + +describe("Table - Keyboard Navigation with Fixed Headers", () => { + function isDisplayedInsideViewport(element: string) { + cy.get(element).then($el => { + const el = $el[0]; + const rect = el.getBoundingClientRect(); + + expect(rect.top).to.be.at.least(0); + expect(rect.left).to.be.at.least(0); + expect(rect.bottom).to.be.lessThan(Cypress.config("viewportHeight")); + expect(rect.right).to.be.lessThan(Cypress.config("viewportWidth")); + }); + } + + it("scrollable container - focused row should always be below the header", () => { + cy.mount( +
+ + My Selectable Products (3) + + + + + ColumnA + Column B + Column C + Column D + + + + + + + + + + + + + + + + + + + + + + A +
+
+ ); + + cy.get("#table0").children("ui5-table-row").as("rows"); + cy.get("#table0").children("ui5-table-header-row").as("headerRow"); + cy.get("@rows").get("#row-21").as("lastRow"); + + cy.get("@lastRow").scrollIntoView(); + cy.get("@lastRow").click("left"); + cy.get("@lastRow").should("be.focused"); + + for (let i = 20; i > 0; i--) { + cy.realPress("{uparrow}"); + cy.get("@rows").get(`#row-${i}`).should("be.focused"); + + isDisplayedInsideViewport("@headerRow"); + + cy.get("@headerRow").then($headerRow => { + cy.get("@rows").get(`#row-${i}`).then($row => { + const headerRowBottom = $headerRow[0].getBoundingClientRect().bottom; + const focusedRowTop = $row[0].getBoundingClientRect().top; + + expect(focusedRowTop).to.be.at.least(headerRowBottom); + }); + }); + } + }); + + it("scrollable table - focused row should always be below the header", () => { + cy.mount( + + + ColumnA + Column B + Column C + Column D + + + + + + + + + + + + + + + + + + + + + + A +
+ ); + + cy.get("#table1").children("ui5-table-row").as("rows"); + cy.get("#table1").children("ui5-table-header-row").as("headerRow"); + cy.get("@rows").get("#row-21-1").as("lastRow"); + + cy.get("@lastRow").scrollIntoView(); + cy.get("@lastRow").click("left"); + cy.get("@lastRow").should("be.focused"); + + for (let i = 20; i > 0; i--) { + cy.realPress("{uparrow}"); + cy.get("@rows").get(`#row-${i}-1`).should("be.focused"); + + isDisplayedInsideViewport("@headerRow"); + + cy.get("@headerRow").then($headerRow => { + cy.get("@rows").get(`#row-${i}-1`).then($row => { + const headerRowBottom = $headerRow[0].getBoundingClientRect().bottom; + const focusedRowTop = $row[0].getBoundingClientRect().top; + + expect(focusedRowTop).to.be.at.least(headerRowBottom); + }); + }); + } + }); + + it("body as scroll container - focused row should always be below the header", () => { + cy.mount( + <> + + My Selectable Products (3) + + + + + ColumnA + Column B + Column C + Column D + + ${Array.from({ length: 100 }).map((row, index) => + + + + + + + + )} +
+ + ); + + cy.get("#table2").children("ui5-table-row").as("rows"); + cy.get("#table2").children("ui5-table-header-row").as("headerRow"); + cy.get("@rows").get("#row-100-2").as("lastRow"); + + cy.get("@lastRow").scrollIntoView(); + cy.get("@lastRow").click("left"); + cy.get("@lastRow").should("be.focused"); + + for (let i = 99; i > 0; i--) { + cy.realPress("{uparrow}"); + cy.get("@rows").get(`#row-${i}-2`).should("be.focused"); + + isDisplayedInsideViewport("@headerRow"); + + cy.get("@headerRow").then($headerRow => { + cy.get("@rows").get(`#row-${i}-2`).then($row => { + const headerRowBottom = $headerRow[0].getBoundingClientRect().bottom; + const focusedRowTop = $row[0].getBoundingClientRect().top; + + expect(focusedRowTop).to.be.at.least(headerRowBottom); + }); + }); + } + }); +});