headless 2.3.1 → 3.0.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/lib/headless.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'headless/cli_util'
2
- require 'headless/video/video_recorder'
1
+ require "headless/cli_util"
2
+ require "headless/video/video_recorder"
3
3
 
4
4
  # A class incapsulating the creation and usage of a headless X server
5
5
  #
@@ -40,10 +40,9 @@ require 'headless/video/video_recorder'
40
40
  # TODO test that reuse actually works with an existing xvfb session
41
41
  #++
42
42
  class Headless
43
-
44
43
  DEFAULT_DISPLAY_NUMBER = 99
45
44
  MAX_DISPLAY_NUMBER = 10_000
46
- DEFAULT_DISPLAY_DIMENSIONS = '1280x1024x24'
45
+ DEFAULT_DISPLAY_DIMENSIONS = "1280x1024x24"
47
46
  DEFAULT_XVFB_LAUNCH_TIMEOUT = 10
48
47
 
49
48
  class Exception < RuntimeError
@@ -73,9 +72,10 @@ class Headless
73
72
  # (default true unless reuse is true and a server is already running)
74
73
  # * +xvfb_launch_timeout+ - how long should we wait for Xvfb to open a
75
74
  # display, before assuming that it is frozen (in seconds, default is 10)
76
- # * +video+ - options to be passed to the ffmpeg video recorder. See Headless::VideoRecorder#initialize for documentation
75
+ # * +video+ - options to be passed to the ffmpeg video recorder.
76
+ # See Headless::VideoRecorder#initialize for documentation
77
77
  def initialize(options = {})
78
- CliUtil.ensure_application_exists!('Xvfb', 'Xvfb not found on your system')
78
+ CliUtil.ensure_application_exists!("Xvfb", "Xvfb not found on your system")
79
79
 
80
80
  @display = options.fetch(:display, DEFAULT_DISPLAY_NUMBER).to_i
81
81
  @xvfb_launch_timeout = options.fetch(:xvfb_launch_timeout, DEFAULT_XVFB_LAUNCH_TIMEOUT).to_i
@@ -83,8 +83,14 @@ class Headless
83
83
  @reuse_display = options.fetch(:reuse, true)
84
84
  @dimensions = options.fetch(:dimensions, DEFAULT_DISPLAY_DIMENSIONS)
85
85
  @video_capture_options = options.fetch(:video, {})
86
+ @extensions = options.fetch(:extensions, [])
87
+ @extensions = [@extensions] unless @extensions.is_a? Array
86
88
 
87
- already_running = xvfb_running? rescue false
89
+ already_running = begin
90
+ xvfb_running?
91
+ rescue
92
+ false
93
+ end
88
94
  @destroy_at_exit = options.fetch(:destroy_at_exit, !(@reuse_display && already_running))
89
95
 
90
96
  @pid = nil # the pid of the running Xvfb process
@@ -95,14 +101,14 @@ class Headless
95
101
 
96
102
  # Switches to the headless server
97
103
  def start
98
- @old_display = ENV['DISPLAY']
99
- ENV['DISPLAY'] = ":#{display}"
104
+ @old_display = ENV["DISPLAY"]
105
+ ENV["DISPLAY"] = ":#{display}"
100
106
  hook_at_exit
101
107
  end
102
108
 
103
109
  # Switches back from the headless server
104
110
  def stop
105
- ENV['DISPLAY'] = @old_display
111
+ ENV["DISPLAY"] = @old_display
106
112
  end
107
113
 
108
114
  # Switches back from the headless server and terminates the headless session
@@ -137,37 +143,42 @@ class Headless
137
143
  # # perform operations in headless mode
138
144
  # end
139
145
  # See #new for options
140
- def self.run(options={}, &block)
146
+ def self.run(options = {}, &block)
141
147
  headless = Headless.new(options)
142
148
  headless.start
143
149
  yield headless
144
150
  ensure
145
- headless && headless.destroy
151
+ headless&.destroy
146
152
  end
147
- class <<self; alias_method :ly, :run; end
153
+ class << self; alias_method :ly, :run; end
148
154
 
149
155
  def video
150
156
  @video_recorder ||= VideoRecorder.new(display, dimensions, @video_capture_options)
151
157
  end
152
158
 
153
- def take_screenshot(file_path, options={})
159
+ def take_screenshot(file_path, options = {})
154
160
  using = options.fetch(:using, :imagemagick)
