@neovici/cosmoz-treenode-navigator 3.0.8 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/cc-test-reporter +0 -0
- package/cosmoz-treenode-button-view.js +199 -113
- package/cosmoz-treenode-navigator.js +295 -496
- package/helpers.js +252 -0
- package/package.json +22 -8
- package/test/cosmoz-treenode-navigator.test.js +62 -28
- package/test/data/basicTree.js +98 -41
- package/web-test-runner.config.mjs +1 -28
package/helpers.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { DefaultTree } from '@neovici/cosmoz-tree/cosmoz-default-tree';
|
|
2
|
+
import basicTree from './test/data/basicTree';
|
|
3
|
+
import { tagged as css } from '@neovici/cosmoz-utils/lib/tagged';
|
|
4
|
+
|
|
5
|
+
const tree = new DefaultTree(basicTree),
|
|
6
|
+
/**
|
|
7
|
+
* Returns true if a given node has children
|
|
8
|
+
* @param {Object} node - The node
|
|
9
|
+
* @return {Boolean} - True if node has children
|
|
10
|
+
*/
|
|
11
|
+
hasChildren = node => {
|
|
12
|
+
return tree.hasChildren(node);
|
|
13
|
+
},
|
|
14
|
+
/**
|
|
15
|
+
* Returns true, if a search string is eligable to trigger a search
|
|
16
|
+
* @param {String} value - The search string
|
|
17
|
+
* @param {Number} searchMinLength - The minimum length of value to be valid
|
|
18
|
+
* @return {Boolean} - If a search should be triggered
|
|
19
|
+
*/
|
|
20
|
+
computeSearching = (value, searchMinLength) => {
|
|
21
|
+
return value && value.length >= searchMinLength && value !== '';
|
|
22
|
+
},
|
|
23
|
+
/**
|
|
24
|
+
* Normalizes and returns an Array of nodes
|
|
25
|
+
* with the properties name, path, parentSectionName, children
|
|
26
|
+
* @param {Array} nodes - The input nodes
|
|
27
|
+
* @return {Array} - The normalized nodes
|
|
28
|
+
*/
|
|
29
|
+
normalizeNodes = nodes => {
|
|
30
|
+
if (!Array.isArray(nodes)) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
return nodes.map(node => {
|
|
34
|
+
if (!node) {
|
|
35
|
+
return node;
|
|
36
|
+
}
|
|
37
|
+
const path = node.pathLocator || node.path,
|
|
38
|
+
pathLocatorSeparator = tree.pathLocatorSeparator,
|
|
39
|
+
parentPath = path.includes(pathLocatorSeparator) ? path.substring(0, path.lastIndexOf(pathLocatorSeparator)) : path;
|
|
40
|
+
return {
|
|
41
|
+
name: node[tree.searchProperty],
|
|
42
|
+
path,
|
|
43
|
+
children: node[tree.childProperty],
|
|
44
|
+
parentSectionName: tree.getPathString(parentPath, tree.searchProperty),
|
|
45
|
+
id: node.id,
|
|
46
|
+
pathLocator: node.pathLocator
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
/**
|
|
51
|
+
* Returns the found nodes based on a search string and a given tree to be searched
|
|
52
|
+
* @param {Boolean} searching - If true, a search should be executed
|
|
53
|
+
* @param {String} searchString - The search string
|
|
54
|
+
* @param {Array} renderedLevel - The node list on which the search should be executed
|
|
55
|
+
* @param {Tree} tree - The main tree
|
|
56
|
+
* @return {Array} - The found nodes
|
|
57
|
+
*/
|
|
58
|
+
computeDataPlane = (searching, searchString, renderedLevel, tree) => {
|
|
59
|
+
if (searching && tree) {
|
|
60
|
+
const results = tree.searchNodes(searchString, renderedLevel, false);
|
|
61
|
+
return normalizeNodes(results);
|
|
62
|
+
}
|
|
63
|
+
return renderedLevel;
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Returns a node array with the children of a node on the given path
|
|
67
|
+
* If the node doesn't have children, the node gets returned
|
|
68
|
+
* @param {String} pathLocator - The separated address parts of a node
|
|
69
|
+
* @param {Tree} tree - The main tree
|
|
70
|
+
* @return {Array} - Nodes
|
|
71
|
+
*/
|
|
72
|
+
renderLevel = (pathLocator, tree) => {
|
|
73
|
+
if (!tree) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const node = tree.getNodeByPathLocator(pathLocator),
|
|
77
|
+
children = tree.getChildren(node),
|
|
78
|
+
level = tree.hasChildren(node) ? children : node,
|
|
79
|
+
sortFunc = (a, b) => {
|
|
80
|
+
// First sort based on "folder" status (containing children)
|
|
81
|
+
if (hasChildren(a)) {
|
|
82
|
+
if (!hasChildren(b)) {
|
|
83
|
+
return -1;
|
|
84
|
+
}
|
|
85
|
+
} else if (hasChildren(b)) {
|
|
86
|
+
return 1;
|
|
87
|
+
}
|
|
88
|
+
// Then sort on searchProperty
|
|
89
|
+
const val1 = a[tree.searchProperty],
|
|
90
|
+
val2 = b[tree.searchProperty];
|
|
91
|
+
|
|
92
|
+
if (val1 > val2) {
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
if (val1 < val2) {
|
|
96
|
+
return -1;
|
|
97
|
+
}
|
|
98
|
+
return 0;
|
|
99
|
+
};
|
|
100
|
+
return normalizeNodes(level)
|
|
101
|
+
.sort(sortFunc);
|
|
102
|
+
},
|
|
103
|
+
/**
|
|
104
|
+
* Returns the classes of a row based its selection state
|
|
105
|
+
* @param {String} classes - The default classes
|
|
106
|
+
* @param {object} node - Node to check
|
|
107
|
+
* @param {object} highlightedNode - Currently highlighted node
|
|
108
|
+
* @return {String} - The CSS classes
|
|
109
|
+
*/
|
|
110
|
+
computeRowClass = (classes, node, highlightedNode) => {
|
|
111
|
+
let selected = false;
|
|
112
|
+
if (highlightedNode) {
|
|
113
|
+
selected = node === highlightedNode
|
|
114
|
+
|| node.id && node.id === highlightedNode.id
|
|
115
|
+
|| node.pathLocator === highlightedNode.pathLocator;
|
|
116
|
+
}
|
|
117
|
+
return selected ? classes + ' selected' : classes;
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
* Selects the doubled clicked node and dispatches an node-dblclicked event.
|
|
121
|
+
* @param {Event} event The triggering event
|
|
122
|
+
* @param {object} host Host
|
|
123
|
+
* @return {undefined}
|
|
124
|
+
*/
|
|
125
|
+
onNodeDblClicked = (event, host) => {
|
|
126
|
+
host.dispatchEvent(new CustomEvent('node-dblclicked', {
|
|
127
|
+
detail: {
|
|
128
|
+
model: event.model
|
|
129
|
+
}
|
|
130
|
+
}));
|
|
131
|
+
},
|
|
132
|
+
/**
|
|
133
|
+
* Returns the name of a given node
|
|
134
|
+
* @param {Object} node - The node
|
|
135
|
+
* @return {String} - The name
|
|
136
|
+
*/
|
|
137
|
+
getNodeName = node => {
|
|
138
|
+
return node[tree.searchProperty];
|
|
139
|
+
},
|
|
140
|
+
/**
|
|
141
|
+
* Returns true, if the button should be visible
|
|
142
|
+
* @param {Boolean} searching - If a search is currently executed
|
|
143
|
+
* @param {String} openNodeLevelPath - The open node level
|
|
144
|
+
* @return {Boolean} - The visibility of the button
|
|
145
|
+
*/
|
|
146
|
+
showGlobalSearchBtn = (searching, openNodeLevelPath) => {
|
|
147
|
+
return searching && openNodeLevelPath !== '';
|
|
148
|
+
},
|
|
149
|
+
/**
|
|
150
|
+
* Returns the nodes on a path specified by a given path locator
|
|
151
|
+
* @param {String} pathLocator - The separated address parts of a node
|
|
152
|
+
* @param {Tree} tree - The main tree
|
|
153
|
+
* @return {Array} - The found nodes or empty array
|
|
154
|
+
*/
|
|
155
|
+
getTreePathParts = (pathLocator, tree) => {
|
|
156
|
+
if (!tree || !pathLocator) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
return normalizeNodes(tree.getPathNodes(pathLocator));
|
|
160
|
+
},
|
|
161
|
+
/**
|
|
162
|
+
* Returns a node based on a given path locator.
|
|
163
|
+
* If pathLocator is empty or not defined, null gets returned.
|
|
164
|
+
* If pathLocator is only partly valid, the last valid node gets returned.
|
|
165
|
+
* @param {String} pathLocator - The separated address parts of a node
|
|
166
|
+
* @param {Tree} tree - The main tree
|
|
167
|
+
* @return {Object} - The found node
|
|
168
|
+
*/
|
|
169
|
+
getNode = (pathLocator, tree) => {
|
|
170
|
+
if (!tree || !pathLocator) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const node = tree.getNodeByPathLocator(pathLocator);
|
|
175
|
+
let nodes;
|
|
176
|
+
|
|
177
|
+
if (!node) {
|
|
178
|
+
nodes = tree.getPathNodes(pathLocator).filter(n => n != null);
|
|
179
|
+
}
|
|
180
|
+
return nodes && nodes.length > 0 ? nodes.pop() : node;
|
|
181
|
+
},
|
|
182
|
+
nodeStyles = css`
|
|
183
|
+
.section {
|
|
184
|
+
background-color: #f5f5f5;
|
|
185
|
+
padding: 5px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.pointer {
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.item {
|
|
193
|
+
padding: 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.item[data-index] {
|
|
197
|
+
background: transparent;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.node-item {
|
|
201
|
+
align-items: center;
|
|
202
|
+
display: flex;
|
|
203
|
+
font-family: 'Roboto', 'Noto', sans-serif;
|
|
204
|
+
font-size: 16px;
|
|
205
|
+
font-weight: 400;
|
|
206
|
+
height: 40px;
|
|
207
|
+
line-height: 24px;
|
|
208
|
+
padding: 6px 12px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.node-item-wrapper {
|
|
212
|
+
width: 100%;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.icon {
|
|
216
|
+
box-sizing: border-box;
|
|
217
|
+
cursor: pointer;
|
|
218
|
+
display: inline-block;
|
|
219
|
+
height: 40px;
|
|
220
|
+
line-height: 1;
|
|
221
|
+
outline: none;
|
|
222
|
+
padding: 8px;
|
|
223
|
+
position: relative;
|
|
224
|
+
user-select: none;
|
|
225
|
+
width: 40px;
|
|
226
|
+
z-index: 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.node-item.selected {
|
|
230
|
+
background-color: var(--cosmoz-listbox-active-color, var(--cosmoz-selection-color, rgba(58, 145, 226, 0.1)));
|
|
231
|
+
transition: background-color 0.2s ease-out;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.node-item.selected .icon svg {
|
|
235
|
+
fill: var(--cosmoz-treenode-navigator-select-node-icon-color);
|
|
236
|
+
transition: color 0.8s ease-out;
|
|
237
|
+
}`;
|
|
238
|
+
|
|
239
|
+
export {
|
|
240
|
+
hasChildren,
|
|
241
|
+
computeSearching,
|
|
242
|
+
normalizeNodes,
|
|
243
|
+
renderLevel,
|
|
244
|
+
computeDataPlane,
|
|
245
|
+
computeRowClass,
|
|
246
|
+
onNodeDblClicked,
|
|
247
|
+
getNodeName,
|
|
248
|
+
showGlobalSearchBtn,
|
|
249
|
+
getTreePathParts,
|
|
250
|
+
getNode,
|
|
251
|
+
nodeStyles
|
|
252
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-treenode-navigator",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A Polymer component that lets you navigate and search through hierarchically structured data-nodes and select one of them.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"polymer",
|
|
@@ -44,27 +44,41 @@
|
|
|
44
44
|
"commitlint": {
|
|
45
45
|
"extends": [
|
|
46
46
|
"@commitlint/config-conventional"
|
|
47
|
-
]
|
|
47
|
+
],
|
|
48
|
+
"rules": {
|
|
49
|
+
"body-max-line-length": [
|
|
50
|
+
1,
|
|
51
|
+
"always",
|
|
52
|
+
100
|
|
53
|
+
]
|
|
54
|
+
}
|
|
48
55
|
},
|
|
49
56
|
"dependencies": {
|
|
57
|
+
"@neovici/cfg": "^1.15.2",
|
|
58
|
+
"@neovici/cosmoz-autocomplete": "^4.0.0",
|
|
50
59
|
"@neovici/cosmoz-dialog": "^3.0.0",
|
|
51
60
|
"@neovici/cosmoz-i18next": "^3.2.0",
|
|
61
|
+
"@neovici/cosmoz-input": "^2.0.0",
|
|
52
62
|
"@neovici/cosmoz-tree": "^3.0.0",
|
|
63
|
+
"@neovici/cosmoz-utils": "^4.0.0",
|
|
64
|
+
"@open-wc/lit-helpers": "^0.4.1",
|
|
53
65
|
"@polymer/iron-icons": "^3.0.0",
|
|
54
|
-
"@polymer/iron-list": "^3.1.0",
|
|
55
66
|
"@polymer/paper-button": "^3.0.0",
|
|
56
67
|
"@polymer/paper-icon-button": "^3.0.0",
|
|
57
68
|
"@polymer/paper-input": "^3.2.0",
|
|
58
69
|
"@polymer/polymer": "^3.4.0",
|
|
59
70
|
"@web/dev-server": "^0.1.25",
|
|
60
71
|
"@web/test-runner": "^0.13.19",
|
|
61
|
-
"@web/test-runner-selenium": "^0.5.2"
|
|
72
|
+
"@web/test-runner-selenium": "^0.5.2",
|
|
73
|
+
"haunted": "^5.0.0",
|
|
74
|
+
"lit": "^2.2.7",
|
|
75
|
+
"lit-html": "^2.0.0"
|
|
62
76
|
},
|
|
63
77
|
"devDependencies": {
|
|
64
|
-
"@commitlint/cli": "^
|
|
65
|
-
"@commitlint/config-conventional": "^
|
|
78
|
+
"@commitlint/cli": "^17.0.0",
|
|
79
|
+
"@commitlint/config-conventional": "^17.0.0",
|
|
66
80
|
"@neovici/eslint-config": "^1.3.0",
|
|
67
|
-
"@open-wc/testing": "^
|
|
81
|
+
"@open-wc/testing": "^3.0.0",
|
|
68
82
|
"@polymer/iron-ajax": "^3.0.0",
|
|
69
83
|
"@polymer/iron-component-page": "^4.0.0",
|
|
70
84
|
"@polymer/iron-demo-helpers": "^3.0.0",
|
|
@@ -75,6 +89,6 @@
|
|
|
75
89
|
"@webcomponents/webcomponentsjs": "^2.0.0",
|
|
76
90
|
"eslint": "^7.0.0",
|
|
77
91
|
"husky": "^6.0.0",
|
|
78
|
-
"semantic-release": "^
|
|
92
|
+
"semantic-release": "^19.0.3"
|
|
79
93
|
}
|
|
80
94
|
}
|
|
@@ -1,56 +1,85 @@
|
|
|
1
1
|
import { assert, fixture, html } from '@open-wc/testing';
|
|
2
2
|
import { DefaultTree } from '@neovici/cosmoz-tree/cosmoz-default-tree';
|
|
3
3
|
import basicTree from './data/basicTree.js';
|
|
4
|
-
import { flush } from '@polymer/polymer/lib/utils/flush';
|
|
5
4
|
import '../cosmoz-treenode-navigator';
|
|
5
|
+
import { computeDataPlane, computeSearching, hasChildren, renderLevel } from '../helpers';
|
|
6
6
|
|
|
7
7
|
suite('cosmoz-treenode-navigator', () => {
|
|
8
8
|
let navigator;
|
|
9
9
|
|
|
10
10
|
setup(async () => {
|
|
11
|
-
navigator = await fixture(html
|
|
12
|
-
|
|
11
|
+
navigator = await fixture(html`
|
|
12
|
+
<cosmoz-treenode-navigator
|
|
13
|
+
.tree=${ new DefaultTree(basicTree) }
|
|
14
|
+
.searchPlaceholder="${ 'Custom search placeholder' }"
|
|
15
|
+
.searchMinLength="${ 2 }"
|
|
16
|
+
>`);
|
|
13
17
|
});
|
|
14
18
|
|
|
15
19
|
test('instantiating the element', () => {
|
|
16
20
|
assert.equal(navigator.tagName, 'COSMOZ-TREENODE-NAVIGATOR');
|
|
17
21
|
});
|
|
18
22
|
|
|
19
|
-
test('dataPlane initialised with tree', () => {
|
|
20
|
-
assert.equal(navigator.dataPlane[0].name, 'Root');
|
|
21
|
-
assert.equal(
|
|
22
|
-
navigator.dataPlane.length,
|
|
23
|
-
navigator.tree._roots.length
|
|
24
|
-
);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
23
|
test('tree length and sort', () => {
|
|
28
24
|
// given a node navigator with some data
|
|
29
25
|
|
|
30
26
|
// when I enter the first node
|
|
31
|
-
navigator.
|
|
32
|
-
.querySelector('#ironList paper-icon-button')
|
|
33
|
-
.click();
|
|
34
|
-
flush();
|
|
27
|
+
navigator.openNodePath = '1000';
|
|
35
28
|
|
|
29
|
+
const dataPlane = computeDataPlane(
|
|
30
|
+
computeSearching(navigator.searchValue, navigator.searchMinLength),
|
|
31
|
+
navigator.searchValue,
|
|
32
|
+
renderLevel(navigator.openNodePath, navigator.tree),
|
|
33
|
+
navigator.tree
|
|
34
|
+
);
|
|
36
35
|
// then I can see the contents of the node
|
|
37
36
|
// and it is ordered folder-first, then alphabetically
|
|
38
|
-
assert.equal(
|
|
39
|
-
assert.equal(
|
|
40
|
-
assert.equal(
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
assert.equal(dataPlane[0].name, 'Data');
|
|
38
|
+
assert.equal(dataPlane[1].name, 'Backup');
|
|
39
|
+
assert.equal(dataPlane.length, 2);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('set proper search placeholder', () => {
|
|
43
|
+
assert.equal(
|
|
44
|
+
navigator.shadowRoot.querySelector('cosmoz-input')
|
|
45
|
+
.shadowRoot
|
|
46
|
+
.querySelector('input').placeholder,
|
|
47
|
+
'Custom search placeholder');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('compute search if value is bigger than searchMinLength', () => {
|
|
51
|
+
assert.equal(computeSearching('long string', navigator.searchMinLength), true);
|
|
52
|
+
assert.equal(computeSearching('a', navigator.searchMinLength), false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('should check if node has children', () => {
|
|
56
|
+
const node = {
|
|
57
|
+
name: 'D:',
|
|
58
|
+
path: '1000',
|
|
59
|
+
children: { 1001: { name: 'Data', pathLocator: '1000.1001', children: { 1002: { name: 'John', pathLocator: '1000.1001.1002' }}}},
|
|
60
|
+
parentSectionName: 'D:',
|
|
61
|
+
pathLocator: '1000'
|
|
62
|
+
};
|
|
63
|
+
assert.equal(hasChildren(node), true);
|
|
64
|
+
const node2 = { name: 'Git', path: '1.5.7', parentSectionName: 'C:/Program Files', pathLocator: '1.5.7' };
|
|
65
|
+
assert.equal(hasChildren(node2), false);
|
|
43
66
|
});
|
|
44
67
|
|
|
45
68
|
test('match search string', () => {
|
|
46
69
|
// given a node navigator with some data
|
|
47
|
-
// when I search for '
|
|
48
|
-
navigator.searchValue = '
|
|
49
|
-
flush();
|
|
70
|
+
// when I search for 'John'
|
|
71
|
+
navigator.searchValue = 'John';
|
|
50
72
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
73
|
+
const dataPlane = computeDataPlane(
|
|
74
|
+
computeSearching(navigator.searchValue, navigator.searchMinLength),
|
|
75
|
+
navigator.searchValue,
|
|
76
|
+
renderLevel('1000', navigator.tree),
|
|
77
|
+
navigator.tree
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
//then I can see only 1 item matching 'John'
|
|
81
|
+
assert.lengthOf(dataPlane, 1);
|
|
82
|
+
assert.equal(dataPlane[0].name, 'John');
|
|
54
83
|
|
|
55
84
|
});
|
|
56
85
|
|
|
@@ -58,9 +87,14 @@ suite('cosmoz-treenode-navigator', () => {
|
|
|
58
87
|
// given a node navigator with some data
|
|
59
88
|
// when I search for 'NONEXISTING'
|
|
60
89
|
navigator.searchValue = 'NONEXISTING';
|
|
61
|
-
|
|
90
|
+
const dataPlane = computeDataPlane(
|
|
91
|
+
computeSearching(navigator.searchValue, navigator.searchMinLength),
|
|
92
|
+
navigator.searchValue,
|
|
93
|
+
renderLevel('1000', navigator.tree),
|
|
94
|
+
navigator.tree
|
|
95
|
+
);
|
|
62
96
|
|
|
63
97
|
//then I can see that is no contents
|
|
64
|
-
assert.lengthOf(
|
|
98
|
+
assert.lengthOf(dataPlane, 0);
|
|
65
99
|
});
|
|
66
100
|
});
|
package/test/data/basicTree.js
CHANGED
|
@@ -1,61 +1,118 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
1: {
|
|
3
|
-
|
|
4
|
-
name: 'Root',
|
|
3
|
+
name: 'C:',
|
|
5
4
|
pathLocator: '1',
|
|
6
5
|
children: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
2: {
|
|
7
|
+
name: 'Windows',
|
|
8
|
+
pathLocator: '1.2',
|
|
9
|
+
children: {
|
|
10
|
+
3: {
|
|
11
|
+
name: 'System',
|
|
12
|
+
pathLocator: '1.2.3',
|
|
13
|
+
children: {}
|
|
14
|
+
},
|
|
15
|
+
4: {
|
|
16
|
+
name: 'Microsoft.NET',
|
|
17
|
+
pathLocator: '1.2.4',
|
|
18
|
+
children: {}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
18
21
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
pathLocator: '1.2.3.4',
|
|
22
|
+
5: {
|
|
23
|
+
name: 'Program Files',
|
|
24
|
+
pathLocator: '1.5',
|
|
23
25
|
children: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
name: 'Node501',
|
|
32
|
-
pathLocator: '1.2.3.4.5.501',
|
|
33
|
-
children: {}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
26
|
+
6: {
|
|
27
|
+
name: 'Microsoft VS Code',
|
|
28
|
+
pathLocator: '1.5.6'
|
|
29
|
+
},
|
|
30
|
+
7: {
|
|
31
|
+
name: 'Git',
|
|
32
|
+
pathLocator: '1.5.7'
|
|
36
33
|
}
|
|
37
34
|
}
|
|
38
35
|
},
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
pathLocator: '1.2',
|
|
36
|
+
100: {
|
|
37
|
+
name: 'Users',
|
|
38
|
+
pathLocator: '1.100',
|
|
43
39
|
children: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
200: {
|
|
41
|
+
name: 'Default',
|
|
42
|
+
pathLocator: '1.100.200',
|
|
43
|
+
children: {
|
|
44
|
+
201: {
|
|
45
|
+
name: 'Documents',
|
|
46
|
+
pathLocator: '1.100.200.201'
|
|
47
|
+
},
|
|
48
|
+
202: {
|
|
49
|
+
name: 'Music',
|
|
50
|
+
pathLocator: '1.100.200.202'
|
|
51
|
+
},
|
|
52
|
+
203: {
|
|
53
|
+
name: 'Pictures',
|
|
54
|
+
pathLocator: '1.100.200.203'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
300: {
|
|
59
|
+
name: 'John',
|
|
60
|
+
pathLocator: '1.100.300',
|
|
48
61
|
children: {
|
|
49
62
|
301: {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
63
|
+
name: 'Documents',
|
|
64
|
+
pathLocator: '1.100.300.301'
|
|
65
|
+
},
|
|
66
|
+
302: {
|
|
67
|
+
name: 'Music',
|
|
68
|
+
pathLocator: '1.100.300.302'
|
|
69
|
+
},
|
|
70
|
+
303: {
|
|
71
|
+
name: 'Pictures',
|
|
72
|
+
pathLocator: '1.100.300.303'
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
400: {
|
|
77
|
+
name: 'Public',
|
|
78
|
+
pathLocator: '1.100.400',
|
|
79
|
+
children: {
|
|
80
|
+
401: {
|
|
81
|
+
name: 'Public Documents',
|
|
82
|
+
pathLocator: '1.100.400.401'
|
|
83
|
+
},
|
|
84
|
+
402: {
|
|
85
|
+
name: 'Public Music',
|
|
86
|
+
pathLocator: '1.100.400.402'
|
|
87
|
+
},
|
|
88
|
+
403: {
|
|
89
|
+
name: 'Public Pictures',
|
|
90
|
+
pathLocator: '1.100.400.403'
|
|
54
91
|
}
|
|
55
92
|
}
|
|
56
93
|
}
|
|
57
94
|
}
|
|
58
95
|
}
|
|
59
96
|
}
|
|
97
|
+
},
|
|
98
|
+
1000: {
|
|
99
|
+
name: 'D:',
|
|
100
|
+
pathLocator: '1000',
|
|
101
|
+
children: {
|
|
102
|
+
1001: {
|
|
103
|
+
name: 'Data',
|
|
104
|
+
pathLocator: '1000.1001',
|
|
105
|
+
children: {
|
|
106
|
+
1002: {
|
|
107
|
+
name: 'John',
|
|
108
|
+
pathLocator: '1000.1001.1002'
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
1002: {
|
|
113
|
+
name: 'Backup',
|
|
114
|
+
pathLocator: '1000.1002'
|
|
115
|
+
}
|
|
116
|
+
}
|
|
60
117
|
}
|
|
61
118
|
};
|
|
@@ -1,28 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { seleniumLauncher } from '@web/test-runner-selenium';
|
|
3
|
-
import webdriver from 'selenium-webdriver';
|
|
4
|
-
import firefox from 'selenium-webdriver/firefox.js';
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
nodeResolve: true,
|
|
8
|
-
coverageConfig: {
|
|
9
|
-
reportDir: 'coverage',
|
|
10
|
-
threshold: {
|
|
11
|
-
statements: 70,
|
|
12
|
-
branches: 70,
|
|
13
|
-
functions: 50,
|
|
14
|
-
lines: 70
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
files: [
|
|
18
|
-
'**!(node_modules)/*.test.js'
|
|
19
|
-
],
|
|
20
|
-
testFramework: { config: { ui: 'tdd' }},
|
|
21
|
-
browsers: [
|
|
22
|
-
chromeLauncher(),
|
|
23
|
-
seleniumLauncher({
|
|
24
|
-
driverBuilder: new webdriver.Builder().forBrowser('firefox').setFirefoxOptions(new firefox.Options().headless())
|
|
25
|
-
})
|
|
26
|
-
]
|
|
27
|
-
|
|
28
|
-
};
|
|
1
|
+
export { default } from '@neovici/cfg/web/test-runner.mjs';
|