poltergeist 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +48 -2
- data/lib/capybara/poltergeist.rb +3 -0
- data/lib/capybara/poltergeist/browser.rb +48 -55
- data/lib/capybara/poltergeist/client.rb +42 -12
- data/lib/capybara/poltergeist/client/agent.coffee +48 -5
- data/lib/capybara/poltergeist/client/browser.coffee +64 -42
- data/lib/capybara/poltergeist/client/compiled/agent.js +71 -8
- data/lib/capybara/poltergeist/client/compiled/browser.js +68 -41
- data/lib/capybara/poltergeist/client/compiled/main.js +34 -5
- data/lib/capybara/poltergeist/client/compiled/node.js +34 -25
- data/lib/capybara/poltergeist/client/compiled/web_page.js +30 -7
- data/lib/capybara/poltergeist/client/main.coffee +26 -3
- data/lib/capybara/poltergeist/client/node.coffee +30 -23
- data/lib/capybara/poltergeist/client/web_page.coffee +31 -7
- data/lib/capybara/poltergeist/driver.rb +54 -19
- data/lib/capybara/poltergeist/errors.rb +63 -6
- data/lib/capybara/poltergeist/inspector.rb +35 -0
- data/lib/capybara/poltergeist/node.rb +15 -5
- data/lib/capybara/poltergeist/server.rb +7 -12
- data/lib/capybara/poltergeist/spawn.rb +17 -0
- data/lib/capybara/poltergeist/util.rb +12 -0
- data/lib/capybara/poltergeist/version.rb +1 -1
- data/lib/capybara/poltergeist/web_socket_server.rb +25 -6
- metadata +31 -25
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Poltergeist - A PhantomJS driver for Capybara #
|
2
2
|
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
4
4
|
|
5
5
|
[![Build Status](https://secure.travis-ci.org/jonleighton/poltergeist.png)](http://travis-ci.org/jonleighton/poltergeist)
|
6
|
+
[![Dependency Status](https://gemnasium.com/jonleighton/poltergeist.png)](https://gemnasium.com/jonleighton/poltergeist)
|
6
7
|
|
7
8
|
Poltergeist is a driver for [Capybara](https://github.com/jnicklas/capybara). It allows you to
|
8
9
|
run your Capybara tests on a headless [WebKit](http://webkit.org) browser,
|
@@ -10,7 +11,7 @@ provided by [PhantomJS](http://www.phantomjs.org/).
|
|
10
11
|
|
11
12
|
## Installation ##
|
12
13
|
|
13
|
-
Add `poltergeist` to your Gemfile, and
|
14
|
+
Add `poltergeist` to your Gemfile, and in your test setup add:
|
14
15
|
|
15
16
|
``` ruby
|
16
17
|
require 'capybara/poltergeist'
|
@@ -172,6 +173,51 @@ makes debugging easier). Running `rake autocompile` will watch the
|
|
172
173
|
|
173
174
|
## Changes ##
|
174
175
|
|
176
|
+
### 0.5.0 ###
|
177
|
+
|
178
|
+
#### Features ####
|
179
|
+
|
180
|
+
* Detect if clicking an element will fail. If the click will actually
|
181
|
+
hit another element (because that element is in front of the one we
|
182
|
+
want to click), the user will now see an exception explaining what
|
183
|
+
happened and which element would actually be targeted by the click. This
|
184
|
+
should aid debugging. [Issue #25]
|
185
|
+
|
186
|
+
* Click elements at their middle position rather than the top-left.
|
187
|
+
This is presumed to be more likely to succeed because the top-left
|
188
|
+
may be obscured by overlapping elements, negative margins, etc. [Issue #26]
|
189
|
+
|
190
|
+
* Add experimental support for using the remote WebKit web inspector.
|
191
|
+
This will only work with PhantomJS 1.5, which is not yet released,
|
192
|
+
so it won't be officially supported by Poltergeist until 1.5 is
|
193
|
+
released. [Issue #31]
|
194
|
+
|
195
|
+
* Add `page.driver.quit` method. If you spawn additional Capybara
|
196
|
+
sessions, you might want to use this to reap the child phantomjs
|
197
|
+
process. [Issue #24]
|
198
|
+
|
199
|
+
* Errors produced by Javascript on the page will now generate an
|
200
|
+
exception within Ruby. [Issue #27]
|
201
|
+
|
202
|
+
#### Bug fixes ####
|
203
|
+
|
204
|
+
* Fix bug where we could end up interacting with an obsolete element. [Issue #30]
|
205
|
+
|
206
|
+
* Raise an suitable error if PhantomJS returns a non-zero exit status.
|
207
|
+
Previously a version error would be raised, indicating that the
|
208
|
+
PhantomJS version was too old when in fact it did not start at all. [Issue #23]
|
209
|
+
|
210
|
+
* Ensure the `:timeout` option is actually used. [Issue #36]
|
211
|
+
|
212
|
+
* Nodes need to know which page they are associated with. Before this,
|
213
|
+
if Javascript caused a new page to load, existing node references
|
214
|
+
would be wrong, but wouldn't raise an ObsoleteNode error. [Issue #39]
|
215
|
+
|
216
|
+
* In some circumstances, we could end up missing an inline element
|
217
|
+
when attempting to click it. This is due to the use of
|
218
|
+
`getBoundingClientRect()`. We're now using `getClientRects()` to
|
219
|
+
address this.
|
220
|
+
|
175
221
|
### 0.4.0 ###
|
176
222
|
|
177
223
|
* Element click position is now calculated using the native
|
data/lib/capybara/poltergeist.rb
CHANGED
@@ -9,6 +9,9 @@ module Capybara
|
|
9
9
|
autoload :Server, 'capybara/poltergeist/server'
|
10
10
|
autoload :WebSocketServer, 'capybara/poltergeist/web_socket_server'
|
11
11
|
autoload :Client, 'capybara/poltergeist/client'
|
12
|
+
autoload :Util, 'capybara/poltergeist/util'
|
13
|
+
autoload :Inspector, 'capybara/poltergeist/inspector'
|
14
|
+
autoload :Spawn, 'capybara/poltergeist/spawn'
|
12
15
|
|
13
16
|
require 'capybara/poltergeist/errors'
|
14
17
|
end
|
@@ -1,23 +1,13 @@
|
|
1
|
-
require '
|
1
|
+
require 'multi_json'
|
2
2
|
|
3
3
|
module Capybara::Poltergeist
|
4
4
|
class Browser
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :server, :client, :logger
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@
|
11
|
-
@server = Server.new(options.fetch(:timeout, DEFAULT_TIMEOUT))
|
12
|
-
@client = Client.start(server.port, options[:phantomjs])
|
13
|
-
end
|
14
|
-
|
15
|
-
def timeout
|
16
|
-
server.timeout
|
17
|
-
end
|
18
|
-
|
19
|
-
def timeout=(sec)
|
20
|
-
server.timeout = sec
|
7
|
+
def initialize(server, client, logger = nil)
|
8
|
+
@server = server
|
9
|
+
@client = client
|
10
|
+
@logger = logger
|
21
11
|
end
|
22
12
|
|
23
13
|
def restart
|
@@ -25,7 +15,7 @@ module Capybara::Poltergeist
|
|
25
15
|
client.restart
|
26
16
|
end
|
27
17
|
|
28
|
-
def visit(url
|
18
|
+
def visit(url)
|
29
19
|
command 'visit', url
|
30
20
|
end
|
31
21
|
|
@@ -41,36 +31,41 @@ module Capybara::Poltergeist
|
|
41
31
|
command 'source'
|
42
32
|
end
|
43
33
|
|
44
|
-
def find(selector
|
45
|
-
command
|
34
|
+
def find(selector)
|
35
|
+
result = command('find', selector)
|
36
|
+
result['ids'].map { |id| [result['page_id'], id] }
|
46
37
|
end
|
47
38
|
|
48
|
-
def
|
49
|
-
command '
|
39
|
+
def find_within(page_id, id, selector)
|
40
|
+
command 'find_within', page_id, id, selector
|
50
41
|
end
|
51
42
|
|
52
|
-
def
|
53
|
-
command '
|
43
|
+
def text(page_id, id)
|
44
|
+
command 'text', page_id, id
|
54
45
|
end
|
55
46
|
|
56
|
-
def
|
57
|
-
command '
|
47
|
+
def attribute(page_id, id, name)
|
48
|
+
command 'attribute', page_id, id, name.to_s
|
58
49
|
end
|
59
50
|
|
60
|
-
def
|
61
|
-
command '
|
51
|
+
def value(page_id, id)
|
52
|
+
command 'value', page_id, id
|
62
53
|
end
|
63
54
|
|
64
|
-
def
|
65
|
-
command '
|
55
|
+
def set(page_id, id, value)
|
56
|
+
command 'set', page_id, id, value
|
66
57
|
end
|
67
58
|
|
68
|
-
def
|
69
|
-
command
|
59
|
+
def select_file(page_id, id, value)
|
60
|
+
command 'select_file', page_id, id, value
|
70
61
|
end
|
71
62
|
|
72
|
-
def
|
73
|
-
command
|
63
|
+
def tag_name(page_id, id)
|
64
|
+
command('tag_name', page_id, id).downcase
|
65
|
+
end
|
66
|
+
|
67
|
+
def visible?(page_id, id)
|
68
|
+
command 'visible', page_id, id
|
74
69
|
end
|
75
70
|
|
76
71
|
def evaluate(script)
|
@@ -87,24 +82,20 @@ module Capybara::Poltergeist
|
|
87
82
|
command 'pop_frame'
|
88
83
|
end
|
89
84
|
|
90
|
-
def
|
91
|
-
|
85
|
+
def click(page_id, id)
|
86
|
+
command 'click', page_id, id
|
92
87
|
end
|
93
88
|
|
94
|
-
def
|
95
|
-
command '
|
89
|
+
def drag(page_id, id, other_id)
|
90
|
+
command 'drag', page_id, id, other_id
|
96
91
|
end
|
97
92
|
|
98
|
-
def
|
99
|
-
command '
|
93
|
+
def select(page_id, id, value)
|
94
|
+
command 'select', page_id, id, value
|
100
95
|
end
|
101
96
|
|
102
|
-
def
|
103
|
-
command '
|
104
|
-
end
|
105
|
-
|
106
|
-
def trigger(id, event)
|
107
|
-
command 'trigger', id, event
|
97
|
+
def trigger(page_id, id, event)
|
98
|
+
command 'trigger', page_id, id, event.to_s
|
108
99
|
end
|
109
100
|
|
110
101
|
def reset
|
@@ -119,23 +110,19 @@ module Capybara::Poltergeist
|
|
119
110
|
command 'resize', width, height
|
120
111
|
end
|
121
112
|
|
122
|
-
def logger
|
123
|
-
options[:logger]
|
124
|
-
end
|
125
|
-
|
126
|
-
def log(message)
|
127
|
-
logger.puts message if logger
|
128
|
-
end
|
129
|
-
|
130
113
|
def command(name, *args)
|
131
114
|
message = { 'name' => name, 'args' => args }
|
132
115
|
log message.inspect
|
133
116
|
|
134
|
-
json =
|
117
|
+
json = MultiJson.decode(server.send(MultiJson.encode(message)))
|
135
118
|
log json.inspect
|
136
119
|
|
137
120
|
if json['error']
|
138
|
-
|
121
|
+
if json['error']['name'] == 'Poltergeist.JavascriptError'
|
122
|
+
raise JavascriptError.new(json['error'])
|
123
|
+
else
|
124
|
+
raise BrowserError.new(json['error'])
|
125
|
+
end
|
139
126
|
else
|
140
127
|
json['response']
|
141
128
|
end
|
@@ -144,5 +131,11 @@ module Capybara::Poltergeist
|
|
144
131
|
restart
|
145
132
|
raise
|
146
133
|
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def log(message)
|
138
|
+
logger.puts message if logger
|
139
|
+
end
|
147
140
|
end
|
148
141
|
end
|
@@ -1,11 +1,8 @@
|
|
1
|
-
require 'sfl'
|
2
|
-
|
3
1
|
module Capybara::Poltergeist
|
4
2
|
class Client
|
5
3
|
PHANTOMJS_SCRIPT = File.expand_path('../client/compiled/main.js', __FILE__)
|
6
|
-
PHANTOMJS_VERSION =
|
7
|
-
|
8
|
-
attr_reader :pid, :port, :path
|
4
|
+
PHANTOMJS_VERSION = '1.4.1'
|
5
|
+
PHANTOMJS_NAME = 'phantomjs'
|
9
6
|
|
10
7
|
def self.start(*args)
|
11
8
|
client = new(*args)
|
@@ -13,19 +10,33 @@ module Capybara::Poltergeist
|
|
13
10
|
client
|
14
11
|
end
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
attr_reader :pid, :port, :path, :inspector
|
14
|
+
|
15
|
+
def initialize(port, inspector = nil, path = nil)
|
16
|
+
@port = port
|
17
|
+
@inspector = inspector
|
18
|
+
@path = path || PHANTOMJS_NAME
|
19
|
+
|
20
|
+
pid = Process.pid
|
21
|
+
at_exit { stop if Process.pid == pid }
|
20
22
|
end
|
21
23
|
|
22
24
|
def start
|
23
25
|
check_phantomjs_version
|
24
|
-
@pid =
|
26
|
+
@pid = Spawn.spawn(*command)
|
25
27
|
end
|
26
28
|
|
27
29
|
def stop
|
28
|
-
|
30
|
+
if pid
|
31
|
+
begin
|
32
|
+
Process.kill('TERM', pid)
|
33
|
+
Process.wait(pid)
|
34
|
+
rescue Errno::ESRCH, Errno::ECHILD
|
35
|
+
# Zed's dead, baby
|
36
|
+
end
|
37
|
+
|
38
|
+
@pid = nil
|
39
|
+
end
|
29
40
|
end
|
30
41
|
|
31
42
|
def restart
|
@@ -33,15 +44,34 @@ module Capybara::Poltergeist
|
|
33
44
|
start
|
34
45
|
end
|
35
46
|
|
47
|
+
def command
|
48
|
+
@command ||= begin
|
49
|
+
parts = [path]
|
50
|
+
|
51
|
+
if inspector
|
52
|
+
parts << "--remote-debugger-port=#{inspector.port}"
|
53
|
+
parts << "--remote-debugger-autorun=yes"
|
54
|
+
end
|
55
|
+
|
56
|
+
parts << PHANTOMJS_SCRIPT
|
57
|
+
parts << port
|
58
|
+
parts
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
36
62
|
private
|
37
63
|
|
38
64
|
def check_phantomjs_version
|
39
65
|
return if @phantomjs_version_checked
|
40
66
|
|
41
67
|
version = `#{path} --version`.chomp
|
42
|
-
|
68
|
+
|
69
|
+
if $? != 0
|
70
|
+
raise PhantomJSFailed.new($?)
|
71
|
+
elsif version < PHANTOMJS_VERSION
|
43
72
|
raise PhantomJSTooOld.new(version)
|
44
73
|
end
|
74
|
+
|
45
75
|
@phantomjs_version_checked = true
|
46
76
|
end
|
47
77
|
end
|
@@ -7,18 +7,28 @@ class PoltergeistAgent
|
|
7
7
|
@windows = []
|
8
8
|
this.pushWindow(window)
|
9
9
|
|
10
|
+
externalCall: (name, arguments) ->
|
11
|
+
try
|
12
|
+
{ value: this[name].apply(this, arguments) }
|
13
|
+
catch error
|
14
|
+
{ error: error.toString() }
|
15
|
+
|
10
16
|
pushWindow: (new_window) ->
|
11
17
|
@windows.push(new_window)
|
12
18
|
|
13
19
|
@window = new_window
|
14
20
|
@document = @window.document
|
15
21
|
|
22
|
+
null
|
23
|
+
|
16
24
|
popWindow: ->
|
17
25
|
@windows.pop()
|
18
26
|
|
19
27
|
@window = @windows[@windows.length - 1]
|
20
28
|
@document = @window.document
|
21
29
|
|
30
|
+
null
|
31
|
+
|
22
32
|
pushFrame: (id) ->
|
23
33
|
this.pushWindow @document.getElementById(id).contentWindow
|
24
34
|
|
@@ -28,9 +38,8 @@ class PoltergeistAgent
|
|
28
38
|
currentUrl: ->
|
29
39
|
window.location.toString()
|
30
40
|
|
31
|
-
find: (selector,
|
32
|
-
|
33
|
-
results = @document.evaluate(selector, context, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
|
41
|
+
find: (selector, within = @document) ->
|
42
|
+
results = @document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
|
34
43
|
ids = []
|
35
44
|
|
36
45
|
for i in [0...results.snapshotLength]
|
@@ -51,8 +60,12 @@ class PoltergeistAgent
|
|
51
60
|
|
52
61
|
nodeCall: (id, name, arguments) ->
|
53
62
|
node = this.get(id)
|
63
|
+
throw new PoltergeistAgent.ObsoleteNode if node.isObsolete()
|
54
64
|
node[name].apply(node, arguments)
|
55
65
|
|
66
|
+
class PoltergeistAgent.ObsoleteNode
|
67
|
+
toString: -> "PoltergeistAgent.ObsoleteNode"
|
68
|
+
|
56
69
|
class PoltergeistAgent.Node
|
57
70
|
@EVENTS = {
|
58
71
|
FOCUS: ['blur', 'focus', 'focusin', 'focusout'],
|
@@ -65,6 +78,9 @@ class PoltergeistAgent.Node
|
|
65
78
|
parentId: ->
|
66
79
|
@agent.register(@element.parentNode)
|
67
80
|
|
81
|
+
find: (selector) ->
|
82
|
+
@agent.find(selector, @element)
|
83
|
+
|
68
84
|
isObsolete: ->
|
69
85
|
obsolete = (element) =>
|
70
86
|
if element.parentNode?
|
@@ -151,8 +167,16 @@ class PoltergeistAgent.Node
|
|
151
167
|
true
|
152
168
|
|
153
169
|
position: ->
|
154
|
-
rect = @element.
|
155
|
-
|
170
|
+
rect = @element.getClientRects()[0]
|
171
|
+
|
172
|
+
{
|
173
|
+
top: rect.top,
|
174
|
+
right: rect.right,
|
175
|
+
left: rect.left,
|
176
|
+
bottom: rect.bottom,
|
177
|
+
width: rect.width,
|
178
|
+
height: rect.height
|
179
|
+
}
|
156
180
|
|
157
181
|
trigger: (name) ->
|
158
182
|
if Node.EVENTS.MOUSE.indexOf(name) != -1
|
@@ -169,6 +193,25 @@ class PoltergeistAgent.Node
|
|
169
193
|
|
170
194
|
@element.dispatchEvent(event)
|
171
195
|
|
196
|
+
clickTest: (x, y) ->
|
197
|
+
el = origEl = document.elementFromPoint(x, y)
|
198
|
+
|
199
|
+
while el
|
200
|
+
if el == @element
|
201
|
+
return { status: 'success' }
|
202
|
+
else
|
203
|
+
el = el.parentNode
|
204
|
+
|
205
|
+
{ status: 'failure', selector: origEl && this.getSelector(origEl) }
|
206
|
+
|
207
|
+
getSelector: (el) ->
|
208
|
+
selector = if el.tagName != 'HTML' then this.getSelector(el.parentNode) + ' ' else ''
|
209
|
+
selector += el.tagName.toLowerCase()
|
210
|
+
selector += "##{el.id}" if el.id
|
211
|
+
for className in el.classList
|
212
|
+
selector += ".#{className}"
|
213
|
+
selector
|
214
|
+
|
172
215
|
window.__poltergeist = new PoltergeistAgent
|
173
216
|
|
174
217
|
document.addEventListener(
|
@@ -1,11 +1,12 @@
|
|
1
1
|
class Poltergeist.Browser
|
2
2
|
constructor: (@owner) ->
|
3
|
-
@state
|
3
|
+
@state = 'default'
|
4
|
+
@page_id = 0
|
5
|
+
|
4
6
|
this.resetPage()
|
5
7
|
|
6
8
|
resetPage: ->
|
7
9
|
@page.release() if @page?
|
8
|
-
|
9
10
|
@page = new Poltergeist.WebPage
|
10
11
|
|
11
12
|
@page.onLoadStarted = =>
|
@@ -13,37 +14,58 @@ class Poltergeist.Browser
|
|
13
14
|
|
14
15
|
@page.onLoadFinished = (status) =>
|
15
16
|
if @state == 'loading'
|
16
|
-
|
17
|
+
this.sendResponse(status)
|
17
18
|
@state = 'default'
|
18
19
|
|
20
|
+
@page.onInitialized = =>
|
21
|
+
@page_id += 1
|
22
|
+
|
23
|
+
sendResponse: (response) ->
|
24
|
+
errors = @page.errors()
|
25
|
+
|
26
|
+
if errors.length > 0
|
27
|
+
@page.clearErrors()
|
28
|
+
@owner.sendError(new Poltergeist.JavascriptError(errors))
|
29
|
+
else
|
30
|
+
@owner.sendResponse(response)
|
31
|
+
|
32
|
+
node: (page_id, id) ->
|
33
|
+
if page_id == @page_id
|
34
|
+
@page.get(id)
|
35
|
+
else
|
36
|
+
throw new Poltergeist.ObsoleteNode
|
37
|
+
|
19
38
|
visit: (url) ->
|
20
39
|
@state = 'loading'
|
21
40
|
@page.open(url)
|
22
41
|
|
23
42
|
current_url: ->
|
24
|
-
|
43
|
+
this.sendResponse @page.currentUrl()
|
25
44
|
|
26
45
|
body: ->
|
27
|
-
|
46
|
+
this.sendResponse @page.content()
|
28
47
|
|
29
48
|
source: ->
|
30
|
-
|
49
|
+
this.sendResponse @page.source()
|
50
|
+
|
51
|
+
find: (selector) ->
|
52
|
+
this.sendResponse(page_id: @page_id, ids: @page.find(selector))
|
31
53
|
|
32
|
-
|
33
|
-
|
54
|
+
find_within: (page_id, id, selector) ->
|
55
|
+
this.sendResponse this.node(page_id, id).find(selector)
|
34
56
|
|
35
|
-
text: (id) ->
|
36
|
-
|
57
|
+
text: (page_id, id) ->
|
58
|
+
this.sendResponse this.node(page_id, id).text()
|
37
59
|
|
38
|
-
attribute: (id, name) ->
|
39
|
-
|
60
|
+
attribute: (page_id, id, name) ->
|
61
|
+
this.sendResponse this.node(page_id, id).getAttribute(name)
|
40
62
|
|
41
|
-
value: (id) ->
|
42
|
-
|
63
|
+
value: (page_id, id) ->
|
64
|
+
this.sendResponse this.node(page_id, id).value()
|
43
65
|
|
44
|
-
set: (id, value) ->
|
45
|
-
|
46
|
-
|
66
|
+
set: (page_id, id, value) ->
|
67
|
+
this.node(page_id, id).set(value)
|
68
|
+
this.sendResponse(true)
|
47
69
|
|
48
70
|
# PhantomJS only allows us to reference the element by CSS selector, not XPath,
|
49
71
|
# so we have to add an attribute to the element to identify it, then remove it
|
@@ -52,8 +74,8 @@ class Poltergeist.Browser
|
|
52
74
|
# PhantomJS does not support multiple-file inputs, so we have to blatently cheat
|
53
75
|
# by temporarily changing it to a single-file input. This obviously could break
|
54
76
|
# things in various ways, which is not ideal, but it works in the simplest case.
|
55
|
-
select_file: (id, value) ->
|
56
|
-
element =
|
77
|
+
select_file: (page_id, id, value) ->
|
78
|
+
element = this.node(page_id, id)
|
57
79
|
|
58
80
|
multiple = element.isMultiple()
|
59
81
|
|
@@ -65,38 +87,38 @@ class Poltergeist.Browser
|
|
65
87
|
element.removeAttribute('_poltergeist_selected')
|
66
88
|
element.setAttribute('multiple', 'multiple') if multiple
|
67
89
|
|
68
|
-
|
90
|
+
this.sendResponse(true)
|
69
91
|
|
70
|
-
select: (id, value) ->
|
71
|
-
|
92
|
+
select: (page_id, id, value) ->
|
93
|
+
this.sendResponse this.node(page_id, id).select(value)
|
72
94
|
|
73
|
-
tag_name: (id) ->
|
74
|
-
|
95
|
+
tag_name: (page_id, id) ->
|
96
|
+
this.sendResponse this.node(page_id, id).tagName()
|
75
97
|
|
76
|
-
visible: (id) ->
|
77
|
-
|
98
|
+
visible: (page_id, id) ->
|
99
|
+
this.sendResponse this.node(page_id, id).isVisible()
|
78
100
|
|
79
101
|
evaluate: (script) ->
|
80
|
-
|
102
|
+
this.sendResponse JSON.parse(@page.evaluate("function() { return JSON.stringify(#{script}) }"))
|
81
103
|
|
82
104
|
execute: (script) ->
|
83
105
|
@page.execute("function() { #{script} }")
|
84
|
-
|
106
|
+
this.sendResponse(true)
|
85
107
|
|
86
108
|
push_frame: (id) ->
|
87
109
|
@page.pushFrame(id)
|
88
|
-
|
110
|
+
this.sendResponse(true)
|
89
111
|
|
90
112
|
pop_frame: ->
|
91
113
|
@page.popFrame()
|
92
|
-
|
114
|
+
this.sendResponse(true)
|
93
115
|
|
94
|
-
click: (id) ->
|
116
|
+
click: (page_id, id) ->
|
95
117
|
# If the click event triggers onLoadStarted, we will transition to the 'loading'
|
96
118
|
# state and wait for onLoadFinished before sending a response.
|
97
119
|
@state = 'clicked'
|
98
120
|
|
99
|
-
|
121
|
+
this.node(page_id, id).click()
|
100
122
|
|
101
123
|
# Use a timeout in order to let the stack clear, so that the @page.onLoadStarted
|
102
124
|
# callback can (possibly) fire, before we decide whether to send a response.
|
@@ -104,22 +126,22 @@ class Poltergeist.Browser
|
|
104
126
|
=>
|
105
127
|
if @state == 'clicked'
|
106
128
|
@state = 'default'
|
107
|
-
|
129
|
+
this.sendResponse(true)
|
108
130
|
,
|
109
131
|
10
|
110
132
|
)
|
111
133
|
|
112
|
-
drag: (id, other_id) ->
|
113
|
-
|
114
|
-
|
134
|
+
drag: (page_id, id, other_id) ->
|
135
|
+
this.node(page_id, id).dragTo(@page.get(other_id))
|
136
|
+
this.sendResponse(true)
|
115
137
|
|
116
|
-
trigger: (id, event) ->
|
117
|
-
|
118
|
-
|
138
|
+
trigger: (page_id, id, event) ->
|
139
|
+
this.node(page_id, id).trigger(event)
|
140
|
+
this.sendResponse(event)
|
119
141
|
|
120
142
|
reset: ->
|
121
143
|
this.resetPage()
|
122
|
-
|
144
|
+
this.sendResponse(true)
|
123
145
|
|
124
146
|
render: (path, full) ->
|
125
147
|
dimensions = @page.validatedDimensions()
|
@@ -135,11 +157,11 @@ class Poltergeist.Browser
|
|
135
157
|
@page.setClipRect(left: 0, top: 0, width: viewport.width, height: viewport.height)
|
136
158
|
@page.render(path)
|
137
159
|
|
138
|
-
|
160
|
+
this.sendResponse(true)
|
139
161
|
|
140
162
|
resize: (width, height) ->
|
141
163
|
@page.setViewportSize(width: width, height: height)
|
142
|
-
|
164
|
+
this.sendResponse(true)
|
143
165
|
|
144
166
|
exit: ->
|
145
167
|
phantom.exit()
|