New room list: add keyboard navigation support (#29805)
* feat: support up/down arrow navigation in the new room list * feat: support tabbing in the new room list * test: update snapshots * test(e2e): fix room list test * test(new room list): add landmark navigation test * test(e2e): update screenshot test * test: add test to `RoomListItemView` * test(e2e): add keyboard navigation tests * refactor: rename `setIsHover` on `setIsHoverWithDelay`
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
import React from "react";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { render } from "jest-matrix-react";
|
||||
import { fireEvent } from "@testing-library/dom";
|
||||
|
||||
import { mkRoom, stubClient } from "../../../../../test-utils";
|
||||
import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel";
|
||||
@@ -15,6 +16,7 @@ import { RoomList } from "../../../../../../src/components/views/rooms/RoomListP
|
||||
import DMRoomMap from "../../../../../../src/utils/DMRoomMap";
|
||||
import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms";
|
||||
import { SortOption } from "../../../../../../src/components/viewmodels/roomlist/useSorter";
|
||||
import { Landmark, LandmarkNavigation } from "../../../../../../src/accessibility/LandmarkNavigation";
|
||||
|
||||
describe("<RoomList />", () => {
|
||||
let matrixClient: MatrixClient;
|
||||
@@ -53,4 +55,16 @@ describe("<RoomList />", () => {
|
||||
const { asFragment } = render(<RoomList vm={vm} />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ shortcut: { key: "F6", ctrlKey: true, shiftKey: true }, isPreviousLandmark: true, label: "PreviousLandmark" },
|
||||
{ shortcut: { key: "F6", ctrlKey: true }, isPreviousLandmark: false, label: "NextLandmark" },
|
||||
])("should navigate to the landmark on NextLandmark.$label action", ({ shortcut, isPreviousLandmark }) => {
|
||||
const spyFindLandmark = jest.spyOn(LandmarkNavigation, "findAndFocusNextLandmark").mockReturnValue();
|
||||
const { getByTestId } = render(<RoomList vm={vm} />);
|
||||
const roomList = getByTestId("room-list");
|
||||
fireEvent.keyDown(roomList, shortcut);
|
||||
|
||||
expect(spyFindLandmark).toHaveBeenCalledWith(Landmark.ROOM_LIST, isPreviousLandmark);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -91,6 +91,17 @@ describe("<RoomListItemView />", () => {
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "More Options" })).toBeInTheDocument());
|
||||
});
|
||||
|
||||
test("should hover decoration if focused", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<RoomListItemView room={room} isSelected={false} />, withClientContextRenderOptions(matrixClient));
|
||||
const listItem = screen.getByRole("button", { name: `Open room ${room.name}` });
|
||||
await user.click(listItem);
|
||||
expect(listItem).toHaveClass("mx_RoomListItemView_hover");
|
||||
|
||||
await user.tab();
|
||||
await waitFor(() => expect(listItem).not.toHaveClass("mx_RoomListItemView_hover"));
|
||||
});
|
||||
|
||||
test("should be selected if isSelected=true", async () => {
|
||||
const { asFragment } = render(<RoomListItemView room={room} isSelected={true} />);
|
||||
expect(screen.queryByRole("button", { name: `Open room ${room.name}` })).toHaveAttribute(
|
||||
|
||||
@@ -15,7 +15,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="ReactVirtualized__Grid ReactVirtualized__List mx_RoomList_List"
|
||||
role="grid"
|
||||
style="box-sizing: border-box; direction: ltr; height: 1500px; position: relative; width: 1500px; will-change: transform; overflow-x: hidden; overflow-y: hidden;"
|
||||
tabindex="0"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="ReactVirtualized__Grid__innerScrollContainer"
|
||||
@@ -28,6 +28,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 0px; width: 100%;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -79,6 +80,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 48px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -130,6 +132,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 96px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -181,6 +184,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 144px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -232,6 +236,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 192px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -283,6 +288,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 240px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -334,6 +340,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 288px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -385,6 +392,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 336px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -436,6 +444,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 384px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -487,6 +496,7 @@ exports[`<RoomList /> should render a room list 1`] = `
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
role="gridcell"
|
||||
style="height: 48px; left: 0px; position: absolute; top: 432px; width: 100%;"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -6,6 +6,7 @@ exports[`<RoomListItemView /> should be selected if isSelected=true 1`] = `
|
||||
aria-label="Open room room1"
|
||||
aria-selected="true"
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty mx_RoomListItemView_selected"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -60,6 +61,7 @@ exports[`<RoomListItemView /> should display notification decoration 1`] = `
|
||||
aria-label="Open room room1"
|
||||
aria-selected="false"
|
||||
class="mx_RoomListItemView mx_RoomListItemView_notification_decoration"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -126,6 +128,7 @@ exports[`<RoomListItemView /> should render a room item 1`] = `
|
||||
aria-label="Open room room1"
|
||||
aria-selected="false"
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
@@ -180,6 +183,7 @@ exports[`<RoomListItemView /> should render a room item with a message preview 1
|
||||
aria-label="Open room room1"
|
||||
aria-selected="false"
|
||||
class="mx_RoomListItemView mx_RoomListItemView_empty"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user