-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathuseTreeGridLevelNavigation.test.ts
More file actions
134 lines (112 loc) · 4.24 KB
/
Copy pathuseTreeGridLevelNavigation.test.ts
File metadata and controls
134 lines (112 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import * as React from 'react';
import { renderHook } from '@testing-library/react';
import { ArrowDown, ArrowUp } from '@fluentui/keyboard-keys';
import type { TreeGridTabsterMoveFocusEventDetail } from '../components/TreeGrid';
import { useTreeGridLevelNavigation } from './useTreeGridLevelNavigation';
const createRow = (level: number): HTMLDivElement => {
const row = document.createElement('div');
row.setAttribute('role', 'row');
row.setAttribute('aria-level', String(level));
row.tabIndex = 0;
row.scrollIntoView = jest.fn();
document.body.appendChild(row);
return row;
};
const createWrappedRow = (
level: number,
treeGrid: HTMLElement
): HTMLDivElement => {
const wrapper = document.createElement('div');
const row = document.createElement('div');
row.setAttribute('role', 'row');
row.setAttribute('aria-level', String(level));
row.tabIndex = 0;
row.scrollIntoView = jest.fn();
wrapper.appendChild(row);
treeGrid.appendChild(wrapper);
return row;
};
const createTreeGrid = (): HTMLDivElement => {
const treeGrid = document.createElement('div');
treeGrid.setAttribute('role', 'treegrid');
document.body.appendChild(treeGrid);
return treeGrid;
};
const createKeyboardEvent = (
key: string,
target: HTMLElement
): KeyboardEvent => {
const event = new KeyboardEvent('keydown', { bubbles: true, key });
Object.defineProperty(event, 'target', {
configurable: true,
value: target,
});
return event;
};
const createReactKeyboardEvent = (
nativeEvent: KeyboardEvent
): React.KeyboardEvent<HTMLElement> => {
const preventDefault = jest.fn();
return {
key: nativeEvent.key,
nativeEvent,
preventDefault,
isDefaultPrevented: () => preventDefault.mock.calls.length > 0,
target: nativeEvent.target,
} as unknown as React.KeyboardEvent<HTMLElement>;
};
const createMoveFocusEvent = (
relatedEvent: KeyboardEvent,
owner: HTMLElement
): CustomEvent<TreeGridTabsterMoveFocusEventDetail> => {
return new CustomEvent<TreeGridTabsterMoveFocusEventDetail>(
'tabstermovefocus',
{
cancelable: true,
detail: { owner, relatedEvent },
}
);
};
describe('useTreeGridLevelNavigation', () => {
afterEach(() => {
document.body.innerHTML = '';
});
it('focuses the next row at the same level', () => {
const { result } = renderHook(() => useTreeGridLevelNavigation());
const treeGrid = createTreeGrid();
const currentRow = createWrappedRow(2, treeGrid);
createWrappedRow(3, treeGrid);
const nextRow = createWrappedRow(2, treeGrid);
const nativeEvent = createKeyboardEvent(ArrowDown, currentRow);
const keyboardEvent = createReactKeyboardEvent(nativeEvent);
result.current.onKeyDown(keyboardEvent);
expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(nextRow.scrollIntoView).toHaveBeenCalledWith({ block: 'nearest' });
expect(nextRow).toBe(document.activeElement);
});
it('allows shallower-boundary navigation to fall through', () => {
const { result } = renderHook(() => useTreeGridLevelNavigation());
const treeGrid = createTreeGrid();
const parentRow = createWrappedRow(1, treeGrid);
const currentRow = createWrappedRow(2, treeGrid);
const nativeEvent = createKeyboardEvent(ArrowUp, currentRow);
const keyboardEvent = createReactKeyboardEvent(nativeEvent);
const moveFocusEvent = createMoveFocusEvent(nativeEvent, parentRow);
result.current.onTabsterMoveFocus(moveFocusEvent);
result.current.onKeyDown(keyboardEvent);
expect(moveFocusEvent.defaultPrevented).toBe(false);
expect(keyboardEvent.preventDefault).not.toHaveBeenCalled();
});
it('skips wrapper elements when finding adjacent rows', () => {
const { result } = renderHook(() => useTreeGridLevelNavigation());
const treeGrid = createTreeGrid();
const currentRow = createWrappedRow(1, treeGrid);
const nextRow = createWrappedRow(1, treeGrid);
const nativeEvent = createKeyboardEvent(ArrowDown, currentRow);
const keyboardEvent = createReactKeyboardEvent(nativeEvent);
result.current.onKeyDown(keyboardEvent);
expect(keyboardEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(nextRow.scrollIntoView).toHaveBeenCalledWith({ block: 'nearest' });
expect(nextRow).toBe(document.activeElement);
});
});