155
161
  case using
156
162
  when :imagemagick
157
- CliUtil.ensure_application_exists!('import', "imagemagick is not found on your system. Please install it using sudo apt-get install imagemagick")
158
- system "#{CliUtil.path_to('import')} -display localhost:#{display} -window root #{file_path}"
163
+ CliUtil.ensure_application_exists!("import",
164
+ "imagemagick is not found on your system. " \
165
+ "Please install it using sudo apt-get install imagemagick")
166
+ system "#{CliUtil.path_to("import")} -display :#{display} -window root #{file_path}"
159
167
  when :xwd
160
- CliUtil.ensure_application_exists!('xwd', "xwd is not found on your system. Please install it using sudo apt-get install X11-apps")
161
- system "#{CliUtil.path_to('xwd')} -display localhost:#{display} -silent -root -out #{file_path}"
168
+ CliUtil.ensure_application_exists!("xwd",
169
+ "xwd is not found on your system. " \
170
+ "Please install it using sudo apt-get install X11-apps")
171
+ system "#{CliUtil.path_to("xwd")} -display localhost:#{display} -silent -root -out #{file_path}"
162
172
  when :graphicsmagick, :gm
163
- CliUtil.ensure_application_exists!('gm', "graphicsmagick is not found on your system. Please install it.")
164
- system "#{CliUtil.path_to('gm')} import -display localhost:#{display} -window root #{file_path}"
173
+ CliUtil.ensure_application_exists!("gm", "graphicsmagick is not found on your system. " \
174
+ "Please install it.")
175
+ system "#{CliUtil.path_to("gm")} import -display localhost:#{display} -window root #{file_path}"
165
176
  else
166
- raise Headless::Exception.new('Unknown :using option value')
177
+ raise Headless::Exception.new("Unknown :using option value")
167
178
  end
168
179
  end
169
180
 
170
- private
181
+ private
171
182
 
172
183
  def attach_xvfb
173
184
  possible_display_set = @autopick_display ? @display..MAX_DISPLAY_NUMBER : Array(@display)
@@ -187,26 +198,30 @@ private
187
198
  def launch_xvfb
188
199
  out_pipe, in_pipe = IO.pipe
189
200
  @pid = Process.spawn(
190
- CliUtil.path_to("Xvfb"), ":#{display}", "-screen", "0", dimensions, "-ac",
191
- err: in_pipe)
201
+ CliUtil.path_to("Xvfb"), ":#{display}", "-screen", "0", dimensions, "-ac", *extensions,
202
+ err: in_pipe
203
+ )
192
204
  raise Headless::Exception.new("Xvfb did not launch - something's wrong") unless @pid
205
+
193
206
  # According to docs, you should either wait or detach on spawned procs:
194
207
  Process.detach @pid
195
- return ensure_xvfb_launched(out_pipe)
196
- ensure
197
- in_pipe.close
208
+ ensure_xvfb_launched(out_pipe)
209
+ ensure
210
+ in_pipe.close
198
211
  end
199
212
 
200
213
  def ensure_xvfb_launched(out_pipe)
201
214
  start_time = Time.now
202
215
  errors = ""
203
- begin
216
+ loop do
204
217
  begin
205
218
  errors += out_pipe.read_nonblock(10000)
206
- if errors.include? "Cannot establish any listening sockets"
207
- raise Headless::Exception.new("Display socket is taken but lock file is missing - check the Headless troubleshooting guide")
208
- end
209
- if errors.include? "Server is already active for display #{display}"
219
+ if errors.include? "directory /tmp/.X11-unix will not be created."
220
+ raise Headless::Exception, "/tmp/.X11-unix is missing - check the Headless troubleshooting guide"
221
+ elsif errors.include? "Cannot establish any listening sockets"
222
+ raise Headless::Exception,
223
+ "Display socket is taken but lock file is missing - check the Headless troubleshooting guide"
224
+ elsif errors.include? "Server is already active for display #{display}"
210
225
  # This can happen if there is a race to grab the lock file.
211
226
  # Not an exception, just return false to let pick_available_display choose another:
212
227
  return false
@@ -215,13 +230,16 @@ private
215
230
  # will retry next cycle
216
231
  end
217
232
  sleep 0.01 # to avoid cpu hogging
