-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
257 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 25 additions & 2 deletions
27
vuu-ui/packages/vuu-table/src/__tests__/__component__/Table.cy.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,41 @@ | ||
import React from "react"; | ||
// TODO try and get TS path alias working to avoid relative paths like this | ||
import { Instruments } from "../../../../../showcase/src/examples/Table/SIMUL.examples"; | ||
import { SimulTable } from "../../../../../showcase/src/examples/Table/SIMUL.examples"; | ||
import { TestTable } from "../../../../../showcase/src/examples/Table/Table.examples"; | ||
import { assertRenderedRows } from "./table-test-utils"; | ||
|
||
const withAriaIndex = (index: number) => ({ | ||
name: (_: string, el: Element) => el.ariaRowIndex === `${index}`, | ||
}); | ||
|
||
describe("WHEN it initially renders", () => { | ||
const RENDER_BUFFER = 5; | ||
const ROW_COUNT = 1000; | ||
const tableConfig = { | ||
renderBufferSize: RENDER_BUFFER, | ||
headerHeight: 25, | ||
height: 625, | ||
rowCount: ROW_COUNT, | ||
rowHeight: 20, | ||
width: 1000, | ||
}; | ||
|
||
it("THEN expected classname is present", () => { | ||
cy.mount( | ||
<Instruments | ||
<SimulTable | ||
data-testid="table" | ||
renderBufferSize={5} | ||
height={625} | ||
tableName="instruments" | ||
width={800} | ||
/> | ||
); | ||
const container = cy.findByTestId("table"); | ||
container.should("have.class", "vuuTable"); | ||
}); | ||
|
||
it("THEN expected number of rows are present, with buffered rows, all with correct aria index", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
assertRenderedRows({ from: 0, to: 30 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); |
203 changes: 178 additions & 25 deletions
203
vuu-ui/packages/vuu-table/src/__tests__/__component__/Table.scrolling.cy.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,184 @@ | ||
import React from "react"; | ||
// TODO try and get TS path alias working to avoid relative paths like this | ||
import { TestTable } from "../../../../../showcase/src/examples/Table/Table.examples"; | ||
import { assertRenderedRows, withAriaIndex } from "./table-test-utils"; | ||
|
||
const withAriaIndex = (index: number) => ({ | ||
name: (_: string, el: HTMLElement) => el.ariaRowIndex === `${index}`, | ||
}); | ||
describe("Table scrolling and keyboard navigation", () => { | ||
const RENDER_BUFFER = 5; | ||
const ROW_COUNT = 1000; | ||
const tableConfig = { | ||
renderBufferSize: RENDER_BUFFER, | ||
headerHeight: 25, | ||
height: 625, | ||
rowCount: ROW_COUNT, | ||
rowHeight: 20, | ||
width: 1000, | ||
}; | ||
describe("Page Keys", () => { | ||
describe("WHEN first cell is focussed and page down pressed", () => { | ||
it("THEN table scrolls down and next page of rows are rendered, first cell of new page is focussed", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
|
||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 1" }).click(); | ||
cy.findByRole("cell", { name: "row 1" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 1" }).should("be.focused"); | ||
cy.realPress("PageDown"); | ||
|
||
cy.findByRole("row", withAriaIndex(25)).should("not.exist"); | ||
cy.findByRole("row", withAriaIndex(26)).should("exist"); | ||
|
||
cy.get(".vuuTable-contentContainer") | ||
.then((el) => el[0].scrollTop) | ||
.should("equal", 600); | ||
|
||
// row 31 should be top row in viewport | ||
cy.findByRole("row", withAriaIndex(31)).should( | ||
"have.css", | ||
"transform", | ||
"matrix(1, 0, 0, 1, 0, 600)" | ||
); | ||
|
||
cy.findByRole("cell", { name: "row 31" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 31" }).should("be.focused"); | ||
}); | ||
|
||
describe("AND WHEN page up is then pressed", () => { | ||
it("THEN table is back to original state, and first cell is once again focussed", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
|
||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 1" }).click(); | ||
|
||
cy.realPress("PageDown"); | ||
cy.wait(60); | ||
cy.realPress("PageUp"); | ||
|
||
cy.findByRole("cell", { name: "row 1" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 1" }).should("be.focused"); | ||
|
||
assertRenderedRows({ from: 0, to: 30 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("Home / End Keys", () => { | ||
describe("WHEN topmost rows are in viewport, first cell is focussed and Home key pressed ", () => { | ||
it("THEN nothing changes", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 1" }).click(); | ||
cy.realPress("Home"); | ||
cy.findByRole("cell", { name: "row 1" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 1" }).should("be.focused"); | ||
assertRenderedRows({ from: 0, to: 30 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
describe("WHEN topmost rows are in viewport, cell in middle of viewport is focussed and Home key pressed ", () => { | ||
it("THEN no scrolling, but focus moves to first cell", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 5" }).click(); | ||
cy.realPress("Home"); | ||
cy.findByRole("cell", { name: "row 1" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 1" }).should("be.focused"); | ||
assertRenderedRows({ from: 0, to: 30 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
|
||
describe("WHEN topmost rows are in viewport, first cell is focussed and End key pressed ", () => { | ||
it("THEN scrolls to end of data, last cell is focussed (same column)", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 1" }).click(); | ||
cy.realPress("End"); | ||
cy.findByRole("cell", { name: "row 1,000" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 1,000" }).should("be.focused"); | ||
assertRenderedRows({ from: 970, to: 1000 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
|
||
describe("WHEN topmost rows are in viewport, cell mid viewport focussed and End key pressed ", () => { | ||
it("THEN scrolls to end of data, last cell is focussed (same column)", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 10" }).click(); | ||
cy.realPress("End"); | ||
cy.findByRole("cell", { name: "row 1,000" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 1,000" }).should("be.focused"); | ||
assertRenderedRows({ from: 970, to: 1000 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("Arrow Up / Down Keys", () => { | ||
describe("WHEN topmost rows are in viewport, first cell is focussed and Down Arrow key pressed ", () => { | ||
it("THEN no scrolling, focus moved down to next cell", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 1" }).click(); | ||
cy.realPress("ArrowDown"); | ||
cy.findByRole("cell", { name: "row 2" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 2" }).should("be.focused"); | ||
assertRenderedRows({ from: 0, to: 30 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
describe("WHEN topmost rows are in viewport, first cell in last row is focussed and Down Arrow key pressed ", () => { | ||
it("THEN scroll down by 1 row, cell in bottom row has focus", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
// interestingly, realClick doesn't work here | ||
cy.findByRole("cell", { name: "row 30" }).click(); | ||
cy.realPress("ArrowDown"); | ||
cy.findByRole("cell", { name: "row 31" }).should( | ||
"have.attr", | ||
"tabindex", | ||
"0" | ||
); | ||
cy.findByRole("cell", { name: "row 31" }).should("be.focused"); | ||
assertRenderedRows({ from: 1, to: 31 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("WHEN it initially renders", () => { | ||
it("THEN expected number of rows are present, with buffered rows, all with correct aria index", () => { | ||
cy.mount( | ||
<TestTable | ||
data-testid="table" | ||
renderBufferSize={5} | ||
headerHeight={25} | ||
height={625} | ||
rowHeight={20} | ||
width={1000} | ||
/> | ||
); | ||
|
||
// Note the Table Headers row is included in count | ||
const container = cy.findAllByRole("row").should("have.length", 36); | ||
cy.findByRole("row", withAriaIndex(0)).should("not.exist"); | ||
cy.findByRole("row", withAriaIndex(1)).should("be.visible"); | ||
cy.findByRole("row", withAriaIndex(30)).should("be.visible"); | ||
cy.findByRole("row", withAriaIndex(31)).should("not.be.visible"); | ||
cy.findByRole("row", withAriaIndex(35)).should("not.be.visible"); | ||
cy.findByRole("row", withAriaIndex(36)).should("not.exist"); | ||
describe("scrolling with Scrollbar", () => { | ||
describe("WHEN scrolled down by a distance equating to 500 rows", () => { | ||
it("THEN correct rows are within viewport", () => { | ||
cy.mount(<TestTable {...tableConfig} />); | ||
cy.get(".vuuTable-scrollbarContainer").scrollTo(0, 10000); | ||
assertRenderedRows({ from: 500, to: 530 }, RENDER_BUFFER, ROW_COUNT); | ||
}); | ||
}); | ||
}); | ||
}); |
43 changes: 43 additions & 0 deletions
43
vuu-ui/packages/vuu-table/src/__tests__/__component__/table-test-utils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { VuuRange } from "packages/vuu-protocol-types"; | ||
|
||
export const withAriaIndex = (index: number) => ({ | ||
name: (_: string, el: Element) => el.ariaRowIndex === `${index}`, | ||
}); | ||
|
||
export const assertRenderedRows = ( | ||
{ from, to }: VuuRange, | ||
renderBufferSize: number, | ||
totalRowCount: number | ||
) => { | ||
const leadingBufferedRows = from < renderBufferSize ? from : renderBufferSize; | ||
const offsetFromEnd = totalRowCount - to; | ||
const trailingBufferedRows = | ||
offsetFromEnd < renderBufferSize | ||
? Math.min(0, offsetFromEnd) | ||
: renderBufferSize; | ||
const renderedRowCount = | ||
to - from + leadingBufferedRows + trailingBufferedRows; | ||
|
||
// Note the Table Headers row is included in count, hence the + 1 | ||
cy.findAllByRole("row").should("have.length", renderedRowCount + 1); | ||
|
||
// we use the aria index for locators, which is 1 based | ||
const firstRenderedRow = from - leadingBufferedRows + 1; | ||
const firstVisibleRow = from + 1; | ||
const lastVisibleRow = to; | ||
const lastRenderedRow = to + trailingBufferedRows; | ||
|
||
cy.findByRole("row", withAriaIndex(firstRenderedRow - 1)).should("not.exist"); | ||
cy.findByRole("row", withAriaIndex(firstVisibleRow)).should("be.visible"); | ||
cy.findByRole("row", withAriaIndex(lastVisibleRow)).should("be.visible"); | ||
|
||
if (trailingBufferedRows > 0) { | ||
cy.findByRole("row", withAriaIndex(lastVisibleRow + 1)).should( | ||
"not.be.visible" | ||
); | ||
cy.findByRole("row", withAriaIndex(lastRenderedRow)).should( | ||
"not.be.visible" | ||
); | ||
} | ||
cy.findByRole("row", withAriaIndex(lastRenderedRow + 1)).should("not.exist"); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters