288 lines
8.9 KiB
TypeScript
288 lines
8.9 KiB
TypeScript
|
|
import {Component} from '@angular/core';
|
||
|
|
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||
|
|
import {FlatTreeControl, NestedTreeControl} from '@angular/cdk/tree';
|
||
|
|
import {
|
||
|
|
MatTreeFlatDataSource,
|
||
|
|
MatTreeFlattener,
|
||
|
|
MatTreeModule,
|
||
|
|
MatTreeNestedDataSource,
|
||
|
|
} from '@angular/material/tree';
|
||
|
|
import {HarnessLoader} from '@angular/cdk/testing';
|
||
|
|
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
|
||
|
|
import {MatTreeHarness} from './tree-harness';
|
||
|
|
|
||
|
|
describe('MatTreeHarness', () => {
|
||
|
|
let fixture: ComponentFixture<TreeHarnessTest>;
|
||
|
|
let loader: HarnessLoader;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
TestBed.configureTestingModule({
|
||
|
|
imports: [MatTreeModule, TreeHarnessTest],
|
||
|
|
});
|
||
|
|
|
||
|
|
fixture = TestBed.createComponent(TreeHarnessTest);
|
||
|
|
fixture.detectChanges();
|
||
|
|
loader = TestbedHarnessEnvironment.loader(fixture);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should load harness with 2 tress', async () => {
|
||
|
|
const trees = await loader.getAllHarnesses(MatTreeHarness);
|
||
|
|
|
||
|
|
expect(trees.length).toBe(2);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should get correct number of children and descendants', async () => {
|
||
|
|
const trees = await loader.getAllHarnesses(MatTreeHarness);
|
||
|
|
const flatTree = trees[0];
|
||
|
|
const nestedTree = trees[1];
|
||
|
|
const flatTreeDescendants = await flatTree.getNodes();
|
||
|
|
const nestedDescendants = await nestedTree.getNodes();
|
||
|
|
|
||
|
|
// flat nodes are not rendered until expanded
|
||
|
|
expect(flatTreeDescendants.length).toBe(2);
|
||
|
|
|
||
|
|
await flatTreeDescendants[0].expand();
|
||
|
|
|
||
|
|
expect((await flatTree.getNodes()).length).toBe(5);
|
||
|
|
|
||
|
|
expect(nestedDescendants.length).toBe(8);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should correctly get correct node with text (flat tree)', async () => {
|
||
|
|
const trees = await loader.getAllHarnesses(MatTreeHarness);
|
||
|
|
const flatTree = trees[0];
|
||
|
|
const flatTreeNodes = await flatTree.getNodes({text: /Flat Group/});
|
||
|
|
expect(flatTreeNodes.length).toBe(2);
|
||
|
|
const secondGroup = flatTreeNodes[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 correct node with text (nested tree)', async () => {
|
||
|
|
const trees = await loader.getAllHarnesses(MatTreeHarness);
|
||
|
|
const nestedTree = trees[1];
|
||
|
|
const nestedTreeNodes = await nestedTree.getNodes({text: /2./});
|
||
|
|
expect(nestedTreeNodes.length).toBe(3);
|
||
|
|
const thirdGroup = nestedTreeNodes[1];
|
||
|
|
|
||
|
|
expect(await thirdGroup.getText()).toBe('Nested Leaf 2.1.1');
|
||
|
|
expect(await thirdGroup.getLevel()).toBe(3);
|
||
|
|
expect(await thirdGroup.isDisabled()).toBe(false);
|
||
|
|
expect(await thirdGroup.isExpanded()).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should toggle expansion', async () => {
|
||
|
|
const trees = await loader.getAllHarnesses(MatTreeHarness);
|
||
|
|
const nestedTree = trees[1];
|
||
|
|
const nestedTreeNodes = await nestedTree.getNodes();
|
||
|
|
const firstGroup = nestedTreeNodes[0];
|
||
|
|
|
||
|
|
expect(await firstGroup.isExpanded()).toBe(false);
|
||
|
|
await firstGroup.expand();
|
||
|
|
expect(await firstGroup.isExpanded()).toBe(true);
|
||
|
|
await firstGroup.expand();
|
||
|
|
// no-op if already expanded
|
||
|
|
expect(await firstGroup.isExpanded()).toBe(true);
|
||
|
|
await firstGroup.collapse();
|
||
|
|
expect(await firstGroup.isExpanded()).toBe(false);
|
||
|
|
await firstGroup.collapse();
|
||
|
|
// no-op if already collapsed
|
||
|
|
expect(await firstGroup.isExpanded()).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should correctly get tree structure', async () => {
|
||
|
|
const trees = await loader.getAllHarnesses(MatTreeHarness);
|
||
|
|
const flatTree = trees[0];
|
||
|
|
|
||
|
|
expect(await flatTree.getTreeStructure()).toEqual({
|
||
|
|
children: [{text: 'Flat Group 1'}, {text: 'Flat Group 2'}],
|
||
|
|
});
|
||
|
|
|
||
|
|
const firstGroup = (await flatTree.getNodes({text: /Flat Group 1/}))[0];
|
||
|
|
await firstGroup.expand();
|
||
|
|
|
||
|
|
expect(await flatTree.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'},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
|
||
|
|
const secondGroup = (await flatTree.getNodes({text: /Flat Group 2/}))[0];
|
||
|
|
await secondGroup.expand();
|
||
|
|
|
||
|
|
expect(await flatTree.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',
|
||
|
|
children: [{text: 'Flat Group 2.1'}],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should correctly get tree structure', async () => {
|
||
|
|
const trees = await loader.getAllHarnesses(MatTreeHarness);
|
||
|
|
const nestedTree = trees[1];
|
||
|
|
expect(await nestedTree.getTreeStructure()).toEqual({
|
||
|
|
children: [{text: 'Nested Group 1'}, {text: 'Nested Group 2'}],
|
||
|
|
});
|
||
|
|
|
||
|
|
const firstGroup = (await nestedTree.getNodes({text: /Nested Group 1/}))[0];
|
||
|
|
await firstGroup.expand();
|
||
|
|
expect(await nestedTree.getTreeStructure()).toEqual({
|
||
|
|
children: [
|
||
|
|
{
|
||
|
|
text: 'Nested Group 1',
|
||
|
|
children: [
|
||
|
|
{text: 'Nested Leaf 1.1'},
|
||
|
|
{text: 'Nested Leaf 1.2'},
|
||
|
|
{text: 'Nested Leaf 1.3'},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
{text: 'Nested Group 2'},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
|
||
|
|
const secondGroup = (await nestedTree.getNodes({text: /Nested Group 2/}))[0];
|
||
|
|
await secondGroup.expand();
|
||
|
|
expect(await nestedTree.getTreeStructure()).toEqual({
|
||
|
|
children: [
|
||
|
|
{
|
||
|
|
text: 'Nested Group 1',
|
||
|
|
children: [
|
||
|
|
{text: 'Nested Leaf 1.1'},
|
||
|
|
{text: 'Nested Leaf 1.2'},
|
||
|
|
{text: 'Nested Leaf 1.3'},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text: 'Nested Group 2',
|
||
|
|
children: [{text: 'Nested Group 2.1'}],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
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'}],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
const NESTED_TREE_DATA: Node[] = [
|
||
|
|
{
|
||
|
|
name: 'Nested Group 1',
|
||
|
|
children: [{name: 'Nested Leaf 1.1'}, {name: 'Nested Leaf 1.2'}, {name: 'Nested Leaf 1.3'}],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: 'Nested Group 2',
|
||
|
|
children: [
|
||
|
|
{
|
||
|
|
name: 'Nested Group 2.1',
|
||
|
|
children: [{name: 'Nested Leaf 2.1.1'}, {name: 'Nested Leaf 2.1.2'}],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
interface ExampleFlatNode {
|
||
|
|
expandable: boolean;
|
||
|
|
name: string;
|
||
|
|
level: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
@Component({
|
||
|
|
template: `
|
||
|
|
<mat-tree [dataSource]="flatTreeDataSource" [treeControl]="flatTreeControl">
|
||
|
|
<!-- This is the tree node template for leaf nodes -->
|
||
|
|
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>
|
||
|
|
{{node.name}}
|
||
|
|
</mat-tree-node>
|
||
|
|
<!-- This is the tree node template for expandable nodes -->
|
||
|
|
<mat-tree-node *matTreeNodeDef="let node;when: flatTreeHasChild" matTreeNodePadding isExpandable>
|
||
|
|
<button matTreeNodeToggle>
|
||
|
|
Toggle
|
||
|
|
</button>
|
||
|
|
{{node.name}}
|
||
|
|
</mat-tree-node>
|
||
|
|
</mat-tree>
|
||
|
|
<mat-tree [dataSource]="nestedTreeDataSource" [treeControl]="nestedTreeControl">
|
||
|
|
<!-- This is the tree node template for leaf nodes -->
|
||
|
|
<mat-nested-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
|
||
|
|
{{node.name}}
|
||
|
|
</mat-nested-tree-node>
|
||
|
|
<!-- This is the tree node template for expandable nodes -->
|
||
|
|
<mat-nested-tree-node *matTreeNodeDef="let node; when: nestedTreeHasChild" isExpandable>
|
||
|
|
<button matTreeNodeToggle>
|
||
|
|
Toggle
|
||
|
|
</button>
|
||
|
|
{{node.name}}
|
||
|
|
<ul [class.example-tree-invisible]="!nestedTreeControl.isExpanded(node)">
|
||
|
|
<ng-container matTreeNodeOutlet></ng-container>
|
||
|
|
</ul>
|
||
|
|
</mat-nested-tree-node>
|
||
|
|
</mat-tree>
|
||
|
|
`,
|
||
|
|
standalone: true,
|
||
|
|
imports: [MatTreeModule],
|
||
|
|
})
|
||
|
|
class TreeHarnessTest {
|
||
|
|
private _transformer = (node: Node, level: number) => {
|
||
|
|
return {
|
||
|
|
expandable: !!node.children && node.children.length > 0,
|
||
|
|
name: node.name,
|
||
|
|
level: level,
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
treeFlattener = new MatTreeFlattener(
|
||
|
|
this._transformer,
|
||
|
|
node => node.level,
|
||
|
|
node => node.expandable,
|
||
|
|
node => node.children,
|
||
|
|
);
|
||
|
|
flatTreeControl = new FlatTreeControl<ExampleFlatNode>(
|
||
|
|
node => node.level,
|
||
|
|
node => node.expandable,
|
||
|
|
);
|
||
|
|
flatTreeDataSource = new MatTreeFlatDataSource(this.flatTreeControl, this.treeFlattener);
|
||
|
|
nestedTreeControl = new NestedTreeControl<Node>(node => node.children);
|
||
|
|
nestedTreeDataSource = new MatTreeNestedDataSource<Node>();
|
||
|
|
|
||
|
|
constructor() {
|
||
|
|
this.flatTreeDataSource.data = FLAT_TREE_DATA;
|
||
|
|
this.nestedTreeDataSource.data = NESTED_TREE_DATA;
|
||
|
|
}
|
||
|
|
|
||
|
|
flatTreeHasChild = (_: number, node: ExampleFlatNode) => node.expandable;
|
||
|
|
|
||
|
|
nestedTreeHasChild = (_: number, node: Node) => !!node.children && node.children.length > 0;
|
||
|
|
}
|