218
- raise Headless::Exception.new("Xvfb launched but did not complete initialization") if (Time.now-start_time)>=@xvfb_launch_timeout
219
- # Continue looping until Xvfb has written its pidfile:
220
- end while !xvfb_running?
233
+ if (Time.now - start_time) >= @xvfb_launch_timeout
234
+ raise Headless::Exception.new("Xvfb launched but did not complete initialization")
235
+ end
236
+ # Continue looping until Xvfb has written its pidfile:
237
+ break if xvfb_running?
238
+ end
221
239
 
222
240
  # If for any reason the pid file doesn't match ours, we lost the race to
223
241
  # get the file lock:
224
- return @pid == read_xvfb_pid
242
+ @pid == read_xvfb_pid
225
243
  end
226
244
 
227
245
  def xvfb_mine?
@@ -252,4 +270,8 @@ private
252
270
  end
253
271
  end
254
272
  end
273
+
274
+ def extensions
275
+ @extensions.map { |ext| "+" + ext.to_s }
276
+ end
255
277
  end
@@ -1,28 +1,44 @@
1
- require 'headless'
1
+ require "headless"
2
2
 
3
3
  describe Headless do
4
4
  before do
5
- ENV['DISPLAY'] = ":31337"
5
+ ENV["DISPLAY"] = ":31337"
6
6
  stub_environment
7
7
  end
8
8
 
9
- describe 'launch options' do
9
+ describe "launch options" do
10
10
  before do
11
11
  allow_any_instance_of(Headless).to receive(:ensure_xvfb_launched).and_return(true)
12
12
  end
13
13
 
14
14
  it "starts Xvfb" do
15
- expect(Process).to receive(:spawn).with(*(%w(/usr/bin/Xvfb :99 -screen 0 1280x1024x24 -ac)+[hash_including(:err)])).and_return(123)
16
- headless = Headless.new
15
+ expect(Process).to receive(:spawn).with(*(%w[/usr/bin/Xvfb :99 -screen 0 1280x1024x24
16
+ -ac] + [hash_including(:err)])).and_return(123)
17
+ Headless.new
17
18
  end
18
19
 
19
20
  it "allows setting screen dimensions" do
20
- expect(Process).to receive(:spawn).with(*(%w(/usr/bin/Xvfb :99 -screen 0 1024x768x16 -ac)+[hash_including(:err)])).and_return(123)
21
- headless = Headless.new(:dimensions => "1024x768x16")
21
+ expect(Process).to receive(:spawn).with(*(%w[/usr/bin/Xvfb :99 -screen 0 1024x768x16
22
+ -ac] + [hash_including(:err)])).and_return(123)
23
+ Headless.new(dimensions: "1024x768x16")
24
+ end
25
+
26
+ it "allows to enable extensions", focus: true do
27
+ expect(Process).to receive(:spawn).with(*(%w[/usr/bin/Xvfb :99 -screen 0 1280x1024x24 -ac
28
+ +iglx] + [hash_including(:err)])).and_return(123)
29
+ Headless.new(extensions: [:iglx])
30
+
31
+ expect(Process).to receive(:spawn).with(*(%w[/usr/bin/Xvfb :99 -screen 0 1280x1024x24 -ac
32
+ +iglx] + [hash_including(:err)])).and_return(123)
33
+ Headless.new(extensions: "iglx")
34
+
35
+ expect(Process).to receive(:spawn).with(*(%w[/usr/bin/Xvfb :99 -screen 0 1280x1024x24 -ac +iglx
36
+ +dummy] + [hash_including(:err)])).and_return(123)
37
+ Headless.new(extensions: ["iglx", :dummy])
22
38
  end
23
39
  end
24
40
 
25
- context 'with stubbed launch_xvfb' do
41
+ context "with stubbed launch_xvfb" do
26
42
  before do
27
43
  allow_any_instance_of(Headless).to receive(:launch_xvfb).and_return(true)
28
44
  end
@@ -40,15 +56,15 @@ describe Headless do
40
56
 
41
57
  context "when Xvfb is already running and was started by this user" do
42
58
  before do
43
- allow(Headless::CliUtil).to receive(:read_pid).with('/tmp/.X99-lock').and_return(31337)
59
+ allow(Headless::CliUtil).to receive(:read_pid).with("/tmp/.X99-lock").and_return(31337)
44
60
  allow(Headless::CliUtil).to receive(:process_running?).with(31337).and_return(true)
