UNPKG

6.46 kBPlain TextView Raw
1// *****************************************************************************
2// Copyright (C) 2019 Thomas Drosdzoll.
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License v. 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0.
7//
8// This Source Code may also be made available under the following Secondary
9// Licenses when the conditions for such availability set forth in the Eclipse
10// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11// with the GNU Classpath Exception which is available at
12// https://www.gnu.org/software/classpath/license.html.
13//
14// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15// *****************************************************************************
16
17import { expect, assert } from 'chai';
18import { MockTreeModel } from './test/mock-tree-model';
19import { TreeModel } from './tree-model';
20import { TreeNode, CompositeTreeNode, Tree, TreeImpl } from './tree';
21import { ExpandableTreeNode } from './tree-expansion';
22import { createTreeTestContainer } from './test/tree-test-container';
23import { timeout } from '../../common/promise-util';
24
25describe('TreeExpansionService', () => {
26 let model: TreeModel;
27 beforeEach(() => {
28 model = createTreeModel();
29 model.root = MockTreeModel.HIERARCHICAL_MOCK_ROOT();
30 });
31 describe('expandNode', () => {
32 it("won't expand an already expanded node", done => {
33 const node: ExpandableTreeNode = retrieveNode<ExpandableTreeNode>('1');
34 model.expandNode(node).then(result => {
35 expect(result).to.be.undefined;
36 done();
37 });
38 });
39
40 it('will expand a collapsed node', done => {
41 const node: ExpandableTreeNode = retrieveNode<ExpandableTreeNode>('1');
42 model.collapseNode(node).then(() => {
43 model.expandNode(node).then(result => {
44 expect(result).to.be.eq(result);
45 done();
46 });
47 });
48 });
49
50 it("won't expand an undefined node", done => {
51 model.expandNode(undefined).then(result => {
52 expect(result).to.be.undefined;
53 done();
54 });
55 });
56 });
57
58 describe('collapseNode', () => {
59 it('will collapse an expanded node', done => {
60 const node: ExpandableTreeNode = retrieveNode<ExpandableTreeNode>('1');
61 model.collapseNode(node).then(result => {
62 expect(result).to.be.eq(result);
63 done();
64 });
65 });
66
67 it("won't collapse an already collapsed node", done => {
68 const node: ExpandableTreeNode = retrieveNode<ExpandableTreeNode>('1');
69 model.collapseNode(node).then(() => {
70 model.collapseNode(node).then(result => {
71 expect(result).to.be.false;
72 done();
73 });
74 });
75 });
76
77 it('cannot collapse a leaf node', done => {
78 const node: ExpandableTreeNode = retrieveNode<ExpandableTreeNode>('1.1.2');
79 model.collapseNode(node).then(result => {
80 expect(result).to.be.false;
81 done();
82 });
83 });
84 });
85
86 describe('collapseAll', () => {
87 it('will collapse all nodes recursively', done => {
88 model.collapseAll(retrieveNode<CompositeTreeNode>('1')).then(result => {
89 expect(result).to.be.eq(result);
90 done();
91 });
92 });
93
94 it("won't collapse nodes recursively if the root node is collapsed already", done => {
95 model.collapseNode(retrieveNode<ExpandableTreeNode>('1')).then(() => {
96 model.collapseAll(retrieveNode<CompositeTreeNode>('1')).then(result => {
97 expect(result).to.be.eq(result);
98 done();
99 });
100 });
101 });
102 });
103
104 describe('toggleNodeExpansion', () => {
105 it('changes the expansion state from expanded to collapsed', done => {
106 const node = retrieveNode<ExpandableTreeNode>('1');
107 model.onExpansionChanged((e: Readonly<ExpandableTreeNode>) => {
108 expect(e).to.be.equal(node);
109 expect(e.expanded).to.be.false;
110 });
111 model.toggleNodeExpansion(node).then(() => {
112 done();
113 });
114 });
115
116 it('changes the expansion state from collapsed to expanded', done => {
117 const node = retrieveNode<ExpandableTreeNode>('1');
118 model.collapseNode(node).then(() => {
119 });
120 model.onExpansionChanged((e: Readonly<ExpandableTreeNode>) => {
121 expect(e).to.be.equal(node);
122 expect(e.expanded).to.be.true;
123 });
124 model.toggleNodeExpansion(node).then(() => {
125 done();
126 });
127 });
128 });
129
130 it('node should be refreshed on expansion', async () => {
131 const container = createTreeTestContainer();
132 container.rebind(Tree).to(class extends TreeImpl {
133
134 protected override async resolveChildren(parent: CompositeTreeNode): Promise<TreeNode[]> {
135 await timeout(200);
136 return [{
137 id: 'child',
138 parent
139 }];
140 }
141
142 });
143 const root: ExpandableTreeNode = {
144 id: 'parent',
145 parent: undefined,
146 children: [],
147 expanded: false
148 };
149
150 const treeModel = container.get<TreeModel>(TreeModel);
151 treeModel.root = root;
152
153 assert.isFalse(root.expanded, 'before');
154 assert.equal(root.children.length, 0, 'before');
155
156 const expanding = treeModel.expandNode(root);
157 assert.isFalse(root.expanded, 'between');
158 assert.equal(root.children.length, 0, 'between');
159
160 await expanding;
161 assert.isTrue(root.expanded, 'after');
162 assert.equal(root.children.length, 1, 'after');
163 });
164
165 function createTreeModel(): TreeModel {
166 const container = createTreeTestContainer();
167 return container.get(TreeModel);
168 }
169 function retrieveNode<T extends TreeNode>(id: string): Readonly<T> {
170 const readonlyNode: Readonly<T> = model.getNode(id) as T;
171 return readonlyNode;
172 }
173});
174
\No newline at end of file