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
         |