lib/capybara/poltergeist/client/browser.coffee in poltergeist-1.7.0 vs lib/capybara/poltergeist/client/browser.coffee in poltergeist-1.8.0
- old
+ new
@@ -1,7 +1,7 @@
class Poltergeist.Browser
- constructor: (@owner, width, height) ->
+ constructor: (width, height) ->
@width = width || 1024
@height = height || 768
@pages = []
@js_errors = true
@_debug = false
@@ -55,41 +55,34 @@
@pages.push(page)
getPageByHandle: (handle) ->
@pages.filter((p) -> !p.closed && p.handle == handle)[0]
- runCommand: (name, args) ->
+ runCommand: (command) ->
+ @current_command = command
@currentPage.state = 'default'
- this[name].apply(this, args)
+ this[command.name].apply(this, command.args)
debug: (message) ->
if @_debug
console.log "poltergeist [#{new Date().getTime()}] #{message}"
setModalMessage: (msg) ->
@processed_modal_messages.push(msg)
- sendResponse: (response) ->
- errors = @currentPage.errors
- @currentPage.clearErrors()
-
- if errors.length > 0 && @js_errors
- @owner.sendError(new Poltergeist.JavascriptError(errors))
- else
- @owner.sendResponse(response)
-
add_extension: (extension) ->
@currentPage.injectExtension extension
- this.sendResponse 'success'
+ @current_command.sendResponse 'success'
node: (page_id, id) ->
if @currentPage.id == page_id
@currentPage.get(id)
else
throw new Poltergeist.ObsoleteNode
visit: (url) ->
+
@currentPage.state = 'loading'
#reset modal processing state when changing page
@processed_modal_messages = []
@confirm_processes = []
@prompt_responses = []
@@ -103,156 +96,176 @@
@currentPage.open(url)
if /#/.test(url) && prevUrl.split('#')[0] == url.split('#')[0]
# Hash change occurred, so there will be no onLoadFinished
@currentPage.state = 'default'
- this.sendResponse(status: 'success')
+ @current_command.sendResponse(status: 'success')
else
+ command = @current_command
@currentPage.waitState 'default', =>
if @currentPage.statusCode == null && @currentPage.status == 'fail'
- @owner.sendError(new Poltergeist.StatusFailError)
+ command.sendError(new Poltergeist.StatusFailError(url))
else
- this.sendResponse(status: @currentPage.status)
+ command.sendResponse(status: @currentPage.status)
current_url: ->
- this.sendResponse @currentPage.currentUrl()
+ @current_command.sendResponse @currentPage.currentUrl()
status_code: ->
- this.sendResponse @currentPage.statusCode
+ @current_command.sendResponse @currentPage.statusCode
body: ->
- this.sendResponse @currentPage.content()
+ @current_command.sendResponse @currentPage.content()
source: ->
- this.sendResponse @currentPage.source
+ @current_command.sendResponse @currentPage.source
title: ->
- this.sendResponse @currentPage.title()
+ @current_command.sendResponse @currentPage.title()
find: (method, selector) ->
- this.sendResponse(page_id: @currentPage.id, ids: @currentPage.find(method, selector))
+ @current_command.sendResponse(page_id: @currentPage.id, ids: @currentPage.find(method, selector))
find_within: (page_id, id, method, selector) ->
- this.sendResponse this.node(page_id, id).find(method, selector)
+ @current_command.sendResponse this.node(page_id, id).find(method, selector)
all_text: (page_id, id) ->
- this.sendResponse this.node(page_id, id).allText()
+ @current_command.sendResponse this.node(page_id, id).allText()
visible_text: (page_id, id) ->
- this.sendResponse this.node(page_id, id).visibleText()
+ @current_command.sendResponse this.node(page_id, id).visibleText()
delete_text: (page_id, id) ->
- this.sendResponse this.node(page_id, id).deleteText()
+ @current_command.sendResponse this.node(page_id, id).deleteText()
+ property: (page_id, id, name) ->
+ @current_command.sendResponse this.node(page_id, id).getProperty(name)
+
attribute: (page_id, id, name) ->
- this.sendResponse this.node(page_id, id).getAttribute(name)
+ @current_command.sendResponse this.node(page_id, id).getAttribute(name)
attributes: (page_id, id, name) ->
- this.sendResponse this.node(page_id, id).getAttributes()
+ @current_command.sendResponse this.node(page_id, id).getAttributes()
parents: (page_id, id) ->
- this.sendResponse this.node(page_id, id).parentIds()
+ @current_command.sendResponse this.node(page_id, id).parentIds()
value: (page_id, id) ->
- this.sendResponse this.node(page_id, id).value()
+ @current_command.sendResponse this.node(page_id, id).value()
set: (page_id, id, value) ->
this.node(page_id, id).set(value)
- this.sendResponse(true)
+ @current_command.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.
select_file: (page_id, id, value) ->
node = this.node(page_id, id)
@currentPage.beforeUpload(node.id)
@currentPage.uploadFile('[_poltergeist_selected]', value)
@currentPage.afterUpload(node.id)
+ if phantom.version.major == 2
+ # In phantomjs 2 - uploadFile only fully works if executed within a user action
+ # It does however setup the filenames to be uploaded, so if we then click on the
+ # file input element the filenames will get set
+ @click(page_id, id)
+ else
+ @current_command.sendResponse(true)
- this.sendResponse(true)
-
select: (page_id, id, value) ->
- this.sendResponse this.node(page_id, id).select(value)
+ @current_command.sendResponse this.node(page_id, id).select(value)
tag_name: (page_id, id) ->
- this.sendResponse this.node(page_id, id).tagName()
+ @current_command.sendResponse this.node(page_id, id).tagName()
visible: (page_id, id) ->
- this.sendResponse this.node(page_id, id).isVisible()
+ @current_command.sendResponse this.node(page_id, id).isVisible()
disabled: (page_id, id) ->
- this.sendResponse this.node(page_id, id).isDisabled()
+ @current_command.sendResponse this.node(page_id, id).isDisabled()
path: (page_id, id) ->
- this.sendResponse this.node(page_id, id).path()
+ @current_command.sendResponse this.node(page_id, id).path()
evaluate: (script) ->
- this.sendResponse @currentPage.evaluate("function() { return #{script} }")
+ @current_command.sendResponse @currentPage.evaluate("function() { return #{script} }")
execute: (script) ->
@currentPage.execute("function() { #{script} }")
- this.sendResponse(true)
+ @current_command.sendResponse(true)
frameUrl: (frame_name) ->
@currentPage.frameUrl(frame_name)
- push_frame: (name, timeout = new Date().getTime() + 2000) ->
+ pushFrame: (command, name, timeout) ->
+ if Array.isArray(name)
+ frame = this.node(name...)
+ name = frame.getAttribute('name') || frame.getAttribute('id')
+ unless name
+ frame.setAttribute('name', "_random_name_#{new Date().getTime()}")
+ name = frame.getAttribute('name')
+
if @frameUrl(name) in @currentPage.blockedUrls()
- this.sendResponse(true)
+ command.sendResponse(true)
else if @currentPage.pushFrame(name)
if @currentPage.currentUrl() == 'about:blank'
@currentPage.state = 'awaiting_frame_load'
@currentPage.waitState 'default', =>
- this.sendResponse(true)
+ command.sendResponse(true)
else
- this.sendResponse(true)
+ command.sendResponse(true)
else
if new Date().getTime() < timeout
- setTimeout((=> this.push_frame(name, timeout)), 50)
+ setTimeout((=> @pushFrame(command, name, timeout)), 50)
else
- @owner.sendError(new Poltergeist.FrameNotFound(name))
+ command.sendError(new Poltergeist.FrameNotFound(name))
+ push_frame: (name, timeout = (new Date().getTime()) + 2000) ->
+ @pushFrame(@current_command, name, timeout)
+
pop_frame: ->
- this.sendResponse(@currentPage.popFrame())
+ @current_command.sendResponse(@currentPage.popFrame())
window_handles: ->
handles = @pages.filter((p) -> !p.closed).map((p) -> p.handle)
- this.sendResponse(handles)
+ @current_command.sendResponse(handles)
window_handle: (name = null) ->
handle = if name
page = @pages.filter((p) -> !p.closed && p.windowName() == name)[0]
if page then page.handle else null
else
@currentPage.handle
- this.sendResponse(handle)
+ @current_command.sendResponse(handle)
switch_to_window: (handle) ->
+ command = @current_command
page = @getPageByHandle(handle)
if page
if page != @currentPage
page.waitState 'default', =>
@currentPage = page
- this.sendResponse(true)
+ command.sendResponse(true)
else
- this.sendResponse(true)
+ command.sendResponse(true)
else
throw new Poltergeist.NoSuchWindowError
open_new_window: ->
this.execute 'window.open()'
- this.sendResponse(true)
+ @current_command.sendResponse(true)
close_window: (handle) ->
page = @getPageByHandle(handle)
if page
page.release()
- this.sendResponse(true)
+ @current_command.sendResponse(true)
else
- this.sendResponse(false)
+ @current_command.sendResponse(false)
mouse_event: (page_id, id, name) ->
# Get the node before changing state, in case there is an exception
node = this.node(page_id, id)
@@ -260,18 +273,20 @@
# state and wait for onLoadFinished before sending a response.
@currentPage.state = 'mouse_event'
@last_mouse_event = node.mouseEvent(name)
+ command = @current_command
+
setTimeout =>
# If the state is still the same then navigation event won't happen
if @currentPage.state == 'mouse_event'
@currentPage.state = 'default'
- this.sendResponse(position: @last_mouse_event)
+ command.sendResponse(position: @last_mouse_event)
else
@currentPage.waitState 'default', =>
- this.sendResponse(position: @last_mouse_event)
+ command.sendResponse(position: @last_mouse_event)
, 5
click: (page_id, id) ->
this.mouse_event page_id, id, 'click'
@@ -284,34 +299,34 @@
hover: (page_id, id) ->
this.mouse_event page_id, id, 'mousemove'
click_coordinates: (x, y) ->
@currentPage.sendEvent('click', x, y)
- this.sendResponse(click: { x: x, y: y })
+ @current_command.sendResponse(click: { x: x, y: y })
drag: (page_id, id, other_id) ->
this.node(page_id, id).dragTo this.node(page_id, other_id)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
drag_by: (page_id, id, x, y) ->
this.node(page_id, id).dragBy(x, y)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
trigger: (page_id, id, event) ->
this.node(page_id, id).trigger(event)
- this.sendResponse(event)
+ @current_command.sendResponse(event)
equals: (page_id, id, other_id) ->
- this.sendResponse this.node(page_id, id).isEqual(this.node(page_id, other_id))
+ @current_command.sendResponse this.node(page_id, id).isEqual(this.node(page_id, other_id))
reset: ->
this.resetPage()
- this.sendResponse(true)
+ @current_command.sendResponse(true)
scroll_to: (left, top) ->
@currentPage.setScrollPosition(left: left, top: top)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
send_keys: (page_id, id, keys) ->
target = this.node(page_id, id)
# Programmatically generated focus doesn't work for `sendKeys`.
@@ -328,23 +343,23 @@
@currentPage.sendEvent('keypress', key, null, null, modifier_code)
@currentPage.sendEvent('keyup', modifier_key) for modifier_key in modifier_keys
else
@currentPage.sendEvent('keypress', key)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
render_base64: (format, full, selector = null)->
this.set_clip_rect(full, selector)
encoded_image = @currentPage.renderBase64(format)
- this.sendResponse(encoded_image)
+ @current_command.sendResponse(encoded_image)
render: (path, full, selector = null) ->
dimensions = this.set_clip_rect(full, selector)
@currentPage.setScrollPosition(left: 0, top: 0)
@currentPage.render(path)
@currentPage.setScrollPosition(left: dimensions.left, top: dimensions.top)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
set_clip_rect: (full, selector) ->
dimensions = @currentPage.validatedDimensions()
[document, viewport] = [dimensions.document, dimensions.viewport]
@@ -359,35 +374,35 @@
@currentPage.setClipRect(rect)
dimensions
set_paper_size: (size) ->
@currentPage.setPaperSize(size)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
set_zoom_factor: (zoom_factor) ->
@currentPage.setZoomFactor(zoom_factor)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
resize: (width, height) ->
@currentPage.setViewportSize(width: width, height: height)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
network_traffic: ->
- this.sendResponse(@currentPage.networkTraffic())
+ @current_command.sendResponse(@currentPage.networkTraffic())
clear_network_traffic: ->
@currentPage.clearNetworkTraffic()
- this.sendResponse(true)
+ @current_command.sendResponse(true)
get_headers: ->
- this.sendResponse(@currentPage.getCustomHeaders())
+ @current_command.sendResponse(@currentPage.getCustomHeaders())
set_headers: (headers) ->
# Workaround for https://code.google.com/p/phantomjs/issues/detail?id=745
@currentPage.setUserAgent(headers['User-Agent']) if headers['User-Agent']
@currentPage.setCustomHeaders(headers)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
add_headers: (headers) ->
allHeaders = @currentPage.getCustomHeaders()
for name, value of headers
allHeaders[name] = value
@@ -396,44 +411,44 @@
add_header: (header, permanent) ->
@currentPage.addTempHeader(header) unless permanent
this.add_headers(header)
response_headers: ->
- this.sendResponse(@currentPage.responseHeaders())
+ @current_command.sendResponse(@currentPage.responseHeaders())
cookies: ->
- this.sendResponse(@currentPage.cookies())
+ @current_command.sendResponse(@currentPage.cookies())
# We're using phantom.addCookie so that cookies can be set
# before the first page load has taken place.
set_cookie: (cookie) ->
phantom.addCookie(cookie)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
remove_cookie: (name) ->
@currentPage.deleteCookie(name)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
clear_cookies: () ->
phantom.clearCookies()
- this.sendResponse(true)
+ @current_command.sendResponse(true)
cookies_enabled: (flag) ->
phantom.cookiesEnabled = flag
- this.sendResponse(true)
+ @current_command.sendResponse(true)
set_http_auth: (user, password) ->
@currentPage.setHttpAuth(user, password)
- this.sendResponse(true)
+ @current_command.sendResponse(true)
set_js_errors: (value) ->
@js_errors = value
- this.sendResponse(true)
+ @current_command.sendResponse(true)
set_debug: (value) ->
@_debug = value
- this.sendResponse(true)
+ @current_command.sendResponse(true)
exit: ->
phantom.exit()
noop: ->
@@ -442,36 +457,38 @@
# This command is purely for testing error handling
browser_error: ->
throw new Error('zomg')
go_back: ->
+ command = @current_command
if @currentPage.canGoBack
@currentPage.state = 'loading'
@currentPage.goBack()
@currentPage.waitState 'default', =>
- this.sendResponse(true)
+ command.sendResponse(true)
else
- this.sendResponse(false)
+ command.sendResponse(false)
go_forward: ->
+ command = @current_command
if @currentPage.canGoForward
@currentPage.state = 'loading'
@currentPage.goForward()
@currentPage.waitState 'default', =>
- this.sendResponse(true)
+ command.sendResponse(true)
else
- this.sendResponse(false)
+ command.sendResponse(false)
set_url_blacklist: ->
@currentPage.urlBlacklist = Array.prototype.slice.call(arguments)
- @sendResponse(true)
+ @current_command.sendResponse(true)
set_confirm_process: (process) ->
@confirm_processes.push process
- @sendResponse(true)
+ @current_command.sendResponse(true)
set_prompt_response: (response) ->
@prompt_responses.push response
- @sendResponse(true)
+ @current_command.sendResponse(true)
modal_message: ->
- @sendResponse(@processed_modal_messages.shift())
+ @current_command.sendResponse(@processed_modal_messages.shift())