45
61
  allow(Headless::CliUtil).to receive(:process_mine?).with(31337).and_return(true)
46
62
 
47
- allow(Headless::CliUtil).to receive(:read_pid).with('/tmp/.X100-lock').and_return(nil)
63
+ allow(Headless::CliUtil).to receive(:read_pid).with("/tmp/.X100-lock").and_return(nil)
48
64
  end
49
65
 
50
66
  context "and display reuse is allowed" do
51
- let(:options) { {:reuse => true} }
67
+ let(:options) { {reuse: true} }
52
68
 
53
69
  it "should reuse the existing Xvfb" do
54
70
  expect(Headless.new(options).display).to eq 99
@@ -60,21 +76,21 @@ describe Headless do
60
76
  end
61
77
 
62
78
  context "and display reuse is not allowed" do
63
- let(:options) { {:reuse => false} }
79
+ let(:options) { {reuse: false} }
64
80
 
65
81
  it "should pick the next available display number" do
66
82
  expect(Headless.new(options).display).to eq 100
67
83
  end
68
84
 
69
85
  context "and display number is explicitly set" do
70
- let(:options) { {:reuse => false, :display => 99} }
86
+ let(:options) { {reuse: false, display: 99} }
71
87
 
72
88
  it "should fail with an exception" do
73
89
  expect { Headless.new(options) }.to raise_error(Headless::Exception)
74
90
  end
75
91
 
76
92
  context "and autopicking is allowed" do
77
- let(:options) { {:reuse => false, :display => 99, :autopick => true} }
93
+ let(:options) { {reuse: false, display: 99, autopick: true} }
78
94
 
79
95
  it "should pick the next available display number" do
80
96
  expect(Headless.new(options).display).to eq 100
@@ -84,17 +100,17 @@ describe Headless do
84
100
  end
85
101
  end
86
102
 
87
- context 'when Xvfb is started, but by another user' do
103
+ context "when Xvfb is started, but by another user" do
88
104
  before do
89
- allow(Headless::CliUtil).to receive(:read_pid).with('/tmp/.X99-lock').and_return(31337)
105
+ allow(Headless::CliUtil).to receive(:read_pid).with("/tmp/.X99-lock").and_return(31337)
90
106
  allow(Headless::CliUtil).to receive(:process_running?).with(31337).and_return(true)
91
107
  allow(Headless::CliUtil).to receive(:process_mine?).with(31337).and_return(false)
92
108
 
93
- allow(Headless::CliUtil).to receive(:read_pid).with('/tmp/.X100-lock').and_return(nil)
109
+ allow(Headless::CliUtil).to receive(:read_pid).with("/tmp/.X100-lock").and_return(nil)
94
110
  end
95
111
 
96
112
  context "and display autopicking is not allowed" do
97
- let(:options) { {:autopick => false} }
113
+ let(:options) { {autopick: false} }
98
114
 
99
115
  it "should reuse the display" do
100
116
  expect(Headless.new(options).display).to eq 99
@@ -102,7 +118,7 @@ describe Headless do
102
118
  end
103
119
 
104
120
  context "and display autopicking is allowed" do
105
- let(:options) { {:autopick => true} }
121
+ let(:options) { {autopick: true} }
106
122
 
107
123
  it "should pick the next display number" do
108
124
  expect(Headless.new(options).display).to eq 100
@@ -115,19 +131,19 @@ describe Headless do
115
131
  let(:headless) { Headless.new }
116
132
  describe "#start" do
117
133
  it "switches to the headless server" do
118
- expect(ENV['DISPLAY']).to eq ":31337"
134
+ expect(ENV["DISPLAY"]).to eq ":31337"
119
135
  headless.start
120
- expect(ENV['DISPLAY']).to eq ":99"
136
+ expect(ENV["DISPLAY"]).to eq ":99"
121
137
  end
122
138
  end
123
139
 
124
140
  describe "#stop" do
125
141
  it "switches back from the headless server" do
126
- expect(ENV['DISPLAY']).to eq ":31337"
142
+ expect(ENV["DISPLAY"]).to eq ":31337"
127
143
  headless.start
128
- expect(ENV['DISPLAY']).to eq ":99"
144
+ expect(ENV["DISPLAY"]).to eq ":99"
129
145
  headless.stop
130
- expect(ENV['DISPLAY']).to eq ":31337"
146
+ expect(ENV["DISPLAY"]).to eq ":31337"
131
147
  end
