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; 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: ` {{node.name}} {{node.name}} {{node.name}} {{node.name}}
`, 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( node => node.level, node => node.expandable, ); flatTreeDataSource = new MatTreeFlatDataSource(this.flatTreeControl, this.treeFlattener); nestedTreeControl = new NestedTreeControl(node => node.children); nestedTreeDataSource = new MatTreeNestedDataSource(); 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; }