headless 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +5 -0
- data/README.md +67 -54
- data/headless.gemspec +1 -1
- data/lib/headless.rb +1 -1
- data/lib/headless/video/video_recorder.rb +1 -1
- data/spec/headless_spec.rb +10 -10
- data/spec/video_recorder_spec.rb +7 -7
- metadata +15 -29
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ecdab81182658752d292ec13079deae78ed26241
|
4
|
+
data.tar.gz: 2f61437e9fe159aa2160e45263f731e20a43ffb8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ca8f638bd43c1ddbda26171974b2c4bd11e0508d5c973c5ce35553658e8e647df8bb9027fa62e31c00fde382bf8f87ebd352d762904e3bddefc653169b8b5731
|
7
|
+
data.tar.gz: af8d46f3c14dbc2d0f8bea5bdfc04e7b2e917f878ac208abcf91f30c3bbc5f66582540c488b8a89b97f76527f4da0e825e0a6d6e6af715160d78b3ad4d7283a2
|
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -16,71 +16,75 @@ Documentation is available at [rdoc.info](http://rdoc.info/projects/leonid-shevt
|
|
16
16
|
|
17
17
|
On Debian/Ubuntu:
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
```sh
|
20
|
+
sudo apt-get install xvfb
|
21
|
+
gem install headless
|
22
|
+
```
|
21
23
|
|
22
24
|
## Usage
|
23
25
|
|
24
26
|
Block mode:
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
```ruby
|
29
|
+
require 'rubygems'
|
30
|
+
require 'headless'
|
31
|
+
require 'selenium-webdriver'
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
Headless.ly do
|
34
|
+
driver = Selenium::WebDriver.for :firefox
|
35
|
+
driver.navigate.to 'http://google.com'
|
36
|
+
puts driver.title
|
37
|
+
end
|
38
|
+
```
|
35
39
|
|
36
40
|
Object mode:
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
|
42
|
+
```ruby
|
43
|
+
require 'rubygems'
|
44
|
+
require 'headless'
|
45
|
+
require 'selenium-webdriver'
|
41
46
|
|
42
|
-
|
43
|
-
|
47
|
+
headless = Headless.new
|
48
|
+
headless.start
|
44
49
|
|
45
|
-
|
46
|
-
|
47
|
-
|
50
|
+
driver = Selenium::WebDriver.for :firefox
|
51
|
+
driver.navigate.to 'http://google.com'
|
52
|
+
puts driver.title
|
48
53
|
|
49
|
-
|
54
|
+
headless.destroy
|
55
|
+
```
|
50
56
|
|
51
57
|
## Cucumber
|
52
58
|
|
53
59
|
Running cucumber headless is now as simple as adding a before and after hook in `features/support/env.rb`:
|
54
60
|
|
61
|
+
```ruby
|
62
|
+
# change the condition to fit your setup
|
63
|
+
if Capybara.current_driver == :selenium
|
64
|
+
require 'headless'
|
55
65
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
headless = Headless.new
|
61
|
-
headless.start
|
62
|
-
end
|
66
|
+
headless = Headless.new
|
67
|
+
headless.start
|
68
|
+
end
|
69
|
+
```
|
63
70
|
|
64
71
|
## Running tests in parallel
|
65
72
|
|
66
73
|
If you have multiple threads running acceptance tests in parallel, you want to spawn Headless before forking, and then reuse that instance with `destroy_at_exit: false`.
|
67
74
|
You can even spawn a Headless instance in one ruby script, and then reuse the same instance in other scripts by specifying the same display number and `reuse: true`.
|
68
75
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
# test_suite_that_could_be_ran_multiple_times.rb
|
74
|
-
headless = Headless.new(display: 100, reuse: true, destroy_at_exit: false)
|
75
|
-
# Xvfb is already started by the first script
|
76
|
-
|
77
|
-
# reap_headless.rb
|
78
|
-
headless = Headless.new(display: 100, reuse: true)
|
79
|
-
headless.destroy
|
80
|
-
|
76
|
+
```ruby
|
77
|
+
# spawn_headless.rb
|
78
|
+
Headless.new(display: 100, destroy_at_exit: false).start
|
81
79
|
|
80
|
+
# test_suite_that_could_be_ran_multiple_times.rb
|
81
|
+
Headless.new(display: 100, reuse: true, destroy_at_exit: false).start
|
82
82
|
|
83
|
-
|
83
|
+
# reap_headless.rb
|
84
|
+
headless = Headless.new(display: 100, reuse: true)
|
85
|
+
headless.destroy
|
86
|
+
```
|
87
|
+
|
84
88
|
|
85
89
|
## Cucumber with wkhtmltopdf
|
86
90
|
|
@@ -88,29 +92,33 @@ _Note: this is true for other programs which may use headless at the same time a
|
|
88
92
|
|
89
93
|
When wkhtmltopdf is using Headless, and cucumber is invoking a block of code which uses a headless session, make sure to override the default display of cucumber to retain browser focus. Assuming wkhtmltopdf is using the default display of 99, make sure to set the display to a value != 99 in `features/support/env.rb` file. This may be the cause of `Connection refused - connect(2) (Errno::ECONNREFUSED)`.
|
90
94
|
|
91
|
-
|
92
|
-
|
95
|
+
```ruby
|
96
|
+
headless = Headless.new(:display => '100')
|
97
|
+
headless.start
|
98
|
+
```
|
93
99
|
|
94
100
|
## Capturing video
|
95
101
|
|
96
102
|
Video is captured using `ffmpeg`. You can install it on Debian/Ubuntu via `sudo apt-get install ffmpeg` or on OS X via `brew install ffmpeg`. You can capture video continuously or capture scenarios separately. Here is typical use case:
|
97
103
|
|
98
|
-
|
104
|
+
```ruby
|
105
|
+
require 'headless'
|
99
106
|
|
100
|
-
|
101
|
-
|
107
|
+
headless = Headless.new
|
108
|
+
headless.start
|
102
109
|
|
103
|
-
|
104
|
-
|
105
|
-
|
110
|
+
Before do
|
111
|
+
headless.video.start_capture
|
112
|
+
end
|
106
113
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
+
After do |scenario|
|
115
|
+
if scenario.failed?
|
116
|
+
headless.video.stop_and_save("/tmp/#{BUILD_ID}/#{scenario.name.split.join("_")}.mov")
|
117
|
+
else
|
118
|
+
headless.video.stop_and_discard
|
119
|
+
end
|
120
|
+
end
|
121
|
+
```
|
114
122
|
|
115
123
|
## Taking screenshots
|
116
124
|
|
@@ -123,3 +131,8 @@ Images are captured using `import` utility which is part of `imagemagick` librar
|
|
123
131
|
---
|
124
132
|
|
125
133
|
© 2011 Leonid Shevtsov, released under the MIT license
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/leonid-shevtsov/headless/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
138
|
+
|
data/headless.gemspec
CHANGED
data/lib/headless.rb
CHANGED
@@ -8,7 +8,7 @@ class Headless
|
|
8
8
|
CliUtil.ensure_application_exists!('ffmpeg', 'Ffmpeg not found on your system. Install it with sudo apt-get install ffmpeg')
|
9
9
|
|
10
10
|
@display = display
|
11
|
-
@dimensions = dimensions
|
11
|
+
@dimensions = dimensions[/.+(?=x)/]
|
12
12
|
|
13
13
|
@pid_file_path = options.fetch(:pid_file_path, "/tmp/.headless_ffmpeg_#{@display}.pid")
|
14
14
|
@tmp_file_path = options.fetch(:tmp_file_path, "/tmp/.headless_ffmpeg_#{@display}.mov")
|
data/spec/headless_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Headless do
|
|
9
9
|
context "instantiation" do
|
10
10
|
context "when Xvfb is not installed" do
|
11
11
|
before do
|
12
|
-
Headless::CliUtil.stub
|
12
|
+
Headless::CliUtil.stub(:application_exists?).and_return(false)
|
13
13
|
end
|
14
14
|
|
15
15
|
it "raises an error" do
|
@@ -33,8 +33,8 @@ describe Headless do
|
|
33
33
|
|
34
34
|
context "when Xvfb is already running" do
|
35
35
|
before do
|
36
|
-
Headless::CliUtil.stub
|
37
|
-
Headless::CliUtil.stub
|
36
|
+
Headless::CliUtil.stub(:read_pid).with('/tmp/.X99-lock').and_return(31337)
|
37
|
+
Headless::CliUtil.stub(:read_pid).with('/tmp/.X100-lock').and_return(nil)
|
38
38
|
end
|
39
39
|
|
40
40
|
context "and display reuse is allowed" do
|
@@ -72,8 +72,8 @@ describe Headless do
|
|
72
72
|
|
73
73
|
context 'when Xvfb is started, but by another user' do
|
74
74
|
before do
|
75
|
-
Headless::CliUtil.stub
|
76
|
-
Headless::CliUtil.stub
|
75
|
+
Headless::CliUtil.stub(:read_pid).with('/tmp/.X99-lock') { raise Errno::EPERM }
|
76
|
+
Headless::CliUtil.stub(:read_pid).with('/tmp/.X100-lock').and_return(nil)
|
77
77
|
end
|
78
78
|
|
79
79
|
context "and display autopicking is not allowed" do
|
@@ -116,7 +116,7 @@ describe Headless do
|
|
116
116
|
|
117
117
|
describe "#destroy" do
|
118
118
|
before do
|
119
|
-
Headless::CliUtil.stub
|
119
|
+
Headless::CliUtil.stub(:read_pid).and_return(4444)
|
120
120
|
end
|
121
121
|
|
122
122
|
it "switches back from the headless server and terminates the headless session" do
|
@@ -148,7 +148,7 @@ describe Headless do
|
|
148
148
|
let(:headless) { Headless.new }
|
149
149
|
|
150
150
|
it "raises an error if imagemagick is not installed" do
|
151
|
-
Headless::CliUtil.stub
|
151
|
+
Headless::CliUtil.stub(:application_exists?).and_return(false)
|
152
152
|
|
153
153
|
lambda { headless.take_screenshot }.should raise_error(Headless::Exception)
|
154
154
|
end
|
@@ -165,9 +165,9 @@ describe Headless do
|
|
165
165
|
private
|
166
166
|
|
167
167
|
def stub_environment
|
168
|
-
Headless::CliUtil.stub
|
169
|
-
Headless::CliUtil.stub
|
170
|
-
Headless::CliUtil.stub
|
168
|
+
Headless::CliUtil.stub(:application_exists?).and_return(true)
|
169
|
+
Headless::CliUtil.stub(:read_pid).and_return(nil)
|
170
|
+
Headless::CliUtil.stub(:path_to).and_return("/usr/bin/Xvfb")
|
171
171
|
|
172
172
|
# TODO this is wrong. But, as long as Xvfb is started inside the constructor (which is also wrong), I don't see another option to make tests pass
|
173
173
|
Headless.any_instance.stub(:ensure_xvfb_is_running).and_return(true)
|
data/spec/video_recorder_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe Headless::VideoRecorder do
|
|
7
7
|
|
8
8
|
describe "instantiation" do
|
9
9
|
before do
|
10
|
-
Headless::CliUtil.stub
|
10
|
+
Headless::CliUtil.stub(:application_exists?).and_return(false)
|
11
11
|
end
|
12
12
|
|
13
13
|
it "throws an error if ffmpeg is not installed" do
|
@@ -17,16 +17,16 @@ describe Headless::VideoRecorder do
|
|
17
17
|
|
18
18
|
describe "#capture" do
|
19
19
|
it "starts ffmpeg" do
|
20
|
-
Headless::CliUtil.stub(:path_to
|
21
|
-
Headless::CliUtil.should_receive(:fork_process).with(/ffmpeg -y -r 30 -g 600 -s
|
20
|
+
Headless::CliUtil.stub(:path_to).and_return('ffmpeg')
|
21
|
+
Headless::CliUtil.should_receive(:fork_process).with(/ffmpeg -y -r 30 -g 600 -s 1024x768 -f x11grab -i :99 -vcodec qtrle/, "/tmp/.headless_ffmpeg_99.pid", '/dev/null')
|
22
22
|
|
23
23
|
recorder = Headless::VideoRecorder.new(99, "1024x768x32")
|
24
24
|
recorder.start_capture
|
25
25
|
end
|
26
26
|
|
27
27
|
it "starts ffmpeg with specified codec" do
|
28
|
-
Headless::CliUtil.stub(:path_to
|
29
|
-
Headless::CliUtil.should_receive(:fork_process).with(/ffmpeg -y -r 30 -g 600 -s
|
28
|
+
Headless::CliUtil.stub(:path_to).and_return('ffmpeg')
|
29
|
+
Headless::CliUtil.should_receive(:fork_process).with(/ffmpeg -y -r 30 -g 600 -s 1024x768 -f x11grab -i :99 -vcodec libvpx/, "/tmp/.headless_ffmpeg_99.pid", '/dev/null')
|
30
30
|
|
31
31
|
recorder = Headless::VideoRecorder.new(99, "1024x768x32", {:codec => 'libvpx'})
|
32
32
|
recorder.start_capture
|
@@ -67,7 +67,7 @@ describe Headless::VideoRecorder do
|
|
67
67
|
private
|
68
68
|
|
69
69
|
def stub_environment
|
70
|
-
Headless::CliUtil.stub
|
71
|
-
Headless::CliUtil.stub
|
70
|
+
Headless::CliUtil.stub(:application_exists?).and_return(true)
|
71
|
+
Headless::CliUtil.stub(:fork_process).and_return(true)
|
72
72
|
end
|
73
73
|
end
|
metadata
CHANGED
@@ -1,59 +1,52 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: headless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Leonid Shevtsov
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-06-03 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rspec
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- - ~>
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '2.6'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- - ~>
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '2.6'
|
46
|
-
description:
|
47
|
-
|
48
|
-
|
49
|
-
'
|
41
|
+
description: |2
|
42
|
+
Headless is a Ruby interface for Xvfb. It allows you to create a headless display straight from Ruby code, hiding some low-level action.
|
50
43
|
email: leonid@shevtsov.me
|
51
44
|
executables: []
|
52
45
|
extensions: []
|
53
46
|
extra_rdoc_files: []
|
54
47
|
files:
|
55
|
-
- .gitignore
|
56
|
-
- .travis.yml
|
48
|
+
- ".gitignore"
|
49
|
+
- ".travis.yml"
|
57
50
|
- CHANGELOG
|
58
51
|
- Gemfile
|
59
52
|
- LICENSE
|
@@ -67,33 +60,26 @@ files:
|
|
67
60
|
- spec/video_recorder_spec.rb
|
68
61
|
homepage: http://leonid.shevtsov.me/en/headless
|
69
62
|
licenses: []
|
63
|
+
metadata: {}
|
70
64
|
post_install_message:
|
71
65
|
rdoc_options: []
|
72
66
|
require_paths:
|
73
67
|
- lib
|
74
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
69
|
requirements:
|
77
|
-
- -
|
70
|
+
- - ">="
|
78
71
|
- !ruby/object:Gem::Version
|
79
72
|
version: '0'
|
80
|
-
segments:
|
81
|
-
- 0
|
82
|
-
hash: -3030427348639260588
|
83
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
-
none: false
|
85
74
|
requirements:
|
86
|
-
- -
|
75
|
+
- - ">="
|
87
76
|
- !ruby/object:Gem::Version
|
88
77
|
version: '0'
|
89
|
-
segments:
|
90
|
-
- 0
|
91
|
-
hash: -3030427348639260588
|
92
78
|
requirements:
|
93
79
|
- Xvfb
|
94
80
|
rubyforge_project:
|
95
|
-
rubygems_version:
|
81
|
+
rubygems_version: 2.2.2
|
96
82
|
signing_key:
|
97
|
-
specification_version:
|
83
|
+
specification_version: 4
|
98
84
|
summary: Ruby headless display interface
|
99
85
|
test_files: []
|