132
148
  end
133
149
 
@@ -137,13 +153,13 @@ describe Headless do
137
153
  end
138
154
 
139
155
  it "switches back from the headless server and terminates the headless session" do
140
- expect(Process).to receive(:kill).with('TERM', 4444)
156
+ expect(Process).to receive(:kill).with("TERM", 4444)
141
157
 
142
- expect(ENV['DISPLAY']).to eq ":31337"
158
+ expect(ENV["DISPLAY"]).to eq ":31337"
143
159
  headless.start
144
- expect(ENV['DISPLAY']).to eq ":99"
160
+ expect(ENV["DISPLAY"]).to eq ":99"
145
161
  headless.destroy
146
- expect(ENV['DISPLAY']).to eq ":31337"
162
+ expect(ENV["DISPLAY"]).to eq ":31337"
147
163
  end
148
164
  end
149
165
  end
@@ -165,72 +181,72 @@ describe Headless do
165
181
  let(:headless) { Headless.new }
166
182
 
167
183
  it "raises an error if unknown value for option :using is used" do
168
- expect { headless.take_screenshot('a.png', :using => :teleportation) }.to raise_error(Headless::Exception)
184
+ expect { headless.take_screenshot("a.png", using: :teleportation) }.to raise_error(Headless::Exception)
169
185
  end
170
186
 
171
187
  it "raises an error if imagemagick is not installed, with default options" do
172
- allow(Headless::CliUtil).to receive(:application_exists?).with('import').and_return(false)
188
+ allow(Headless::CliUtil).to receive(:application_exists?).with("import").and_return(false)
173
189
 
174
- expect { headless.take_screenshot('a.png') }.to raise_error(Headless::Exception)
190
+ expect { headless.take_screenshot("a.png") }.to raise_error(Headless::Exception)
175
191
  end
176
192
 
177
193
  it "raises an error if imagemagick is not installed, with using: :imagemagick" do
178
- allow(Headless::CliUtil).to receive(:application_exists?).with('import').and_return(false)
194
+ allow(Headless::CliUtil).to receive(:application_exists?).with("import").and_return(false)
179
195
 
180
- expect { headless.take_screenshot('a.png', :using => :imagemagick) }.to raise_error(Headless::Exception)
196
+ expect { headless.take_screenshot("a.png", using: :imagemagick) }.to raise_error(Headless::Exception)
181
197
  end
182
198
 
183
199
  it "raises an error if xwd is not installed, with using: :xwd" do
184
- allow(Headless::CliUtil).to receive(:application_exists?).with('xwd').and_return(false)
200
+ allow(Headless::CliUtil).to receive(:application_exists?).with("xwd").and_return(false)
185
201
 
186
- expect { headless.take_screenshot('a.png', :using => :xwd) }.to raise_error(Headless::Exception)
202
+ expect { headless.take_screenshot("a.png", using: :xwd) }.to raise_error(Headless::Exception)
187
203
  end
188
204
 
189
205
  it "raises an error if gm is not installed with using: :graphicsmagick" do
190
- allow(Headless::CliUtil).to receive(:application_exists?).with('gm').and_return(false)
206
+ allow(Headless::CliUtil).to receive(:application_exists?).with("gm").and_return(false)
191
207
 
192
- expect { headless.take_screenshot('a.png', :using => :graphicsmagick) }.to raise_error(Headless::Exception)
208
+ expect { headless.take_screenshot("a.png", using: :graphicsmagick) }.to raise_error(Headless::Exception)
193
209
  end
194
210
 
195
211
  it "raises an error if gm is not installed with using: :gm" do
196
- allow(Headless::CliUtil).to receive(:application_exists?).with('gm').and_return(false)
212
+ allow(Headless::CliUtil).to receive(:application_exists?).with("gm").and_return(false)
197
213
 
198
- expect { headless.take_screenshot('a.png', :using => :gm) }.to raise_error(Headless::Exception)
214
+ expect { headless.take_screenshot("a.png", using: :gm) }.to raise_error(Headless::Exception)
199
215
  end
200
216
 
201
217
  it "issues command to take screenshot, with default options" do
