Class: Headless

Inherits:
Object
  • Object
show all
Defined in:
lib/headless.rb,
lib/headless/cli_util.rb,
lib/headless/video/video_recorder.rb

Overview

A class incapsulating the creation and usage of a headless X server

Prerequisites

  • X Window System

  • Xvfb

Usage

Block mode:

require 'rubygems'
require 'headless'
require 'selenium-webdriver'

Headless.ly do
  driver = Selenium::WebDriver.for :firefox
  driver.navigate.to 'http://google.com'
  puts driver.title
end

Object mode:

require 'rubygems'
require 'headless'
require 'selenium-webdriver'

headless = Headless.new
headless.start

driver = Selenium::WebDriver.for :firefox
driver.navigate.to 'http://google.com'
puts driver.title

headless.destroy

– TODO test that reuse actually works with an existing xvfb session ++

Defined Under Namespace

Classes: CliUtil, Exception, VideoRecorder

Constant Summary collapse

DEFAULT_DISPLAY_NUMBER =
99
MAX_DISPLAY_NUMBER =
10_000
DEFAULT_DISPLAY_DIMENSIONS =
'1280x1024x24'
XVFB_LAUNCH_TIMEOUT =

How long should we wait for Xvfb to open a display, before assuming that it is frozen (in seconds)

10

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Headless

Creates a new headless server, but does NOT switch to it immediately. Call #start for that

List of available options:

  • display (default 99) - what display number to listen to;

  • reuse (default true) - if given display server already exists, should we use it or try another?

  • autopick (default true is display number isn’t explicitly set) - if Headless should automatically pick a display, or fail if the given one is not available.

  • dimensions (default 1280x1024x24) - display dimensions and depth. Not all combinations are possible, refer to man Xvfb.

  • destroy_at_exit (default true) - if a display is started but not stopped, should it be destroyed when the script finishes?



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/headless.rb', line 67

def initialize(options = {})
  CliUtil.ensure_application_exists!('Xvfb', 'Xvfb not found on your system')

  @display = options.fetch(:display, DEFAULT_DISPLAY_NUMBER).to_i
  @autopick_display = options.fetch(:autopick, !options.key?(:display))
  @reuse_display = options.fetch(:reuse, true)
  @dimensions = options.fetch(:dimensions, DEFAULT_DISPLAY_DIMENSIONS)
  @video_capture_options = options.fetch(:video, {})
  @destroy_at_exit = options.fetch(:destroy_at_exit, true)

  # FIXME Xvfb launch should not happen inside the constructor
  attach_xvfb
end

Instance Attribute Details

#dimensionsObject (readonly)

The display dimensions



57
58
59
# File 'lib/headless.rb', line 57

def dimensions
  @dimensions
end

#displayObject (readonly)

The display number



54
55
56
# File 'lib/headless.rb', line 54

def display
  @display
end

Class Method Details

.run(options = {}, &block) ⇒ Object Also known as: ly

Block syntax:

Headless.run do
  # perform operations in headless mode
end

See #new for options



105
106
107
108
109
110
111
# File 'lib/headless.rb', line 105

def self.run(options={}, &block)
  headless = Headless.new(options)
  headless.start
  yield headless
ensure
  headless && headless.destroy
end

Instance Method Details

#destroyObject

Switches back from the headless server and terminates the headless session



94
95
96
97
# File 'lib/headless.rb', line 94

def destroy
  stop
  CliUtil.kill_process(pid_filename)
end

#startObject

Switches to the headless server



82
83
84
85
86
# File 'lib/headless.rb', line 82

def start
  @old_display = ENV['DISPLAY']
  ENV['DISPLAY'] = ":#{display}"
  hook_at_exit
end

#stopObject

Switches back from the headless server



89
90
91
# File 'lib/headless.rb', line 89

def stop
  ENV['DISPLAY'] = @old_display
end

#take_screenshot(file_path) ⇒ Object



118
119
120
121
122
# File 'lib/headless.rb', line 118

def take_screenshot(file_path)
  CliUtil.ensure_application_exists!('import', "imagemagick not found on your system. Please install it using sudo apt-get install imagemagick")

  system "#{CliUtil.path_to('import')} -display localhost:#{display} -window root #{file_path}"
end

#videoObject



114
115
116
# File 'lib/headless.rb', line 114

def video
  @video_recorder ||= VideoRecorder.new(display, dimensions, @video_capture_options)
end