<!DOCTYPE html>
<meta charset=utf-8>
<title>Node.cloneNode</title>
<link rel=help href="https://dom.spec.whatwg.org/#dom-node-clonenode">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<script>
function assert_equal_node(nodeA, nodeB) {
  assert_equals(nodeB.nodeType, nodeA.nodeType, "nodeType");
  assert_equals(nodeB.nodeName, nodeA.nodeName, "nodeName");

  if (nodeA.nodeType === Node.ELEMENT_NODE) {
    assert_equals(nodeB.prefix, nodeA.prefix);
    assert_equals(nodeB.namespaceURI, nodeA.namespaceURI);
    assert_equals(nodeB.localName, nodeA.localName);
    assert_equals(nodeB.tagName, nodeA.tagName);
    assert_not_equals(nodeB.attributes != nodeA.attributes);
    assert_equals(nodeB.attributes.length, nodeA.attributes.length);
    for (var i = 0, il = nodeA.attributes.length; i < il; ++i) {
      assert_not_equals(nodeB.attributes[i], nodeA.attributes[i]);
      assert_equals(nodeB.attributes[i].name, nodeA.attributes[i].name);
      assert_equals(nodeB.attributes[i].prefix, nodeA.attributes[i].prefix);
      assert_equals(nodeB.attributes[i].namespaceURI, nodeA.attributes[i].namespaceURI);
      assert_equals(nodeB.attributes[i].value, nodeA.attributes[i].value);
    }
  }
}

function check_copy(orig, copy, type) {
    assert_not_equals(orig, copy);
    assert_equal_node(orig, copy);
    assert_true(orig instanceof type, "Should be type");
    assert_true(copy instanceof type, "Should be type");
}

function create_element_and_check(localName, type) {
  test(function() {
    var element = document.createElement(localName);
    var copy = element.cloneNode();
    check_copy(element, copy, type);
  }, "createElement(" + localName + ")");
}

