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
@@ -0,0 +1,35 @@
|
|
1
|
+
module Capybara::Poltergeist
|
2
|
+
class Inspector
|
3
|
+
BROWSERS = %w(chromium chromium-browser google-chrome safari)
|
4
|
+
|
5
|
+
def self.detect_browser
|
6
|
+
@browser ||= BROWSERS.find { |name| system("which #{name} &>/dev/null") }
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(browser = nil)
|
10
|
+
@browser = browser.respond_to?(:to_str) ? browser : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def browser
|
14
|
+
@browser ||= self.class.detect_browser
|
15
|
+
end
|
16
|
+
|
17
|
+
def port
|
18
|
+
@port ||= Util.find_available_port
|
19
|
+
end
|
20
|
+
|
21
|
+
def url
|
22
|
+
"http://localhost:#{port}/"
|
23
|
+
end
|
24
|
+
|
25
|
+
def open
|
26
|
+
if browser
|
27
|
+
Spawn.spawn(browser, url)
|
28
|
+
else
|
29
|
+
raise Error, "Could not find a browser executable to open #{url}. " \
|
30
|
+
"You can specify one manually using e.g. `:inspector => 'chromium'` " \
|
31
|
+
"as a configuration option for Poltergeist."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,5 +1,12 @@
|
|
1
1
|
module Capybara::Poltergeist
|
2
2
|
class Node < Capybara::Driver::Node
|
3
|
+
attr_reader :page_id
|
4
|
+
|
5
|
+
def initialize(driver, page_id, id)
|
6
|
+
super(driver, id)
|
7
|
+
@page_id = page_id
|
8
|
+
end
|
9
|
+
|
3
10
|
alias id native
|
4
11
|
|
5
12
|
def browser
|
@@ -7,17 +14,20 @@ module Capybara::Poltergeist
|
|
7
14
|
end
|
8
15
|
|
9
16
|
def command(name, *args)
|
10
|
-
browser.send(name, id, *args)
|
17
|
+
browser.send(name, page_id, id, *args)
|
11
18
|
rescue BrowserError => error
|
12
|
-
|
13
|
-
|
19
|
+
case error.name
|
20
|
+
when 'Poltergeist.ObsoleteNode'
|
21
|
+
raise ObsoleteNode.new(self, error.response)
|
22
|
+
when 'Poltergeist.ClickFailed'
|
23
|
+
raise ClickFailed.new(self, error.response)
|
14
24
|
else
|
15
|
-
raise
|
25
|
+
raise
|
16
26
|
end
|
17
27
|
end
|
18
28
|
|
19
29
|
def find(selector)
|
20
|
-
|
30
|
+
command(:find_within, selector).map { |id| self.class.new(driver, page_id, id) }
|
21
31
|
end
|
22
32
|
|
23
33
|
def text
|
@@ -3,7 +3,7 @@ module Capybara::Poltergeist
|
|
3
3
|
attr_reader :port, :socket, :timeout
|
4
4
|
|
5
5
|
def initialize(timeout = nil)
|
6
|
-
@port = find_available_port
|
6
|
+
@port = Util.find_available_port
|
7
7
|
@timeout = timeout
|
8
8
|
start
|
9
9
|
end
|
@@ -16,22 +16,17 @@ module Capybara::Poltergeist
|
|
16
16
|
@socket = WebSocketServer.new(port, timeout)
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def stop
|
20
20
|
@socket.close
|
21
|
-
@socket = WebSocketServer.new(port, timeout)
|
22
21
|
end
|
23
22
|
|
24
|
-
def
|
25
|
-
|
23
|
+
def restart
|
24
|
+
stop
|
25
|
+
start
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
def find_available_port
|
31
|
-
server = TCPServer.new('127.0.0.1', 0)
|
32
|
-
server.addr[1]
|
33
|
-
ensure
|
34
|
-
server.close if server
|
28
|
+
def send(message)
|
29
|
+
@socket.send(message) or raise DeadClient.new(message)
|
35
30
|
end
|
36
31
|
end
|
37
32
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'childprocess'
|
2
|
+
|
3
|
+
module Capybara::Poltergeist
|
4
|
+
module Spawn
|
5
|
+
def self.spawn(*args)
|
6
|
+
args = args.map(&:to_s)
|
7
|
+
|
8
|
+
if RUBY_VERSION >= "1.9"
|
9
|
+
Process.spawn(*args)
|
10
|
+
else
|
11
|
+
process = ChildProcess.build(*args)
|
12
|
+
process.start
|
13
|
+
process.pid
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -54,16 +54,34 @@ module Capybara::Poltergeist
|
|
54
54
|
# just keep reading until we've received a full frame)
|
55
55
|
RECV_SIZE = 1024
|
56
56
|
|
57
|
+
# How many seconds to try to bind to the port for before failing
|
58
|
+
BIND_TIMEOUT = 5
|
59
|
+
|
57
60
|
attr_reader :port, :parser, :socket, :handler, :server
|
58
61
|
attr_accessor :timeout
|
59
62
|
|
60
63
|
def initialize(port, timeout = nil)
|
61
64
|
@port = port
|
62
65
|
@parser = Http::Parser.new
|
63
|
-
@server =
|
66
|
+
@server = start_server
|
64
67
|
@timeout = timeout
|
65
68
|
end
|
66
69
|
|
70
|
+
def start_server
|
71
|
+
time = Time.now
|
72
|
+
|
73
|
+
begin
|
74
|
+
TCPServer.open(port)
|
75
|
+
rescue Errno::EADDRINUSE
|
76
|
+
if (Time.now - time) < BIND_TIMEOUT
|
77
|
+
sleep(0.01)
|
78
|
+
retry
|
79
|
+
else
|
80
|
+
raise
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
67
85
|
def connected?
|
68
86
|
!socket.nil?
|
69
87
|
end
|
@@ -104,11 +122,12 @@ module Capybara::Poltergeist
|
|
104
122
|
end
|
105
123
|
end
|
106
124
|
|
107
|
-
# Block until the next message is available from the Web Socket
|
125
|
+
# Block until the next message is available from the Web Socket.
|
126
|
+
# Raises Errno::EWOULDBLOCK if timeout is reached.
|
108
127
|
def receive
|
109
128
|
until handler.message?
|
110
|
-
IO.select([socket], [], [], timeout)
|
111
|
-
data = socket.
|
129
|
+
IO.select([socket], [], [], timeout) or raise Errno::EWOULDBLOCK
|
130
|
+
data = socket.recv(RECV_SIZE)
|
112
131
|
break if data.empty?
|
113
132
|
handler.parse(data)
|
114
133
|
end
|
@@ -121,12 +140,12 @@ module Capybara::Poltergeist
|
|
121
140
|
accept unless connected?
|
122
141
|
socket.write handler.encode(message)
|
123
142
|
receive
|
124
|
-
rescue Errno::
|
143
|
+
rescue Errno::EWOULDBLOCK
|
125
144
|
raise TimeoutError.new(message)
|
126
145
|
end
|
127
146
|
|
128
147
|
def close
|
129
|
-
[server, socket].each do |s|
|
148
|
+
[server, socket].compact.each do |s|
|
130
149
|
s.close_read
|
131
150
|
s.close_write
|
132
151
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poltergeist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-03-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capybara
|
16
|
-
requirement: &
|
16
|
+
requirement: &20962640 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,32 +21,32 @@ dependencies:
|
|
21
21
|
version: '1.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *20962640
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement: &
|
26
|
+
name: multi_json
|
27
|
+
requirement: &20960260 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '1.
|
32
|
+
version: '1.0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *20960260
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement: &
|
37
|
+
name: childprocess
|
38
|
+
requirement: &20958720 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
43
|
+
version: '0.3'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *20958720
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: http_parser.rb
|
49
|
-
requirement: &
|
49
|
+
requirement: &20957520 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,21 +54,24 @@ dependencies:
|
|
54
54
|
version: 0.5.3
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *20957520
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: faye-websocket
|
60
|
-
requirement: &
|
60
|
+
requirement: &21890060 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version: 0.
|
65
|
+
version: '0.4'
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.4.4
|
66
69
|
type: :runtime
|
67
70
|
prerelease: false
|
68
|
-
version_requirements: *
|
71
|
+
version_requirements: *21890060
|
69
72
|
- !ruby/object:Gem::Dependency
|
70
73
|
name: rspec
|
71
|
-
requirement: &
|
74
|
+
requirement: &21888340 !ruby/object:Gem::Requirement
|
72
75
|
none: false
|
73
76
|
requirements:
|
74
77
|
- - ~>
|
@@ -76,10 +79,10 @@ dependencies:
|
|
76
79
|
version: 2.8.0
|
77
80
|
type: :development
|
78
81
|
prerelease: false
|
79
|
-
version_requirements: *
|
82
|
+
version_requirements: *21888340
|
80
83
|
- !ruby/object:Gem::Dependency
|
81
84
|
name: sinatra
|
82
|
-
requirement: &
|
85
|
+
requirement: &21886720 !ruby/object:Gem::Requirement
|
83
86
|
none: false
|
84
87
|
requirements:
|
85
88
|
- - ~>
|
@@ -87,10 +90,10 @@ dependencies:
|
|
87
90
|
version: '1.0'
|
88
91
|
type: :development
|
89
92
|
prerelease: false
|
90
|
-
version_requirements: *
|
93
|
+
version_requirements: *21886720
|
91
94
|
- !ruby/object:Gem::Dependency
|
92
95
|
name: rake
|
93
|
-
requirement: &
|
96
|
+
requirement: &21886100 !ruby/object:Gem::Requirement
|
94
97
|
none: false
|
95
98
|
requirements:
|
96
99
|
- - ~>
|
@@ -98,10 +101,10 @@ dependencies:
|
|
98
101
|
version: 0.9.2
|
99
102
|
type: :development
|
100
103
|
prerelease: false
|
101
|
-
version_requirements: *
|
104
|
+
version_requirements: *21886100
|
102
105
|
- !ruby/object:Gem::Dependency
|
103
106
|
name: image_size
|
104
|
-
requirement: &
|
107
|
+
requirement: &21212360 !ruby/object:Gem::Requirement
|
105
108
|
none: false
|
106
109
|
requirements:
|
107
110
|
- - ~>
|
@@ -109,7 +112,7 @@ dependencies:
|
|
109
112
|
version: '1.0'
|
110
113
|
type: :development
|
111
114
|
prerelease: false
|
112
|
-
version_requirements: *
|
115
|
+
version_requirements: *21212360
|
113
116
|
description: PhantomJS driver for Capybara
|
114
117
|
email:
|
115
118
|
- j@jonathanleighton.com
|
@@ -121,9 +124,12 @@ files:
|
|
121
124
|
- lib/capybara/poltergeist/client.rb
|
122
125
|
- lib/capybara/poltergeist/server.rb
|
123
126
|
- lib/capybara/poltergeist/browser.rb
|
127
|
+
- lib/capybara/poltergeist/inspector.rb
|
124
128
|
- lib/capybara/poltergeist/errors.rb
|
129
|
+
- lib/capybara/poltergeist/util.rb
|
125
130
|
- lib/capybara/poltergeist/web_socket_server.rb
|
126
131
|
- lib/capybara/poltergeist/version.rb
|
132
|
+
- lib/capybara/poltergeist/spawn.rb
|
127
133
|
- lib/capybara/poltergeist/driver.rb
|
128
134
|
- lib/capybara/poltergeist/client/connection.coffee
|
129
135
|
- lib/capybara/poltergeist/client/node.coffee
|