202
- allow(Headless::CliUtil).to receive(:path_to).with('import').and_return('path/import')
203
- expect(headless).to receive(:system).with("path/import -display localhost:99 -window root /tmp/image.png")
218
+ allow(Headless::CliUtil).to receive(:path_to).with("import").and_return("path/import")
219
+ expect(headless).to receive(:system).with("path/import -display :99 -window root /tmp/image.png")
204
220
  headless.take_screenshot("/tmp/image.png")
205
221
  end
206
222
 
207
223
  it "issues command to take screenshot, with using: :imagemagick" do
208
- allow(Headless::CliUtil).to receive(:path_to).with('import').and_return('path/import')
209
- expect(headless).to receive(:system).with("path/import -display localhost:99 -window root /tmp/image.png")
210
- headless.take_screenshot("/tmp/image.png", :using => :imagemagick)
224
+ allow(Headless::CliUtil).to receive(:path_to).with("import").and_return("path/import")
225
+ expect(headless).to receive(:system).with("path/import -display :99 -window root /tmp/image.png")
226
+ headless.take_screenshot("/tmp/image.png", using: :imagemagick)
211
227
  end
212
228
 
213
229
  it "issues command to take screenshot, with using: :xwd" do
214
- allow(Headless::CliUtil).to receive(:path_to).with('xwd').and_return('path/xwd')
230
+ allow(Headless::CliUtil).to receive(:path_to).with("xwd").and_return("path/xwd")
215
231
  expect(headless).to receive(:system).with("path/xwd -display localhost:99 -silent -root -out /tmp/image.png")
216
- headless.take_screenshot("/tmp/image.png", :using => :xwd)
232
+ headless.take_screenshot("/tmp/image.png", using: :xwd)
217
233
  end
218
234
 
219
235
  it "issues command to take screenshot, with using: :graphicsmagick" do
220
- allow(Headless::CliUtil).to receive(:path_to).with('gm').and_return('path/gm')
236
+ allow(Headless::CliUtil).to receive(:path_to).with("gm").and_return("path/gm")
221
237
  expect(headless).to receive(:system).with("path/gm import -display localhost:99 -window root /tmp/image.png")
222
- headless.take_screenshot("/tmp/image.png", :using => :graphicsmagick)
238
+ headless.take_screenshot("/tmp/image.png", using: :graphicsmagick)
223
239
  end
224
240
 
225
241
  it "issues command to take screenshot, with using: :gm" do
226
- allow(Headless::CliUtil).to receive(:path_to).with('gm').and_return('path/gm')
242
+ allow(Headless::CliUtil).to receive(:path_to).with("gm").and_return("path/gm")
227
243
  expect(headless).to receive(:system).with("path/gm import -display localhost:99 -window root /tmp/image.png")
228
- headless.take_screenshot("/tmp/image.png", :using => :gm)
244
+ headless.take_screenshot("/tmp/image.png", using: :gm)
229
245
  end
230
246
  end
231
247
  end
232
248
 
233
- private
249
+ private
234
250
 
235
251
  def stub_environment
236
252
  allow(Headless::CliUtil).to receive(:application_exists?).and_return(true)
@@ -1,29 +1,29 @@
1
- require 'headless'
2
- require 'selenium-webdriver'
1
+ require "headless"
2
+ require "selenium-webdriver"
3
3
 
4
- describe 'Integration test' do
4
+ describe "Integration test" do
5
5
  let!(:headless) { Headless.new }
6
6
  before { headless.start }
7
7
 
8
8
  after { headless.destroy_sync }
9
9
 
10
- it 'should use xvfb' do
10
+ it "should use xvfb" do
11
11
  work_with_browser
12
12
  end
13
13
 
14
- it 'should record screenshots' do
14
+ it "should record screenshots" do
15
15
  headless.take_screenshot("test.jpg")
16
16
  expect(File.exist?("test.jpg")).to eq true
17
17
  end
18
18
 
19
- it 'should record video with ffmpeg' do
19
+ it "should record video with ffmpeg" do
20
20
  headless.video.start_capture
21
21
  work_with_browser
22
22
  headless.video.stop_and_save("test.mov")
23
23
  expect(File.exist?("test.mov")).to eq true
24
24
  end
25
25
 
