Skip to content

Commit

Permalink
refactor(material/tree): add unit tests for opt-out (#28237)
Browse files Browse the repository at this point in the history
Add unit tests to cover the use of LegacyTreeKeyManager, which opts out
of updated focus management behavior.
  • Loading branch information
zarend authored Dec 6, 2023
1 parent ab5cb56 commit ee50445
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/cdk/tree/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ ng_test_library(
),
deps = [
":tree",
"//src/cdk/a11y",
"//src/cdk/bidi",
"//src/cdk/collections",
"//src/cdk/keycodes",
Expand Down
92 changes: 92 additions & 0 deletions src/cdk/tree/tree-using-legacy-key-manager.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {Component, ElementRef, QueryList, ViewChild, ViewChildren} from '@angular/core';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {of} from 'rxjs';
import {CdkTreeModule} from './tree-module';
import {NOOP_TREE_KEY_MANAGER_FACTORY_PROVIDER} from '@angular/cdk/a11y';

describe('CdkTree when provided LegacyTreeKeyManager', () => {
let fixture: ComponentFixture<SimpleCdkTreeApp>;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [CdkTreeModule],
declarations: [SimpleCdkTreeApp],
providers: [NOOP_TREE_KEY_MANAGER_FACTORY_PROVIDER],
}).compileComponents();

fixture = TestBed.createComponent(SimpleCdkTreeApp);
fixture.detectChanges();
});

describe('with default node options', () => {
it('renders nodes with tabindex attribute of -1', () => {
const treeItems = fixture.componentInstance.treeNodes;

expect(treeItems.map(x => `${x.nativeElement.getAttribute('tabindex')}`).join(', '))
.withContext('tabindex of tree nodes')
.toEqual('-1, -1');
});
});

describe('when focusing the second node', () => {
beforeEach(() => {
const treeItems = fixture.componentInstance.treeNodes;

treeItems.get(1)!.nativeElement.focus();
fixture.detectChanges();
});

it('does not change tabindex of nodes', () => {
const treeItems = fixture.componentInstance.treeNodes;

expect(treeItems.map(x => `${x.nativeElement.getAttribute('tabindex')}`).join(', '))
.withContext('tabindex of tree nodes')
.toEqual('-1, -1');
});
});

describe('when clicking the second node', () => {
beforeEach(() => {
const treeItems = fixture.componentInstance.treeNodes;

treeItems.get(1)!.nativeElement.click();
fixture.detectChanges();
});

it('does not change active element', () => {
expect(document.activeElement).toEqual(document.body);
});

it('does not change tabindex of nodes', () => {
const treeItems = fixture.componentInstance.treeNodes;

expect(treeItems.map(x => `${x.nativeElement.getAttribute('tabindex')}`).join(', '))
.withContext('tabindex of tree nodes')
.toEqual('-1, -1');
});
});
});

class MinimalTestData {
constructor(public name: string) {}
children: MinimalTestData[] = [];
}

