Class: Selenium::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/selenium/server.rb

Overview

Wraps the remote server jar

Usage:

server = Selenium::Server.new('/path/to/selenium-server-standalone.jar')
server.start

Automatically download the given version:

server = Selenium::Server.get '2.6.0'
server.start

or the latest version:

server = Selenium::Server.get :latest
server.start

Run the server in the background:

server = Selenium::Server.new(jar, :background => true)
server.start

Add additional arguments:

server = Selenium::Server.new(jar)
server << ["--additional", "args"]
server.start

Defined Under Namespace

Classes: Error

Constant Summary collapse

CL_RESET =
WebDriver::Platform.windows? ? '' : "\r\e[0K"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(jar, opts = {}) ⇒ Server

Returns a new instance of Server.

Parameters:

  • jar (String)

    Path to the server jar.

  • opts (Hash) (defaults to: {})

    the options to create the server process with

Options Hash (opts):

  • :port (Integer)

    Port the server should listen on (default: 4444).

  • :timeout (Integer)

    Seconds to wait for server launch/shutdown (default: 30)

  • :background (true, false)

    Run the server in the background (default: false)

  • :log (true, false, String)

    Either a path to a log file, or true to pass server log to stdout.

Raises:

  • (Errno::ENOENT)

    if the jar file does not exist



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/selenium/server.rb', line 183

def initialize(jar, opts = {})
  raise Errno::ENOENT, jar unless File.exist?(jar)

  @java = opts.fetch(:java, 'java')
  @jar = jar
  @host = '127.0.0.1'
  @role = opts.fetch(:role, 'standalone')
  @port = opts.fetch(:port, WebDriver::PortProber.above(4444))
  @timeout = opts.fetch(:timeout, 30)
  @background = opts.fetch(:background, false)
  @additional_args = opts.fetch(:args, [])
  @log = opts[:log]
  if opts[:log_level]
    @log ||= true
    @additional_args << '--log-level'
    @additional_args << opts[:log_level].to_s
  end

  @log_file = nil
end

Instance Attribute Details

#backgroundObject

The Mode of the Server :standalone, #hub, #node



169
170
171
# File 'lib/selenium/server.rb', line 169

def background
  @background
end

#hostObject

The Mode of the Server :standalone, #hub, #node



169
170
171
# File 'lib/selenium/server.rb', line 169

def host
  @host
end

#logObject

The Mode of the Server :standalone, #hub, #node



169
170
171
# File 'lib/selenium/server.rb', line 169

def log
  @log
end

#portObject

The Mode of the Server :standalone, #hub, #node



169
170
171
# File 'lib/selenium/server.rb', line 169

def port
  @port
end

#roleObject

The Mode of the Server :standalone, #hub, #node



169
170
171
# File 'lib/selenium/server.rb', line 169

def role
  @role
end

#timeoutObject

The Mode of the Server :standalone, #hub, #node



169
170
171
# File 'lib/selenium/server.rb', line 169

def timeout
  @timeout
end

Class Method Details

.available_assetsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



116
117
118
119
120
121
122
123
# File 'lib/selenium/server.rb', line 116

def available_assets
  @available_assets ||= net_http_start('api.github.com') do |http|
    json = http.get('/repos/seleniumhq/selenium/releases').body
    all_assets = JSON.parse(json).map { |release| release['assets'] }.flatten
    server_assets = all_assets.select { |asset| asset['name'].match(/selenium-server-(\d+\.\d+\.\d+)\.jar/) }
    server_assets.each_with_object({}) { |asset, hash| hash[asset.delete('name')] = asset }
  end
end

.download(required_version = :latest) ⇒ String

Download the given version of the selenium-server jar and return location

Parameters:

  • required_version (String, Symbol) (defaults to: :latest)

    X.Y.Z defaults to ‘:latest’

Returns:

  • (String)

    location of downloaded file



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/selenium/server.rb', line 81

def download(required_version = :latest)
  required_version = latest if required_version == :latest
  download_file_name = "selenium-server-#{required_version}.jar"

  return download_file_name if File.exist? download_file_name

  begin
    download_location = available_assets[download_file_name]['browser_download_url']
    released = Net::HTTP.get_response(URI.parse(download_location))
    redirected = URI.parse released.header['location']

    File.open(download_file_name, 'wb') do |destination|
      download_server(redirected, destination)
    end
  rescue StandardError
    FileUtils.rm_rf download_file_name
    raise
  end

  download_file_name
end

.download_server(uri, destination) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/selenium/server.rb', line 137

def download_server(uri, destination)
  net_http_start('github-releases.githubusercontent.com') do |http|
    request = Net::HTTP::Get.new uri
    resp = http.request(request) do |response|
      total = response.content_length
      progress = 0
      segment_count = 0

      response.read_body do |segment|
        progress += segment.length
        segment_count += 1

        if (segment_count % 15).zero?
          percent = progress.fdiv(total) * 100
          print "#{CL_RESET}Downloading #{destination.path}: #{percent.to_i}% (#{progress} / #{total})"
          segment_count = 0
        end

        destination.write(segment)
      end
    end

    raise Error, "#{resp.code} for #{destination.path}" unless resp.is_a? Net::HTTPSuccess
  end
end

.get(required_version = :latest, opts = {}) ⇒ Selenium::Server

Download the given version of the selenium-server jar and return instance

Parameters:

  • required_version (String, Symbol) (defaults to: :latest)

    X.Y.Z defaults to ‘:latest’

  • opts (Hash) (defaults to: {})

Returns:



70
71
72
# File 'lib/selenium/server.rb', line 70

def get(required_version = :latest, opts = {})
  new(download(required_version), opts)
end

.latestObject

Ask GitHub what the latest selenium-server version is.



107
108
109
110
111
112
# File 'lib/selenium/server.rb', line 107

def latest
  @latest ||= begin
    available = available_assets.keys.map { |key| key[/selenium-server-(\d+\.\d+\.\d+)\.jar/, 1] }
    available.map { |asset| Gem::Version.new(asset) }.max.to_s
  end
end

.net_http_start(address) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/selenium/server.rb', line 125

def net_http_start(address, &)
  http_proxy = ENV.fetch('http_proxy', nil) || ENV.fetch('HTTP_PROXY', nil)
  if http_proxy
    http_proxy = "http://#{http_proxy}" unless http_proxy.start_with?('http://')
    uri = URI.parse(http_proxy)

    Net::HTTP.start(address, nil, uri.host, uri.port, &)
  else
    Net::HTTP.start(address, use_ssl: true, &)
  end
end

Instance Method Details

#<<(arg) ⇒ Object



222
223
224
225
226
227
228
# File 'lib/selenium/server.rb', line 222

def <<(arg)
  if arg.is_a?(Array)
    @additional_args += arg
  else
    @additional_args << arg.to_s
  end
end

#startObject



204
205
206
207
208
209
# File 'lib/selenium/server.rb', line 204

def start
  process.start
  poll_for_service

  process.wait unless @background
end

#stopObject



211
212
213
214
215
216
# File 'lib/selenium/server.rb', line 211

def stop
  stop_process if @process
  poll_for_shutdown

  @log_file&.close
end

#webdriver_urlObject



218
219
220
# File 'lib/selenium/server.rb', line 218

def webdriver_url
  "http://#{@host}:#{@port}/wd/hub"
end