Permalink
Browse files

Added `querySelector` and `querySelectorAll` based on the [DOM

Selector API](http://www.w3.org/TR/selectors-api/).  Use this
instead of `find` method.
  • Loading branch information...
1 parent 503aea8 commit 2e14582d1154825de995cf6c85256f17bd1f67c6 @assaf committed Dec 22, 2010
Showing with 189 additions and 108 deletions.
  1. +14 −4 CHANGELOG.md
  2. +13 −7 Cakefile
  3. +50 −14 README.md
  4. +18 −2 spec/browser-spec.coffee
  5. +35 −35 spec/forms-spec.coffee
  6. +1 −2 spec/helpers.coffee
  7. +38 −39 src/zombie/browser.coffee
  8. +20 −5 src/zombie/sizzle.coffee
View
@@ -1,5 +1,15 @@
# CHANGELOG #
+### Version 0.7.0 2010-12-22
+
+Added `querySelector` and `querySelectorAll` based on the [DOM Selector
+API](http://www.w3.org/TR/selectors-api/). Use this instead of `find`
+method.
+
+ 184 tests
+ 2.0 sec to complete
+
+
### Version 0.6.5 2010-12-21
Fixed lack of JavaScript source code: CoffeeScript moved to src,
@@ -46,8 +56,8 @@ Fixed: browser now creates new window for each new document.
Added window.JSON.
- 178 tests.
- 1.8 sec to complete.
+ 178 tests
+ 1.8 sec to complete
### Version 0.6.0 2010-12-20
@@ -60,5 +70,5 @@ Sammy.js), timers, XHR, cookies, local and session storage.
Still very rough around the edges.
- 175 tests.
- 1.8 sec to complete.
+ 175 tests
+ 1.8 sec to complete
View
@@ -40,8 +40,14 @@ task "setup", "Install development dependencies", ->
build = (callback)->
log "Compiling CoffeeScript to JavaScript ...", green
- exec "rm -rf lib && coffee -c -l -o lib src", callback
-task "build", -> build onerror
+ exec "rm -rf lib && coffee -c -l -b -o lib src", callback
+task "build", "Compile CoffeeScript to JavaScript", -> build onerror
+
+task "watch", "Continously compile CoffeeScript to JavaScript", ->
+ cmd = spawn("coffee", ["-cw", "-o", "lib", "src"])
+ cmd.stdout.on "data", (data)-> log data, green
+ cmd.stderr.on "data", (data)-> log data, red
+
task "clean", "Remove temporary files and such", ->
exec "rm -rf html lib man1", onerror
@@ -110,10 +116,10 @@ generateDocs = (callback)->
documentSource (err)->
onerror err
generateMan callback
-task "doc:pages", -> documentPages onerror
-task "doc:source", -> documentSource onerror
-task "doc:man", -> generateMan onerror
-task "doc", "Generate documentation", -> generateDocs onerror
+task "doc:pages", "Generate documentation for main pages", -> documentPages onerror
+task "doc:source", "Generate documentation from source files", -> documentSource onerror
+task "doc:man", "Generate man pages", -> generateMan onerror
+task "doc", "Generate all documentation", -> generateDocs onerror
## Publishing ##
@@ -124,7 +130,7 @@ publishDocs = (callback)->
onerror err
log "Uploading documentation ...", green
exec "rsync -cr --del --progress html/ labnotes.org:/var/www/zombie/", callback
-task "doc:publish", -> publishDocs onerror
+task "doc:publish", "Publish documentation to site", -> publishDocs onerror
task "publish", "Publish new version (Git, NPM, site)", ->
runTests (err)->
View
@@ -14,13 +14,13 @@ Let's try to sign up to a page and see what happens:
var zombie = require("zombie");
// Load the page from localhost
- zombie.visit("http://localhost:3000/", function (browser) {
+ zombie.visit("http://localhost:3000/", function (err, browser) {
// Fill email, password and submit form
browser.
fill("email", "zombie@underworld.dead").
fill("password", "eat-the-living").
- pressButton("Sign Me Up!", function(browser) {
+ pressButton("Sign Me Up!", function(err, browser) {
// Form submitted, new page loaded.
assert.equal(browser.text("title"), "Welcome To Brains Depot");
@@ -32,13 +32,45 @@ Let's try to sign up to a page and see what happens:
Well, that was easy.
-### Getting Around
+### Walking And Waiting
-A browser has one window open, and typically one document open in that window.
-The `Browser` class adds many high-level functions on top of what you can already
-do with windows and documents.
+To start off we're going to need a browser. A browser maintains state
+across requests: history, cookies, HTML 5 local and session stroage. A
+browser has a main window, and typically a document loaded into that
+window.
-Callbacks are called either with an `Error` object or `null`, `Browser`.
+You can create a new `zombie.Browser` and point it at a document, either
+by setting the `location` property or calling its `visit` method. As a
+shortcut, you can just call the `zombie.visit` method with a URL and
+callback.
+
+The browser will load the document and if the document includes any
+scripts, also load and execute these scripts. It will then process some
+events, for example, anything your scripts do on page load. All of
+that, just like a real browser, happens asynchronously.
+
+To wait for the page to fully load and all events to fire, you pass
+`visit` a callback function. This function takes two arguments. If
+everything is successful (page loaded, events run), the callback is
+called with `null` and a reference to the browser. If anything went
+wrong (page not loaded, event errors), the callback is called with an
+error.
+
+If you worked with Node.js before you're familiar with this callback
+pattern. Every time you see a callback in the Zombie.js API, it works
+that way: the first argument is an error, or null if there is no error,
+with interesting value in the second argument.
+
+Typically the second argument would be a reference to the browser or
+window object you called. This may seem redudant, but works suprisingly
+well when composing with other asynchronous APIs, for example, when
+using Zombie.js with Vows.
+
+Whenever you want to wait for all events to be processed, just call
+`browser.wait` with a callback.
+
+
+### Browser API
#### Browser.visit(url, callback)
@@ -74,11 +106,6 @@ Returns all the cookies for this domain/path. Path defaults to "/".
Returns the main window's document. Only valid after opening a document (see `browser.open`).
-#### browser.find(selector, context?) => [Elements]
-
-Returns an array of all the elements that match the selector. Without context,
-searches through the entire document.
-
#### browser.fill(field, value) => this
Fill in a field: input field or text area.
@@ -91,7 +118,7 @@ function will call `wait`.
#### browser.html(selector?, context?) => String
-Returns the HTML contents of the selected elements (see also `browser.find`).
+Returns the HTML contents of the selected elements.
#### browser.last_error => Object
@@ -132,6 +159,14 @@ Press a button (button element or input of type `submit`). Typically this will
submit the form. Use the callback to wait for the from submission, page to
load and all events run their course.
+#### browser.querySelector(selector) => Element
+
+Select a single element (first match) and return it.
+
+#### browser.querySelectorAll(selector) => NodeList
+
+Select multiple elements and return a static node list.
+
#### browser.select(field, value) => this
Selects an option.
@@ -142,7 +177,7 @@ Returns session Storage based on the document origin (hostname/port).
#### browser.text(selector, context?) => String
-Returns the text contents of the selected elements (see also `browser.find`).
+Returns the text contents of the selected elements.
#### browser.uncheck(field) => this
@@ -167,6 +202,7 @@ The terminator is optional and can be one of:
Returns the main window.
+
## Guts
Zombie.js is written in
View
@@ -34,6 +34,7 @@ brains.get "/living", (req, res)-> res.send """
<textarea name="likes" id="field-likes"></textarea>
<input type="password" name="password" id="field-password">
</form>
+ <div class="now">Walking Aimlessly</div>
</body>
</html>
"""
@@ -75,15 +76,30 @@ vows.describe("Browser").addBatch(
"run app":
zombie.wants "http://localhost:3003/living"
- "should execute route": (browser)-> assert.equal browser.find("#main")[0].innerHTML, "The Living"
+ "should execute route": (browser)-> assert.equal browser.text("#main"), "The Living"
"should change location": (browser)-> assert.equal browser.location, "http://localhost:3003/living#/"
"move around":
topic: (browser)->
browser.location = "#/dead"
browser.wait @callback
- "should execute route": (browser)-> assert.equal browser.find("#main")[0].innerHTML, "The Living Dead"
+ "should execute route": (browser)-> assert.equal browser.text("#main"), "The Living Dead"
"should change location": (browser)-> assert.equal browser.location, "http://localhost:3003/living#/dead"
+ "content selection":
+ zombie.wants "http://localhost:3003/living"
+ "query text":
+ topic: (browser)-> browser
+ "should query from document": (browser)-> assert.equal browser.text(".now"), "Walking Aimlessly"
+ "should query from context": (browser)-> assert.equal browser.text(".now", browser.body), "Walking Aimlessly"
+ "should query from context": (browser)-> assert.equal browser.text(".now", browser.querySelector("#main")), ""
+ "should combine multiple elements": (browser)-> assert.equal browser.text("form label"), "Name Email"
+ "query html":
+ topic: (browser)-> browser
+ "should query from document": (browser)-> assert.equal browser.html(".now"), "<div class=\"now\">Walking Aimlessly</div>"
+ "should query from context": (browser)-> assert.equal browser.html(".now", browser.body), "Walking Aimlessly"
+ "should query from context": (browser)-> assert.equal browser.html(".now", browser.querySelector("#main")), ""
+ "should combine multiple elements": (browser)-> assert.equal browser.html("#main, a"), "<div id=\"main\">The Living</div><a href=\"/dead\">Kill</a>"
+
"click link":
zombie.wants "http://localhost:3003/living"
topic: (browser)->
Oops, something went wrong.

0 comments on commit 2e14582

Please sign in to comment.