xref: /aosp_15_r20/development/tools/winscope/src/viewers/common/properties_presenter_test.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
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 */
16
17import {assertDefined} from 'common/assert_utils';
18import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder';
19import {PropertyTreeBuilder} from 'test/unit/property_tree_builder';
20import {TreeNodeUtils} from 'test/unit/tree_node_utils';
21import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node';
22import {PropertySource} from 'trace/tree_node/property_tree_node';
23import {TextFilter} from 'viewers/common/text_filter';
24import {DiffType} from './diff_type';
25import {PropertiesPresenter} from './properties_presenter';
26import {UiPropertyTreeNode} from './ui_property_tree_node';
27
28describe('PropertiesPresenter', () => {
29  const pTree = new PropertyTreeBuilder()
30    .setIsRoot(true)
31    .setRootId('Test Trace')
32    .setName('entry')
33    .setChildren([
34      {name: 'defProp', value: false, source: PropertySource.DEFAULT},
35      {name: 'setProp', value: 1},
36      {name: 'otherProp', value: 2},
37      {name: 'calcProp', value: true, source: PropertySource.CALCULATED},
38    ])
39    .build();
40  const hTree = new HierarchyTreeBuilder()
41    .setId('Test Trace')
42    .setName('entry')
43    .setProperties({setProp: 2})
44    .build();
45  let presenter: PropertiesPresenter;
46
47  beforeAll(async () => {
48    jasmine.addCustomEqualityTester(TreeNodeUtils.treeNodeEqualityTester);
49  });
50
51  beforeEach(() => {
52    presenter = new PropertiesPresenter({}, new TextFilter(), []);
53    presenter.setPropertiesTree(pTree);
54  });
55
56  it('exposes user options', () => {
57    expect(presenter.getUserOptions()).toEqual({});
58    const testOptions = {test: {name: 'Test opt', enabled: false}};
59    presenter.applyPropertiesUserOptionsChange(testOptions);
60    expect(presenter.getUserOptions()).toEqual(testOptions);
61  });
62
63  it('updates highlighted property', () => {
64    expect(presenter.getHighlightedProperty()).toEqual('');
65    const id = '4';
66    presenter.applyHighlightedPropertyChange(id);
67    expect(presenter.getHighlightedProperty()).toEqual(id);
68    presenter.applyHighlightedPropertyChange(id);
69    expect(presenter.getHighlightedProperty()).toEqual('');
70  });
71
72  it('updates properties tree to show diffs based on user option', async () => {
73    let formattedTree = await getFormattedTree(hTree);
74    expect(getDiff(formattedTree, 'setProp')).toEqual(DiffType.NONE);
75    expect(getDiff(formattedTree, 'otherProp')).toEqual(DiffType.NONE);
76
77    presenter.applyPropertiesUserOptionsChange({
78      showDiff: {name: '', enabled: true},
79    });
80    formattedTree = await getFormattedTree();
81    expect(getDiff(formattedTree, 'setProp')).toEqual(DiffType.ADDED);
82    expect(getDiff(formattedTree, 'otherProp')).toEqual(DiffType.ADDED);
83
84    formattedTree = await getFormattedTree(hTree);
85    formattedTree = assertDefined(presenter.getFormattedTree());
86    expect(getDiff(formattedTree, 'setProp')).toEqual(DiffType.MODIFIED);
87    expect(getDiff(formattedTree, 'otherProp')).toEqual(DiffType.ADDED);
88  });
89
90  it('shows/hides defaults based on user option', async () => {
91    expect((await getFormattedTree()).getAllChildren().length).toEqual(2);
92    presenter.applyPropertiesUserOptionsChange({
93      showDefaults: {name: '', enabled: true},
94    });
95    expect((await getFormattedTree()).getAllChildren().length).toEqual(3);
96  });
97
98  it('filters properties tree', async () => {
99    expect((await getFormattedTree()).getAllChildren().length).toEqual(2);
100    const filter = new TextFilter('setProp');
101    presenter.applyPropertiesFilterChange(filter);
102    expect(presenter.getTextFilter()).toEqual(filter);
103    expect((await getFormattedTree()).getAllChildren().length).toEqual(1);
104  });
105
106  it('keeps calculated properties', async () => {
107    const tree = await getFormattedTree(undefined, undefined, true);
108    expect(tree.getAllChildren().length).toEqual(3);
109  });
110
111  it('overrides display name', async () => {
112    const tree = await getFormattedTree(undefined, 'Override Name');
113    expect(tree.getDisplayName()).toEqual('Override Name');
114  });
115
116  it('keeps allowlist default properties', async () => {
117    presenter.updateDefaultAllowList(['defProp']);
118    expect((await getFormattedTree()).getChildByName('defProp')).toBeDefined();
119  });
120
121  it('discards denylist properties', async () => {
122    presenter = new PropertiesPresenter({}, new TextFilter(), ['setProp']);
123    presenter.setPropertiesTree(pTree);
124    const tree = await getFormattedTree();
125    expect(tree.getChildByName('setProp')).toBeUndefined();
126  });
127
128  it('applies custom operations', async () => {
129    const operation = jasmine.createSpyObj('operation', ['apply']);
130    presenter = new PropertiesPresenter({}, new TextFilter(), [], [operation]);
131    presenter.setPropertiesTree(pTree);
132    await getFormattedTree();
133    expect(operation.apply).toHaveBeenCalledTimes(1);
134  });
135
136  function getDiff(tree: UiPropertyTreeNode, propertyName: string): DiffType {
137    return assertDefined(tree.getChildByName(propertyName)).getDiff();
138  }
139
140  async function getFormattedTree(
141    previousHierarchyTree?: HierarchyTreeNode,
142    displayName?: string,
143    keepCalculated = false,
144  ): Promise<UiPropertyTreeNode> {
145    await presenter.formatPropertiesTree(
146      previousHierarchyTree,
147      displayName,
148      keepCalculated,
149    );
150    return assertDefined(presenter.getFormattedTree());
151  }
152});
153