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.
@@ -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
- if error.text == 'Poltergeist.ObsoleteNode'
13
- raise ObsoleteNode.new(self)
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 error
25
+ raise
16
26
  end
17
27
  end
18
28
 
19
29
  def find(selector)
20
- browser.find(selector, id).map { |node| self.class.new(driver, node) }
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 restart
19
+ def stop
20
20
  @socket.close
21
- @socket = WebSocketServer.new(port, timeout)
22
21
  end
23
22
 
24
- def send(message)
25
- @socket.send(message) or raise DeadClient.new(message)
23
+ def restart
24
+ stop
25
+ start
26
26
  end
27
27
 
28
- private
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
@@ -0,0 +1,12 @@
1
+ require 'socket'
2
+
3
+ module Capybara::Poltergeist
4
+ module Util
5
+ def self.find_available_port
6
+ server = TCPServer.new('127.0.0.1', 0)
7
+ server.addr[1]
8
+ ensure
9
+ server.close if server
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Poltergeist
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  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 = TCPServer.open(port)
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.recv_nonblock(RECV_SIZE)
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::EAGAIN, Errno::EWOULDBLOCK
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.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-02-18 00:00:00.000000000 Z
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: &16526020 !ruby/object:Gem::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: *16526020
24
+ version_requirements: *20962640
25
25
  - !ruby/object:Gem::Dependency
26
- name: json
27
- requirement: &16525520 !ruby/object:Gem::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.6'
32
+ version: '1.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *16525520
35
+ version_requirements: *20960260
36
36
  - !ruby/object:Gem::Dependency
37
- name: sfl
38
- requirement: &16525060 !ruby/object:Gem::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: '2.0'
43
+ version: '0.3'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *16525060
46
+ version_requirements: *20958720
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: http_parser.rb
49
- requirement: &16524600 !ruby/object:Gem::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: *16524600
57
+ version_requirements: *20957520
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: faye-websocket
60
- requirement: &16524140 !ruby/object:Gem::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.2.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: *16524140
71
+ version_requirements: *21890060
69
72
  - !ruby/object:Gem::Dependency
70
73
  name: rspec
71
- requirement: &16523680 !ruby/object:Gem::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: *16523680
82
+ version_requirements: *21888340
80
83
  - !ruby/object:Gem::Dependency
81
84
  name: sinatra
82
- requirement: &16523220 !ruby/object:Gem::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: *16523220
93
+ version_requirements: *21886720
91
94
  - !ruby/object:Gem::Dependency
92
95
  name: rake
93
- requirement: &16522760 !ruby/object:Gem::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: *16522760
104
+ version_requirements: *21886100
102
105
  - !ruby/object:Gem::Dependency
103
106
  name: image_size
104
- requirement: &16522300 !ruby/object:Gem::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: *16522300
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