// test1: createElement
test(function() {
    create_element_and_check("a",         HTMLAnchorElement);
    create_element_and_check("abbr",      HTMLElement);
    create_element_and_check("acronym",   HTMLElement);
    create_element_and_check("address",   HTMLElement);
    create_element_and_check("applet",    HTMLAppletElement);
    create_element_and_check("area",      HTMLAreaElement);
    create_element_and_check("article",   HTMLElement);
    create_element_and_check("aside",     HTMLElement);
    create_element_and_check("audio",     HTMLAudioElement);
    create_element_and_check("b",         HTMLElement);
    create_element_and_check("base",      HTMLBaseElement);
    create_element_and_check("bdi",       HTMLElement);
    create_element_and_check("bdo",       HTMLElement);
    create_element_and_check("bgsound",   HTMLElement);
    create_element_and_check("big",       HTMLElement);
    create_element_and_check("blockquote",HTMLElement);
    create_element_and_check("body",      HTMLBodyElement);
    create_element_and_check("br",        HTMLBRElement);
    create_element_and_check("button",    HTMLButtonElement);
    create_element_and_check("canvas",    HTMLCanvasElement);
    create_element_and_check("caption",   HTMLTableCaptionElement);
    create_element_and_check("center",    HTMLElement);
    create_element_and_check("cite",      HTMLElement);
    create_element_and_check("code",      HTMLElement);
    create_element_and_check("col",       HTMLTableColElement);
    create_element_and_check("colgroup",  HTMLTableColElement);
    create_element_and_check("data",      HTMLDataElement);
    create_element_and_check("datalist",  HTMLDataListElement);
    create_element_and_check("dialog",    HTMLDialogElement);
    create_element_and_check("dd",        HTMLElement);
    create_element_and_check("del",       HTMLModElement);
    create_element_and_check("details",   HTMLElement);
    create_element_and_check("dfn",       HTMLElement);
    create_element_and_check("dir",       HTMLDirectoryElement);
    create_element_and_check("div",       HTMLDivElement);
    create_element_and_check("dl",        HTMLDListElement);
    create_element_and_check("dt",        HTMLElement);
    create_element_and_check("embed",     HTMLEmbedElement);
    create_element_and_check("fieldset",  HTMLFieldSetElement);
    create_element_and_check("figcaption",HTMLElement);
    create_element_and_check("figure",    HTMLElement);
    create_element_and_check("font",      HTMLFontElement);
    create_element_and_check("footer",    HTMLElement);
    create_element_and_check("form",      HTMLFormElement);
    create_element_and_check("frame",     HTMLFrameElement);
    create_element_and_check("frameset",  HTMLFrameSetElement);
    create_element_and_check("h1",        HTMLHeadingElement);
    create_element_and_check("h2",        HTMLHeadingElement);
    create_element_and_check("h3",        HTMLHeadingElement);
    create_element_and_check("h4",        HTMLHeadingElement);
    create_element_and_check("h5",        HTMLHeadingElement);
    create_element_and_check("h6",        HTMLHeadingElement);
    create_element_and_check("head",      HTMLHeadElement);
    create_element_and_check("header",    HTMLElement);
    create_element_and_check("hgroup",    HTMLElement);
    create_element_and_check("hr",        HTMLHRElement);
    create_element_and_check("html",      HTMLHtmlElement);
    create_element_and_check("i",         HTMLElement);
    create_element_and_check("iframe",    HTMLIFrameElement);
    create_element_and_check("img",       HTMLImageElement);
    create_element_and_check("input",     HTMLInputElement);
    create_element_and_check("ins",       HTMLModElement);
    create_element_and_check("isindex",   HTMLElement);
    create_element_and_check("kbd",       HTMLElement);
    create_element_and_check("label",     HTMLLabelElement);
    create_element_and_check("legend",    HTMLLegendElement);
    create_element_and_check("li",        HTMLLIElement);
    create_element_and_check("link",      HTMLLinkElement);
    create_element_and_check("main",      HTMLElement);
    create_element_and_check("map",       HTMLMapElement);
    create_element_and_check("mark",      HTMLElement);
    create_element_and_check("marquee",   HTMLElement);
    create_element_and_check("meta",      HTMLMetaElement);
    create_element_and_check("meter",     HTMLMeterElement);
    create_element_and_check("nav",       HTMLElement);
    create_element_and_check("nobr",      HTMLElement);
    create_element_and_check("noframes",  HTMLElement);
    create_element_and_check("noscript",  HTMLElement);
    create_element_and_check("object",    HTMLObjectElement);
    create_element_and_check("ol",        HTMLOListElement);
    create_element_and_check("optgroup",  HTMLOptGroupElement);
    create_element_and_check("option",    HTMLOptionElement);
    create_element_and_check("output",    HTMLOutputElement);
    create_element_and_check("p",         HTMLParagraphElement);
    create_element_and_check("param",     HTMLParamElement);
    create_element_and_check("pre",       HTMLPreElement);
    create_element_and_check("progress",  HTMLProgressElement);
    create_element_and_check("q",         HTMLQuoteElement);
    create_element_and_check("rp",        HTMLElement);
    create_element_and_check("rt",        HTMLElement);
    create_element_and_check("ruby",      HTMLElement);
    create_element_and_check("s",         HTMLElement);
    create_element_and_check("samp",      HTMLElement);
    create_element_and_check("script",    HTMLScriptElement);
    create_element_and_check("section",   HTMLElement);
    create_element_and_check("select",    HTMLSelectElement);
    create_element_and_check("small",     HTMLElement);
    create_element_and_check("source",    HTMLSourceElement);
    create_element_and_check("spacer",    HTMLElement);
    create_element_and_check("span",      HTMLSpanElement);
    create_element_and_check("strike",    HTMLElement);
    create_element_and_check("style",     HTMLStyleElement);
    create_element_and_check("sub",       HTMLElement);
    create_element_and_check("summary",   HTMLElement);
    create_element_and_check("sup",       HTMLElement);
    create_element_and_check("table",     HTMLTableElement);
    create_element_and_check("tbody",     HTMLTableSectionElement);
    create_element_and_check("td",        HTMLTableCellElement);
    create_element_and_check("template",  HTMLTemplateElement);
    create_element_and_check("textarea",  HTMLTextAreaElement);
    create_element_and_check("th",        HTMLTableCellElement);
    create_element_and_check("time",      HTMLTimeElement);
    create_element_and_check("title",     HTMLTitleElement);
    create_element_and_check("tr",        HTMLTableRowElement);
    create_element_and_check("tt",        HTMLElement);
    create_element_and_check("track",     HTMLTrackElement);
    create_element_and_check("u",         HTMLElement);
    create_element_and_check("ul",        HTMLUListElement);
    create_element_and_check("var",       HTMLElement);
    create_element_and_check("video",     HTMLVideoElement);
    create_element_and_check("unknown",   HTMLUnknownElement);
    create_element_and_check("wbr",       HTMLElement);
}, "");

