Skip to content

docs(material/tree): add harness example for tree #21082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/components-examples/material/tree/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ ng_module(
]),
module_name = "@angular/components-examples/material/tree",
deps = [
"//src/cdk/testing",
"//src/cdk/testing/testbed",
"//src/material/button",
"//src/material/checkbox",
"//src/material/icon",
"//src/material/input",
"//src/material/progress-bar",
"//src/material/tree",
"//src/material/tree/testing",
"@npm//@angular/platform-browser",
"@npm//@angular/platform-browser-dynamic",
"@npm//@types/jasmine",
],
)

Expand Down
3 changes: 3 additions & 0 deletions src/components-examples/material/tree/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import {MatTreeModule} from '@angular/material/tree';
import {TreeChecklistExample} from './tree-checklist/tree-checklist-example';
import {TreeDynamicExample} from './tree-dynamic/tree-dynamic-example';
import {TreeFlatOverviewExample} from './tree-flat-overview/tree-flat-overview-example';
import {TreeHarnessExample} from './tree-harness/tree-harness-example';
import {TreeLoadmoreExample} from './tree-loadmore/tree-loadmore-example';
import {TreeNestedOverviewExample} from './tree-nested-overview/tree-nested-overview-example';

export {
TreeChecklistExample,
TreeDynamicExample,
TreeFlatOverviewExample,
TreeHarnessExample,
TreeLoadmoreExample,
TreeNestedOverviewExample,
};
Expand All @@ -24,6 +26,7 @@ const EXAMPLES = [
TreeChecklistExample,
TreeDynamicExample,
TreeFlatOverviewExample,
TreeHarnessExample,
TreeLoadmoreExample,
TreeNestedOverviewExample,
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!-- This is the tree node template for leaf nodes -->
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>
<!-- use a disabled button to provide padding for tree leaf -->
<button mat-icon-button disabled></button>
{{node.name}}
</mat-tree-node>
<!-- This is the tree node template for expandable nodes -->
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>
<button mat-icon-button matTreeNodeToggle
[attr.aria-label]="'Toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
{{node.name}}
</mat-tree-node>
</mat-tree>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {TestBed, ComponentFixture, waitForAsync} from '@angular/core/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {MatTreeHarness} from '@angular/material/tree/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting}
from '@angular/platform-browser-dynamic/testing';
import {MatTreeModule} from '@angular/material/tree';
import {TreeHarnessExample} from './tree-harness-example';
import {MatIconModule} from '@angular/material/icon';

describe('TreeHarnessExample', () => {
let fixture: ComponentFixture<TreeHarnessExample>;
let loader: HarnessLoader;

beforeAll(() => {
TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
});

beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [MatTreeModule, MatIconModule],
declarations: [TreeHarnessExample]
}).compileComponents();
fixture = TestBed.createComponent(TreeHarnessExample);
fixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(fixture);
})
);

it('should get correct number of children and descendants', async () => {
const tree = await loader.getHarness(MatTreeHarness);
const treeDescendants = await tree.getNodes();

// flat nodes are not rendered until expanded
expect(treeDescendants.length).toBe(2);

await treeDescendants[0].expand();

expect((await tree.getNodes()).length).toBe(5);
});

it('should correctly get correct node with text', async () => {
const tree = await loader.getHarness(MatTreeHarness);
const treeNodes = await tree.getNodes({text: /Flat Group/});
expect(treeNodes.length).toBe(2);
const secondGroup = treeNodes[0];

expect(await secondGroup.getText()).toBe('Flat Group 1');
expect(await secondGroup.getLevel()).toBe(1);
expect(await secondGroup.isDisabled()).toBe(false);
expect(await secondGroup.isExpanded()).toBe(false);
});

it ('should correctly get tree structure', async () => {
const tree = await loader.getHarness(MatTreeHarness);

expect(await tree.getTreeStructure()).toEqual({
children: [
{text: 'Flat Group 1'},
{text: 'Flat Group 2'}
]
});

const firstGroup = (await tree.getNodes({text: /Flat Group 1/}))[0];
await firstGroup.expand();

expect(await tree.getTreeStructure()).toEqual({
children: [
{
text: 'Flat Group 1',
children: [
{text: 'Flat Leaf 1.1'},
{text: 'Flat Leaf 1.2'},
{text: 'Flat Leaf 1.3'}
]
},
{text: 'Flat Group 2'}
]
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {FlatTreeControl} from '@angular/cdk/tree';
import {Component} from '@angular/core';
import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';

interface Node {
name: string;
children?: Node[];
}

const FLAT_TREE_DATA: Node[] = [
{
name: 'Flat Group 1',
children: [
{name: 'Flat Leaf 1.1'},
{name: 'Flat Leaf 1.2'},
{name: 'Flat Leaf 1.3'},
]
}, {
name: 'Flat Group 2',
children: [
{
name: 'Flat Group 2.1',
children: [
{name: 'Flat Leaf 2.1.1'},
{name: 'Flat Leaf 2.1.2'},
{name: 'Flat Leaf 2.1.3'},
]
}
]
},
];

interface ExampleFlatNode {
expandable: boolean;
name: string;
level: number;
}

/**
* @title Testing with MatTreeHarness
*/
@Component({
selector: 'tree-harness-example',
templateUrl: 'tree-harness-example.html',
})
export class TreeHarnessExample {
private _transformer = (node: Node, level: number) => {
return {
expandable: !!node.children && node.children.length > 0,
name: node.name,
level: level,
};
}

treeControl = new FlatTreeControl<ExampleFlatNode>(
node => node.level, node => node.expandable);

treeFlattener = new MatTreeFlattener(
this._transformer, node => node.level, node => node.expandable, node => node.children);

dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

constructor() {
this.dataSource.data = FLAT_TREE_DATA;
}

hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
}