Skip to content

Commit be10b97

Browse files
committed
test(pivot): column & row headers activedescendant
1 parent da75100 commit be10b97

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-keyboard-nav.spec.ts

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,25 @@ import { IgxPivotGridMultipleRowComponent, IgxPivotGridTestBaseComponent } from
66
import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec';
77
import { IgxPivotGridComponent } from './pivot-grid.component';
88
import { IgxPivotRowDimensionHeaderComponent } from './pivot-row-dimension-header.component';
9+
import { DebugElement } from '@angular/core';
10+
import { IgxPivotHeaderRowComponent } from './pivot-header-row.component';
11+
import { PivotRowLayoutType } from 'igniteui-angular';
912

1013
const DEBOUNCE_TIME = 250;
1114
const PIVOT_TBODY_CSS_CLASS = '.igx-grid__tbody';
1215
const PIVOT_ROW_DIMENSION_CONTENT = 'igx-pivot-row-dimension-content';
1316
const PIVOT_HEADER_ROW = 'igx-pivot-header-row';
1417
const HEADER_CELL_CSS_CLASS = '.igx-grid-th';
1518
const ACTIVE_CELL_CSS_CLASS = '.igx-grid-th--active';
19+
const CSS_CLASS_ROW_DIMENSION_CONTAINER = '.igx-grid__tbody-pivot-dimension'
20+
const CSS_CLASS_TBODY_CONTENT = '.igx-grid__tbody-content';
1621

1722
describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
1823
describe('General Keyboard Navigation', () => {
1924
let fixture: ComponentFixture<IgxPivotGridMultipleRowComponent>;
2025
let pivotGrid: IgxPivotGridComponent;
26+
let rowDimension: DebugElement;
27+
let headerRow: DebugElement;
2128

2229
beforeEach(waitForAsync(() => {
2330
TestBed.configureTestingModule({
@@ -28,10 +35,14 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
2835
}).compileComponents();
2936
}));
3037

31-
beforeEach(fakeAsync(() => {
38+
beforeEach(fakeAsync(async () => {
3239
fixture = TestBed.createComponent(IgxPivotGridMultipleRowComponent);
3340
fixture.detectChanges();
3441
pivotGrid = fixture.componentInstance.pivotGrid;
42+
await fixture.whenStable();
43+
rowDimension = fixture.debugElement.query(
44+
By.css(CSS_CLASS_ROW_DIMENSION_CONTAINER));
45+
headerRow = fixture.debugElement.query(By.directive(IgxPivotHeaderRowComponent));
3546
}));
3647

3748
it('should allow navigating between row headers', () => {
@@ -43,24 +54,32 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
4354
fixture.detectChanges();
4455

4556
GridFunctions.verifyHeaderIsFocused(firstCell.parent);
46-
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
57+
// for the row dimensions headers, the active descendant is set on the div having
58+
// tabindex="0" and class '.igx-grid__tbody-pivot-dimension';
59+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, firstCell.nativeElement.id);
60+
expect(firstCell.nativeElement.getAttribute('role')).toBe('rowheader');
61+
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
4762
expect(activeCells.length).toBe(1);
4863

4964
UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', firstCell.nativeElement);
5065
fixture.detectChanges();
5166
GridFunctions.verifyHeaderIsFocused(secondCell.parent);
67+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, secondCell.nativeElement.id);
68+
expect(firstCell.nativeElement.getAttribute('role')).toBe('rowheader');
5269
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
5370
expect(activeCells.length).toBe(1);
5471

5572
// should do nothing if wrong key is pressed
5673
UIInteractions.simulateClickAndSelectEvent(firstCell);
5774
fixture.detectChanges();
5875
GridFunctions.verifyHeaderIsFocused(firstCell.parent);
76+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, firstCell.nativeElement.id);
5977
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
6078
expect(activeCells.length).toBe(1);
6179
UIInteractions.triggerKeyDownEvtUponElem('h', firstCell.nativeElement);
6280
fixture.detectChanges();
6381
GridFunctions.verifyHeaderIsFocused(firstCell.parent);
82+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, firstCell.nativeElement.id);
6483
});
6584

6685
it('should not go outside of the boundaries of the row dimensions content', () => {
@@ -75,6 +94,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
7594
fixture.detectChanges();
7695

7796
GridFunctions.verifyHeaderIsFocused(firstCell.parent);
97+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, firstCell.nativeElement.id);
7898
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
7999
expect(activeCells.length).toBe(1);
80100

@@ -85,6 +105,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
85105
fixture.detectChanges();
86106

87107
GridFunctions.verifyHeaderIsFocused(thirdCell.parent);
108+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, thirdCell.nativeElement.id);
88109
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
89110
expect(activeCells.length).toBe(1);
90111
});
@@ -100,12 +121,14 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
100121
UIInteractions.triggerKeyDownEvtUponElem('End', firstCell.nativeElement);
101122
fixture.detectChanges();
102123
GridFunctions.verifyHeaderIsFocused(thirdCell.parent);
124+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, thirdCell.nativeElement.id);
103125
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
104126
expect(activeCells.length).toBe(1);
105127

