|  | <!DOCTYPE html> | 
|  | <meta charset=utf-8> | 
|  | <title>Node.textContent</title> | 
|  | <script src="/resources/testharness.js"></script> | 
|  | <script src="/resources/testharnessreport.js"></script> | 
|  | <div id="log"></div> | 
|  | <script> | 
|  | // XXX mutation observers? | 
|  | // XXX Range gravitation? | 
|  |  | 
|  | var documents, doctypes; | 
|  | setup(function() { | 
|  | documents = [ | 
|  | [document, "parser"], | 
|  | [document.implementation.createDocument("", "test", null), "createDocument"], | 
|  | [document.implementation.createHTMLDocument("title"), "createHTMLDocument"], | 
|  | ] | 
|  | doctypes = [ | 
|  | [document.doctype, "parser"], | 
|  | [document.implementation.createDocumentType("x", "", ""), "script"], | 
|  | ] | 
|  | }) | 
|  |  | 
|  | // Getting | 
|  | // DocumentFragment, Element: | 
|  | test(function() { | 
|  | var element = document.createElement("div") | 
|  | assert_equals(element.textContent, "") | 
|  | }, "For an empty Element, textContent should be the empty string") | 
|  |  | 
|  | test(function() { | 
|  | assert_equals(document.createDocumentFragment().textContent, "") | 
|  | }, "For an empty DocumentFragment, textContent should be the empty string") | 
|  |  | 
|  | test(function() { | 
|  | var el = document.createElement("div") | 
|  | el.appendChild(document.createComment(" abc ")) | 
|  | el.appendChild(document.createTextNode("\tDEF\t")) | 
|  | el.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | assert_equals(el.textContent, "\tDEF\t") | 
|  | }, "Element with children") | 
|  |  | 
|  | test(function() { | 
|  | var el = document.createElement("div") | 
|  | var child = document.createElement("div") | 
|  | el.appendChild(child) | 
|  | child.appendChild(document.createComment(" abc ")) | 
|  | child.appendChild(document.createTextNode("\tDEF\t")) | 
|  | child.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | assert_equals(el.textContent, "\tDEF\t") | 
|  | }, "Element with descendants") | 
|  |  | 
|  | test(function() { | 
|  | var df = document.createDocumentFragment() | 
|  | df.appendChild(document.createComment(" abc ")) | 
|  | df.appendChild(document.createTextNode("\tDEF\t")) | 
|  | df.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | assert_equals(df.textContent, "\tDEF\t") | 
|  | }, "DocumentFragment with children") | 
|  |  | 
|  | test(function() { | 
|  | var df = document.createDocumentFragment() | 
|  | var child = document.createElement("div") | 
|  | df.appendChild(child) | 
|  | child.appendChild(document.createComment(" abc ")) | 
|  | child.appendChild(document.createTextNode("\tDEF\t")) | 
|  | child.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | assert_equals(df.textContent, "\tDEF\t") | 
|  | }, "DocumentFragment with descendants") | 
|  |  | 
|  | // Text, ProcessingInstruction, Comment: | 
|  | test(function() { | 
|  | assert_equals(document.createTextNode("").textContent, "") | 
|  | }, "For an empty Text, textContent should be the empty string") | 
|  |  | 
|  | test(function() { | 
|  | assert_equals(document.createProcessingInstruction("x", "").textContent, "") | 
|  | }, "For an empty ProcessingInstruction, textContent should be the empty string") | 
|  |  | 
|  | test(function() { | 
|  | assert_equals(document.createComment("").textContent, "") | 
|  | }, "For an empty Comment, textContent should be the empty string") | 
|  |  | 
|  | test(function() { | 
|  | assert_equals(document.createTextNode("abc").textContent, "abc") | 
|  | }, "For a Text with data, textContent should be that data") | 
|  |  | 
|  | test(function() { | 
|  | assert_equals(document.createProcessingInstruction("x", "abc").textContent, | 
|  | "abc") | 
|  | }, "For a ProcessingInstruction with data, textContent should be that data") | 
|  |  | 
|  | test(function() { | 
|  | assert_equals(document.createComment("abc").textContent, "abc") | 
|  | }, "For a Comment with data, textContent should be that data") | 
|  |  | 
|  | // Any other node: | 
|  | documents.forEach(function(argument) { | 
|  | var doc = argument[0], creator = argument[1] | 
|  | test(function() { | 
|  | assert_equals(doc.textContent, null) | 
|  | }, "For Documents created by " + creator + ", textContent should be null") | 
|  | }) | 
|  |  | 
|  | doctypes.forEach(function(argument) { | 
|  | var doctype = argument[0], creator = argument[1] | 
|  | test(function() { | 
|  | assert_equals(doctype.textContent, null) | 
|  | }, "For DocumentType created by " + creator + ", textContent should be null") | 
|  | }) | 
|  |  | 
|  | // Setting | 
|  | // DocumentFragment, Element: | 
|  | var arguments = [ | 
|  | [null, null], | 
|  | [undefined, null], | 
|  | ["", null], | 
|  | [42, "42"], | 
|  | ["abc", "abc"], | 
|  | ["<b>xyz<\/b>", "<b>xyz<\/b>"], | 
|  | ["d\0e", "d\0e"] | 
|  | // XXX unpaired surrogate? | 
|  | ] | 
|  | arguments.forEach(function(aValue) { | 
|  | var argument = aValue[0], expectation = aValue[1] | 
|  | var check = function(aElementOrDocumentFragment) { | 
|  | if (expectation === null) { | 
|  | assert_equals(aElementOrDocumentFragment.textContent, "") | 
|  | assert_equals(aElementOrDocumentFragment.firstChild, null) | 
|  | } else { | 
|  | assert_equals(aElementOrDocumentFragment.textContent, expectation) | 
|  | assert_equals(aElementOrDocumentFragment.childNodes.length, 1, | 
|  | "Should have one child") | 
|  | var firstChild = aElementOrDocumentFragment.firstChild | 
|  | assert_true(firstChild instanceof Text, "child should be a Text") | 
|  | assert_equals(firstChild.data, expectation) | 
|  | } | 
|  | } | 
|  |  | 
|  | test(function() { | 
|  | var el = document.createElement("div") | 
|  | el.textContent = argument | 
|  | check(el) | 
|  | }, "Element without children set to " + format_value(argument)) | 
|  |  | 
|  | test(function() { | 
|  | var el = document.createElement("div") | 
|  | var text = el.appendChild(document.createTextNode("")) | 
|  | el.textContent = argument | 
|  | check(el) | 
|  | assert_equals(text.parentNode, null, | 
|  | "Preexisting Text should have been removed") | 
|  | }, "Element with empty text node as child set to " + format_value(argument)) | 
|  |  | 
|  | test(function() { | 
|  | var el = document.createElement("div") | 
|  | el.appendChild(document.createComment(" abc ")) | 
|  | el.appendChild(document.createTextNode("\tDEF\t")) | 
|  | el.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | el.textContent = argument | 
|  | check(el) | 
|  | }, "Element with children set to " + format_value(argument)) | 
|  |  | 
|  | test(function() { | 
|  | var el = document.createElement("div") | 
|  | var child = document.createElement("div") | 
|  | el.appendChild(child) | 
|  | child.appendChild(document.createComment(" abc ")) | 
|  | child.appendChild(document.createTextNode("\tDEF\t")) | 
|  | child.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | el.textContent = argument | 
|  | check(el) | 
|  | assert_equals(child.childNodes.length, 3, | 
|  | "Should not have changed the internal structure of the removed nodes.") | 
|  | }, "Element with descendants set to " + format_value(argument)) | 
|  |  | 
|  | test(function() { | 
|  | var df = document.createDocumentFragment() | 
|  | df.textContent = argument | 
|  | check(df) | 
|  | }, "DocumentFragment without children set to " + format_value(argument)) | 
|  |  | 
|  | test(function() { | 
|  | var df = document.createDocumentFragment() | 
|  | var text = df.appendChild(document.createTextNode("")) | 
|  | df.textContent = argument | 
|  | check(df) | 
|  | assert_equals(text.parentNode, null, | 
|  | "Preexisting Text should have been removed") | 
|  | }, "DocumentFragment with empty text node as child set to " + format_value(argument)) | 
|  |  | 
|  | test(function() { | 
|  | var df = document.createDocumentFragment() | 
|  | df.appendChild(document.createComment(" abc ")) | 
|  | df.appendChild(document.createTextNode("\tDEF\t")) | 
|  | df.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | df.textContent = argument | 
|  | check(df) | 
|  | }, "DocumentFragment with children set to " + format_value(argument)) | 
|  |  | 
|  | test(function() { | 
|  | var df = document.createDocumentFragment() | 
|  | var child = document.createElement("div") | 
|  | df.appendChild(child) | 
|  | child.appendChild(document.createComment(" abc ")) | 
|  | child.appendChild(document.createTextNode("\tDEF\t")) | 
|  | child.appendChild(document.createProcessingInstruction("x", " ghi ")) | 
|  | df.textContent = argument | 
|  | check(df) | 
|  | assert_equals(child.childNodes.length, 3, | 
|  | "Should not have changed the internal structure of the removed nodes.") | 
|  | }, "DocumentFragment with descendants set to " + format_value(argument)) | 
|  | }) | 
|  |  | 
|  | // Text, ProcessingInstruction, Comment: | 
|  | test(function() { | 
|  | var text = document.createTextNode("abc") | 
|  | text.textContent = "def" | 
|  | assert_equals(text.textContent, "def") | 
|  | assert_equals(text.data, "def") | 
|  | }, "For a Text, textContent should set the data") | 
|  |  | 
|  | test(function() { | 
|  | var pi = document.createProcessingInstruction("x", "abc") | 
|  | pi.textContent = "def" | 
|  | assert_equals(pi.textContent, "def") | 
|  | assert_equals(pi.data, "def") | 
|  | assert_equals(pi.target, "x") | 
|  | }, "For a ProcessingInstruction, textContent should set the data") | 
|  |  | 
|  | test(function() { | 
|  | var comment = document.createComment("abc") | 
|  | comment.textContent = "def" | 
|  | assert_equals(comment.textContent, "def") | 
|  | assert_equals(comment.data, "def") | 
|  | }, "For a Comment, textContent should set the data") | 
|  |  | 
|  | // Any other node: | 
|  | documents.forEach(function(argument) { | 
|  | var doc = argument[0], creator = argument[1] | 
|  | test(function() { | 
|  | var root = doc.documentElement | 
|  | doc.textContent = "a" | 
|  | assert_equals(doc.textContent, null) | 
|  | assert_equals(doc.documentElement, root) | 
|  | }, "For Documents created by " + creator + ", setting textContent should do nothing") | 
|  | }) | 
|  |  | 
|  | doctypes.forEach(function(argument) { | 
|  | var doctype = argument[0], creator = argument[1] | 
|  | test(function() { | 
|  | var props = { | 
|  | name: doctype.name, | 
|  | publicId: doctype.publicId, | 
|  | systemId: doctype.systemId, | 
|  | } | 
|  | doctype.textContent = "b" | 
|  | assert_equals(doctype.textContent, null) | 
|  | assert_equals(doctype.name, props.name, "name should not change") | 
|  | assert_equals(doctype.publicId, props.publicId, "publicId should not change") | 
|  | assert_equals(doctype.systemId, props.systemId, "systemId should not change") | 
|  | }, "For DocumentType created by " + creator + ", setting textContent should do nothing") | 
|  | }) | 
|  |  | 
|  | </script> |