headless 0.0.1
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/LICENSE +20 -0
- data/README.md +62 -0
- data/lib/headless.rb +117 -0
- metadata +69 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Leonid Shevtsov
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Headless
|
2
|
+
|
3
|
+
Headless is a Ruby interface for Xvfb. It allows you to create a headless display straight from Ruby code, hiding some low-level action.
|
4
|
+
|
5
|
+
I created it so I can run Selenium tests in Cucumber without any shell scripting. Even more, you can go headless only when you run tests against Selenium.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
On Debian/Ubuntu:
|
10
|
+
|
11
|
+
sudo apt-get install xvfb
|
12
|
+
gem install headless
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
Block mode:
|
17
|
+
|
18
|
+
require 'rubygems'
|
19
|
+
require 'headless'
|
20
|
+
require 'selenium-webdriver'
|
21
|
+
|
22
|
+
Headless.ly do
|
23
|
+
driver = Selenium::WebDriver.for :firefox
|
24
|
+
driver.navigate.to 'http://google.com'
|
25
|
+
puts driver.title
|
26
|
+
end
|
27
|
+
|
28
|
+
Object mode:
|
29
|
+
|
30
|
+
require 'rubygems'
|
31
|
+
require 'headless'
|
32
|
+
require 'selenium-webdriver'
|
33
|
+
|
34
|
+
headless = Headless.new
|
35
|
+
headless.start
|
36
|
+
|
37
|
+
driver = Selenium::WebDriver.for :firefox
|
38
|
+
driver.navigate.to 'http://google.com'
|
39
|
+
puts driver.title
|
40
|
+
|
41
|
+
headless.destroy
|
42
|
+
|
43
|
+
## Cucumber
|
44
|
+
|
45
|
+
Running cucumber headless is now as simple as adding a before and after hook in `features/support/env.rb`:
|
46
|
+
|
47
|
+
|
48
|
+
# change the condition to fit your setup
|
49
|
+
if Capybara.current_driver == :selenium
|
50
|
+
require 'headless'
|
51
|
+
|
52
|
+
headless = Headless.new
|
53
|
+
headless.start
|
54
|
+
|
55
|
+
at_exit do
|
56
|
+
headless.destroy
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
---
|
61
|
+
|
62
|
+
© 2010 Leonid Shevtsov, released under the MIT license
|
data/lib/headless.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# A class incapsulating the creation and usage of a headless X server
|
2
|
+
#
|
3
|
+
# == Prerequisites
|
4
|
+
#
|
5
|
+
# * X Window System
|
6
|
+
# * Xvfb[http://en.wikipedia.org/wiki/Xvfb]
|
7
|
+
#
|
8
|
+
# == Usage
|
9
|
+
#
|
10
|
+
# Block mode:
|
11
|
+
#
|
12
|
+
# require 'rubygems'
|
13
|
+
# require 'headless'
|
14
|
+
# require 'selenium-webdriver'
|
15
|
+
#
|
16
|
+
# Headless.ly do
|
17
|
+
# driver = Selenium::WebDriver.for :firefox
|
18
|
+
# driver.navigate.to 'http://google.com'
|
19
|
+
# puts driver.title
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Object mode:
|
23
|
+
#
|
24
|
+
# require 'rubygems'
|
25
|
+
# require 'headless'
|
26
|
+
# require 'selenium-webdriver'
|
27
|
+
#
|
28
|
+
# headless = Headless.new
|
29
|
+
# headless.start
|
30
|
+
#
|
31
|
+
# driver = Selenium::WebDriver.for :firefox
|
32
|
+
# driver.navigate.to 'http://google.com'
|
33
|
+
# puts driver.title
|
34
|
+
#
|
35
|
+
# headless.destroy
|
36
|
+
#--
|
37
|
+
# TODO test that reuse actually works with an existing xvfb session
|
38
|
+
# TODO maybe write a command-line wrapper like
|
39
|
+
# headlessly firefox
|
40
|
+
#++
|
41
|
+
class Headless
|
42
|
+
|
43
|
+
class Exception < ::Exception
|
44
|
+
end
|
45
|
+
|
46
|
+
# The display number
|
47
|
+
attr_reader :display
|
48
|
+
|
49
|
+
# Creates a new headless server, but NOT switches to it immediately. Call #start for that
|
50
|
+
def initialize(options = {})
|
51
|
+
@xvfb = `which Xvfb`.strip
|
52
|
+
raise Exception.new('Xvfb not found on your system') if @xvfb == ''
|
53
|
+
|
54
|
+
# TODO more options, like display dimensions and depth; set up default dimensions and depth
|
55
|
+
@display = options.fetch(:display, 99).to_i
|
56
|
+
@reuse_display = options.fetch(:reuse, true)
|
57
|
+
|
58
|
+
#TODO more logic here, autopicking the display number
|
59
|
+
if @reuse_display
|
60
|
+
launch_xvfb unless read_pid
|
61
|
+
elsif read_pid
|
62
|
+
raise Exception.neW("Display :#{display} is already taken and reuse=false")
|
63
|
+
else
|
64
|
+
launch_xvfb
|
65
|
+
end
|
66
|
+
|
67
|
+
raise Exception.new("Xvfb did not launch - something's wrong") unless read_pid
|
68
|
+
end
|
69
|
+
|
70
|
+
# Switches to the headless server
|
71
|
+
def start
|
72
|
+
@old_display = ENV['DISPLAY']
|
73
|
+
ENV['DISPLAY'] = ":#{display}"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Switches back from the headless server
|
77
|
+
def stop
|
78
|
+
ENV['DISPLAY'] = @old_display
|
79
|
+
end
|
80
|
+
|
81
|
+
# Switches back from the headless server and terminates the headless session
|
82
|
+
def destroy
|
83
|
+
stop
|
84
|
+
Process.kill('TERM', xvfb_pid) if read_pid
|
85
|
+
end
|
86
|
+
|
87
|
+
# Block syntax:
|
88
|
+
#
|
89
|
+
# Headless.run do
|
90
|
+
# # perform operations in headless mode
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# Alias: #ly (Headless.ly)
|
94
|
+
def self.run(options={}, &block)
|
95
|
+
headless = Headless.new(options)
|
96
|
+
headless.start
|
97
|
+
yield headless
|
98
|
+
headless.destroy
|
99
|
+
end
|
100
|
+
|
101
|
+
class <<self; alias_method :ly, :run; end
|
102
|
+
|
103
|
+
private
|
104
|
+
attr_reader :xvfb_pid
|
105
|
+
|
106
|
+
def launch_xvfb
|
107
|
+
system "#{@xvfb} :#{display} -ac >/dev/null 2>&1 &"
|
108
|
+
sleep 1
|
109
|
+
end
|
110
|
+
|
111
|
+
def read_pid
|
112
|
+
@xvfb_pid=(File.read("/tmp/.X#{display}-lock") rescue "").strip.to_i
|
113
|
+
@xvfb_pid=nil if @xvfb_pid==0
|
114
|
+
@xvfb_pid
|
115
|
+
#TODO maybe check that the process still exists
|
116
|
+
end
|
117
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: headless
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Leonid Shevtsov
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-06 00:00:00 +03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: " Headless is a Ruby interface for Xvfb. It allows you to create a headless display straight from Ruby code, hiding some low-level action.\n"
|
23
|
+
email: leonid@shevtsov.me
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- lib/headless.rb
|
32
|
+
- README.md
|
33
|
+
- LICENSE
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/leonid-shevtsov/headless
|
36
|
+
licenses: []
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
hash: 3
|
49
|
+
segments:
|
50
|
+
- 0
|
51
|
+
version: "0"
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
requirements:
|
62
|
+
- Xvfb
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.3.7
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: Ruby headless display interface
|
68
|
+
test_files: []
|
69
|
+
|