1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | import { expect, assert } from 'chai';
|
18 | import { MockTreeModel } from './test/mock-tree-model';
|
19 | import { TreeModel } from './tree-model';
|
20 | import { TreeNode, CompositeTreeNode, Tree, TreeImpl } from './tree';
|
21 | import { ExpandableTreeNode } from './tree-expansion';
|
22 | import { createTreeTestContainer } from './test/tree-test-container';
|
23 | import { timeout } from '../../common/promise-util';
|
24 |
|
25 | describe('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 |