blob: 09ffc97e8b44efb142ff4e75ebe38e817a10d05c [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
function test()
{
let documentNode;
async function nodeForSelector(selector) {
let nodeId = await documentNode.querySelector(selector);
return WI.domManager.nodeForId(nodeId);
}
function testNodeMatchesPath(node, message, {regular, full}) {
InspectorTest.expectEqual(WI.cssPath(node), regular, message);
if (full) {
let actual = WI.cssPath(node, {full: true});
InspectorTest.assert(actual === full, `Full path ${actual} doesn't match expected ${full}.`);
}
}
let suite = InspectorTest.createAsyncSuite("WI.cssPath");
suite.addTestCase({
name: "WI.cssPath.TopLevelNode",
description: "Top level nodes like html, body, and head are unique.",
async test() {
let html = await nodeForSelector("html");
testNodeMatchesPath(html, "HTML element should have simple selector 'html'.", {
regular: `html`,
full: `html`,
});
let body = await nodeForSelector("html > body");
testNodeMatchesPath(body, "BODY element should have simple selector 'body'.", {
regular: `body`,
full: `html > body[onload="runTest()"]`,
});
let head = await nodeForSelector("html > head");
testNodeMatchesPath(head, "HEAD element should have simple selector 'head'.", {
regular: `head`,
full: `html > head`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.ElementWithID",
description: "Element with ID is unique (#id). Path does not need to go past it.",
async test() {
let test = await nodeForSelector("#id-test");
testNodeMatchesPath(test, "Element with id should have simple selector '#id-test'.", {
regular: `#id-test`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#id-test`,
});
let div = await nodeForSelector("#id-test > div");
testNodeMatchesPath(div, "Element inside element with id should have path from id.", {
regular: `#id-test > div`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#id-test > div`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.InputElementFlair",
description: "Input elements include their type.",
async test() {
let input = await nodeForSelector("#input-test input");
testNodeMatchesPath(input, "Input element should include type.", {
regular: `#input-test > input[type="password"]`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#input-test > input[type="password"]`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.UniqueTagName",
description: "Elements with unique tag name do not need nth-child.",
async test() {
let span = await nodeForSelector("#unique-tag-test > span");
testNodeMatchesPath(span, "Elements with unique tag name should not need nth-child().", {
regular: `#unique-tag-test > span`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#unique-tag-test > span`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.NonUniqueTagName",
description: "Elements with non-unique tag name need nth-child.",
async test() {
let span = await nodeForSelector("#non-unique-tag-test > span ~ span");
testNodeMatchesPath(span, "Elements with non-unique tag name should need nth-child().", {
regular: `#non-unique-tag-test > span:nth-child(3)`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#non-unique-tag-test > span:nth-child(3)`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.UniqueClassName",
description: "Elements with unique class names should include their class names.",
async test() {
let beta = await nodeForSelector("#unique-class-test > .beta");
testNodeMatchesPath(beta, "Elements with unique class names should include their class names.", {
regular: `#unique-class-test > div.alpha.beta`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#unique-class-test > div.alpha.beta`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.NonUniqueClassName",
description: "Elements with non-unique class names should not include their class names.",
async test() {
let div = await nodeForSelector("#non-unique-class-test > div ~ div");
testNodeMatchesPath(div, "Elements with non-unique class names should not include their class names.", {
regular: `#non-unique-class-test > div:nth-child(2)`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#non-unique-class-test > div.alpha:nth-child(2)`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.UniqueTagAndClassName",
description: "Elements with unique tag and class name just use tag for simplicity.",
async test() {
let alpha = await nodeForSelector("#unique-tag-and-class-test > .alpha");
testNodeMatchesPath(alpha, "Elements with unique tag and class names should just have simple tag.", {
regular: `#unique-tag-and-class-test > div`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#unique-tag-and-class-test > div.alpha`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.DeepPath",
description: "Tests for element with complex path.",
async test() {
let small = await nodeForSelector("small");
testNodeMatchesPath(small, "Should be able to create path for deep elements.", {
regular: `body > div > div.deep-path-test > ul > li > div:nth-child(4) > ul > li.active > a > small`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div.deep-path-test > ul > li > div:nth-child(4) > ul.list > li.active > a[href="#"] > small`,
});
}
});
suite.addTestCase({
name: "WI.cssPath.PseudoElement",
description: "For a pseudo element we should get the path of the parent and append the pseudo element selector.",
async test() {
let div = await nodeForSelector("#pseudo-element-test > div ~ div");
let pseudoElementBefore = div.beforePseudoElement();
InspectorTest.assert(pseudoElementBefore);
testNodeMatchesPath(pseudoElementBefore, "Should be able to create path for ::before pseudo elements.", {
regular: `#pseudo-element-test > div:nth-child(3)::before`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#pseudo-element-test > div:nth-child(3)::before`,
});
let pseudoElementAfter = div.afterPseudoElement();
InspectorTest.assert(pseudoElementAfter);
testNodeMatchesPath(pseudoElementAfter, "Should be able to create path for ::after pseudo elements.", {
regular: `#pseudo-element-test > div:nth-child(3)::after`,
full: `html > body[onload="runTest()"] > div[style="visibility:hidden"] > div#pseudo-element-test > div:nth-child(3)::after`,
});
}
});
// FIXME: Write tests for nodes inside a Shadow DOM Tree.
WI.domManager.requestDocument((node) => {
documentNode = node;
suite.runTestCasesAndFinish();
});
}
</script>
</head>
<body onload="runTest()">
<p>Test for WI.cssPath.</p>
<!-- If display:none pseudo elements are not created. -->
<div style="visibility:hidden">
<div id="id-test">
<div></div>
</div>
<div id="input-test">
<input type="password">
</div>
<div id="unique-tag-test">
<div></div>
<span></span>
<div></div>
</div>
<div id="non-unique-tag-test">
<div></div>
<span></span>
<span></span>
<div></div>
</div>
<div id="unique-class-test">
<div class="alpha"></div>
<div class="alpha beta"></div>
<div class="alpha"></div>
</div>
<div id="non-unique-class-test">
<div class="alpha"></div>
<div class="alpha"></div>
<div class="alpha"></div>
</div>
<div id="unique-tag-and-class-test">
<div class="alpha"></div>
</div>
<div class="deep-path-test">
<ul>
<li>
<h1></h1>
<div></div>
<div></div>
<div>
<ul class="list">
<li></li>
<li class="active"><a href="#"><small></small></a></li>
<li></li>
</ul>
</div>
</li>
</ul>
</div>
<div id="pseudo-element-test">
<style>
#pseudo-element-test > div~div::before { content: "before"; }
#pseudo-element-test > div~div::after { content: "after"; }
</style>
<div></div>
<div></div>
</div>
</div>
</body>
</html>