lib/capybara/poltergeist/client/browser.coffee in poltergeist-0.6.0 vs lib/capybara/poltergeist/client/browser.coffee in poltergeist-0.7.0
- old
+ new
@@ -1,19 +1,24 @@
class Poltergeist.Browser
- constructor: (@owner) ->
+ constructor: (@owner, width, height) ->
+ @width = width || 1024
+ @height = height || 768
@state = 'default'
@page_id = 0
this.resetPage()
resetPage: ->
@page.release() if @page?
- @page = new Poltergeist.WebPage
+ @page = new Poltergeist.WebPage(@width, @height)
@page.onLoadStarted = =>
@state = 'loading' if @state == 'clicked'
+ @page.onNavigationRequested = (url, navigation) =>
+ @state = 'loading' if @state == 'clicked' && navigation == 'FormSubmitted'
+
@page.onLoadFinished = (status) =>
if @state == 'loading'
this.sendResponse(status)
@state = 'default'
@@ -23,98 +28,78 @@
sendResponse: (response) ->
errors = @page.errors()
if errors.length > 0
@page.clearErrors()
- @owner.sendError(new Poltergeist.JavascriptError(errors))
+ throw new Poltergeist.JavascriptError(errors)
else
@owner.sendResponse(response)
- getNode: (page_id, id, callback) ->
+ node: (page_id, id) ->
if page_id == @page_id
- callback.call this, @page.get(id)
+ @page.get(id)
else
- @owner.sendError(new Poltergeist.ObsoleteNode)
+ throw new Poltergeist.ObsoleteNode
- nodeCall: (page_id, id, fn, args...) ->
- callback = args.pop()
-
- this.getNode(
- page_id, id,
- (node) ->
- result = node[fn](args...)
-
- if result instanceof Poltergeist.ObsoleteNode
- @owner.sendError(result)
- else
- callback.call(this, result, node)
- )
-
- visit: (url) ->
+ visit: (url, headers) ->
@state = 'loading'
- @page.open(url)
+ @page.open(url, operation: "get", headers: headers)
current_url: ->
this.sendResponse @page.currentUrl()
+ status_code: ->
+ this.sendResponse @page.statusCode()
+
body: ->
this.sendResponse @page.content()
source: ->
this.sendResponse @page.source()
find: (selector) ->
this.sendResponse(page_id: @page_id, ids: @page.find(selector))
find_within: (page_id, id, selector) ->
- this.nodeCall(page_id, id, 'find', selector, this.sendResponse)
+ this.sendResponse this.node(page_id, id).find(selector)
text: (page_id, id) ->
- this.nodeCall(page_id, id, 'text', this.sendResponse)
+ this.sendResponse this.node(page_id, id).text()
attribute: (page_id, id, name) ->
- this.nodeCall(page_id, id, 'getAttribute', name, this.sendResponse)
+ this.sendResponse this.node(page_id, id).getAttribute(name)
value: (page_id, id) ->
- this.nodeCall(page_id, id, 'value', this.sendResponse)
+ this.sendResponse this.node(page_id, id).value()
set: (page_id, id, value) ->
- this.nodeCall(page_id, id, 'set', value, -> this.sendResponse(true))
+ this.node(page_id, id).set(value)
+ this.sendResponse(true)
# PhantomJS only allows us to reference the element by CSS selector, not XPath,
# so we have to add an attribute to the element to identify it, then remove it
# afterwards.
- #
- # PhantomJS does not support multiple-file inputs, so we have to blatently cheat
- # by temporarily changing it to a single-file input. This obviously could break
- # things in various ways, which is not ideal, but it works in the simplest case.
select_file: (page_id, id, value) ->
- this.nodeCall(
- page_id, id, 'isMultiple',
- (multiple, node) ->
- node.removeAttribute('multiple') if multiple
- node.setAttribute('_poltergeist_selected', '')
+ node = this.node(page_id, id)
- @page.uploadFile('[_poltergeist_selected]', value)
+ node.setAttribute('_poltergeist_selected', '')
+ @page.uploadFile('[_poltergeist_selected]', value)
+ node.removeAttribute('_poltergeist_selected')
- node.removeAttribute('_poltergeist_selected')
- node.setAttribute('multiple', 'multiple') if multiple
+ this.sendResponse(true)
- this.sendResponse(true)
- )
-
select: (page_id, id, value) ->
- this.nodeCall(page_id, id, 'select', value, this.sendResponse)
+ this.sendResponse this.node(page_id, id).select(value)
tag_name: (page_id, id) ->
- this.nodeCall(page_id, id, 'tagName', this.sendResponse)
+ this.sendResponse this.node(page_id, id).tagName()
visible: (page_id, id) ->
- this.nodeCall(page_id, id, 'isVisible', this.sendResponse)
+ this.sendResponse this.node(page_id, id).isVisible()
evaluate: (script) ->
- this.sendResponse JSON.parse(@page.evaluate("function() { return JSON.stringify(#{script}) }"))
+ this.sendResponse @page.evaluate("function() { return #{script} }")
execute: (script) ->
@page.execute("function() { #{script} }")
this.sendResponse(true)
@@ -125,48 +110,34 @@
pop_frame: ->
@page.popFrame()
this.sendResponse(true)
click: (page_id, id) ->
- # We just check the node is not obsolete before proceeding. If it is,
- # the callback will not fire.
- this.nodeCall(
- page_id, id, 'isObsolete',
- (obsolete, node) ->
- # If the click event triggers onLoadStarted, we will transition to the 'loading'
- # state and wait for onLoadFinished before sending a response.
- @state = 'clicked'
+ # Get the node before changing state, in case there is an exception
+ node = this.node(page_id, id)
- click = node.click()
+ # If the click event triggers onNavigationRequested, we will transition to the 'loading'
+ # state and wait for onLoadFinished before sending a response.
+ @state = 'clicked'
- # Use a timeout in order to let the stack clear, so that the @page.onLoadStarted
- # callback can (possibly) fire, before we decide whether to send a response.
- setTimeout(
- =>
- if @state == 'clicked'
- @state = 'default'
+ node.click()
- if click instanceof Poltergeist.ClickFailed
- @owner.sendError(click)
- else
- this.sendResponse(true)
- ,
- 10
- )
- )
+ if @state != 'loading'
+ @state = 'default'
+ this.sendResponse(true)
drag: (page_id, id, other_id) ->
- this.nodeCall(
- page_id, id, 'isObsolete'
- (obsolete, node) ->
- node.dragTo(@page.get(other_id))
- this.sendResponse(true)
- )
+ this.node(page_id, id).dragTo this.node(page_id, other_id)
+ this.sendResponse(true)
trigger: (page_id, id, event) ->
- this.nodeCall(page_id, id, 'trigger', event, -> this.sendResponse(event))
+ this.node(page_id, id).trigger(event)
+ this.sendResponse(event)
+ equals: (page_id, id, other_id) ->
+ this.sendResponse this.node(page_id, id).isEqual(this.node(page_id, other_id))
+
reset: ->
this.resetPage()
this.sendResponse(true)
render: (path, full) ->
@@ -187,10 +158,17 @@
resize: (width, height) ->
@page.setViewportSize(width: width, height: height)
this.sendResponse(true)
+ network_traffic: ->
+ this.sendResponse(@page.networkTraffic())
+
exit: ->
phantom.exit()
noop: ->
# NOOOOOOP!
+
+ # This command is purely for testing error handling
+ browser_error: ->
+ throw new Error('zomg')