Skip to content
This repository has been archived by the owner on Dec 16, 2023. It is now read-only.

Commit

Permalink
Added support for scripts that use document.write.
Browse files Browse the repository at this point in the history
  • Loading branch information
assaf committed Dec 28, 2010
1 parent 778e0d8 commit 901d806
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 13 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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/)",
Expand Down
2 changes: 0 additions & 2 deletions spec/browser-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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)
33 changes: 24 additions & 9 deletions src/zombie/jsdom_patches.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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.
Expand Down

0 comments on commit 901d806

Please sign in to comment.