106128
UIInteractions.triggerKeyDownEvtUponElem('Home', thirdCell.nativeElement);
107129
fixture.detectChanges();
108130
GridFunctions.verifyHeaderIsFocused(firstCell.parent);
131+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, firstCell.nativeElement.id);
109132
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
110133
expect(activeCells.length).toBe(1);
111134
});
@@ -124,6 +147,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
124147
By.directive(IgxPivotRowDimensionHeaderComponent));
125148
const lastCell = allGroups[allGroups.length - 1];
126149
GridFunctions.verifyHeaderIsFocused(lastCell.parent);
150+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, lastCell.nativeElement.id);
127151
const activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
128152
expect(activeCells.length).toBe(1);
129153
});
@@ -143,6 +167,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
143167
By.directive(IgxPivotRowDimensionHeaderComponent));
144168
const firstCell = allGroups[0];
145169
GridFunctions.verifyHeaderIsFocused(firstCell.parent);
170+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, firstCell.nativeElement.id);
146171
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
147172
expect(activeCells.length).toBe(1);
148173

@@ -156,6 +181,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
156181
By.directive(IgxPivotRowDimensionHeaderComponent));
157182
const secondCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[1];
158183
GridFunctions.verifyHeaderIsFocused(secondCell.parent);
184+
GridFunctions.verifyPivotElementActiveDescendant(rowDimension, secondCell.nativeElement.id);
159185
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
160186
expect(activeCells.length).toBe(1);
161187

@@ -170,7 +196,9 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
170196
firstHeader = fixture.debugElement.queryAll(
171197
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0];
172198
GridFunctions.verifyHeaderIsFocused(firstHeader.parent);
173-
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
199+
// for the column headers, the active descendant is set on the header row element
200+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, firstHeader.nativeElement.id);
201+
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
174202
expect(activeCells.length).toBe(1);
175203

176204
UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', pivotGrid.theadRow.nativeElement);
@@ -179,6 +207,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
179207
const secondHeader = fixture.debugElement.queryAll(
180208
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1];
181209
GridFunctions.verifyHeaderIsFocused(secondHeader.parent);
210+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, secondHeader.nativeElement.id);
182211
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
183212
expect(activeCells.length).toBe(1);
184213
});
@@ -193,6 +222,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
193222
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0];
194223

195224
GridFunctions.verifyHeaderIsFocused(firstHeader.parent);
225+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, firstHeader.nativeElement.id);
196226
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
197227
expect(activeCells.length).toBe(1);
198228

@@ -204,6 +234,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
204234
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`));
205235
const lastHeader = allHeaders[allHeaders.length - 1];
206236
GridFunctions.verifyHeaderIsFocused(lastHeader.parent);
237+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, lastHeader.nativeElement.id);
207238
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
208239
expect(activeCells.length).toBe(1);
209240
});
@@ -222,20 +253,58 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
222253
firstHeader = fixture.debugElement.queryAll(
223254
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0];
224255
GridFunctions.verifyHeaderIsFocused(firstHeader.parent);
225-
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
256+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, firstHeader.nativeElement.id);
257+
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
226258
expect(activeCells.length).toBe(1);
227259

228260
UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', firstHeader.nativeElement);
229261
fixture.detectChanges();
230262
const secondHeader = fixture.debugElement.queryAll(
231263
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1];
232264
GridFunctions.verifyHeaderIsFocused(secondHeader.parent);
265+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, secondHeader.nativeElement.id);
266+
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
267+
expect(activeCells.length).toBe(1);
268+
});
269+
270+
it('should navigate properly among row dimension column headers for horizontal row layout', () => {
271+
pivotGrid.pivotUI = {
272+
...pivotGrid.pivotUI,
273+
rowLayout: PivotRowLayoutType.Horizontal,
274+
showRowHeaders: true
275+
};
276+
fixture.detectChanges();
277+
278+
let firstHeader = fixture.debugElement.queryAll(
279+
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0];
280+
UIInteractions.simulateClickAndSelectEvent(firstHeader);
281+
fixture.detectChanges();
282+
283+
firstHeader = fixture.debugElement.queryAll(
284+
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0];
285+
GridFunctions.verifyHeaderIsFocused(firstHeader.parent);
286+
// for the row dimensions column headers in horizontal layout,
287+
// the active descendant is set on the header row element.
288+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, firstHeader.nativeElement.id);
289+
expect(firstHeader.nativeElement.getAttribute('role')).toBe('columnheader');
290+
let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
291+
expect(activeCells.length).toBe(1);
292+
293+
UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', pivotGrid.theadRow.nativeElement);
294+
fixture.detectChanges();
295+
296+
const secondHeader = fixture.debugElement.queryAll(
297+
By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1];
298+
GridFunctions.verifyHeaderIsFocused(secondHeader.parent);
299+
GridFunctions.verifyPivotElementActiveDescendant(headerRow, secondHeader.nativeElement.id);
300+
expect(firstHeader.nativeElement.getAttribute('role')).toBe('columnheader');
233301
activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`));
234302
expect(activeCells.length).toBe(1);
235303
});
236304

