Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added support for scripts that use document.write.

  • Loading branch information...
commit 901d806b60177185ec12df26dc8c8a55a0b07ee6 1 parent 778e0d8
@assaf authored
View
4 CHANGELOG.md
@@ -5,13 +5,15 @@ zombie.js changelog(1) -- Changelog
Now parsing documents using HTML5, which can deal better with tag soup.
+Added support for scripts that use document.write.
+
Added troublehsooting guide.
Fixed naming issue: browser.last_request is now lastRequest, same for
lastResponse and lastError.
189 Tests
- 2.3 sec to complete
+ 2.5 sec to complete
## Version 0.7.3 2010-12-27
View
2  package.json
@@ -1,6 +1,6 @@
{
"name": "zombie",
- "version": "0.7.3",
+ "version": "0.7.4",
"description": "Insanely fast, full-stack, headless testing using node.js",
"homepage": "http://zombie.labnotes.org/",
"author": "Assaf Arkin <assaf@labnotes.org> (http://labnotes.org/)",
View
2  spec/browser-spec.coffee
@@ -190,8 +190,6 @@ vows.describe("Browser").addBatch(
"should run script": (browser)-> assert.equal browser.document.title, "Script document.write"
"adding script using appendChild":
zombie.wants "http://localhost:3003/script/append"
- "should change html": (browser)->
- console.log browser.html()
"should run script": (browser)-> assert.equal browser.document.title, "Script appendChild"
).export(module)
View
33 src/zombie/jsdom_patches.coffee
@@ -94,8 +94,9 @@ core.resourceLoader.download = (url, callback)->
# - JSDOM assumes a SCRIPT element would have one text node, it may have
# more, and in the second case, it has none.
# - HTML5 creates the SCRIPT element first, then adds the script
-# contents to the element. We handle that by catching the
-# DOMCharacterDataModified event.
+# contents to the element. We handle that by catching appendChild
+# with a text node and DOMCharacterDataModified event on the text
+# node.
# - Scripts can be added using document.write, so we need to patch
# document.write so it adds the script instead of erasing the
# document.
@@ -111,21 +112,33 @@ advise = (clazz, method, advice)->
ret = impl.apply(this, arguments)
args.unshift ret
return advice.apply(this, args) || ret
+
+# JSDOM had advise for appendChild, but doesn't seem to do much if the
+# child is a text node.
+advise core.Node, "appendChild", (ret, newChild, refChild)->
+ if this.ownerDocument && newChild.nodeType == this.TEXT_NODE
+ ev = this.ownerDocument.createEvent("MutationEvents")
+ ev.initMutationEvent("DOMNodeInsertedIntoDocument", true, false, this, null, null, null, null)
+ newChild.parentNode.dispatchEvent(ev)
+
# DOMCharacterDataModified event fired when text is added to a
# TextNode. This is a crappy implementation, a good one would old and
# new values in the event.
-advise core.Text, "appendData", (value)->
- doc = this.ownerDocument
- ev = doc.createEvent("MutationEvents")
- ev.initMutationEvent("DOMCharacterDataModified", true, false, this, this.nodeValue.replace(value, ""), this.nodeValue, null, null)
- this.dispatchEvent ev
+core.CharacterData.prototype.__defineSetter__ "_nodeValue", (newValue)->
+ oldValue = @_text || ""
+ @_text = newValue
+ if @ownerDocument && @parentNode
+ ev = @ownerDocument.createEvent("MutationEvents")
+ ev.initMutationEvent("DOMCharacterDataModified", true, false, this, oldValue, newValue, null, null)
+ @dispatchEvent ev
+core.CharacterData.prototype.__defineGetter__ "_nodeValue", -> @_text
# Add support for DOMCharacterDataModified, so we can execute a script
# when its text contents is changed. Safari and Firefox support that.
core.Document.prototype._elementBuilders["script"] = (doc, s)->
script = new core.HTMLScriptElement(doc, s)
script.addEventListener "DOMCharacterDataModified", (event)->
- code = event.newValue.trim()
+ code = event.target.nodeValue.trim()
if code.length > 0
src = this.sourceLocation || {}
filename = src.file || this.ownerDocument.URL
@@ -140,12 +153,14 @@ core.Document.prototype._elementBuilders["script"] = (doc, s)->
(item.value for item in this.children).join("") + " "
return script
+# Fix document.write so it can handle calling document.write from a
+# script while loading the document.
core.HTMLDocument.prototype._write = (html)->
if @readyState == "loading" && @_parser
# During page loading, document.write appends to the current element
open = @_parser.tree.open_elements.last()
parser = new html5.Parser(document: this)
- parser.parse_fragment(html, open)
+ node = parser.parse_fragment(html, open.parentNode)
else
# When loading page, parse from scratch.
# After page loading, empty document and parse from scratch.
Please sign in to comment.
Something went wrong with that request. Please try again.