1 var initialize_ElementTest = function() {
3 InspectorTest.findNode = function(matchFunction, callback)
5 callback = InspectorTest.safeWrap(callback);
7 var pendingRequests = 0;
8 function processChildren(node)
14 var children = (node.children() || []).concat(node.shadowRoots()).concat(Object.values(node.pseudoElements() || {}));
15 if (node.templateContent())
16 children.push(node.templateContent());
17 else if (node.importedDocument())
18 children.push(node.importedDocument());
20 for (var i = 0; i < children.length; ++i) {
21 var childNode = children[i];
22 if (matchFunction(childNode)) {
28 childNode.getChildNodes(processChildren.bind(null, childNode));
34 if (!result && !pendingRequests)
38 WebInspector.domModel.requestDocument(documentRequested.bind(this));
39 function documentRequested(doc)
42 doc.getChildNodes(processChildren.bind(null, doc));
46 InspectorTest.nodeWithId = function(idValue, callback)
48 function nodeIdMatches(node)
50 return node.getAttribute("id") === idValue;
52 InspectorTest.findNode(nodeIdMatches, callback);
55 InspectorTest.shadowRootByHostId = function(idValue, callback)
57 function shadowRootMatches(node)
59 return node.isShadowRoot() && node.parentNode.getAttribute("id") === idValue;
61 InspectorTest.findNode(shadowRootMatches, callback);
64 InspectorTest.nodeWithClass = function(classValue, callback)
66 function nodeClassMatches(node)
68 var classAttr = node.getAttribute("class");
69 return classAttr && classAttr.indexOf(classValue) > -1;
71 InspectorTest.findNode(nodeClassMatches, callback);
74 InspectorTest.expandedNodeWithId = function(idValue)
77 function callback(node)
81 InspectorTest.nodeWithId(idValue, callback);
85 InspectorTest.selectNode = function(node)
87 WebInspector.Revealer.reveal(node);
90 InspectorTest.selectNodeWithId = function(idValue, callback)
92 callback = InspectorTest.safeWrap(callback);
93 function onNodeFound(node)
95 InspectorTest.selectNode(node);
98 InspectorTest.nodeWithId(idValue, onNodeFound);
101 function waitForStylesRebuild(matchFunction, callback, requireRebuild)
103 (function sniff(node, rebuild)
105 if ((rebuild || !requireRebuild) && node && matchFunction(node)) {
109 InspectorTest.addSniffer(WebInspector.StylesSidebarPane.prototype, "_nodeStylesUpdatedForTest", sniff);
113 InspectorTest.waitForStyles = function(idValue, callback, requireRebuild)
115 callback = InspectorTest.safeWrap(callback);
117 function nodeWithId(node)
119 return node.getAttribute("id") === idValue;
122 waitForStylesRebuild(nodeWithId, callback, requireRebuild);
125 InspectorTest.waitForStylesForClass = function(classValue, callback, requireRebuild)
127 callback = InspectorTest.safeWrap(callback);
129 function nodeWithClass(node)
131 var classAttr = node.getAttribute("class");
132 return classAttr && classAttr.indexOf(classValue) > -1;
135 waitForStylesRebuild(nodeWithClass, callback, requireRebuild);
138 InspectorTest.selectNodeAndWaitForStyles = function(idValue, callback)
140 WebInspector.inspectorView.showPanel("elements");
142 callback = InspectorTest.safeWrap(callback);
146 InspectorTest.waitForStyles(idValue, stylesUpdated, true);
147 InspectorTest.selectNodeWithId(idValue, nodeSelected);
149 function nodeSelected(node)
154 function stylesUpdated()
156 callback(targetNode);
160 InspectorTest.selectNodeAndWaitForStylesWithComputed = function(idValue, callback)
162 callback = InspectorTest.safeWrap(callback);
164 function stylesCallback(targetNode)
166 InspectorTest.addSniffer(WebInspector.ComputedStyleSidebarPane.prototype, "onContentReady", callback);
167 WebInspector.panels.elements.sidebarPanes.computedStyle.expand();
170 InspectorTest.selectNodeAndWaitForStyles(idValue, stylesCallback);
173 InspectorTest.firstElementsTreeOutline = function()
175 return WebInspector.panels.elements._treeOutlines[0];
178 InspectorTest.dumpSelectedElementStyles = function(excludeComputed, excludeMatched, omitLonghands, includeSelectorGroupMarks)
180 function extractText(element)
182 var text = element.textContent;
185 var anchor = element.querySelector("[data-uncopyable]");
188 var anchorText = anchor.getAttribute("data-uncopyable");
189 var uiLocation = anchor.__uiLocation;
190 var anchorTarget = uiLocation ? (uiLocation.uiSourceCode.name() + ":" + (uiLocation.lineNumber + 1) + ":" + (uiLocation.columnNumber + 1)) : "";
191 return anchorText + " -> " + anchorTarget;
194 function buildMarkedSelectors(element)
197 for (var node = element.firstChild; node; node = node.nextSibling) {
198 if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains("selector-matches"))
199 result += "[$" + node.textContent + "$]";
201 result += node.textContent;
206 var styleSections = WebInspector.panels.elements.sidebarPanes.styles.sections;
207 for (var pseudoId in styleSections) {
208 var pseudoName = WebInspector.StylesSidebarPane.PseudoIdNames[pseudoId];
209 var sections = styleSections[pseudoId];
210 for (var i = 0; i < sections.length; ++i) {
211 var section = sections[i];
212 if (section.computedStyle && excludeComputed)
214 if (section.rule && excludeMatched)
216 if (section.element && section.element.classList.contains("user-rule") && !WebInspector.settings.showUserAgentStyles.get())
218 if (section.element.previousSibling && section.element.previousSibling.className === "sidebar-separator")
219 InspectorTest.addResult("======== " + section.element.previousSibling.textContent + " ========");
220 InspectorTest.addResult((section.expanded ? "[expanded] " : "[collapsed] ") + (section.noAffect ? "[no-affect] " : ""));
221 var chainEntries = section.titleElement.querySelectorAll(".media-list .media");
222 chainEntries = Array.prototype.slice.call(chainEntries);
223 if (section.titleElement.children[1])
224 chainEntries.push(section.titleElement.children[1]);
226 for (var j = 0; j < chainEntries.length; ++j) {
227 var chainEntry = chainEntries[j];
228 var entryLine = includeSelectorGroupMarks ? buildMarkedSelectors(chainEntry.children[1]) : chainEntry.children[1].textContent;
229 if (chainEntry.children[2])
230 entryLine += " " + chainEntry.children[2].textContent;
231 entryLine += " (" + extractText(chainEntry.children[0]) + ")";
232 InspectorTest.addResult(entryLine);
235 InspectorTest.dumpStyleTreeOutline(section.propertiesTreeOutline, omitLonghands ? 1 : 2);
236 InspectorTest.addResult("");
238 InspectorTest.addResult("");
242 InspectorTest.toggleStyleProperty = function(propertyName, checked)
244 var treeItem = InspectorTest.getElementStylePropertyTreeItem(propertyName);
245 treeItem.toggleEnabled({ target: { checked: checked }, consume: function() { } });
248 InspectorTest.toggleMatchedStyleProperty = function(propertyName, checked)
250 var treeItem = InspectorTest.getMatchedStylePropertyTreeItem(propertyName);
251 treeItem.toggleEnabled({ target: { checked: checked }, consume: function() { } });
254 InspectorTest.expandAndDumpSelectedElementEventListeners = function(callback)
256 InspectorTest.expandSelectedElementEventListeners(function() {
257 InspectorTest.dumpSelectedElementEventListeners(callback);
261 InspectorTest.expandSelectedElementEventListeners = function(callback)
263 var sidebarPane = WebInspector.panels.elements.sidebarPanes.eventListeners;
264 sidebarPane.expand();
266 InspectorTest.runAfterPendingDispatches(function() {
267 InspectorTest.expandSelectedElementEventListenersSubsections(callback);
271 InspectorTest.expandSelectedElementEventListenersSubsections = function(callback)
273 var eventListenerSections = WebInspector.panels.elements.sidebarPanes.eventListeners.sections;
274 for (var i = 0; i < eventListenerSections.length; ++i)
275 eventListenerSections[i].expand();
277 // Multiple sections may expand.
278 InspectorTest.runAfterPendingDispatches(function() {
279 InspectorTest.expandSelectedElementEventListenersEventBars(callback);
283 InspectorTest.expandSelectedElementEventListenersEventBars = function(callback)
285 var eventListenerSections = WebInspector.panels.elements.sidebarPanes.eventListeners.sections;
286 for (var i = 0; i < eventListenerSections.length; ++i) {
287 var eventBarChildren = eventListenerSections[i]._eventBars.children;
288 for (var j = 0; j < eventBarChildren.length; ++j)
289 eventBarChildren[j]._section.expand();
292 // Multiple sections may expand.
293 InspectorTest.runAfterPendingDispatches(callback);
296 InspectorTest.dumpSelectedElementEventListeners = function(callback)
298 function formatSourceNameProperty(value)
300 return "[clipped-for-test]/" + value.replace(/(.*?\/)LayoutTests/, "LayoutTests");
303 var eventListenerSections = WebInspector.panels.elements.sidebarPanes.eventListeners.sections;
304 for (var i = 0; i < eventListenerSections.length; ++i) {
305 var section = eventListenerSections[i];
306 var eventType = section._title;
307 InspectorTest.addResult("");
308 InspectorTest.addResult("======== " + eventType + " ========");
309 var eventBarChildren = section._eventBars.children;
310 for (var j = 0; j < eventBarChildren.length; ++j) {
311 var objectPropertiesSection = eventBarChildren[j]._section;
312 InspectorTest.dumpObjectPropertySection(objectPropertiesSection, {
313 sourceName: formatSourceNameProperty
321 InspectorTest.dumpObjectPropertySection = function(section, formatters)
323 var expandedSubstring = section.expanded ? "[expanded]" : "[collapsed]";
324 InspectorTest.addResult(expandedSubstring + " " + section.titleElement.textContent + " " + section.subtitleAsTextForTest);
325 if (!section.propertiesForTest)
328 for (var i = 0; i < section.propertiesForTest.length; ++i) {
329 var property = section.propertiesForTest[i];
330 var key = property.name;
331 var value = property.value._description;
332 if (key in formatters)
333 value = formatters[key](value);
334 InspectorTest.addResult(" " + key + ": " + value);
338 InspectorTest.dumpObjectPropertySectionDeep = function(section)
340 function domNodeToString(node) {
342 return "'" + node.textContent + "'";
346 function dumpTreeElementRecursively(treeElement, prefix) {
347 if ("nameElement" in treeElement)
348 InspectorTest.addResult(prefix + domNodeToString(treeElement.nameElement) + " => " + domNodeToString(treeElement.valueElement));
350 InspectorTest.addResult(prefix + treeElement.title);
351 for (var i = 0; i < treeElement.children.length; i++)
352 dumpTreeElementRecursively(treeElement.children[i], prefix + " ");
355 var childNodes = section.propertiesTreeOutline.children;
356 for (var i = 0; i < childNodes.length; i++) {
357 dumpTreeElementRecursively(childNodes[i], "");
361 // FIXME: this returns the first tree item found (may fail for same-named properties in a style).
362 InspectorTest.getElementStylePropertyTreeItem = function(propertyName)
364 var styleSections = WebInspector.panels.elements.sidebarPanes.styles.sections[0];
365 var elementStyleSection = styleSections[1];
366 return InspectorTest.getFirstPropertyTreeItemForSection(elementStyleSection, propertyName);
369 // FIXME: this returns the first tree item found (may fail for same-named properties in a style).
370 InspectorTest.getMatchedStylePropertyTreeItem = function(propertyName)
372 var styleSections = WebInspector.panels.elements.sidebarPanes.styles.sections[0];
373 for (var i = 1; i < styleSections.length; ++i) {
374 var treeItem = InspectorTest.getFirstPropertyTreeItemForSection(styleSections[i], propertyName);
381 InspectorTest.getFirstPropertyTreeItemForSection = function(section, propertyName)
383 var outline = section.propertiesTreeOutline;
384 for (var i = 0; i < outline.children.length; ++i) {
385 var treeItem = outline.children[i];
386 if (treeItem.name === propertyName)
392 InspectorTest.dumpStyleTreeOutline = function(treeItem, depth)
394 var children = treeItem.children;
395 for (var i = 0; i < children.length; ++i)
396 InspectorTest.dumpStyleTreeItem(children[i], "", depth || 2);
399 InspectorTest.dumpStyleTreeItem = function(treeItem, prefix, depth)
401 // Filter out width and height properties in order to minimize
403 if (!treeItem.listItemElement.textContent.indexOf("width") ||
404 !treeItem.listItemElement.textContent.indexOf("height"))
407 if (treeItem.listItemElement.classList.contains("inherited"))
410 if (treeItem.listItemElement.classList.contains("overloaded") || treeItem.listItemElement.classList.contains("inactive") || treeItem.listItemElement.classList.contains("not-parsed-ok"))
411 typePrefix += "/-- overloaded --/ ";
412 if (treeItem.listItemElement.classList.contains("disabled"))
413 typePrefix += "/-- disabled --/ ";
414 var textContent = treeItem.listItemElement.textContent;
416 // Add non-selectable url text.
417 var textData = treeItem.listItemElement.querySelector("[data-uncopyable]");
419 textContent += textData.getAttribute("data-uncopyable");
420 InspectorTest.addResult(prefix + typePrefix + textContent);
423 var children = treeItem.children;
424 for (var i = 0; children && i < children.length; ++i)
425 InspectorTest.dumpStyleTreeItem(children[i], prefix + " ", depth);
429 InspectorTest.dumpElementsTree = function(rootNode, depth, resultsArray)
431 function beautify(element)
433 return element.innerText.replace(/\u200b/g, "").replace(/\n/g, "\\n").trim();
436 function dumpMap(name, map)
440 result.push(id + "=" + map[id]);
443 return name + ":[" + result.join(",") + "]";
446 function userPropertyDataDump(treeItem)
448 if (treeItem._elementCloseTag)
451 var userProperties = "";
452 var node = treeItem.representedObject;
454 userProperties += dumpMap("userProperties", node._userProperties);
455 var dump = dumpMap("descendantUserAttributeCounters", node._descendantUserPropertyCounters);
458 userProperties += ", ";
459 userProperties += dump;
462 userProperties = " [" + userProperties + "]";
464 return userProperties;
467 function print(treeItem, prefix, depth)
469 if (treeItem.listItemElement) {
471 if (treeItem.hasChildren) {
472 if (treeItem.expanded)
479 var userProperties = userPropertyDataDump(treeItem);
480 var value = prefix + expander + beautify(treeItem.listItemElement) + userProperties;
482 resultsArray.push(value);
484 InspectorTest.addResult(value);
487 if (!treeItem.expanded)
490 var children = treeItem.children;
491 var newPrefix = treeItem === treeItem.treeOutline ? "" : prefix + " ";
492 for (var i = 0; depth && children && i < children.length; ++i) {
493 if (!children[i]._elementCloseTag)
494 print(children[i], newPrefix, depth - 1);
496 print(children[i], prefix, depth);
500 var treeOutline = InspectorTest.firstElementsTreeOutline();
501 treeOutline._updateModifiedNodes();
502 print(rootNode ? treeOutline.findTreeElement(rootNode) : treeOutline, "", depth || 10000);
505 InspectorTest.expandElementsTree = function(callback)
507 callback = InspectorTest.safeWrap(callback);
509 function expand(treeItem)
511 var children = treeItem.children;
512 for (var i = 0; children && i < children.length; ++i) {
513 children[i].expand();
518 function onAllNodesAvailable()
520 InspectorTest.firstElementsTreeOutline()._updateModifiedNodes();
521 expand(InspectorTest.firstElementsTreeOutline());
524 WebInspector.inspectorView.showPanel("elements");
525 InspectorTest.findNode(function() { return false; }, onAllNodesAvailable);
528 InspectorTest.dumpDOMAgentTree = function(node)
530 if (!WebInspector.domModel._document)
533 function dump(node, prefix)
535 InspectorTest.addResult(prefix + node.nodeName());
536 prefix = prefix + " ";
538 if (node.templateContent())
539 dump(node.templateContent(), prefix);
540 if (node.importedDocument())
541 dump(node.importedDocument(), prefix);
542 var shadowRoots = node.shadowRoots();
543 for (var i = 0; i < shadowRoots.length; ++i)
544 dump(shadowRoots[i], prefix);
545 var children = node.children();
546 for (var i = 0; children && i < children.length; ++i)
547 dump(children[i], prefix);
553 InspectorTest.rangeText = function(range)
556 return "[undefined-undefined]";
557 return "[" + range.startLine + ":" + range.startColumn + "-" + range.endLine + ":" + range.endColumn + "]";
560 InspectorTest.generateUndoTest = function(testBody)
562 function result(next)
564 var testNode = InspectorTest.expandedNodeWithId(/function\s([^(]*)/.exec(testBody)[1]);
565 InspectorTest.addResult("Initial:");
566 InspectorTest.dumpElementsTree(testNode);
572 InspectorTest.addResult("Post-action:");
573 InspectorTest.dumpElementsTree(testNode);
574 WebInspector.domModel.undo(redo);
579 InspectorTest.addResult("Post-undo (initial):");
580 InspectorTest.dumpElementsTree(testNode);
581 WebInspector.domModel.redo(done);
586 InspectorTest.addResult("Post-redo (action):");
587 InspectorTest.dumpElementsTree(testNode);
591 result.toString = function()
593 return testBody.toString();
600 InspectorTest.dumpRulesArray = function(rules, currentIndent)
604 currentIndent = currentIndent || "";
605 for (var i = 0; i < rules.length; ++i)
606 InspectorTest.dumpRule(rules[i], currentIndent);
609 InspectorTest.dumpRuleMatchesArray = function(matches, currentIndent)
613 currentIndent = currentIndent || "";
614 for (var i = 0; i < matches.length; ++i)
615 InspectorTest.dumpRule(matches[i].rule, currentIndent);
618 InspectorTest.dumpRule = function(rule, currentIndent)
620 function selectorRange()
622 var selectors = rule.selectorList.selectors;
623 if (!selectors || !selectors[0].range)
626 for (var i = 0; i < selectors.length; ++i) {
627 var range = selectors[i].range;
628 ranges.push(range.startLine + ":" + range.startColumn + "-" + range.endLine + ":" + range.endColumn);
630 return ", " + ranges.join("; ");
633 currentIndent = currentIndent || "";
635 if (!rule.type || rule.type === "style") {
636 InspectorTest.addResult(currentIndent + rule.selectorList.text + ": [" + rule.origin + selectorRange() + "] {");
637 InspectorTest.dumpStyle(rule.style, currentIndent + indent);
638 InspectorTest.addResult(currentIndent + "}");
642 if (rule.type === "media") {
643 InspectorTest.addResult(currentIndent + "@media " + rule.mediaText + " {");
644 InspectorTest.dumpRulesArray(rule.childRules, currentIndent + indent);
645 InspectorTest.addResult(currentIndent + "}");
649 if (rule.type === "import") {
650 InspectorTest.addResult(currentIndent + "@import: header=" + InspectorTest.rangeText(rule.headerRange) + ", body=" + InspectorTest.rangeText(rule.bodyRange));
654 if (rule.type === "page" || rule.type === "font-face") {
655 if (rule.type === "page")
656 InspectorTest.addResult(currentIndent + rule.selectorList.text + " {");
658 InspectorTest.addResult(currentIndent + "@" + rule.type + " " + (rule.selectorList.text ? rule.selectorList.text + " " : "") + "{");
659 InspectorTest.dumpStyle(rule.style, currentIndent + indent);
660 InspectorTest.addResult(currentIndent + "}");
664 if (rule.type === "charset") {
665 InspectorTest.addResult("@charset");
669 InspectorTest.addResult(currentIndent + "[UNKNOWN RULE]: header=" + InspectorTest.rangeText(rule.headerRange) + ", body=" + InspectorTest.rangeText(rule.bodyRange));
672 InspectorTest.dumpStyle = function(style, currentIndent)
674 currentIndent = currentIndent || "";
676 InspectorTest.addResult(currentIndent + "[NO STYLE]");
679 for (var i = 0; i < style.cssProperties.length; ++i) {
680 var property = style.cssProperties[i];
681 if (!property.disabled)
682 InspectorTest.addResult(currentIndent + "['" + property.name + "':'" + property.value + "'" + (property.important ? " is-important" : "") + (("parsedOk" in property) ? " non-parsed" : "") +"] @" + InspectorTest.rangeText(property.range) + " ");
684 InspectorTest.addResult(currentIndent + "[text='" + property.text + "'] disabled");
688 InspectorTest.dumpCSSStyleDeclaration = function(style, currentIndent)
690 currentIndent = currentIndent || "";
692 InspectorTest.addResult(currentIndent + "[NO STYLE]");
695 var properties = style.allProperties;
696 for (var i = 0; i < properties.length; ++i) {
697 var property = properties[i];
698 if (!property.disabled)
699 InspectorTest.addResult(currentIndent + "['" + property.name + "':'" + property.value + "'" + (property.important ? " is-important" : "") + (!property["parsedOk"] ? " non-parsed" : "") +"] @" + InspectorTest.rangeText(property.range) + " ");
701 InspectorTest.addResult(currentIndent + "[text='" + property.text + "'] disabled");
705 InspectorTest.dumpBreadcrumb = function(message)
708 InspectorTest.addResult(message + ":");
710 var crumbs = WebInspector.inspectorView.panel("elements").crumbsElement;
711 var crumb = crumbs.lastChild;
713 result.unshift(crumb.textContent);
714 crumb = crumb.previousSibling;
716 InspectorTest.addResult(result.join(" > "));
719 InspectorTest.matchingSelectors = function(rule)
722 for (var i = 0; i < rule.matchingSelectors.length; ++i)
723 selectors.push(rule.selectors[rule.matchingSelectors[i]].value);
724 return "[" + selectors.join(", ") + "]";
727 InspectorTest.addNewRule = function(selector, callback)
729 // Click "Add new rule".
730 document.getElementById("add-style-button-test-id").click();
731 var section = WebInspector.panels.elements.sidebarPanes.styles.sections[0][2];
732 if (typeof selector === "string")
733 section._selectorElement.textContent = selector;
734 section._selectorElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
735 InspectorTest.addSniffer(WebInspector.BlankStylePropertiesSection.prototype, "makeNormal", callback);
738 InspectorTest.dumpInspectorHighlight = function(node, callback)
740 node.boxModel(function(boxModel) {
741 var rectNames = ["margin", "border", "padding", "content"];
742 for (var i = 0; i < rectNames.length; i++) {
743 var rect = boxModel[rectNames[i]];
744 InspectorTest.addResult(rectNames[i] + " rect is " + (rect[4] - rect[0]) + " x " + (rect[5] - rect[1]) + " at (" + rect[0] + ", " + rect[1] + ")");
750 InspectorTest.dumpInspectorHighlightShape = function(node, callback)
752 node.boxModel(function(shapes) {
753 InspectorTest.addResult(JSON.stringify(shapes.shapeOutside.shape));