1 package org.jsoup.nodes; 2 3 import org.jsoup.Jsoup; 4 import org.jsoup.TextUtil; 5 import org.jsoup.integration.ParseTest; 6 import org.jsoup.nodes.Document.OutputSettings; 7 import org.jsoup.nodes.Document.OutputSettings.Syntax; 8 import org.jsoup.parser.ParseSettings; 9 import org.jsoup.parser.Parser; 10 import org.jsoup.select.Elements; 11 import org.junit.jupiter.api.Disabled; 12 import org.junit.jupiter.api.Test; 13 14 import java.io.*; 15 import java.nio.charset.Charset; 16 import java.nio.charset.StandardCharsets; 17 import java.util.List; 18 19 import static org.junit.jupiter.api.Assertions.*; 20 21 /** 22 Tests for Document. 23 24 @author Jonathan Hedley, jonathan@hedley.net */ 25 public class DocumentTest { 26 private static final String charsetUtf8 = "UTF-8"; 27 private static final String charsetIso8859 = "ISO-8859-1"; 28 29 setTextPreservesDocumentStructure()30 @Test public void setTextPreservesDocumentStructure() { 31 Document doc = Jsoup.parse("<p>Hello</p>"); 32 doc.text("Replaced"); 33 assertEquals("Replaced", doc.text()); 34 assertEquals("Replaced", doc.body().text()); 35 assertEquals(1, doc.select("head").size()); 36 } 37 testTitles()38 @Test public void testTitles() { 39 Document noTitle = Jsoup.parse("<p>Hello</p>"); 40 Document withTitle = Jsoup.parse("<title>First</title><title>Ignore</title><p>Hello</p>"); 41 42 assertEquals("", noTitle.title()); 43 noTitle.title("Hello"); 44 assertEquals("Hello", noTitle.title()); 45 assertEquals("Hello", noTitle.select("title").first().text()); 46 47 assertEquals("First", withTitle.title()); 48 withTitle.title("Hello"); 49 assertEquals("Hello", withTitle.title()); 50 assertEquals("Hello", withTitle.select("title").first().text()); 51 52 Document normaliseTitle = Jsoup.parse("<title> Hello\nthere \n now \n"); 53 assertEquals("Hello there now", normaliseTitle.title()); 54 } 55 testOutputEncoding()56 @Test public void testOutputEncoding() { 57 Document doc = Jsoup.parse("<p title=π>π & < > </p>"); 58 // default is utf-8 59 assertEquals("<p title=\"π\">π & < ></p>", doc.body().html()); 60 assertEquals("UTF-8", doc.outputSettings().charset().name()); 61 62 doc.outputSettings().charset("ascii"); 63 assertEquals(Entities.EscapeMode.base, doc.outputSettings().escapeMode()); 64 assertEquals("<p title=\"π\">π & < ></p>", doc.body().html()); 65 66 doc.outputSettings().escapeMode(Entities.EscapeMode.extended); 67 assertEquals("<p title=\"π\">π & < ></p>", doc.body().html()); 68 } 69 testXhtmlReferences()70 @Test public void testXhtmlReferences() { 71 Document doc = Jsoup.parse("< > & " ' ×"); 72 doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml); 73 assertEquals("< > & \" ' ×", doc.body().html()); 74 } 75 testNormalisesStructure()76 @Test public void testNormalisesStructure() { 77 Document doc = Jsoup.parse("<html><head><script>one</script><noscript><p>two</p></noscript></head><body><p>three</p></body><p>four</p></html>"); 78 assertEquals("<html><head><script>one</script><noscript><p>two</noscript></head><body><p>three</p><p>four</p></body></html>", TextUtil.stripNewlines(doc.html())); 79 } 80 accessorsWillNormalizeStructure()81 @Test public void accessorsWillNormalizeStructure() { 82 Document doc = new Document(""); 83 assertEquals("", doc.html()); 84 85 Element body = doc.body(); 86 assertEquals("body", body.tagName()); 87 Element head = doc.head(); 88 assertEquals("head", head.tagName()); 89 assertEquals("<html><head></head><body></body></html>", TextUtil.stripNewlines(doc.html())); 90 } 91 accessorsAreCaseInsensitive()92 @Test public void accessorsAreCaseInsensitive() { 93 Parser parser = Parser.htmlParser().settings(ParseSettings.preserveCase); 94 Document doc = parser.parseInput("<!DOCTYPE html><HTML><HEAD><TITLE>SHOUTY</TITLE></HEAD><BODY>HELLO</BODY></HTML>", ""); 95 96 Element body = doc.body(); 97 assertEquals("BODY", body.tagName()); 98 assertEquals("body", body.normalName()); 99 Element head = doc.head(); 100 assertEquals("HEAD", head.tagName()); 101 assertEquals("body", body.normalName()); 102 103 Element root = doc.selectFirst("html"); 104 assertEquals("HTML", root.tagName()); 105 assertEquals("html", root.normalName()); 106 assertEquals("SHOUTY", doc.title()); 107 } 108 testClone()109 @Test public void testClone() { 110 Document doc = Jsoup.parse("<title>Hello</title> <p>One<p>Two"); 111 Document clone = doc.clone(); 112 113 assertEquals("<html><head><title>Hello</title></head><body><p>One</p><p>Two</p></body></html>", TextUtil.stripNewlines(clone.html())); 114 clone.title("Hello there"); 115 clone.expectFirst("p").text("One more").attr("id", "1"); 116 assertEquals("<html><head><title>Hello there</title></head><body><p id=\"1\">One more</p><p>Two</p></body></html>", TextUtil.stripNewlines(clone.html())); 117 assertEquals("<html><head><title>Hello</title></head><body><p>One</p><p>Two</p></body></html>", TextUtil.stripNewlines(doc.html())); 118 } 119 testBasicIndent()120 @Test void testBasicIndent() { 121 Document doc = Jsoup.parse("<title>Hello</title> <p>One<p>Two"); 122 String expect = "<html>\n <head>\n <title>Hello</title>\n </head>\n <body>\n <p>One</p>\n <p>Two</p>\n </body>\n</html>"; 123 assertEquals(expect, doc.html()); 124 } 125 testClonesDeclarations()126 @Test public void testClonesDeclarations() { 127 Document doc = Jsoup.parse("<!DOCTYPE html><html><head><title>Doctype test"); 128 Document clone = doc.clone(); 129 130 assertEquals(doc.html(), clone.html()); 131 assertEquals("<!doctype html><html><head><title>Doctype test</title></head><body></body></html>", 132 TextUtil.stripNewlines(clone.html())); 133 } 134 testLocation()135 @Test public void testLocation() throws IOException { 136 // tests location vs base href 137 File in = ParseTest.getFile("/htmltests/basehref.html"); 138 Document doc = Jsoup.parse(in, "UTF-8", "http://example.com/"); 139 String location = doc.location(); 140 String baseUri = doc.baseUri(); 141 assertEquals("http://example.com/", location); 142 assertEquals("https://example.com/path/file.html?query", baseUri); 143 assertEquals("./anotherfile.html", doc.expectFirst("a").attr("href")); 144 assertEquals("https://example.com/path/anotherfile.html", doc.expectFirst("a").attr("abs:href")); 145 } 146 testLocationFromString()147 @Test public void testLocationFromString() { 148 Document doc = Jsoup.parse("<p>Hello"); 149 assertEquals("", doc.location()); 150 } 151 testHtmlAndXmlSyntax()152 @Test public void testHtmlAndXmlSyntax() { 153 String h = "<!DOCTYPE html><body><img async checked='checked' src='&<>\"'><>&"<foo />bar"; 154 Document doc = Jsoup.parse(h); 155 156 doc.outputSettings().syntax(Syntax.html); 157 assertEquals("<!doctype html>\n" + 158 "<html>\n" + 159 " <head></head>\n" + 160 " <body>\n" + 161 " <img async checked src=\"&<>"\"><>&\"<foo />bar\n" + 162 " </body>\n" + 163 "</html>", doc.html()); 164 165 doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml); 166 assertEquals("<!DOCTYPE html>\n" + 167 "<html>\n" + 168 " <head></head>\n" + 169 " <body>\n" + 170 " <img async=\"\" checked=\"checked\" src=\"&<>"\" /><>&\"<foo />bar\n" + 171 " </body>\n" + 172 "</html>", doc.html()); 173 } 174 htmlParseDefaultsToHtmlOutputSyntax()175 @Test public void htmlParseDefaultsToHtmlOutputSyntax() { 176 Document doc = Jsoup.parse("x"); 177 assertEquals(Syntax.html, doc.outputSettings().syntax()); 178 } 179 testHtmlAppendable()180 @Test public void testHtmlAppendable() { 181 String htmlContent = "<html><head><title>Hello</title></head><body><p>One</p><p>Two</p></body></html>"; 182 Document document = Jsoup.parse(htmlContent); 183 OutputSettings outputSettings = new OutputSettings(); 184 185 outputSettings.prettyPrint(false); 186 document.outputSettings(outputSettings); 187 assertEquals(htmlContent, document.html(new StringWriter()).toString()); 188 } 189 testOverflowClone()190 @Test public void testOverflowClone() { 191 StringBuilder sb = new StringBuilder(); 192 sb.append("<head><base href='https://jsoup.org/'>"); 193 for (int i = 0; i < 100000; i++) { 194 sb.append("<div>"); 195 } 196 sb.append("<p>Hello <a href='/example.html'>there</a>"); 197 198 Document doc = Jsoup.parse(sb.toString()); 199 200 String expectedLink = "https://jsoup.org/example.html"; 201 assertEquals(expectedLink, doc.selectFirst("a").attr("abs:href")); 202 Document clone = doc.clone(); 203 doc.hasSameValue(clone); 204 assertEquals(expectedLink, clone.selectFirst("a").attr("abs:href")); 205 } 206 DocumentsWithSameContentAreEqual()207 @Test public void DocumentsWithSameContentAreEqual() { 208 Document docA = Jsoup.parse("<div/>One"); 209 Document docB = Jsoup.parse("<div/>One"); 210 Document docC = Jsoup.parse("<div/>Two"); 211 212 assertNotEquals(docA, docB); 213 assertEquals(docA, docA); 214 assertEquals(docA.hashCode(), docA.hashCode()); 215 assertNotEquals(docA.hashCode(), docC.hashCode()); 216 } 217 DocumentsWithSameContentAreVerifiable()218 @Test public void DocumentsWithSameContentAreVerifiable() { 219 Document docA = Jsoup.parse("<div/>One"); 220 Document docB = Jsoup.parse("<div/>One"); 221 Document docC = Jsoup.parse("<div/>Two"); 222 223 assertTrue(docA.hasSameValue(docB)); 224 assertFalse(docA.hasSameValue(docC)); 225 } 226 227 @Test testMetaCharsetUpdateUtf8()228 public void testMetaCharsetUpdateUtf8() { 229 final Document doc = createHtmlDocument("changeThis"); 230 doc.updateMetaCharsetElement(true); 231 doc.charset(Charset.forName(charsetUtf8)); 232 233 final String htmlCharsetUTF8 = "<html>\n" + 234 " <head>\n" + 235 " <meta charset=\"" + charsetUtf8 + "\">\n" + 236 " </head>\n" + 237 " <body></body>\n" + 238 "</html>"; 239 assertEquals(htmlCharsetUTF8, doc.toString()); 240 241 Element selectedElement = doc.select("meta[charset]").first(); 242 assertEquals(charsetUtf8, doc.charset().name()); 243 assertEquals(charsetUtf8, selectedElement.attr("charset")); 244 assertEquals(doc.charset(), doc.outputSettings().charset()); 245 } 246 247 @Test testMetaCharsetUpdateIso8859()248 public void testMetaCharsetUpdateIso8859() { 249 final Document doc = createHtmlDocument("changeThis"); 250 doc.updateMetaCharsetElement(true); 251 doc.charset(Charset.forName(charsetIso8859)); 252 253 final String htmlCharsetISO = "<html>\n" + 254 " <head>\n" + 255 " <meta charset=\"" + charsetIso8859 + "\">\n" + 256 " </head>\n" + 257 " <body></body>\n" + 258 "</html>"; 259 assertEquals(htmlCharsetISO, doc.toString()); 260 261 Element selectedElement = doc.select("meta[charset]").first(); 262 assertEquals(charsetIso8859, doc.charset().name()); 263 assertEquals(charsetIso8859, selectedElement.attr("charset")); 264 assertEquals(doc.charset(), doc.outputSettings().charset()); 265 } 266 267 @Test testMetaCharsetUpdateNoCharset()268 public void testMetaCharsetUpdateNoCharset() { 269 final Document docNoCharset = Document.createShell(""); 270 docNoCharset.updateMetaCharsetElement(true); 271 docNoCharset.charset(Charset.forName(charsetUtf8)); 272 273 assertEquals(charsetUtf8, docNoCharset.select("meta[charset]").first().attr("charset")); 274 275 final String htmlCharsetUTF8 = "<html>\n" + 276 " <head>\n" + 277 " <meta charset=\"" + charsetUtf8 + "\">\n" + 278 " </head>\n" + 279 " <body></body>\n" + 280 "</html>"; 281 assertEquals(htmlCharsetUTF8, docNoCharset.toString()); 282 } 283 284 @Test testMetaCharsetUpdateDisabled()285 public void testMetaCharsetUpdateDisabled() { 286 final Document docDisabled = Document.createShell(""); 287 288 final String htmlNoCharset = "<html>\n" + 289 " <head></head>\n" + 290 " <body></body>\n" + 291 "</html>"; 292 assertEquals(htmlNoCharset, docDisabled.toString()); 293 assertNull(docDisabled.select("meta[charset]").first()); 294 } 295 296 @Test testMetaCharsetUpdateDisabledNoChanges()297 public void testMetaCharsetUpdateDisabledNoChanges() { 298 final Document doc = createHtmlDocument("dontTouch"); 299 300 final String htmlCharset = "<html>\n" + 301 " <head>\n" + 302 " <meta charset=\"dontTouch\">\n" + 303 " <meta name=\"charset\" content=\"dontTouch\">\n" + 304 " </head>\n" + 305 " <body></body>\n" + 306 "</html>"; 307 assertEquals(htmlCharset, doc.toString()); 308 309 Element selectedElement = doc.select("meta[charset]").first(); 310 assertNotNull(selectedElement); 311 assertEquals("dontTouch", selectedElement.attr("charset")); 312 313 selectedElement = doc.select("meta[name=charset]").first(); 314 assertNotNull(selectedElement); 315 assertEquals("dontTouch", selectedElement.attr("content")); 316 } 317 318 @Test testMetaCharsetUpdateEnabledAfterCharsetChange()319 public void testMetaCharsetUpdateEnabledAfterCharsetChange() { 320 final Document doc = createHtmlDocument("dontTouch"); 321 doc.charset(Charset.forName(charsetUtf8)); 322 323 Element selectedElement = doc.select("meta[charset]").first(); 324 assertEquals(charsetUtf8, selectedElement.attr("charset")); 325 assertTrue(doc.select("meta[name=charset]").isEmpty()); 326 } 327 328 @Test testMetaCharsetUpdateCleanup()329 public void testMetaCharsetUpdateCleanup() { 330 final Document doc = createHtmlDocument("dontTouch"); 331 doc.updateMetaCharsetElement(true); 332 doc.charset(Charset.forName(charsetUtf8)); 333 334 final String htmlCharsetUTF8 = "<html>\n" + 335 " <head>\n" + 336 " <meta charset=\"" + charsetUtf8 + "\">\n" + 337 " </head>\n" + 338 " <body></body>\n" + 339 "</html>"; 340 341 assertEquals(htmlCharsetUTF8, doc.toString()); 342 } 343 344 @Test testMetaCharsetUpdateXmlUtf8()345 public void testMetaCharsetUpdateXmlUtf8() { 346 final Document doc = createXmlDocument("1.0", "changeThis", true); 347 doc.updateMetaCharsetElement(true); 348 doc.charset(Charset.forName(charsetUtf8)); 349 350 final String xmlCharsetUTF8 = "<?xml version=\"1.0\" encoding=\"" + charsetUtf8 + "\"?>\n" + 351 "<root>\n" + 352 " node\n" + 353 "</root>"; 354 assertEquals(xmlCharsetUTF8, doc.toString()); 355 356 XmlDeclaration selectedNode = (XmlDeclaration) doc.childNode(0); 357 assertEquals(charsetUtf8, doc.charset().name()); 358 assertEquals(charsetUtf8, selectedNode.attr("encoding")); 359 assertEquals(doc.charset(), doc.outputSettings().charset()); 360 } 361 362 @Test testMetaCharsetUpdateXmlIso8859()363 public void testMetaCharsetUpdateXmlIso8859() { 364 final Document doc = createXmlDocument("1.0", "changeThis", true); 365 doc.updateMetaCharsetElement(true); 366 doc.charset(Charset.forName(charsetIso8859)); 367 368 final String xmlCharsetISO = "<?xml version=\"1.0\" encoding=\"" + charsetIso8859 + "\"?>\n" + 369 "<root>\n" + 370 " node\n" + 371 "</root>"; 372 assertEquals(xmlCharsetISO, doc.toString()); 373 374 XmlDeclaration selectedNode = (XmlDeclaration) doc.childNode(0); 375 assertEquals(charsetIso8859, doc.charset().name()); 376 assertEquals(charsetIso8859, selectedNode.attr("encoding")); 377 assertEquals(doc.charset(), doc.outputSettings().charset()); 378 } 379 380 @Test testMetaCharsetUpdateXmlNoCharset()381 public void testMetaCharsetUpdateXmlNoCharset() { 382 final Document doc = createXmlDocument("1.0", "none", false); 383 doc.updateMetaCharsetElement(true); 384 doc.charset(Charset.forName(charsetUtf8)); 385 386 final String xmlCharsetUTF8 = "<?xml version=\"1.0\" encoding=\"" + charsetUtf8 + "\"?>\n" + 387 "<root>\n" + 388 " node\n" + 389 "</root>"; 390 assertEquals(xmlCharsetUTF8, doc.toString()); 391 392 XmlDeclaration selectedNode = (XmlDeclaration) doc.childNode(0); 393 assertEquals(charsetUtf8, selectedNode.attr("encoding")); 394 } 395 396 @Test testMetaCharsetUpdateXmlDisabled()397 public void testMetaCharsetUpdateXmlDisabled() { 398 final Document doc = createXmlDocument("none", "none", false); 399 400 final String xmlNoCharset = "<root>\n" + 401 " node\n" + 402 "</root>"; 403 assertEquals(xmlNoCharset, doc.toString()); 404 } 405 406 @Test testMetaCharsetUpdateXmlDisabledNoChanges()407 public void testMetaCharsetUpdateXmlDisabledNoChanges() { 408 final Document doc = createXmlDocument("dontTouch", "dontTouch", true); 409 410 final String xmlCharset = "<?xml version=\"dontTouch\" encoding=\"dontTouch\"?>\n" + 411 "<root>\n" + 412 " node\n" + 413 "</root>"; 414 assertEquals(xmlCharset, doc.toString()); 415 416 XmlDeclaration selectedNode = (XmlDeclaration) doc.childNode(0); 417 assertEquals("dontTouch", selectedNode.attr("encoding")); 418 assertEquals("dontTouch", selectedNode.attr("version")); 419 } 420 421 @Test testMetaCharsetUpdatedDisabledPerDefault()422 public void testMetaCharsetUpdatedDisabledPerDefault() { 423 final Document doc = createHtmlDocument("none"); 424 assertFalse(doc.updateMetaCharsetElement()); 425 } 426 createHtmlDocument(String charset)427 private Document createHtmlDocument(String charset) { 428 final Document doc = Document.createShell(""); 429 doc.head().appendElement("meta").attr("charset", charset); 430 doc.head().appendElement("meta").attr("name", "charset").attr("content", charset); 431 432 return doc; 433 } 434 createXmlDocument(String version, String charset, boolean addDecl)435 private Document createXmlDocument(String version, String charset, boolean addDecl) { 436 final Document doc = new Document(""); 437 doc.appendElement("root").text("node"); 438 doc.outputSettings().syntax(Syntax.xml); 439 440 if(addDecl) { 441 XmlDeclaration decl = new XmlDeclaration("xml", false); 442 decl.attr("version", version); 443 decl.attr("encoding", charset); 444 doc.prependChild(decl); 445 } 446 447 return doc; 448 } 449 450 @Test testShiftJisRoundtrip()451 public void testShiftJisRoundtrip() throws Exception { 452 String input = 453 "<html>" 454 + "<head>" 455 + "<meta http-equiv=\"content-type\" content=\"text/html; charset=Shift_JIS\" />" 456 + "</head>" 457 + "<body>" 458 + "before after" 459 + "</body>" 460 + "</html>"; 461 InputStream is = new ByteArrayInputStream(input.getBytes(StandardCharsets.US_ASCII)); 462 463 Document doc = Jsoup.parse(is, null, "http://example.com"); 464 doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml); 465 466 String output = new String(doc.html().getBytes(doc.outputSettings().charset()), doc.outputSettings().charset()); 467 468 assertFalse(output.contains("?"), "Should not have contained a '?'."); 469 assertTrue(output.contains(" ") || output.contains(" "), 470 "Should have contained a ' ' or a ' '."); 471 } 472 parseAndHtmlOnDifferentThreads()473 @Test public void parseAndHtmlOnDifferentThreads() throws InterruptedException { 474 String html = "<p>Alrighty then it's not \uD83D\uDCA9. <span>Next</span></p>"; // 475 String asci = "<p>Alrighty then it's not 💩. <span>Next</span></p>"; 476 477 final Document doc = Jsoup.parse(html); 478 final String[] out = new String[1]; 479 final Elements p = doc.select("p"); 480 assertEquals(html, p.outerHtml()); 481 482 Thread thread = new Thread(() -> { 483 out[0] = p.outerHtml(); 484 doc.outputSettings().charset(StandardCharsets.US_ASCII); 485 }); 486 thread.start(); 487 thread.join(); 488 489 assertEquals(html, out[0]); 490 assertEquals(StandardCharsets.US_ASCII, doc.outputSettings().charset()); 491 assertEquals(asci, p.outerHtml()); 492 } 493 testDocumentTypeGet()494 @Test public void testDocumentTypeGet() { 495 String html = "\n\n<!-- comment --> <!doctype html><p>One</p>"; 496 Document doc = Jsoup.parse(html); 497 DocumentType documentType = doc.documentType(); 498 assertNotNull(documentType); 499 assertEquals("html", documentType.name()); 500 } 501 framesetSupportsBodyMethod()502 @Test public void framesetSupportsBodyMethod() { 503 String html = "<html><head><title>Frame Test</title></head><frameset id=id><frame src=foo.html></frameset>"; 504 Document doc = Jsoup.parse(html); 505 Element head = doc.head(); 506 assertNotNull(head); 507 assertEquals("Frame Test", doc.title()); 508 509 // Frameset docs per html5 spec have no body element - but instead a frameset elelemt 510 assertNull(doc.selectFirst("body")); 511 Element frameset = doc.selectFirst("frameset"); 512 assertNotNull(frameset); 513 514 // the body() method returns body or frameset and does not otherwise modify the document 515 // doing it in body() vs parse keeps the html close to original for round-trip option 516 Element body = doc.body(); 517 assertNotNull(body); 518 assertSame(frameset, body); 519 assertEquals("frame", body.child(0).tagName()); 520 521 assertNull(doc.selectFirst("body")); // did not vivify a body element 522 523 String expected = "<html>\n" + 524 " <head>\n" + 525 " <title>Frame Test</title>\n" + 526 " </head>\n" + 527 " <frameset id=\"id\">\n" + 528 " <frame src=\"foo.html\">\n" + 529 " </frameset>\n" + 530 "</html>"; 531 assertEquals(expected, doc.html()); 532 } 533 forms()534 @Test void forms() { 535 String html = "<body><form id=1><input name=foo></form><form id=2><input name=bar>"; 536 Document doc = Jsoup.parse(html); 537 538 List<FormElement> forms = doc.forms(); 539 assertEquals(2, forms.size()); 540 FormElement form = forms.get(1); 541 assertEquals(1, form.elements().size()); 542 assertEquals("bar", form.elements().first().attr("name")); 543 544 String emptyHtml = "<body>"; 545 Document emptyDoc = Jsoup.parse(emptyHtml); 546 assertEquals(0, emptyDoc.forms().size()); 547 } 548 expectForm()549 @Test void expectForm() { 550 String html = "<body><div name=form></div><form id=1 name=form><input name=foo></form><form id=2><input name=bar>"; 551 Document doc = Jsoup.parse(html); 552 553 // test finds first <form> 554 FormElement formEl1 = doc.expectForm("[name=form]"); 555 assertEquals("1", formEl1.id()); // and not the div 556 557 FormElement formEl2 = doc.expectForm("form"); 558 assertEquals("1", formEl2.id()); 559 560 FormElement formEl3 = doc.expectForm("form:has([name=bar])"); 561 assertEquals("2", formEl3.id()); 562 563 boolean threw = false; 564 try { 565 FormElement nix = doc.expectForm("div"); 566 } catch (IllegalArgumentException e) { 567 threw = true; 568 } 569 assertTrue(threw); 570 571 } 572 } 573