UNPKG

8.82 kBJavaScriptView Raw
1import { __awaiter } from 'tslib';
2import { ContentContainerComponentHarness, HarnessPredicate, ComponentHarness, parallel } from '@angular/cdk/testing';
3import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
4
5/** Harness for interacting with a standard Angular Material tree node. */
6class MatTreeNodeHarness extends ContentContainerComponentHarness {
7 constructor() {
8 super(...arguments);
9 this._toggle = this.locatorForOptional('[matTreeNodeToggle]');
10 }
11 /**
12 * Gets a `HarnessPredicate` that can be used to search for a tree node with specific attributes.
13 * @param options Options for narrowing the search
14 * @return a `HarnessPredicate` configured with the given options.
15 */
16 static with(options = {}) {
17 return getNodePredicate(MatTreeNodeHarness, options);
18 }
19 /** Whether the tree node is expanded. */
20 isExpanded() {
21 return __awaiter(this, void 0, void 0, function* () {
22 return coerceBooleanProperty(yield (yield this.host()).getAttribute('aria-expanded'));
23 });
24 }
25 /** Whether the tree node is disabled. */
26 isDisabled() {
27 return __awaiter(this, void 0, void 0, function* () {
28 return coerceBooleanProperty(yield (yield this.host()).getProperty('aria-disabled'));
29 });
30 }
31 /** Gets the level of the tree node. Note that this gets the aria-level and is 1 indexed. */
32 getLevel() {
33 return __awaiter(this, void 0, void 0, function* () {
34 return coerceNumberProperty(yield (yield this.host()).getAttribute('aria-level'));
35 });
36 }
37 /** Gets the tree node's text. */
38 getText() {
39 return __awaiter(this, void 0, void 0, function* () {
40 return (yield this.host()).text({ exclude: '.mat-tree-node, .mat-nested-tree-node, button' });
41 });
42 }
43 /** Toggles node between expanded/collapsed. Only works when node is not disabled. */
44 toggle() {
45 return __awaiter(this, void 0, void 0, function* () {
46 const toggle = yield this._toggle();
47 if (toggle) {
48 return toggle.click();
49 }
50 });
51 }
52 /** Expands the node if it is collapsed. Only works when node is not disabled. */
53 expand() {
54 return __awaiter(this, void 0, void 0, function* () {
55 if (!(yield this.isExpanded())) {
56 yield this.toggle();
57 }
58 });
59 }
60 /** Collapses the node if it is expanded. Only works when node is not disabled. */
61 collapse() {
62 return __awaiter(this, void 0, void 0, function* () {
63 if (yield this.isExpanded()) {
64 yield this.toggle();
65 }
66 });
67 }
68}
69/** The selector of the host element of a `MatTreeNode` instance. */
70MatTreeNodeHarness.hostSelector = '.mat-tree-node, .mat-nested-tree-node';
71function getNodePredicate(type, options) {
72 return new HarnessPredicate(type, options)
73 .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))
74 .addOption('disabled', options.disabled, (harness, disabled) => __awaiter(this, void 0, void 0, function* () { return (yield harness.isDisabled()) === disabled; }))
75 .addOption('expanded', options.expanded, (harness, expanded) => __awaiter(this, void 0, void 0, function* () { return (yield harness.isExpanded()) === expanded; }))
76 .addOption('level', options.level, (harness, level) => __awaiter(this, void 0, void 0, function* () { return (yield harness.getLevel()) === level; }));
77}
78
79/** Harness for interacting with a standard mat-tree in tests. */
80class MatTreeHarness extends ComponentHarness {
81 /**
82 * Gets a `HarnessPredicate` that can be used to search for a tree with specific attributes.
83 * @param options Options for narrowing the search
84 * @return a `HarnessPredicate` configured with the given options.
85 */
86 static with(options = {}) {
87 return new HarnessPredicate(MatTreeHarness, options);
88 }
89 /** Gets all of the nodes in the tree. */
90 getNodes(filter = {}) {
91 return __awaiter(this, void 0, void 0, function* () {
92 return this.locatorForAll(MatTreeNodeHarness.with(filter))();
93 });
94 }
95 /**
96 * Gets an object representation for the visible tree structure
97 * If a node is under an unexpanded node it will not be included.
98 * Eg.
99 * Tree (all nodes expanded):
100 * `
101 * <mat-tree>
102 * <mat-tree-node>Node 1<mat-tree-node>
103 * <mat-nested-tree-node>
104 * Node 2
105 * <mat-nested-tree-node>
106 * Node 2.1
107 * <mat-tree-node>
108 * Node 2.1.1
109 * <mat-tree-node>
110 * <mat-nested-tree-node>
111 * <mat-tree-node>
112 * Node 2.2
113 * <mat-tree-node>
114 * <mat-nested-tree-node>
115 * </mat-tree>`
116 *
117 * Tree structure:
118 * {
119 * children: [
120 * {
121 * text: 'Node 1',
122 * children: [
123 * {
124 * text: 'Node 2',
125 * children: [
126 * {
127 * text: 'Node 2.1',
128 * children: [{text: 'Node 2.1.1'}]
129 * },
130 * {text: 'Node 2.2'}
131 * ]
132 * }
133 * ]
134 * }
135 * ]
136 * };
137 */
138 getTreeStructure() {
139 return __awaiter(this, void 0, void 0, function* () {
140 const nodes = yield this.getNodes();
141 const nodeInformation = yield parallel(() => nodes.map(node => {
142 return parallel(() => [node.getLevel(), node.getText(), node.isExpanded()]);
143 }));
144 return this._getTreeStructure(nodeInformation, 1, true);
145 });
146 }
147 /**
148 * Recursively collect the structured text of the tree nodes.
149 * @param nodes A list of tree nodes
150 * @param level The level of nodes that are being accounted for during this iteration
151 * @param parentExpanded Whether the parent of the first node in param nodes is expanded
152 */
153 _getTreeStructure(nodes, level, parentExpanded) {
154 var _a, _b, _c;
155 const result = {};
156 for (let i = 0; i < nodes.length; i++) {
157 const [nodeLevel, text, expanded] = nodes[i];
158 const nextNodeLevel = (_b = (_a = nodes[i + 1]) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : -1;
159 // Return the accumulated value for the current level once we reach a shallower level node
160 if (nodeLevel < level) {
161 return result;
162 }
163 // Skip deeper level nodes during this iteration, they will be picked up in a later iteration
164 if (nodeLevel > level) {
165 continue;
166 }
167 // Only add to representation if it is visible (parent is expanded)
168 if (parentExpanded) {
169 // Collect the data under this node according to the following rules:
170 // 1. If the next node in the list is a sibling of the current node add it to the child list
171 // 2. If the next node is a child of the current node, get the sub-tree structure for the
172 // child and add it under this node
173 // 3. If the next node has a shallower level, we've reached the end of the child nodes for
174 // the current parent.
175 if (nextNodeLevel === level) {
176 this._addChildToNode(result, { text });
177 }
178 else if (nextNodeLevel > level) {
179 let children = (_c = this._getTreeStructure(nodes.slice(i + 1), nextNodeLevel, expanded)) === null || _c === void 0 ? void 0 : _c.children;
180 let child = children ? { text, children } : { text };
181 this._addChildToNode(result, child);
182 }
183 else {
184 this._addChildToNode(result, { text });
185 return result;
186 }
187 }
188 }
189 return result;
190 }
191 _addChildToNode(result, child) {
192 result.children ? result.children.push(child) : (result.children = [child]);
193 }
194}
195/** The selector for the host element of a `MatTableHarness` instance. */
196MatTreeHarness.hostSelector = '.mat-tree';
197
198/**
199 * @license
200 * Copyright Google LLC All Rights Reserved.
201 *
202 * Use of this source code is governed by an MIT-style license that can be
203 * found in the LICENSE file at https://angular.io/license
204 */
205
206/**
207 * @license
208 * Copyright Google LLC All Rights Reserved.
209 *
210 * Use of this source code is governed by an MIT-style license that can be
211 * found in the LICENSE file at https://angular.io/license
212 */
213
214export { MatTreeHarness, MatTreeNodeHarness };
215//# sourceMappingURL=testing.mjs.map