OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 function initialize_DumpAccessibilityNodesTest() { | |
6 | |
7 var nodeInfo = {}; | |
8 InspectorTest.trackGetChildNodesEvents(nodeInfo); | |
9 | |
10 InspectorTest.dumpAccessibilityNodesBySelectorAndCompleteTest = function(selecto
r, fetchRelatives, msg) { | |
11 if (msg.error) { | |
12 InspectorTest.log(msg.error.message); | |
13 InspectorTest.completeTest(); | |
14 return; | |
15 } | |
16 | |
17 var rootNode = msg.result.root; | |
18 var rootNodeId = rootNode.nodeId; | |
19 InspectorTest.addNode(nodeInfo, rootNode); | |
20 | |
21 sendQuerySelectorAll(rootNodeId, selector) | |
22 .then((msg) => { return getAXNodes(msg, fetchRelatives || false) } ) | |
23 .then(() => { done(); }) | |
24 .then(() => { | |
25 InspectorTest.completeTest(); | |
26 }) | |
27 .catch((msg) => { InspectorTest.log("Error: " + JSON.stringify(msg)); }) | |
28 } | |
29 | |
30 function sendCommandPromise(command, params) | |
31 { | |
32 return new Promise(function(resolve, reject) { | |
33 InspectorTest.sendCommand(command, params, function(msg) { | |
34 if (msg.error) { | |
35 reject(msg.error); | |
36 return; | |
37 } | |
38 | |
39 resolve(msg); | |
40 }) | |
41 }); | |
42 } | |
43 | |
44 function done() | |
45 { | |
46 sendCommandPromise("Runtime.evaluate", { expression: "done();" }); | |
47 } | |
48 | |
49 function sendQuerySelectorAll(nodeId, selector) | |
50 { | |
51 return sendCommandPromise("DOM.querySelectorAll", { "nodeId": nodeId, "selec
tor": | |
52 selector }); | |
53 } | |
54 | |
55 function getAXNodes(msg, fetchRelatives) | |
56 { | |
57 var promise = Promise.resolve(); | |
58 if (!msg.result || !msg.result.nodeIds) { | |
59 InspectorTest.log("Unexpected result: " + JSON.stringify(msg)); | |
60 InspectorTest.completeTest(); | |
61 } | |
62 msg.result.nodeIds.forEach((id) => { | |
63 if (fetchRelatives) { | |
64 promise = promise.then(() => { | |
65 return sendCommandPromise("Accessibility.getPartialAXTree", { "n
odeId": id, "fetchRelatives": true }); | |
66 }); | |
67 promise = promise.then((msg) => { return rewriteRelatedNodes(msg, id
); }) | |
68 .then((msg) => { return dumpTreeStructure(msg); }); | |
69 | |
70 } | |
71 promise = promise.then(() => { return sendCommandPromise("Accessibility.
getPartialAXTree", { "nodeId": id, "fetchRelatives": false }); }) | |
72 .then((msg) => { return rewriteRelatedNodes(msg, id); }
) | |
73 .then((msg) => { return dumpNode(msg); }); | |
74 | |
75 }); | |
76 return promise; | |
77 } | |
78 | |
79 function describeDomNode(nodeData) | |
80 { | |
81 var description = nodeData.nodeName.toLowerCase(); | |
82 switch (nodeData.nodeType) { | |
83 case Node.ELEMENT_NODE: | |
84 var p = nodeData.attributes.indexOf("id"); | |
85 if (p >= 0) | |
86 description += "#" + nodeData.attributes[p + 1]; | |
87 } | |
88 return description; | |
89 } | |
90 | |
91 function rewriteBackendDomNodeId(axNode, selectedNodeId, promises) | |
92 { | |
93 if (!("backendDOMNodeId" in axNode)) | |
94 return; | |
95 | |
96 function rewriteBackendDomNodeIdPromise(resolve, reject) | |
97 { | |
98 if (!("backendDOMNodeId" in axNode)) { | |
99 resolve(); | |
100 return; | |
101 } | |
102 var backendDOMNodeId = axNode.backendDOMNodeId; | |
103 | |
104 function onDomNodeResolved(backendDOMNodeId, message) | |
105 { | |
106 if (!message.result || !message.result.nodeIds) { | |
107 InspectorTest.log("Unexpected result for pushNodesByBackendIdsTo
Frontend: " + JSON.stringify(message)); | |
108 InspectorTest.completeTest(); | |
109 return; | |
110 } | |
111 var nodeId = message.result.nodeIds[0]; | |
112 if (!(nodeId in nodeInfo)) { | |
113 axNode.domNode = "[NODE NOT FOUND]"; | |
114 resolve(); | |
115 return; | |
116 } | |
117 var domNode = nodeInfo[nodeId]; | |
118 delete axNode.backendDOMNodeId; | |
119 axNode.domNode = describeDomNode(domNode); | |
120 if (nodeId === selectedNodeId) | |
121 axNode.selected = true; | |
122 resolve(); | |
123 } | |
124 | |
125 var params = { "backendNodeIds": [ backendDOMNodeId ] }; | |
126 InspectorTest.sendCommand("DOM.pushNodesByBackendIdsToFrontend", params
, onDomNodeResolved.bind(null, backendDOMNodeId)); | |
127 } | |
128 promises.push(new Promise(rewriteBackendDomNodeIdPromise)); | |
129 } | |
130 | |
131 function rewriteRelatedNode(relatedNode) | |
132 { | |
133 function rewriteRelatedNodePromise(resolve, reject) | |
134 { | |
135 if (!("backendDOMNodeId" in relatedNode)) { | |
136 reject("Could not find backendDOMNodeId in " + JSON.stringify(relate
dNode)); | |
137 return; | |
138 } | |
139 var backendDOMNodeId = relatedNode.backendDOMNodeId; | |
140 | |
141 function onNodeResolved(backendDOMNodeId, message) | |
142 { | |
143 if (!message.result || !message.result.nodeIds) { | |
144 InspectorTest.log("Unexpected result for pushNodesByBackendIdsTo
Frontend: " + JSON.stringify(message)); | |
145 InspectorTest.completeTest(); | |
146 return; | |
147 } | |
148 var nodeId = message.result.nodeIds[0]; | |
149 if (!(nodeId in nodeInfo)) { | |
150 relatedNode.nodeResult = "[NODE NOT FOUND]"; | |
151 resolve(); | |
152 return; | |
153 } | |
154 var domNode = nodeInfo[nodeId]; | |
155 delete relatedNode.backendDOMNodeId; | |
156 relatedNode.nodeResult = describeDomNode(domNode); | |
157 resolve(); | |
158 } | |
159 var params = { "backendNodeIds": [ backendDOMNodeId ] }; | |
160 InspectorTest.sendCommand("DOM.pushNodesByBackendIdsToFrontend", params,
onNodeResolved.bind(null, backendDOMNodeId)); | |
161 | |
162 } | |
163 return new Promise(rewriteRelatedNodePromise); | |
164 } | |
165 | |
166 function checkExists(path, obj) | |
167 { | |
168 var pathComponents = path.split("."); | |
169 var currentPath = []; | |
170 var currentObject = obj; | |
171 for (var component of pathComponents) { | |
172 var isArray = false; | |
173 var index = -1; | |
174 var matches = component.match(/(\w+)\[(\d+)\]/); | |
175 if (matches) { | |
176 isArray = true; | |
177 component = matches[1]; | |
178 index = Number.parseInt(matches[2], 10); | |
179 } | |
180 currentPath.push(component); | |
181 if (!(component in currentObject)) { | |
182 InspectorTest.log("Could not find " + currentPath.join(".") + " in "
+ JSON.stringify(obj, null, " ")); | |
183 InspectorTest.completeTest(); | |
184 } | |
185 if (isArray) | |
186 currentObject = currentObject[component][index]; | |
187 else | |
188 currentObject = currentObject[component]; | |
189 } | |
190 return true; | |
191 } | |
192 | |
193 function check(condition, errorMsg, obj) | |
194 { | |
195 if (condition) | |
196 return true; | |
197 throw new Error(errorMsg + " in " + JSON.stringify(obj, null, " ")); | |
198 } | |
199 | |
200 function rewriteRelatedNodeValue(value, promises) | |
201 { | |
202 checkExists("relatedNodes", value); | |
203 var relatedNodeArray = value.relatedNodes; | |
204 check(Array.isArray(relatedNodeArray), "relatedNodes should be an array", JS
ON.stringify(value)); | |
205 for (var relatedNode of relatedNodeArray) { | |
206 promises.push(rewriteRelatedNode(relatedNode)); | |
207 } | |
208 } | |
209 | |
210 function rewriteRelatedNodes(msg, nodeId) | |
211 { | |
212 if (msg.error) { | |
213 throw new Error(msg.error.message); | |
214 } | |
215 | |
216 var promises = []; | |
217 for (var node of msg.result.nodes) { | |
218 if (node.ignored) { | |
219 checkExists("ignoredReasons", node); | |
220 var properties = node.ignoredReasons; | |
221 } else { | |
222 checkExists("properties", node); | |
223 var properties = node.properties; | |
224 } | |
225 if (node.name && node.name.sources) { | |
226 for (var source of node.name.sources) { | |
227 var value; | |
228 if (source.value) | |
229 value = source.value; | |
230 if (source.attributeValue) | |
231 value = source.attributeValue; | |
232 if (!value) | |
233 continue; | |
234 if (value.type === "idrefList" || | |
235 value.type === "idref" || | |
236 value.type === "nodeList") | |
237 rewriteRelatedNodeValue(value, promises); | |
238 } | |
239 } | |
240 for (var property of properties) { | |
241 if (property.value.type === "idrefList" || | |
242 property.value.type === "idref" || | |
243 property.value.type === "nodeList") | |
244 rewriteRelatedNodeValue(property.value, promises); | |
245 } | |
246 rewriteBackendDomNodeId(node, nodeId, promises); | |
247 } | |
248 return Promise.all(promises).then(() => { return msg; }); | |
249 } | |
250 | |
251 function dumpNode(msg) | |
252 { | |
253 function stripIds(key, value) | |
254 { | |
255 var stripKeys = ["id", "backendDOMNodeId", "nodeId", "parentId"]; | |
256 if (stripKeys.indexOf(key) !== -1) | |
257 return "<" + typeof(value) + ">"; | |
258 var deleteKeys = ["selected"]; | |
259 if (deleteKeys.indexOf(key) !== -1) | |
260 return undefined; | |
261 return value; | |
262 } | |
263 if (!msg.result || !msg.result.nodes || msg.result.nodes.length !== 1) { | |
264 InspectorTest.log("Expected exactly one node in " + JSON.stringify(msg,
null, " ")); | |
265 return; | |
266 } | |
267 InspectorTest.log(JSON.stringify(msg.result.nodes[0], stripIds, " ")); | |
268 } | |
269 | |
270 function dumpTreeStructure(msg) | |
271 { | |
272 function printNodeAndChildren(node, leadingSpace) | |
273 { | |
274 leadingSpace = leadingSpace || ""; | |
275 var string = leadingSpace; | |
276 if (node.selected) | |
277 string += "*"; | |
278 if (node.role) | |
279 string += node.role.value; | |
280 else | |
281 string += "<no role>"; | |
282 string += (node.name && node.name.value !== "" ? " \"" + node.name.value
+ "\"" : ""); | |
283 if (node.children) { | |
284 for (var child of node.children) | |
285 string += "\n" + printNodeAndChildren(child, leadingSpace + " "
); | |
286 } | |
287 return string; | |
288 } | |
289 | |
290 var rawMsg = JSON.stringify(msg, null, " "); | |
291 var nodeMap = {}; | |
292 if ("result" in msg && "nodes" in msg.result) { | |
293 for (var node of msg.result.nodes) | |
294 nodeMap[node.nodeId] = node; | |
295 } | |
296 for (var nodeId in nodeMap) { | |
297 var node = nodeMap[nodeId]; | |
298 if (node.childIds) { | |
299 node.children = []; | |
300 for (var i = 0; i < node.childIds.length && node.childIds.length > 0
;) { | |
301 var childId = node.childIds[i]; | |
302 if (childId in nodeMap) { | |
303 var child = nodeMap[childId]; | |
304 child.parentId = nodeId; | |
305 node.children.push(child); | |
306 | |
307 node.childIds.splice(i, 1); | |
308 } else { | |
309 node.childIds[i] = "<string>"; | |
310 i++; | |
311 } | |
312 } | |
313 if (!node.childIds.length) | |
314 delete node.childIds; | |
315 if (!node.children.length) | |
316 delete node.children; | |
317 } | |
318 } | |
319 var rootNode = Object.values(nodeMap).find((node) => !("parentId" in node)); | |
320 for (var node of Object.values(nodeMap)) | |
321 delete node.parentId; | |
322 | |
323 InspectorTest.log("\n" + printNodeAndChildren(rootNode)); | |
324 } | |
325 | |
326 } | |
OLD | NEW |