237305
it('should allow navigating within the cells of the body', async () => {
238306
const cell = pivotGrid.rowList.first.cells.first;
307+
const tBodyContent = fixture.debugElement.query(By.css(CSS_CLASS_TBODY_CONTENT));
239308
GridFunctions.focusFirstCell(fixture, pivotGrid);
240309
fixture.detectChanges();
241310
expect(pivotGrid.navigation.activeNode.row).toBeUndefined();
@@ -248,8 +317,11 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
248317
fixture.detectChanges();
249318
expect(pivotGrid.navigation.activeNode.row).toBeDefined();
250319
expect(pivotGrid.navigation.activeNode.column).toBeDefined();
320+
// The activedescendant attribute for cells in the grid body
321+
// is set on the tbody content div with tabindex='0'
322+
GridFunctions.verifyPivotElementActiveDescendant(tBodyContent, cell.nativeElement.id);
251323

252-
let activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`));
324+
let activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`));
253325
expect(activeCells.length).toBe(1);
254326
expect(cell.column.field).toEqual('Stanley-UnitsSold');
255327

@@ -261,6 +333,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
261333
activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`));
262334
expect(activeCells.length).toBe(1);
263335
expect(activeCells[0].componentInstance.column.field).toEqual('Stanley-UnitPrice')
336+
GridFunctions.verifyPivotElementActiveDescendant(tBodyContent, activeCells[0].nativeElement.id);
264337
});
265338
});
266339
describe('Row Dimension Expand/Collapse Keyboard Interactions', () => {
@@ -282,7 +355,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => {
282355

283356
it('should allow row dimension expand(Alt + ArrowDown/ArrowRight) and collapse(Alt + ArrowUp/ArrowLeft)', async () => {
284357
const rowDimension = fixture.debugElement.queryAll(
285-
By.css(`.igx-grid__tbody-pivot-dimension`));
358+
By.css(CSS_CLASS_ROW_DIMENSION_CONTAINER));
286359
let allHeaders = fixture.debugElement.queryAll(
287360
By.directive(IgxPivotRowDimensionHeaderComponent));
288361

projects/igniteui-angular/src/lib/test-utils/grid-functions.spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,11 @@ export class GridFunctions {
273273
expect(header.nativeElement.classList.contains(ACTIVE_HEADER_CLASS)).toBe(focused);
274274
}
275275

276+
public static verifyPivotElementActiveDescendant(elem: DebugElement, id: string): void {
277+
const activeDescendant = elem.nativeElement.getAttribute('aria-activedescendant');
278+
expect(activeDescendant).toBe(id);
279+
}
280+
276281
public static verifyHeaderActiveDescendant(headerRow: IgxGridHeaderRowComponent, id: string): void {
277282
const headerRowElem = headerRow.nativeElement;
278283
expect(headerRow.activeDescendant).toBe(id);
@@ -1822,7 +1827,7 @@ export class GridSummaryFunctions {
18221827
}
18231828
export class GridSelectionFunctions {
18241829
public static selectCellsRange =
1825-
async (fix, startCell, endCell, ctrl = false, shift = false) => {
1830+
async (fix, startCell, endCell, ctrl = false, shift = false) => {
18261831
UIInteractions.simulatePointerOverElementEvent('pointerdown', startCell.nativeElement, shift, ctrl);
18271832
fix.detectChanges();
18281833
await wait();

0 commit comments

Comments
 (0)