@Component({
template: `
<cdk-tree #tree [dataSource]="dataSource" [childrenAccessor]="getChildren">
<cdk-tree-node #node *cdkTreeNodeDef="let node">
{{node.name}}
</cdk-tree-node>
</cdk-tree>
`,
})
class SimpleCdkTreeApp {
isExpandable = (node: MinimalTestData) => node.children.length > 0;
getChildren = (node: MinimalTestData) => node.children;

dataSource = of([new MinimalTestData('apple'), new MinimalTestData('banana')]);

@ViewChild('tree', {read: ElementRef}) tree: ElementRef<HTMLElement>;
@ViewChildren('node') treeNodes: QueryList<ElementRef<HTMLElement>>;
}
2 changes: 2 additions & 0 deletions src/material/tree/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ ng_test_library(
deps = [
":tree",
"//src/cdk/a11y",
"//src/cdk/keycodes",
"//src/cdk/testing/private",
"//src/cdk/tree",
"@npm//rxjs",
],
Expand Down
38 changes: 32 additions & 6 deletions src/material/tree/tree-using-legacy-key-manager.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {Component, ElementRef, QueryList, ViewChild, ViewChildren} from '@angular/core';
import {of} from 'rxjs';
import {MatTree} from './tree';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {MatTreeModule} from './tree-module';
import {NOOP_TREE_KEY_MANAGER_FACTORY_PROVIDER} from '@angular/cdk/a11y';
import {DOWN_ARROW} from '@angular/cdk/keycodes';
import {createKeyboardEvent} from '@angular/cdk/testing/private';

describe('MatTree when provided LegacyTreeKeyManager', () => {
let fixture: ComponentFixture<SimpleMatTreeApp>;
Expand All @@ -19,7 +20,7 @@ describe('MatTree when provided LegacyTreeKeyManager', () => {
fixture.detectChanges();
});

describe('when nodes do not have a tabindex set', () => {
describe('when nodes have default options', () => {
it('Should render tabindex attribute of 0', () => {
const treeItems = fixture.componentInstance.treeNodes;

Expand All @@ -30,10 +31,12 @@ describe('MatTree when provided LegacyTreeKeyManager', () => {
});

describe('when nodes have TabIndex Input binding of 42', () => {
it('Should render tabindex attribute of 42.', () => {
beforeEach(() => {
fixture.componentInstance.tabIndexInputBinding = 42;
fixture.detectChanges();
});

it('Should render tabindex attribute of 42.', () => {
const treeItems = fixture.componentInstance.treeNodes;

expect(treeItems.map(x => `${x.nativeElement.getAttribute('tabindex')}`).join(', '))
Expand All @@ -43,17 +46,40 @@ describe('MatTree when provided LegacyTreeKeyManager', () => {
});

describe('when nodes have tabindex attribute binding of 2', () => {
it('should render tabindex attribute of 2', () => {
beforeEach(() => {
fixture.componentInstance.tabindexAttributeBinding = '2';
fixture.detectChanges();
});

it('should render tabindex attribute of 2', () => {
const treeItems = fixture.componentInstance.treeNodes;

expect(treeItems.map(x => `${x.nativeElement.getAttribute('tabindex')}`).join(', '))
.withContext('tabindex of tree nodes')
.toEqual('2, 2, 2');
});
});

describe('when pressing down arrow key', () => {
beforeEach(() => {
const treeElement = fixture.componentInstance.tree.nativeElement;

treeElement.dispatchEvent(createKeyboardEvent('keydown', DOWN_ARROW, 'down'));
fixture.detectChanges();
});

it('should not change the active element', () => {
expect(document.activeElement).toEqual(document.body);
});

it('should not change the tabindex of tree nodes', () => {
const treeItems = fixture.componentInstance.treeNodes;

expect(treeItems.map(x => `${x.nativeElement.getAttribute('tabindex')}`).join(', '))
.withContext('tabindex of tree nodes')
.toEqual('0, 0, 0');
});
});
});

class MinimalTestData {
Expand All @@ -63,7 +89,7 @@ class MinimalTestData {

@Component({
template: `
<mat-tree [dataSource]="dataSource" [childrenAccessor]="getChildren">
<mat-tree #tree [dataSource]="dataSource" [childrenAccessor]="getChildren">
<mat-tree-node #node *matTreeNodeDef="let node"
[tabIndex]="tabIndexInputBinding" tabindex="{{tabindexAttributeBinding}}">
{{node.name}}
Expand All @@ -86,6 +112,6 @@ class SimpleMatTreeApp {
/** Value passed to tabindex attribute binding of each tree node. Null by default. */
tabindexAttributeBinding: string | null = null;

@ViewChild(MatTree) tree: MatTree<MinimalTestData>;
@ViewChild('tree', {read: ElementRef}) tree: ElementRef<HTMLElement>;
@ViewChildren('node') treeNodes: QueryList<ElementRef<HTMLElement>>;
}

0 comments on commit ee50445

Please sign in to comment.