26
- it 'should raise an error when trying to create the same display' do
26
+ it "should raise an error when trying to create the same display" do
27
27
  expect {
28
28
  FileUtils.mv("/tmp/.X#{headless.display}-lock", "/tmp/headless-test-tmp")
29
29
  Headless.new(display: headless.display, reuse: false)
@@ -35,7 +35,7 @@ describe 'Integration test' do
35
35
 
36
36
  def work_with_browser
37
37
  driver = Selenium::WebDriver.for :firefox
38
- driver.navigate.to 'http://google.com'
38
+ driver.navigate.to "http://google.com"
39
39
  expect(driver.title).to match(/Google/)
40
40
  driver.close
41
41
  end
@@ -1,6 +1,6 @@
1
- require 'headless'
1
+ require "headless"
2
2
 
3
- require 'tempfile'
3
+ require "tempfile"
4
4
 
5
5
  describe Headless::VideoRecorder do
6
6
  before do
@@ -8,89 +8,79 @@ describe Headless::VideoRecorder do
8
8
  end
9
9
 
10
10
  describe "instantiation" do
11
-
12
- it "throws an error if provider_binary_path is not installed" do
11
+ it "throws an error if ffmpeg_path is not installed" do
13
12
  allow(Headless::CliUtil).to receive(:application_exists?).and_return(false)
14
13
  expect { Headless::VideoRecorder.new(99, "1024x768x32") }.to raise_error(Headless::Exception)
15
14
  end
16
15
 
17
- it "allows provider_binary_path to be specified" do
18
- Tempfile.open('some_provider') do |f|
19
- v = Headless::VideoRecorder.new(99, "1024x768x32", provider: :ffmpeg, provider_binary_path: f.path)
20
- expect(v.provider_binary_path).to eq(f.path)
16
+ it "allows ffmpeg_path to be specified" do
17
+ Tempfile.open("ffmpeg") do |f|
18
+ v = Headless::VideoRecorder.new(99, "1024x768x32", ffmpeg_path: f.path)
19
+ expect(v.ffmpeg_path).to eq(f.path)
21
20
  end
22
21
  end
23
22
 
24
- it "allows provider_binary_path to be specified" do
25
- Tempfile.open('some_provider') do |f|
26
- v = Headless::VideoRecorder.new(99, "1024x768x32", provider: :ffmpeg, provider_binary_path: f.path)
27
- expect(v.provider_binary_path).to eq(f.path)
23
+ it "supports provider_binary_path for backward compatibility" do
24
+ Tempfile.open("ffmpeg") do |f|
25
+ v = Headless::VideoRecorder.new(99, "1024x768x32", provider_binary_path: f.path)
26
+ expect(v.ffmpeg_path).to eq(f.path)
28
27
  end
29
28
  end
30
-
31
- context "provider_binary_path not specified" do
32
- it "assumes the provider binary is 'ffmpeg' if the provider is :ffmpeg" do
33
- v = Headless::VideoRecorder.new(99, "1024x768x32", provider: :ffmpeg)
34
- expect(v.provider_binary_path).to eq("ffmpeg")
35
- end
36
-
37
- it "assumes the provider binary is 'avconv' if the provider is :libav" do
38
- v = Headless::VideoRecorder.new(99, "1024x768x32", provider: :libav)
39
- expect(v.provider_binary_path).to eq("avconv")
40
- end
41
-
42
- end
43
29
  end
44
30
 
45
31
  describe "#capture" do
46
32
  before do
47
- allow(Headless::CliUtil).to receive(:path_to).and_return('ffmpeg')
33
+ allow(Headless::CliUtil).to receive(:path_to).and_return("ffmpeg")
48
34
  end
49
35
 
50
36
  it "starts ffmpeg" do
51
- expect(Headless::CliUtil).to receive(:fork_process).with(/^ffmpeg -y -r 30 -s 1024x768 -f x11grab -i :99 -g 600 -vcodec qtrle [^ ]+$/, "/tmp/.headless_ffmpeg_99.pid", '/dev/null')
37
+ expect(Headless::CliUtil).to receive(:fork_process).with(
38
+ /^ffmpeg -y -r 30 -s 1024x768 -f x11grab -i :99 -vcodec qtrle [^ ]+$/,
39
+ "/tmp/.headless_ffmpeg_99.pid",
40
+ File::NULL
41
+ )
52
42
 
53
43
  recorder = Headless::VideoRecorder.new(99, "1024x768x32")
54
44
  recorder.start_capture
55
45
  end
56
46
 
57
47
  it "starts ffmpeg with specified codec" do
58
- expect(Headless::CliUtil).to receive(:fork_process).with(/^ffmpeg -y -r 30 -s 1024x768 -f x11grab -i :99 -g 600 -vcodec libvpx [^ ]+$/, "/tmp/.headless_ffmpeg_99.pid", '/dev/null')
59
-
60
- recorder = Headless::VideoRecorder.new(99, "1024x768x32", {:codec => 'libvpx'})
61
- recorder.start_capture
62
- end
63
-
64
- it "starts ffmpeg from ffmpeg provider with correct parameters" do
65
- expect(Headless::CliUtil).to receive(:fork_process).with(/^ffmpeg -y -r 30 -s 1024x768 -f x11grab -i :99 -vcodec qtrle [^ ]+$/, "/tmp/.headless_ffmpeg_99.pid", '/dev/null')
48
+ expect(Headless::CliUtil).to receive(:fork_process).with(
49
+ /^ffmpeg -y -r 30 -s 1024x768 -f x11grab -i :99 -vcodec libvpx [^ ]+$/,
50
+ "/tmp/.headless_ffmpeg_99.pid",
51
+ File::NULL
52
+ )
66
53
 
67
- recorder = Headless::VideoRecorder.new(99, "1024x768x32", {:provider => :ffmpeg})
54
+ recorder = Headless::VideoRecorder.new(99, "1024x768x32", {codec: "libvpx"})
68
55
  recorder.start_capture
69
56
  end
70
57
 
71
58
  it "starts ffmpeg with specified extra device options" do
72
- expect(Headless::CliUtil).to receive(:fork_process).with(/^ffmpeg -y -r 30 -s 1024x768 -f x11grab -draw_mouse 0 -i :99 -g 600 -vcodec qtrle [^ ]+$/, "/tmp/.headless_ffmpeg_99.pid", '/dev/null')
59
+ expect(Headless::CliUtil).to receive(:fork_process).with(
60
+ /^ffmpeg -y -r 30 -s 1024x768 -f x11grab -i :99 -draw_mouse 0 -vcodec qtrle [^ ]+$/,
61
+ "/tmp/.headless_ffmpeg_99.pid", File::NULL
62
+ )
73
63
 
74
- recorder = Headless::VideoRecorder.new(99, "1024x768x32", {:devices => ["-draw_mouse 0"]})
64
+ recorder = Headless::VideoRecorder.new(99, "1024x768x32", {devices: ["-draw_mouse 0"]})
75
65
  recorder.start_capture
76
66
  end
77
67
  end
78
68
 
79
69
  context "stopping video recording" do
80
- let(:tmpfile) { '/tmp/ci.mov' }
81
- let(:filename) { '/tmp/test.mov' }
82
- let(:pidfile) { '/tmp/pid' }
70
+ let(:tmpfile) { "/tmp/ci.mov" }
71
+ let(:filename) { "/tmp/test.mov" }
72
+ let(:pidfile) { "/tmp/pid" }
83
73
 
84
74
  subject do
85
- recorder = Headless::VideoRecorder.new(99, "1024x768x32", :pid_file_path => pidfile, :tmp_file_path => tmpfile)
75
+ recorder = Headless::VideoRecorder.new(99, "1024x768x32", pid_file_path: pidfile, tmp_file_path: tmpfile)
86
76
  recorder.start_capture
87
77
  recorder
88
78
  end
89
79
 
90
80
  describe "using #stop_and_save" do
91
81
  it "stops video recording and saves file" do
92
- expect(Headless::CliUtil).to receive(:kill_process).with(pidfile, :wait => true)
93
- expect(File).to receive(:exists?).with(tmpfile).and_return(true)
82
+ expect(Headless::CliUtil).to receive(:kill_process).with(pidfile, wait: true)
83
+ expect(File).to receive(:exist?).with(tmpfile).and_return(true)
94
84
  expect(FileUtils).to receive(:mv).with(tmpfile, filename)
95
85
 
96
86
  subject.stop_and_save(filename)
@@ -99,7 +89,7 @@ describe Headless::VideoRecorder do
99
89
 
100
90
  describe "using #stop_and_discard" do
101
91
  it "stops video recording and deletes temporary file" do
102
- expect(Headless::CliUtil).to receive(:kill_process).with(pidfile, :wait => true)
92
+ expect(Headless::CliUtil).to receive(:kill_process).with(pidfile, wait: true)
103
93
  expect(FileUtils).to receive(:rm).with(tmpfile)
104
94
 
105
95
  subject.stop_and_discard