1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import {Component, ViewChild} from '@angular/core';
17import {
18  ComponentFixture,
19  ComponentFixtureAutoDetect,
20  TestBed,
21} from '@angular/core/testing';
22import {MatIconModule} from '@angular/material/icon';
23import {MatTooltipModule} from '@angular/material/tooltip';
24import {assertDefined} from 'common/assert_utils';
25import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder';
26import {UiHierarchyTreeNode} from 'viewers/common/ui_hierarchy_tree_node';
27import {HierarchyTreeNodeDataViewComponent} from './hierarchy_tree_node_data_view_component';
28import {PropertyTreeNodeDataViewComponent} from './property_tree_node_data_view_component';
29import {TreeNodeComponent} from './tree_node_component';
30
31describe('TreeNodeComponent', () => {
32  let fixture: ComponentFixture<TestHostComponent>;
33  let component: TestHostComponent;
34  let htmlElement: HTMLElement;
35
36  beforeEach(async () => {
37    await TestBed.configureTestingModule({
38      providers: [{provide: ComponentFixtureAutoDetect, useValue: true}],
39      declarations: [
40        TreeNodeComponent,
41        HierarchyTreeNodeDataViewComponent,
42        PropertyTreeNodeDataViewComponent,
43        TestHostComponent,
44      ],
45      imports: [MatIconModule, MatTooltipModule],
46    }).compileComponents();
47    fixture = TestBed.createComponent(TestHostComponent);
48    component = fixture.componentInstance;
49    htmlElement = fixture.nativeElement;
50    fixture.detectChanges();
51  });
52
53  it('can be created', () => {
54    expect(component).toBeTruthy();
55  });
56
57  it('can generate data view component', () => {
58    component.treeNodeComponent.isPropertyTreeNode = jasmine
59      .createSpy()
60      .and.returnValue(false);
61    fixture.detectChanges();
62    const treeNodeDataView = htmlElement.querySelector(
63      'hierarchy-tree-node-data-view',
64    );
65    expect(treeNodeDataView).toBeTruthy();
66  });
67
68  it('can trigger tree toggle on click of chevron', () => {
69    component.treeNodeComponent.showChevron = jasmine
70      .createSpy()
71      .and.returnValue(true);
72    fixture.detectChanges();
73
74    const spy = spyOn(component.treeNodeComponent.toggleTreeChange, 'emit');
75    const toggleButton = assertDefined(
76      htmlElement.querySelector('.toggle-tree-btn'),
77    );
78    (toggleButton as HTMLButtonElement).click();
79    expect(spy).toHaveBeenCalled();
80  });
81
82  it('can trigger tree expansion on click of expand tree button', () => {
83    const spy = spyOn(component.treeNodeComponent.expandTreeChange, 'emit');
84    const expandButton = assertDefined(
85      htmlElement.querySelector('.expand-tree-btn'),
86    );
87    (expandButton as HTMLButtonElement).click();
88    expect(spy).toHaveBeenCalled();
89  });
90
91  it('can trigger node pin on click of star', () => {
92    component.treeNodeComponent.showPinNodeIcon = jasmine
93      .createSpy()
94      .and.returnValue(true);
95    fixture.detectChanges();
96
97    const spy = spyOn(component.treeNodeComponent.pinNodeChange, 'emit');
98    const pinNodeButton = assertDefined(
99      htmlElement.querySelector('.pin-node-btn'),
100    );
101    (pinNodeButton as HTMLButtonElement).click();
102    expect(spy).toHaveBeenCalledWith(component.node);
103  });
104
105  it('can trigger rect show state toggle on click of icon', () => {
106    component.treeNodeComponent.showStateIcon = 'visibility';
107    fixture.detectChanges();
108
109    const spy = spyOn(component.treeNodeComponent.rectShowStateChange, 'emit');
110    const pinNodeButton = assertDefined(
111      htmlElement.querySelector('.toggle-rect-show-state-btn'),
112    );
113    (pinNodeButton as HTMLButtonElement).click();
114    expect(spy).toHaveBeenCalled();
115  });
116
117  @Component({
118    selector: 'host-component',
119    template: `
120      <tree-node
121        [node]="node"
122        [isExpanded]="false"
123        [isPinned]="false"
124        [isInPinnedSection]="false"
125        [isSelected]="isSelected"></tree-node>
126    `,
127  })
128  class TestHostComponent {
129    node = UiHierarchyTreeNode.from(
130      new HierarchyTreeBuilder()
131        .setId('LayerTraceEntry')
132        .setName('4')
133        .setChildren([{id: 1, name: 'Child 1'}])
134        .build(),
135    );
136
137    isSelected = false;
138
139    @ViewChild(TreeNodeComponent)
140    treeNodeComponent!: TreeNodeComponent;
141  }
142});
143