public void test_A_TagProblem() throws ParseException {
    //
    // java.lang.AssertionError
    // at org.netbeans.modules.html.parser.NodeTreeBuilder.elementPopped(NodeTreeBuilder.java:106)
    //

    // such broken source really confuses the html parser
    String code =
        "<!DOCTYPE html>\n"
            + "<html>\n"
            + "     <title>HTML5 Demo: geolocation</title>\n"
            + "     <body>\n"
            + "         <a>  \n"
            + "         <footer>\n"
            + "             <a>\n"
            + "         </footer> \n"
            + "     </body>\n" // from some reason the tree builder pushes <a> open tag node
            // here?!?!?
            + "</html>  \n";

    HtmlParseResult result = parse(code, false);
    Node root = result.root();

    assertNotNull(root);

    //        NodeUtils.dumpTree(root);
  }
  // Bug 210976 - StringIndexOutOfBoundsException: String index out of range: 399
  public void testIssue210976() throws ParseException {
    String code = "<a href=\"@&msc=@@@&klub=@@@\"></a>";
    //             01234567 8901234567890123456 7890123
    //             0          1         2          3

    HtmlParseResult result = parse(code);
    Node root = result.root();
    assertNotNull(root);

    //        ElementUtils.dumpTree(root);

    OpenTag a = ElementUtils.query(root, "html/body/a");
    assertNotNull(a);
    assertEquals(0, a.from());
    assertEquals(29, a.to());

    Attribute attr = a.getAttribute("href");
    assertNotNull(attr);

    assertNotNull(attr.value());
    assertNotNull(attr.unquotedValue());

    assertEquals("\"@&msc=@@@&klub=@@@\"", attr.value());
    assertEquals("@&msc=@@@&klub=@@@", attr.unquotedValue());
  }
  public void testAllowDialogInDiv() throws ParseException {
    HtmlParseResult result =
        parse(
            "<!doctype html>"
                + "<html>\n"
                + "<title>title</title>\n"
                + "<body>\n"
                + "<div>\n"
                + "</div>\n"
                + "</body>\n"
                + "</html>\n");

    assertNotNull(result.root());

    Node div = ElementUtils.query(result.root(), "html/body/div");
    Collection<HtmlTag> possible = result.getPossibleOpenTags(div);

    assertTrue(!possible.isEmpty());

    HtmlTag divTag = new HtmlTagImpl("div");
    HtmlTag dialogTag = new HtmlTagImpl("dialog");

    assertTrue(possible.contains(divTag));

    // fails - bug
    //        assertFalse(possible.contains(dialogTag));

  }
  public void testUnclosedTitleTag() throws ParseException {
    // this is causing all the nodes missing their logical ranges
    // the body tag is parsed as virtual only regardless the open and end
    // tag is present in the code.

    // looks like caused by the CDATA content of the unclosed title tag
    // which causes the parser consume everything after as unparseable code :-(
    String code = "<!doctype html><html><head><title></head><body></body></html>";
    //             0123456789012345678901234567890123456789012345678901234567890123456789
    //             0         1         2         3         4         5         6

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);

    Node title = ElementUtils.query(result.root(), "html/head/title");
    assertNotNull(title);

    //        NodeUtils.dumpTree(root);

    // FAILING - http://netbeans.org/bugzilla/show_bug.cgi?id=190183

    //        assertTrue(title.semanticEnd() != -1);

  }
  public void testLogicalRangesOfUnclosedOpenTags() throws ParseException {
    HtmlParseResult result =
        parse(
            "<!DOCTYPE html>"
                + "<html>"
                + "<head>"
                + "<title>hello</title>"
                + "</head>"
                + "<body>"
                + "<table>"
                + "</html>");
    Node root = result.root();

    //        NodeUtils.dumpTree(root);

    assertNotNull(root);
    OpenTag htmlOpen = ElementUtils.query(root, "html");
    assertNotNull(htmlOpen);
    CloseTag htmlEnd = htmlOpen.matchingCloseTag();
    assertNotNull(htmlEnd);

    assertNotNull(ElementUtils.query(root, "html/head"));
    assertNotNull(ElementUtils.query(root, "html/head/title"));
    OpenTag body = ElementUtils.query(root, "html/body");
    assertNotNull(body);
    OpenTag table = ElementUtils.query(root, "html/body/table");
    assertNotNull(table);

    // both body and table should be logically closed at the beginning of the html end tag
    assertEquals(htmlEnd.from(), body.semanticEnd());
    assertEquals(htmlEnd.from(), table.semanticEnd());
  }
  //    public void testProblemsReporting() throws ParseException {
  //        HtmlParseResult result = parse("<!DOCTYPE html></section>");
  //        //                              012345678901234567890123456789
  //        //                              0         1         2
  //        Collection<ProblemDescription> problems = result.getProblems();
  //
  //        assertEquals(1, problems.size());
  //        ProblemDescription p = problems.iterator().next();
  //
  //        assertEquals(ProblemDescription.ERROR, p.getType());
  //        assertEquals("nokey", p.getKey()); //XXX fix that
  //        assertEquals("Stray end tag “section”.", p.getText());
  //        assertEquals(15, p.getFrom());
  //        assertEquals(25, p.getTo());
  //
  //    }
  public void testStyle() throws ParseException {
    String code =
        "<!DOCTYPE html>\n<style type=\"text/css\">\n@import \"resources2/ezcompik/newcss2moje.css\";\n</style>\n";
    //             0123456789012345 67890123456 7890123456 789 012345678 90123456789012345678
    // 90123456789012 345678901 23456789
    //             0         1          2          3           4          5         6          7
    //      8           9

    //        NodeTreeBuilder.DEBUG = true;
    //        NodeTreeBuilder.DEBUG_STATES = true;
    HtmlParseResult result = parse(code);
    Node root = result.root();
    assertNotNull(root);
    //        NodeUtils.dumpTree(result.root());

    OpenTag head = ElementUtils.query(root, "html/head");
    assertNotNull(head);
    assertEquals(2, head.children().size());

    Iterator<Element> itr = head.children().iterator();

    OpenTag styleOpenTag = (OpenTag) itr.next();
    assertNotNull(styleOpenTag);
    assertEquals(16, styleOpenTag.from());
    assertEquals(39, styleOpenTag.to());

    Element styleEndTag = itr.next();
    assertNotNull(styleEndTag);
    assertEquals(87, styleEndTag.from());
    assertEquals(95, styleEndTag.to());

    assertSame(styleEndTag, styleOpenTag.matchingCloseTag());
  }
  public void testAddChildToEmptyTag() throws ParseException {
    //        ParseTreeBuilder.setLoggerLevel(Level.ALL);

    String code = "<div align='center'/><a>text</a></div>";
    HtmlParseResult result = parse(code);
    Node root = result.root();
  }
  public void testHtml5Model() throws ParseException {
    String code = "<!doctype html><title>hi</title>";
    HtmlParseResult result = parse(code);

    HtmlModel model = result.model();
    assertNotNull(model);
    //        assertEquals("html5model", model.getModelId());

    Collection<HtmlTag> all = model.getAllTags();
    assertNotNull(all);
    assertEquals(ElementDescriptor.values().length, all.size());

    HtmlTag table = HtmlTagProvider.getTagForElement("table");
    assertNotNull(table);

    assertTrue(all.contains(table));

    // try to modify the unmodifiable collection
    try {
      all.remove(table);
      assertTrue("The tags collection can be modified!", false);
    } catch (UnsupportedOperationException t) {
      // ok
    }
  }
  // unknown node 't' has no parent set
  public void testParseUnknownElementInTable() throws ParseException {
    String code =
        "<!doctype html>"
            + "<html>"
            + "<head><title></title></head>"
            + "<body>"
            + "<table>"
            + "<t>"
            + "</table>"
            + "</body>"
            + "</html>";
    //      NodeTreeBuilder.DEBUG = true;
    HtmlParseResult result = parse(code);
    Node root = result.root();

    //      NodeUtils.dumpTree(root);

    // the 't' node is foster parented, so it goes to the table's parent, not table itself
    Node t = ElementUtils.query(root, "html/body/t");
    assertNotNull(t);
    Node body = ElementUtils.query(root, "html/body");
    assertNotNull(body);

    assertEquals(body, t.parent());
  }
  // Bug 197608 - Non-html tags offered as closing tags using code completion
  public void testIssue197608() throws ParseException {
    //        NodeTreeBuilder.setLoggerLevel(Level.FINER);

    String code = "<div></di   <p> aaa";
    //             0123456789012345

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);
    //        ElementUtils.dumpTree(root);

    Collection<ProblemDescription> problems = result.getProblems();
    assertNotNull(problems);
    assertEquals(2, problems.size());

    Iterator<ProblemDescription> problemsItr = problems.iterator();
    ProblemDescription pd = problemsItr.next();
    assertNotNull(pd.getKey());
    assertNotNull(pd.getText());
    assertEquals(ProblemDescription.ERROR, pd.getType());
    assertEquals(9, pd.getFrom());
    assertEquals(9, pd.getTo());

    pd = problemsItr.next();
    assertNotNull(pd.getKey());
    assertNotNull(pd.getText());
    assertEquals(ProblemDescription.ERROR, pd.getType());
    assertEquals(12, pd.getFrom());
    assertEquals(12, pd.getTo());
  }
  public void testParseFileLongerThan2048chars() throws ParseException {
    StringBuilder b = new StringBuilder();
    for (int i = 0; i < 2048 * 3; i++) {
      b.append('*');
    }

    String code =
        "<!doctype html>\n"
            + "<html>\n"
            + "<title></title>\n"
            + "<body>\n"
            + b.toString()
            + "</body>\n"
            + "</html>\n";

    //        ParseTreeBuilder.setLoggerLevel(Level.ALL);
    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);
    //        ElementUtils.dumpTree(root);

    OpenTag body = ElementUtils.query(result.root(), "html/body");
    assertNotNull(body);

    CloseTag bodyEnd = body.matchingCloseTag();
    assertNotNull(bodyEnd);

    assertEquals(6190, bodyEnd.from());
    assertEquals(6197, bodyEnd.to());
  }
  public void testaParseErrorneousHeadContent() throws ParseException {
    // the &lt; char after the title close tag makes the parse tree really bad
    String code =
        "<!doctype html>\n"
            + "<html>\n"
            + "<head>\n"
            + "<title>\n"
            + "</title> < \n"
            + "</head>\n"
            + "<body>\n"
            + "</body>\n"
            + "</html>\n";

    //        NodeTreeBuilder.DEBUG_STATES = true;
    HtmlParseResult result = parse(code);
    Node root = result.root();
    assertNotNull(root);
    //        NodeUtils.dumpTree(result.root());

    //        Collection<ProblemDescription> problems = result.getProblems();
    //        for(ProblemDescription pd : problems) {
    //            System.out.println(pd);
    //        }

  }
  public void testOnlyDivInFile() throws ParseException {
    String code = "<!doctype html><html><head><title>x</title></head><body><di </body></html>";
    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);

    //        NodeUtils.dumpTree(root);
  }
  private HtmlParseResult parse(FileObject file) throws ParseException {
    HtmlSource source = new HtmlSource(file);
    HtmlParseResult result = SyntaxAnalyzer.create(source).analyze().parseHtml();

    assertNotNull(result);

    assertNodeOffsets(result.root());

    return result;
  }
  // Bug 191873 - IllegalStateException: Stack's top root:ROOT(0-186){} is not the same as
  // <*head>(34-40/47){}
  public void testNodePopWithoutPush() throws ParseException {
    String code = "<!doctype html>" + "<head></head>" + "<meta charset=\"utf-8\" />";

    //        NodeTreeBuilder.setLoggerLevel(Level.FINER);
    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);
    //        NodeUtils.dumpTree(root);

  }
  private HtmlParseResult parse(CharSequence code, boolean validateNodes) throws ParseException {
    HtmlSource source = new HtmlSource(code);
    final HtmlParseResult result = SyntaxAnalyzer.create(source).analyze().parseHtml();

    assertNotNull(result);

    if (validateNodes) {
      assertNodeOffsets(result.root());
    }

    return result;
  }
  // Bug 196479 - Problem with finding end tag for style element
  public void testStyleTag() throws ParseException {
    //        NodeTreeBuilder.setLoggerLevel(Level.FINER);

    String code =
        "<!doctype html>"
            + "<html>"
            + "<head>"
            + "<title></title>"
            + "<style> div { } </style>"
            // 2345678901234        890123456
            + "</head>"
            + "<body>"
            + "</body>"
            + "</html>";

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);
    //        ElementUtils.dumpTree(root);

    Node style = ElementUtils.query(root, "html/head/style");
    assertNotNull(style);

    assertEquals(42, style.from());
    assertEquals(49, style.to());

    // space after the style tag name
    code =
        "<!doctype html>"
            + "<html>"
            + "<head>"
            + "<title></title>"
            + "<style  > div { } </style>"
            // 2345678901234        890123456
            + "</head>"
            + "<body>"
            + "</body>"
            + "</html>";

    result = parse(code);
    root = result.root();

    assertNotNull(root);
    //        ElementUtils.dumpTree(root);

    style = ElementUtils.query(root, "html/head/style");
    assertNotNull(style);

    assertEquals(42, style.from());
    assertEquals(51, style.to());
  }
 public void testHtmlAndBodyTags() throws ParseException {
   HtmlParseResult result =
       parse(
           "<!DOCTYPE html><html><head><title>hello</title></head><body><div>ahoj</div></body></html>");
   Node root = result.root();
   //        NodeUtils.dumpTree(root);
   assertNotNull(root);
   assertNotNull(ElementUtils.query(root, "html"));
   assertNotNull(ElementUtils.query(root, "html/head"));
   assertNotNull(ElementUtils.query(root, "html/head/title"));
   assertNotNull(ElementUtils.query(root, "html/body"));
   assertNotNull(ElementUtils.query(root, "html/body/div"));
 }
  public void testGetPossibleOpenTagsInContext() throws ParseException {
    HtmlParseResult result =
        parse(
            "<!DOCTYPE html><html><head><title>hello</title></head><body><div>ahoj</div></body></html>");

    assertNotNull(result.root());

    Node body = ElementUtils.query(result.root(), "html/body");
    Collection<HtmlTag> possible = result.getPossibleOpenTags(body);

    assertTrue(!possible.isEmpty());

    HtmlTag divTag = new HtmlTagImpl("div");
    HtmlTag headTag = new HtmlTagImpl("head");

    assertTrue(possible.contains(divTag));
    assertFalse(possible.contains(headTag));

    Node head = ElementUtils.query(result.root(), "html/head");
    possible = result.getPossibleOpenTags(head);

    assertTrue(!possible.isEmpty());

    HtmlTag titleTag = new HtmlTagImpl("title");
    assertTrue(possible.contains(titleTag));
    assertFalse(possible.contains(headTag));

    Node html = ElementUtils.query(result.root(), "html");
    possible = result.getPossibleOpenTags(html);
    assertTrue(!possible.isEmpty());
    assertTrue(possible.contains(divTag));
  }
  public void testSelfCloseTagEndOffset() throws ParseException {
    //        ParseTreeBuilder.setLoggerLevel(Level.ALL);

    String code = "<div/>text";
    //             0123456
    HtmlParseResult result = parse(code);
    Node root = result.root();

    OpenTag div = ElementUtils.query(root, "html/body/div");
    assertNotNull(div);

    assertEquals(0, div.from());
    assertEquals(6, div.to());
  }
  public void testBodyTagHasNoParent() throws ParseException {
    String code =
        "<!doctype html> " + "<html> " + "<body >" + "      " + "<       " + "</body>" + "</html>";

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);

    Node body = ElementUtils.query(result.root(), "html/body");
    assertNotNull(body);

    assertNotNull(body.parent());

    //        NodeUtils.dumpTree(root);
  }
  public void testParseNotMatchingBodyTags() throws ParseException {
    String code =
        "<!doctype html>\n"
            + "<html>\n"
            + "<title></title>\n"
            + "<body>\n"
            + "</body>\n"
            + "</html>\n";

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);

    //        NodeUtils.dumpTree(root);
  }
  public void testParseTreeAfterOpenedTag() throws ParseException {
    String code =
        "<!DOCTYPE html>\n"
            + "<html>\n"
            + "<title>HTML5 Demo: geolocation</title>\n"
            + "<body>\n"
            + "<div></\n"
            + "</body>\n"
            + "</html>\n";

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);

    //        NodeUtils.dumpTree(root);
  }
  public void testParseTagAttributeWithoutValue() throws ParseException {
    String code = "<!doctype html><body><div align/></body>";
    HtmlParseResult result = parse(code);
    Node root = result.root();
    assertNotNull(root);

    //        ElementUtils.dumpTree(root);

    OpenTag div = ElementUtils.query(root, "html/body/div");
    assertNotNull(div);

    Attribute attr = div.getAttribute("align");
    assertNotNull(attr);

    assertNull(attr.value());
    assertNull(attr.unquotedValue());
  }
  public void testDivLogicalEndAtTheEOF() throws ParseException {
    String code = "<!doctype html><div><div></div>";
    //             0123456789012345678901234567890123456789
    //                                           ^
    //        NodeTreeBuilder.DEBUG = true;
    HtmlParseResult result = parse(code);
    Node root = result.root();

    //        NodeUtils.dumpTree(root);

    // the 't' node is foster parented, so it goes to the table's parent, not table itself
    OpenTag div = ElementUtils.query(root, "html/body/div");
    assertNotNull(div);

    assertEquals(30, div.semanticEnd());

    code = "<!doctype html><div><div></</div>";
    //      0123456789012345678901234567890123456789
    //                                      ^
    //        NodeTreeBuilder.DEBUG = true;
    result = parse(code);
    root = result.root();

    //        NodeUtils.dumpTree(root);

    // the 't' node is foster parented, so it goes to the table's parent, not table itself
    div = ElementUtils.query(root, "html/body/div");
    assertNotNull(div);

    assertEquals(32, div.semanticEnd());

    code = "<!doctype html><div></";
    //        0123456789012345678901234567890123456789
    //                             ^
    //        NodeTreeBuilder.DEBUG = true;
    result = parse(code);
    root = result.root();

    //        NodeUtils.dumpTree(root);

    // the 't' node is foster parented, so it goes to the table's parent, not table itself
    div = ElementUtils.query(root, "html/body/div");
    assertNotNull(div);

    assertEquals(21, div.semanticEnd());
  }
  public void testAttributes() throws ParseException {
    HtmlParseResult result =
        parse(
            "<!DOCTYPE html><html><head><title>hello</title></head><body onclick=\"alert()\"></body></html>");
    Node root = result.root();
    //        NodeUtils.dumpTree(root);
    assertNotNull(root);
    OpenTag body = ElementUtils.query(root, "html/body");
    assertNotNull(body);

    assertEquals(1, body.attributes().size());

    Attribute attr = body.attributes().iterator().next();
    assertNotNull(attr);
    assertEquals("onclick", attr.name().toString());
    assertEquals("\"alert()\"", attr.value().toString());
  }
  public void testParseUnfinishedCode() throws ParseException {
    String code =
        "<!DOCTYPE HTML>"
            + "<html>"
            + "<head>"
            + "<title>"
            + "</title>"
            + "</head>"
            + "<body>"
            + "</table>"
            + "</html>";

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);

    //        NodeUtils.dumpTree(root);

    Node html = ElementUtils.query(root, "html");
    assertNotNull(html);

    Collection<Element> children = html.children();
    assertEquals(4, children.size()); // <head>, </head>,<body>,</table>
    Iterator<Element> childernItr = children.iterator();

    assertTrue(childernItr.hasNext());
    Element child = childernItr.next();
    assertEquals(ElementType.OPEN_TAG, child.type());
    assertEquals("head", ((OpenTag) child).name().toString());
    assertTrue(childernItr.hasNext());
    child = childernItr.next();
    assertEquals(ElementType.CLOSE_TAG, child.type());
    assertEquals("head", ((CloseTag) child).name().toString());
    assertTrue(childernItr.hasNext());
    child = childernItr.next();
    assertEquals(ElementType.OPEN_TAG, child.type());
    assertEquals("body", ((OpenTag) child).name().toString());
    assertTrue(childernItr.hasNext());
    child = childernItr.next();
    assertEquals(ElementType.CLOSE_TAG, child.type());
    assertEquals("table", ((CloseTag) child).name().toString());

    //        NodeUtils.dumpTree(root);

  }
  public void testParseUnfinishedTagFollowedByChars() throws ParseException {
    String code =
        "<!doctype html> \n"
            + "<html>    \n"
            + "<title>dd</title>\n"
            + "<b\n" // the tag is unfinished during typing
            + "      a\n" // this text is considered as the tag's attribute (correctly)
            + "</body>\n"
            + "</html> ";

    HtmlParseResult result = parse(code);
    Node root = result.root();

    assertNotNull(root);

    //        NodeUtils.dumpTree(root);
  }
  public void testSimpleDocument() throws ParseException {
    String code =
        "<!doctype html><html><head><title>x</title></head><body><div onclick=\"alert();\"/></body></html>";
    //             012345678901234567890123456789012345678901234567890123456789012345678 901234567
    // 8901234567890123456789
    //             0         1         2         3         4         5         6          7
    // 8         9

    //        NodeTreeBuilder.DEBUG_STATES = true;
    HtmlParseResult result = parse(code);
    Node root = result.root();
    assertNotNull(root);
    //        NodeUtils.dumpTree(result.root());

    OpenTag html = ElementUtils.query(root, "html");
    assertEquals("html", html.name());
    assertEquals(15, html.from());
    assertEquals(21, html.to());
    assertEquals(15, html.from());
    assertEquals(95, html.semanticEnd());

    OpenTag body = ElementUtils.query(root, "html/body");
    assertEquals("body", body.name());
    assertEquals(50, body.from());
    assertEquals(56, body.to());
    assertEquals(50, body.from());
    assertEquals(88, body.semanticEnd());

    CloseTag bodyEndTag = body.matchingCloseTag();
    assertNotNull(bodyEndTag);
    assertSame(body, bodyEndTag.matchingOpenTag());
    assertSame(bodyEndTag, body.matchingCloseTag());

    OpenTag title = ElementUtils.query(root, "html/head/title");
    assertEquals("title", title.name());
    assertEquals(27, title.from());
    assertEquals(34, title.to());
    assertEquals(27, title.from());
    assertEquals(43, title.semanticEnd());

    CloseTag titleEndTag = title.matchingCloseTag();
    assertNotNull(titleEndTag);
    assertSame(title, titleEndTag.matchingOpenTag());
    assertSame(titleEndTag, title.matchingCloseTag());
  }
  // Bug 211776 - Self-closing element breaks code folding
  public void testIssue211776() throws ParseException {
    //        ParseTreeBuilder.setLoggerLevel(Level.ALL);

    HtmlParseResult result = parse(getTestFile("testfiles/test6.html"));
    Node root = result.root();
    //        ElementUtils.dumpTree(root);

    OpenTag body = ElementUtils.query(root, "html/body");
    assertNotNull(body);
    assertFalse(body.isEmpty());

    OpenTag link = ElementUtils.query(root, "html/head/link");
    assertNotNull(link);
    assertTrue(link.isEmpty());

    OpenTag div = ElementUtils.query(root, "html/body/div");
    assertNotNull(div);
    assertFalse(div.isEmpty());
  }