Browse files

Fixed test suite so vows command just works.

Added README and license file.
  • Loading branch information...
1 parent 5ca4adc commit 41ee2f2921d5483e986dbb9a4f7cf978bbbecbb8 @assaf committed Dec 9, 2010
View
0 README → CHANGELOG
File renamed without changes.
View
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2010 Assaf Arkin
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
36 README.md
@@ -0,0 +1,36 @@
+Zombie.js
+=========
+
+If you're going to write an insanely fast, headless test tool, how can you not
+call it Zombie? Zombie it is.
+
+Zombie.js is a lightweight framefork for testing client-side JavaScript code in
+a simulated environment. No browser required.
+
+Zombie.js runs on [Node.js](http://nodejs.org/), so it's insanely fast. It
+uses [JSDOM](http://jsdom.org/) to simulate a brower, so it can't find
+incompatibility issues in IE 7.0, but it can spot bugs in your code.
+
+You don't have to, but I really recommend running Zombie.js with
+[Vows](http://vowsjs.org/) , an outstanding BDD test framework for Node.js.
+
+
+Using
+-----
+
+Coming.
+
+
+Contributing
+------------
+
+Fork the project.
+Add tests.
+Make your changes.
+Send me a pull request.
+
+
+License/Credit
+--------------
+
+Zombie.js is copyright of Assaf Arkin, released under the MIT License.
View
4 lib/zombie/browser.coffee
@@ -2,8 +2,8 @@ require.paths.unshift(__dirname)
jsdom = require("jsdom")
require "./jsdom_patches"
history = require("./history")
-event_loop = require("./event_loop")
-xhr = require("./xmlhttprequest")
+event_loop = require("./eventloop")
+xhr = require("./xhr")
# Use the browser to open up new windows and load documents.
#
View
0 lib/zombie/event_loop.coffee → lib/zombie/eventloop.coffee
File renamed without changes.
View
0 lib/zombie/xmlhttprequest.coffee → lib/zombie/xhr.coffee
File renamed without changes.
View
2 package.json
@@ -1,6 +1,6 @@
{
"name": "zombie",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "Superfast headless full stack testing framework using node.js",
"homepage": "https://github.com/assaf/zombie",
"author": "Assaf Arkin <assaf@labnotes.org> (http://labnotes.org/)",
View
9 spec/browser_spec.coffee → spec/browser-spec.coffee
@@ -1,10 +1,9 @@
-vows = require("vows")
-assert = require("assert")
+require("./helpers")
+{ vows: vows, assert: assert, zombie: zombie, brains: brains } = require("vows")
jsdom = require("jsdom")
-{ server: server, visit: visit } = require("./helpers")
-server.get "/scripted", (req, res)->
+brains.get "/scripted", (req, res)->
res.send """
<html>
<head>
@@ -20,7 +19,7 @@ server.get "/scripted", (req, res)->
vows.describe("Browser").addBatch({
"open page":
- visit "http://localhost:3003/scripted"
+ zombie.wants "http://localhost:3003/scripted"
"should create HTML document": (window)-> assert.instanceOf window.document, jsdom.dom.level3.html.HTMLDocument
"should load document from server": (window)-> assert.match window.document.outerHTML, /<body>Hello World<\/body>/
"should load external scripts": (window)->
View
21 spec/event_loop_spec.coffee → spec/eventloop-spec.coffee
@@ -1,9 +1,8 @@
-vows = require("vows", "assert")
-assert = require("assert")
-{ server: server, visit: visit } = require("./helpers")
+require("./helpers")
+{ vows: vows, assert: assert, zombie: zombie, brains: brains } = require("vows")
-server.get "/timeout", (req, res)->
+brains.get "/timeout", (req, res)->
res.send """
<html>
<head><title>One</title></head>
@@ -16,7 +15,7 @@ server.get "/timeout", (req, res)->
</html>
"""
-server.get "/interval", (req, res)->
+brains.get "/interval", (req, res)->
res.send """
<html>
<head><title></title></head>
@@ -33,16 +32,16 @@ server.get "/interval", (req, res)->
vows.describe("EventLoop").addBatch({
"setTimeout":
"no wait":
- visit "http://localhost:3003/timeout"
+ zombie.wants "http://localhost:3003/timeout"
"should not fire any timeout events": (window)-> assert.equal window.document.title, "One"
"should not change clock": (window) -> assert.equal window.clock, 0
"wait for all":
- visit "http://localhost:3003/timeout"
+ zombie.wants "http://localhost:3003/timeout"
ready: (err, window)-> window.wait @callback
"should fire all timeout events": (window)-> assert.equal window.document.title, "One Two Three"
"should move clock forward": (window) -> assert.equal window.clock, 5000
"cancel timeout":
- visit "http://localhost:3003/timeout"
+ zombie.wants "http://localhost:3003/timeout"
ready: (err, window)->
terminate = ->
window.clearTimeout window.second
@@ -54,16 +53,16 @@ vows.describe("EventLoop").addBatch({
"setInterval":
"no wait":
- visit "http://localhost:3003/interval"
+ zombie.wants "http://localhost:3003/interval"
"should not fire any timeout events": (window)-> assert.equal window.document.title, ""
"should not change clock": (window) -> assert.equal window.clock, 0
"wait for five":
- visit "http://localhost:3003/interval"
+ zombie.wants "http://localhost:3003/interval"
ready: (err, window)-> window.wait 5, @callback
"should fire five interval event": (window)-> assert.equal window.document.title, "....."
"should move clock forward": (window) -> assert.equal window.clock, 5000
"cancel interval":
- visit "http://localhost:3003/interval"
+ zombie.wants "http://localhost:3003/interval"
ready: (err, window)->
window.wait 5, =>
window.clearInterval window.interval
View
102 spec/helpers.coffee
@@ -1,47 +1,67 @@
require.paths.push(__dirname + "/../lib")
fs = require("fs")
-browser = exports.browser = require("zombie").browser
+browser = require("zombie").browser
-exports.server = server = require("express").createServer()
-server.get "/", (req, res)->
- res.send "<html><title>Little Red</title></html>"
-server.get "/jquery.js", (req, res)->
+
+# When you run the vows command, it picks all the files in the spec directory
+# and attempts to run their exports. If we wanted to export brains or zombie,
+# Vows would try to run them, even though they're not test suites. So we hack
+# around it by, instead of exporting, assigning them as instance variables on
+# the Vows object. And for convenience we also include assert in there.
+vows = require("vows")
+vows.vows = vows
+vows.assert = require("assert")
+
+# Hack Vows console to figure out when Vows is done running tests and shut down
+# the Web server.
+vows.console = require("vows/console")
+result = vows.console.result
+vows.console.result = (results)->
+ brains.close() if brains.active
+ result.call vows.console, results
+
+
+# An Express server we use to test the browser.
+brains = require("express").createServer()
+brains.get "/", (req, res)->
+ res.send "<html><title>Tap, Tap</title></html>"
+brains.get "/jquery.js", (req, res)->
fs.readFile "#{__dirname}/../data/jquery.js", (err, data)-> res.send data
-server.ready = (callback)->
- if @_waiting
- @_waiting.push callback
- else if @_active
- ++@_active
- callback()
+brains.ready = (callback)->
+ if @active
+ process.nextTick callback
else
- @_waiting = [callback]
- server.listen 3003, ->
- @_active = @_waiting.length
- @_waiting.forEach (callback)-> callback()
- @_waiting = null
+ brains.listen 3003, ->
+ @active = true
+ process.nextTick callback
return # nothing
-server.done = -> @close() if --@_active == 0
-
-
-# Creates a new Vows context that will wait for the HTTP server to be ready,
-# then create a new Browser, visit the specified page (url), run all the tests
-# and shutdown the HTTP server.
-#
-# The second argument is the context with all its tests (and subcontexts). The
-# topic passed to all tests is the browser window after loading the document.
-# However, you can (and often need to) supply a ready function that will be
-# called with err and window; the ready function can then call this.callback.
-exports.visit = (url, context)->
- context ||= {}
- context.topic = ->
- ready = context.ready
- delete context.ready
- server.ready =>
- browser.open url, (err, window)=>
- if ready
- ready.apply this, [err, window]
- else
- @callback err, window
- return
- context.teardown = -> server.done()
- return context
+
+
+# Zombie wants brain.
+zombie =
+ # Returns a new browser
+ new: browser.new
+ # Creates a new Vows context that will wait for the HTTP server to be ready,
+ # then create a new Browser, visit the specified page (url), run all the tests
+ # and shutdown the HTTP server.
+ #
+ # The second argument is the context with all its tests (and subcontexts). The
+ # topic passed to all tests is the browser window after loading the document.
+ # However, you can (and often need to) supply a ready function that will be
+ # called with err and window; the ready function can then call this.callback.
+ wants: (url, context)->
+ context ||= {}
+ context.topic = ->
+ ready = context.ready
+ delete context.ready
+ brains.ready =>
+ browser.open url, (err, window)=>
+ if ready
+ ready.apply this, [err, window]
+ else
+ @callback err, window
+ return
+ return context
+
+vows.zombie = zombie
+vows.brains = brains
View
34 spec/history_spec.coffee → spec/history-spec.coffee
@@ -1,17 +1,15 @@
-vows = require("vows", "assert")
-assert = require("assert")
+require("./helpers")
+{ vows: vows, assert: assert, zombie: zombie, brains: brains } = require("vows")
jsdom = require("jsdom")
-{ server: server, visit: visit } = require("./helpers")
-{ browser: browser } = require("zombie")
-server.get "/boo", (req, res)->
+brains.get "/boo", (req, res)->
res.send "<html><title>Eeek!</title></html>"
vows.describe("History").addBatch({
"new window":
- topic: -> browser.new().window
+ topic: -> zombie.new().window
"should start out empty": (window)-> assert.length window.history, 0
"should start out with no location": (window)-> assert.isUndefined window.location.href
"go forward":
@@ -31,7 +29,7 @@ vows.describe("History").addBatch({
"history":
"pushState":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err,window)->
window.history.pushState { is: "start" }, null, "/start"
window.history.pushState { is: "end" }, null, "/end"
@@ -45,7 +43,7 @@ vows.describe("History").addBatch({
"should fire popstate event": (evt)-> assert.instanceOf evt, jsdom.dom.level3.events.Event
"should include state": (evt)-> assert.equal evt.state.is, "start"
"go forwards":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err, window)->
window.history.pushState { is: "start" }, null, "/start"
window.history.pushState { is: "end" }, null, "/end"
@@ -55,7 +53,7 @@ vows.describe("History").addBatch({
"should fire popstate event": (evt)-> assert.instanceOf evt, jsdom.dom.level3.events.Event
"should include state": (evt)-> assert.equal evt.state.is, "end"
"replaceState":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err,window)->
window.history.pushState { is: "start" }, null, "/start"
window.history.replaceState { is: "end" }, null, "/end"
@@ -72,28 +70,28 @@ vows.describe("History").addBatch({
"location":
"open page":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
"should add page to history": (window)-> assert.length window.history, 1
"should change location URL": (window)-> assert.equal window.location.href, "http://localhost:3003/"
- "should load document": (window)-> assert.match window.document.innerHTML, /Little Red/
+ "should load document": (window)-> assert.match window.document.innerHTML, /Tap, Tap/
"change location":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err, window)->
window.location = "http://localhost:3003/boo"
window.document.addEventListener "DOMContentLoaded", => @callback err, window
"should add page to history": (window)-> assert.length window.history, 2
"should change location URL": (window)-> assert.equal window.location.href, "http://localhost:3003/boo"
"should load document": (window)-> assert.match window.document.innerHTML, /Eeek!/
"change pathname":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err, window)->
window.location.pathname = "/boo"
window.document.addEventListener "DOMContentLoaded", => @callback err, window
"should add page to history": (window)-> assert.length window.history, 2
"should change location URL": (window)-> assert.equal window.location.href, "http://localhost:3003/boo"
"should load document": (window)-> assert.match window.document.innerHTML, /Eeek!/
"change hash":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err, window)->
window.document.innerHTML = "Wolf"
window.addEventListener "hashchange", => @callback err, window
@@ -102,28 +100,28 @@ vows.describe("History").addBatch({
"should change location URL": (window)-> assert.equal window.location.href, "http://localhost:3003/#boo"
"should not reload document": (window)-> assert.match window.document.innerHTML, /Wolf/
"assign":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err, window)->
window.location.assign "http://localhost:3003/boo"
window.document.addEventListener "DOMContentLoaded", => @callback err, window
"should add page to history": (window)-> assert.length window.history, 2
"should change location URL": (window)-> assert.equal window.location.href, "http://localhost:3003/boo"
"should load document": (window)-> assert.match window.document.innerHTML, /Eeek!/
"replace":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err, window)->
window.location.replace "http://localhost:3003/boo"
window.document.addEventListener "DOMContentLoaded", => @callback err, window
"should not add page to history": (window)-> assert.length window.history, 1
"should change location URL": (window)-> assert.equal window.location.href, "http://localhost:3003/boo"
"should load document": (window)-> assert.match window.document.innerHTML, /Eeek!/
"reload":
- visit "http://localhost:3003/"
+ zombie.wants "http://localhost:3003/"
ready: (err, window)->
window.document.innerHTML = "Wolf"
window.location.reload()
window.document.addEventListener "DOMContentLoaded", => @callback err, window
"should not add page to history": (window)-> assert.length window.history, 1
"should not change location URL": (window)-> assert.equal window.location.href, "http://localhost:3003/"
- "should reload document": (window)-> assert.match window.document.innerHTML, /Little Red/
+ "should reload document": (window)-> assert.match window.document.innerHTML, /Tap, Tap/
}).export(module);
View
12 spec/xhr_spec.coffee → spec/xhr-spec.coffee
@@ -1,9 +1,7 @@
-vows = require("vows", "assert")
-assert = require("assert")
-{ server: server, visit: visit } = require("./helpers")
+require("./helpers")
+{ vows: vows, assert: assert, zombie: zombie, brains: brains } = require("vows")
-
-server.get "/xhr", (req, res)->
+brains.get "/xhr", (req, res)->
res.send """
<html>
<head><script src="/jquery.js"></script></head>
@@ -14,12 +12,12 @@ server.get "/xhr", (req, res)->
</body>
</html>
"""
-server.get "/text", (req, res)-> res.send "XMLOL"
+brains.get "/text", (req, res)-> res.send "XMLOL"
vows.describe("XMLHttpRequest").addBatch({
"load asynchronously":
- visit "http://localhost:3003/xhr"
+ zombie.wants "http://localhost:3003/xhr"
ready: (err, window)-> window.wait @callback
"should load resource": (window)-> assert.equal window.response, "XMLOL"
}).export(module);

0 comments on commit 41ee2f2

Please sign in to comment.