Elements { public static String generateCssSelector(Element element, GeneratorContext context) { if (element.id().length() > 0) { return "#" + element.id(); } String tagName = element.tagName().replace(':', '|'); StringBuilder selector = new StringBuilder(tagName); addClasses(element, selector); Element parent = element.parent(); if (parent == null) { return selector.toString(); } if (parent.tagName().equals("body")) { if (context.getSource().contains("<body")) { return "body > " + selector.toString(); } else { return selector.toString(); } } String directChildrenSelector = ">" + selector.toString(); int numberOfDirectChildren = getNumberOfChildren(directChildrenSelector, parent); if (context.isNestedElement()) { int numberOfAllChildren = getNumberOfChildren(selector.toString(), parent); if (numberOfAllChildren != numberOfDirectChildren) { return null; } } if (numberOfDirectChildren > 1) { org.jsoup.select.Elements childrenWithSameSelector = parent .select(directChildrenSelector); String type = childrenWithSameSelector.get(0).tagName(); org.jsoup.select.Elements childrenWithSameType = parent .select(">" + type); int siblingIndex = childrenWithSameType.indexOf(element); if (anyPrecedingSiblingIsAStopElement(childrenWithSameType, siblingIndex)) { return null; } selector.append(String.format(":nth-of-type(%d)", siblingIndex + 1)); } if (hasReachedLastRepeaterElement(context, parent)) { return selector.toString(); } selector.insert(0, " > "); String parentSelector = generateCssSelector(parent, context); return parentSelector == null ? null : parentSelector + selector.toString(); }  static boolean isButton(Element element); static boolean isLink(Element element); static String generateCssSelector(Element element,
			GeneratorContext context);  }
@Test public void cssSelectorWithRegularElements() throws Exception { GeneratorContext context = getContext( "<div>A <div>B <div>C</div></div></div>"); Document document = context.getDocument(); Element divA = document.select("div").get(0); Element divB = document.select("div").get(1); Element divC = document.select("div").get(2); assertThat(generateCssSelector(divA, context)).isEqualTo("div"); assertThat(generateCssSelector(divB, context)).isEqualTo("div > div"); assertThat(generateCssSelector(divC, context)).isEqualTo("div > div > div"); }
@Test public void cssSelectorWithId() throws Exception { GeneratorContext context = getContext( "<div><div id=\"id1\">A <div>B <div>C</div></div></div></div>"); Document document = context.getDocument(); Element divA = document.select("div").get(1); Element divB = document.select("div").get(2); Element divC = document.select("div").get(3); assertThat(generateCssSelector(divA, context)).isEqualTo("#id1"); assertThat(generateCssSelector(divB, context)).isEqualTo("#id1 > div"); assertThat(generateCssSelector(divC, context)) .isEqualTo("#id1 > div > div"); }
@Test public void cssSelectorWithClasses() throws Exception { GeneratorContext context = getContext( "<div><div class=\"a b\">A <div class=\"c\">B <div>C</div></div></div></div>"); Document document = context.getDocument(); Element divA = document.select("div").get(1); Element divB = document.select("div").get(2); Element divC = document.select("div").get(3); assertThat(generateCssSelector(divA, context)).isEqualTo("div > div.a.b"); assertThat(generateCssSelector(divB, context)) .isEqualTo("div > div.a.b > div.c"); assertThat(generateCssSelector(divC, context)) .isEqualTo("div > div.a.b > div.c > div"); }
@Test public void cssSelectorWithNamespacedElements() throws Exception { GeneratorContext context = getContext( "\"<html><body><fb:comments /></body></html>\""); Document document = context.getDocument(); org.jsoup.select.Elements comments = document.select("fb|comments"); assertThat(generateCssSelector(comments.get(0), context)) .isEqualTo("body > fb|comments"); }
@Test public void cssSelectorWithMultipleChildren() throws Exception { GeneratorContext context = getContext( "<div><div>A</div><div>B</div><span></span><div class=\"a\">C</div><div class=\"a\">D</div></div>"); Document document = context.getDocument(); Element divA = document.select("div").get(1); Element divB = document.select("div").get(2); Element divC = document.select("div").get(3); Element divD = document.select("div").get(4); assertThat(generateCssSelector(divA, context)) .isEqualTo("div > div:nth-of-type(1)"); assertThat(generateCssSelector(divB, context)) .isEqualTo("div > div:nth-of-type(2)"); assertThat(generateCssSelector(divC, context)) .isEqualTo("div > div.a:nth-of-type(3)"); assertThat(generateCssSelector(divD, context)) .isEqualTo("div > div.a:nth-of-type(4)"); }
@Test public void cssSelectorStopsAtRepeater() throws Exception { GeneratorContext context = getContext( "<div>A <div ng-repeat=\"item in items\">B <div class=\"a\">C <div>D</div></div></div></div>"); Document document = context.getDocument(); Element divB = document.select("div").get(1); Element divC = document.select("div").get(2); Element divD = document.select("div").get(3); context.pushNgRepeat(divB, "item in items"); context.pushLocatorPartGenerator( new SingleElementLocatorPartGenerator(divC, LocatorSources.ID)); assertThat(generateCssSelector(divC, context)).isEqualTo("div.a"); assertThat(generateCssSelector(divD, context)).isEqualTo("div.a > div"); }
@Test public void cssSelectorDoesNotGenerateSelectorIfNestedRepeaterHasSimilarElements() throws Exception { GeneratorContext context = getContext( "<div ng-repeat=\"item in items\">A <div class=\"a\">B <div ng-repeat=\"element in elements\">C <div class=\"a\">D</div></div></div></div>"); Document document = context.getDocument(); Element divA = document.select("div").get(0); Element divB = document.select("div").get(1); Element divC = document.select("div").get(2); Element divD = document.select("div").get(3); context.pushNgRepeat(divA, "item in items"); context.pushLocatorPartGenerator( new SingleElementLocatorPartGenerator(divC, LocatorSources.ID)); assertThat(generateCssSelector(divB, context)).isNull(); context.popLocatorPartGenerator(); context.pushNgRepeat(divC, "element in elements"); context.pushLocatorPartGenerator( new SingleElementLocatorPartGenerator(divC, LocatorSources.ID)); assertThat(generateCssSelector(divD, context)).isEqualTo("div.a"); }