test(function() {
    var fragment = document.createDocumentFragment();
    var copy = fragment.cloneNode();
    check_copy(fragment, copy, DocumentFragment);
}, "createDocumentFragment");

test(function() {
    var text = document.createTextNode("hello world");
    var copy = text.cloneNode();
    check_copy(text, copy, Text);
    assert_equals(text.data, copy.data);
    assert_equals(text.wholeText, copy.wholeText);
}, "createTextNode");

test(function() {
    var comment = document.createComment("a comment");
    var copy = comment.cloneNode();
    check_copy(comment, copy, Comment);
    assert_equals(comment.data, copy.data);
}, "createComment");

test(function() {
  var el = document.createElement("foo");
  el.setAttribute("a", "b");
  el.setAttribute("c", "d");
  var c = el.cloneNode();
  check_copy(el, c, Element);
}, "createElement with attributes")

test(function() {
  var el = document.createElementNS("http://www.w3.org/1999/xhtml", "foo:div");
  var c = el.cloneNode();
  check_copy(el, c, HTMLDivElement);
}, "createElementNS HTML")

test(function() {
  var el = document.createElementNS("http://www.example.com/", "foo:div");
  var c = el.cloneNode();
  check_copy(el, c, Element);
}, "createElementNS non-HTML")

test(function() {
    var pi = document.createProcessingInstruction("target", "data");
    var copy = pi.cloneNode();
    check_copy(pi, copy, ProcessingInstruction);
    assert_equals(pi.data, copy.data);
    assert_equals(pi.target, pi.target);
}, "createProcessingInstruction");

test(function() {
    var doctype = document.implementation.createDocumentType("html", "public", "system");
    var copy = doctype.cloneNode();
    check_copy(doctype, copy, DocumentType);
    assert_equals(doctype.name, copy.name);
    assert_equals(doctype.publicId, copy.publicId);
    assert_equals(doctype.systemId, copy.systemId);
}, "implementation.createDocumentType");

test(function() {
    var doc = document.implementation.createDocument(null, null);
    var copy = doc.cloneNode();
    check_copy(doc, copy, Document);
    assert_equals(doc.contentType, copy.contentType);
}, "implementation.createDocument");

test(function() {
    var html = document.implementation.createHTMLDocument("title");
    var copy = html.cloneNode();
    check_copy(html, copy, Document);
    assert_equals(copy.title, "");
}, "implementation.createHTMLDocument");

test(function() {
    var parent = document.createElement("div");
    var child1 = document.createElement("div");
    var child2 = document.createElement("div");
    var grandChild = document.createElement("div");

    child2.appendChild(grandChild);
    parent.appendChild(child1);
    parent.appendChild(child2);

    var deep = true;
    var copy = parent.cloneNode(deep);

    check_copy(parent, copy, HTMLDivElement);
    assert_equals(copy.childNodes.length, 2);

    check_copy(child1, copy.childNodes[0], HTMLDivElement);
    assert_equals(copy.childNodes[0].childNodes.length, 0);

    check_copy(child2, copy.childNodes[1], HTMLDivElement);
    assert_equals(copy.childNodes[1].childNodes.length, 1);
    check_copy(grandChild, copy.childNodes[1].childNodes[0], HTMLDivElement);

    deep = false;
    copy = parent.cloneNode(deep);

    check_copy(parent, copy, HTMLDivElement);
    assert_equals(copy.childNodes.length, 0);
}, "node with children");
</script>