poltergeist 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
[](http://travis-ci.org/jonleighton/poltergeist)
|
6
|
+
[](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()
|