mediawiki_selenium 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 329d08a407bf34d62782833f29ddc148c36e75c0
4
- data.tar.gz: 34f4f2700b159884ddb8b5e6ddf77c935c8fd9ee
3
+ metadata.gz: 9883a47e71cdb76841699d8292442f00a6312a63
4
+ data.tar.gz: 6af66ee6695ba0e33cb68ade1aa2bae67566cadc
5
5
  SHA512:
6
- metadata.gz: b87efa97ee1d7ad227c7d30264daf1b1144a0cedaf3ccb46495a5a68081781fe8ae4cab1db855d7b5dfce880c7ede665e3de58736a4582a521c847c1f16b43e3
7
- data.tar.gz: 84993de521a0a42243a8420d91fdb6a41eef45abbc9281a356197968715652b9b5fad2f809799ec5d716b18e4e081da249c8dd248d3865baff9d26be6aea78b8
6
+ metadata.gz: 1656892e8f622ce63c4683d0a14f5626834d102be62512bbc8c7510adce55467a1b6cc9eee1a5e229f1b6985323997ca86b9cf86b914607d3117d7dd95d28d30
7
+ data.tar.gz: 4a7fb08977d4c047721e9329a8e31fdfabf176c4a7efd1d83cee36014e68eb084abe2acfc8dca13bab39c5c5054b61547ab8a045f635c786b9d4d573fef9066e
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  .bundle
2
2
  /.yardoc/
3
3
  /doc/
4
+ /tmp/
4
5
  .gem
5
6
  *.gem
6
7
  Gemfile.lock
data/README.md CHANGED
@@ -37,7 +37,7 @@ Create a `Gemfile` in the root of your MediaWiki-related project that
37
37
  specifies the version of `mediawiki_selenium` you wish to use (typically the
38
38
  latest version).
39
39
 
40
- gem 'mediawiki_selenium', '~> 1.4.0'
40
+ gem 'mediawiki_selenium', '~> 1.5.0'
41
41
 
42
42
  Install the gem and its dependencies by running `bundle install`. (If
43
43
  [Bundler](http://bundler.io/) is not yet installed, install it with
@@ -223,6 +223,12 @@ See https://www.mediawiki.org/wiki/Gerrit
223
223
 
224
224
  ## Release notes
225
225
 
226
+ ### 1.5.0 2015-07-23
227
+ * Video recording of headless browser sessions are now saved to
228
+ `HEADLESS_CAPTURE_PATH` for failed scenarios
229
+ * Page objects can now reference the current `Environment` object as `env` in
230
+ their page URL ERb
231
+
226
232
  ### 1.4.0 2015-06-26
227
233
  * New user factory module provides account fixtures for a greater level of
228
234
  isolation/atomicity between scenarios
data/UPGRADE.md CHANGED
@@ -5,7 +5,7 @@
5
5
  First, update the `Gemfile` in your project's root directory to specify the
6
6
  new version.
7
7
 
8
- gem 'mediawiki_selenium', '~> 1.4.0'
8
+ gem 'mediawiki_selenium', '~> 1.5.0'
9
9
 
10
10
  ## Upgrade gems and dependencies
11
11
 
@@ -0,0 +1,40 @@
1
+ @integration
2
+ Feature: Recording of headless sessions
3
+
4
+ As a developer writing and running headless tests, it would be helpful to
5
+ have a video recording of the session so that troubleshooting/debugging
6
+ failures can be done more easily.
7
+
8
+ Background:
9
+ Given I have `Xvfb` installed
10
+ And I have `avconv` installed
11
+ And I have configured my environment from `ENV` and with:
12
+ """
13
+ headless: true
14
+ headless_display: 20
15
+ headless_capture_path: tmp/log
16
+ """
17
+ And the "tmp/log" directory exists
18
+
19
+ Scenario: A video file is saved upon teardown for failed scenarios
20
+ Given the current scenario name is "Some scenario"
21
+ And I have started a browser
22
+ When the scenario fails
23
+ Then the file "tmp/log/Some scenario.mp4" should exist
24
+
25
+ Scenario: A video file is not saved for passing scenarios
26
+ Given the current scenario name is "Some scenario"
27
+ And I have started a browser
28
+ When the scenario passes
29
+ Then the file "tmp/log/Some scenario.mp4" should not exist
30
+
31
+ Scenario: A video per session is saved
32
+ Given the current scenario name is "Some scenario"
33
+ And I have started a browser
34
+ And the scenario fails
35
+ And the next scenario begins
36
+ And the current scenario name is "Some other scenario"
37
+ And I have started a browser
38
+ When the scenario fails
39
+ Then the file "tmp/log/Some scenario.mp4" should exist
40
+ And the file "tmp/log/Some other scenario.mp4" should exist
@@ -1,12 +1,22 @@
1
+ Before do
2
+ @tmp_files = []
3
+ end
4
+
5
+ After do
6
+ @env.teardown unless @env.nil?
7
+ @tmp_files.each { |path| FileUtils.rm_r(path) if File.exist?(path) }
8
+ end
9
+
1
10
  Given(/^I have configured my environment with:$/) do |yaml|
2
- @env = MediawikiSelenium::Environment.new(YAML.load(yaml))
11
+ @configs = [YAML.load(yaml)]
12
+ @env = MediawikiSelenium::Environment.new(*@configs)
3
13
  end
4
14
 
5
15
  Given(/^I have configured my environment from `ENV`(?: and with:)?$/) do |*args|
6
- configs = [ENV]
7
- configs << YAML.load(args.first) if args.length > 0
16
+ @configs = [ENV]
17
+ @configs << YAML.load(args.first) if args.length > 0
8
18
 
9
- @env = MediawikiSelenium::Environment.new(*configs)
19
+ @env = MediawikiSelenium::Environment.new(*@configs)
10
20
  end
11
21
 
12
22
  Given(/^I have set "(.*?)" in my shell$/) do |var|
@@ -17,6 +27,44 @@ Given(/^I have set "(.*?)" in my shell$/) do |var|
17
27
  end
18
28
  end
19
29
 
20
- After do
21
- @env.teardown unless @env.nil?
30
+ Given(/^I have `(.*?)` installed$/) do |cmd|
31
+ unless system("which #{cmd} > /dev/null") == true
32
+ pending "you must have #{cmd} installed to run this test"
33
+ end
34
+ end
35
+
36
+ Given(/^the "(.*?)" directory exists$/) do |dir|
37
+ @tmp_files << dir unless File.exist?(dir)
38
+ FileUtils.mkdir_p(dir)
39
+ end
40
+
41
+ Given(/^the environment has been setup$/) do
42
+ @env.setup
43
+ end
44
+
45
+ Given(/^the current scenario name is "(.*?)"$/) do |name|
46
+ @scenario_name = name
47
+ end
48
+
49
+ Given(/^the next scenario begins$/) do
50
+ @env = MediawikiSelenium::Environment.new(*@configs)
51
+ end
52
+
53
+ When(/^the scenario ends$/) do
54
+ begin
55
+ # Avoid a race condition within the headless video recorder by waiting
56
+ sleep 0.3
57
+ @env.teardown(name: @scenario_name, status: @scenario_status)
58
+ ensure
59
+ @env = nil
60
+ end
61
+ end
62
+
63
+ When(/^the scenario (fails|passes)$/) do |status|
64
+ @scenario_status = status == 'fails' ? :failed : :passed
65
+ step 'the scenario ends'
66
+ end
67
+
68
+ Then(/^the file "(.*?)" should (not )?exist$/) do |file, negate|
69
+ expect(Pathname.new(file)).send(negate ? :to_not : :to, exist)
22
70
  end
@@ -4,6 +4,7 @@ module MediawikiSelenium
4
4
  autoload :BrowserFactory, 'mediawiki_selenium/browser_factory'
5
5
  autoload :ConfigurationError, 'mediawiki_selenium/configuration_error'
6
6
  autoload :Environment, 'mediawiki_selenium/environment'
7
+ autoload :HeadlessHelper, 'mediawiki_selenium/support/modules/headless_helper'
7
8
  autoload :Initializer, 'mediawiki_selenium/initializer'
8
9
  autoload :PageFactory, 'mediawiki_selenium/page_factory'
9
10
  autoload :Raita, 'mediawiki_selenium/raita'
@@ -104,6 +104,8 @@ module MediawikiSelenium
104
104
  @_config = configs.map { |config| normalize_config(config) }.reduce(:merge)
105
105
  @_factory_cache = {}
106
106
  @_current_alternatives = {}
107
+
108
+ extend(HeadlessHelper) if headless?
107
109
  end
108
110
 
109
111
  # Whether the given environment is equal to this one. Two environments are
@@ -201,6 +203,15 @@ module MediawikiSelenium
201
203
  self
202
204
  end
203
205
 
206
+ # Whether this environment is configured to run in headless mode (using
207
+ # Xvfb via the headless gem).
208
+ #
209
+ # @return [true, false]
210
+ #
211
+ def headless?
212
+ lookup(:headless, default: 'false').to_s == 'true'
213
+ end
214
+
204
215
  # Executes the given block within the context of an environment that uses
205
216
  # a unique browser session and possibly different configuration. Note that
206
217
  # any given configuration overrides are scoped with a `:browser_` prefix.
@@ -339,23 +350,23 @@ module MediawikiSelenium
339
350
  # close any open browsers and perform their own teardown tasks.
340
351
  #
341
352
  # @example Teardown environment resources after each scenario completes
342
- # After do
343
- # teardown(scenario.status)
353
+ # After do |scenario|
354
+ # teardown(name: scenario.name, status: scenario.status)
344
355
  # end
345
356
  #
346
- # @param status [Symbol] Status of the executed scenario.
357
+ # @param info [Hash] Hash of test case information.
347
358
  #
348
359
  # @yield [browser]
349
360
  # @yieldparam browser [Watir::Browser] Browser object, before it's closed.
350
361
  #
351
- def teardown(status = :passed)
362
+ def teardown(info = {})
352
363
  @_factory_cache.each do |(_, browser_name), factory|
353
364
  factory.each do |browser|
354
365
  yield browser if block_given?
355
366
  browser.close unless keep_browser_open? && browser_name != :phantomjs
356
367
  end
357
368
 
358
- factory.teardown(self, status)
369
+ factory.teardown(self, info[:status] || :passed)
359
370
  end
360
371
  end
361
372
 
@@ -11,12 +11,25 @@ module MediawikiSelenium
11
11
  # `PageObject::PageFactory#on_page`. All page URLs are also qualified
12
12
  # using {Environment#wiki_url}.
13
13
  #
14
+ # Additionally, an instance of the current {Environment} is made available
15
+ # as `env` for interpolation of page URLs.
16
+ #
17
+ # @example Referencing the `env` in page URLs
18
+ # class ArticlePage
19
+ # page_url 'User:<%= env.user %>'
20
+ # end
21
+ #
14
22
  # @see http://www.rubydoc.info/github/cheezy/page-object
15
23
  #
16
24
  def on_page(page_class, params = { using_params: {} }, visit = false)
17
25
  @browser = browser if visit || !defined?(@browser)
26
+ env = self
18
27
 
19
28
  super(page_class, params, false) do |page|
29
+ page.define_singleton_method(:env) do
30
+ env
31
+ end
32
+
20
33
  if page.respond_to?(:goto)
21
34
  wiki_url = method(:wiki_url)
22
35
 
@@ -16,20 +16,6 @@ AfterConfiguration do |config|
16
16
  raita_build = MediawikiSelenium::Raita.build_from(env)
17
17
  config.formats << ['MediawikiSelenium::Raita::Logger', { url: raita_url, build: raita_build }]
18
18
  end
19
-
20
- # Initiate headless mode
21
- if ENV['HEADLESS'] == 'true' && ENV['BROWSER'] != 'phantomjs'
22
- require 'headless'
23
-
24
- headless_options = {}.tap do |options|
25
- options[:display] = ENV['HEADLESS_DISPLAY'] if ENV.include?('HEADLESS_DISPLAY')
26
- options[:reuse] = false if ENV['HEADLESS_REUSE'] == 'false'
27
- options[:destroy_at_exit] = false if ENV['HEADLESS_DESTROY_AT_EXIT'] == 'false'
28
- end
29
-
30
- headless = Headless.new(headless_options)
31
- headless.start
32
- end
33
19
  end
34
20
 
35
21
  # Enforce a dependency check for all scenarios tagged with @extension- tags
@@ -79,10 +65,12 @@ Before do |scenario|
79
65
  end
80
66
 
81
67
  After do |scenario|
68
+ scenario_name = test_name(scenario)
69
+
82
70
  if scenario.respond_to?(:status)
83
71
  require 'fileutils'
84
72
 
85
- teardown(scenario.status) do |browser|
73
+ teardown(name: scenario_name, status: scenario.status) do |browser|
86
74
  # Embed remote session URLs
87
75
  if remote? && browser.driver.respond_to?(:session_id)
88
76
  embed("http://saucelabs.com/jobs/#{browser.driver.session_id}", 'text/url')
@@ -92,14 +80,13 @@ After do |scenario|
92
80
  if scenario.failed? && lookup(:screenshot_failures, default: false) == 'true'
93
81
  screen_dir = lookup(:screenshot_failures_path, default: 'screenshots')
94
82
  FileUtils.mkdir_p screen_dir
95
- name = test_name(scenario).gsub(/ /, '_')
83
+ name = scenario_name.gsub(/ /, '_')
96
84
  path = "#{screen_dir}/#{name}.png"
97
85
  browser.screenshot.save path
98
86
  embed path, 'image/png'
99
87
  end
100
-
101
88
  end
102
89
  else
103
- teardown
90
+ teardown(name: scenario_name)
104
91
  end
105
92
  end
@@ -0,0 +1,116 @@
1
+ require 'fileutils'
2
+ require 'headless'
3
+
4
+ module MediawikiSelenium
5
+ # Adds support to {Environment} for running sessions in a headless mode
6
+ # using Xvfb. Video will be recorded for the display and saved for failed
7
+ # scenarios if a `headless_capture_path` environment variable is configured.
8
+ #
9
+ module HeadlessHelper
10
+ class << self
11
+ # Creates a global headless display using the given environment's
12
+ # configuration. If a display has already been created once before, it
13
+ # is simply returned.
14
+ #
15
+ # @param env [Environment] Environment for which to start headless.
16
+ #
17
+ # @return [Headless]
18
+ #
19
+ def create_or_reuse_display(env)
20
+ return @_display unless @_display.nil?
21
+
22
+ options = { video: { provider: :libav, codec: 'libx264' } }
23
+
24
+ display = env.lookup(:headless_display, default: nil)
25
+ options[:display] = display unless display.nil?
26
+
27
+ if env.lookup(:headless_reuse, default: true).to_s == 'false'
28
+ options[:reuse] = false
29
+ end
30
+
31
+ if env.lookup(:headless_destroy_at_exit, default: true).to_s == 'false'
32
+ options[:destroy_at_exit] = false
33
+ end
34
+
35
+ @_display = Headless.new(options)
36
+ @_display.start
37
+
38
+ @_display
39
+ end
40
+
41
+ # Destroys the global headless display created by
42
+ # {create_or_reuse_display}.
43
+ #
44
+ def destroy_display
45
+ @_display.destroy if @_display
46
+ @_display = nil
47
+ end
48
+
49
+ # Whether a global headless display has been created.
50
+ #
51
+ # @return [true, false]
52
+ #
53
+ def display_created?
54
+ !@_display.nil?
55
+ end
56
+ end
57
+
58
+ # Starts a headless display and starts recording before the {Environment}
59
+ # opens a browser for the first time.
60
+ #
61
+ # @see Environment#browser
62
+ #
63
+ def browser
64
+ @_headless_display = HeadlessHelper.create_or_reuse_display(self)
65
+
66
+ if !@_headless_capture && headless_capture?
67
+ @_headless_capture = true
68
+ @_headless_display.video.start_capture
69
+ end
70
+
71
+ super
72
+ end
73
+
74
+ # Whether or not we should perform video capture of the headless display
75
+ # for each new browser session.
76
+ #
77
+ # @return [true, false]
78
+ #
79
+ def headless_capture?
80
+ !headless_capture_path.nil?
81
+ end
82
+
83
+ # Directory where screenshot/video files of headless sessions will be
84
+ # saved. Defaults to writing them to a `log` directory under the workspace
85
+ # directory.
86
+ #
87
+ # @return [String, nil]
88
+ #
89
+ def headless_capture_path
90
+ lookup(:headless_capture_path, default: nil)
91
+ end
92
+
93
+ # Performs teardown tasks for headless operation, saving any video
94
+ # captures to file.
95
+ #
96
+ # @see Environment#teardown
97
+ #
98
+ def teardown(info = {})
99
+ super
100
+ ensure
101
+ if @_headless_capture
102
+ if info[:status] == :failed
103
+ dir = File.absolute_path(headless_capture_path)
104
+ FileUtils.mkdir_p(dir)
105
+
106
+ filename = "#{(info[:name] || 'scenario').tr("#{File::SEPARATOR}\000", '-')}.mp4"
107
+ filename = File.join(dir, filename)
108
+
109
+ @_headless_display.video.stop_and_save(filename)
110
+ else
111
+ @_headless_display.video.stop_and_discard
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -1,3 +1,3 @@
1
1
  module MediawikiSelenium
2
- VERSION = '1.4.0'
2
+ VERSION = '1.5.0'
3
3
  end
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ['lib']
29
29
 
30
30
  spec.add_runtime_dependency 'cucumber', '~> 1.3', '>= 1.3.20'
31
- spec.add_runtime_dependency 'headless', '~> 1.0', '>= 1.0.1'
31
+ spec.add_runtime_dependency 'headless', '~> 2.0', '>= 2.1.0'
32
32
  spec.add_runtime_dependency 'json', '~> 1.8', '>= 1.8.1'
33
33
  spec.add_runtime_dependency 'mediawiki_api', '~> 0.4', '>= 0.4.1'
34
34
  spec.add_runtime_dependency 'page-object', '~> 1.0'
@@ -83,6 +83,22 @@ module MediawikiSelenium
83
83
  end
84
84
  end
85
85
 
86
+ describe '#initialize' do
87
+ subject { Environment.new(config) }
88
+
89
+ context 'when headless mode is enabled' do
90
+ let(:config) { { headless: 'true' } }
91
+
92
+ it { is_expected.to be_a(HeadlessHelper) }
93
+ end
94
+
95
+ context 'when headless mode is disabled' do
96
+ let(:config) { { headless: nil } }
97
+
98
+ it { is_expected.to_not be_a(HeadlessHelper) }
99
+ end
100
+ end
101
+
86
102
  describe '#==' do
87
103
  subject { env == other }
88
104
 
@@ -381,7 +397,7 @@ module MediawikiSelenium
381
397
  end
382
398
 
383
399
  describe '#teardown' do
384
- subject { env.teardown(status) }
400
+ subject { env.teardown(status: status) }
385
401
 
386
402
  let(:status) { :passed }
387
403
  let(:browser_instance) { double(Watir::Browser) }
@@ -393,7 +409,7 @@ module MediawikiSelenium
393
409
 
394
410
  it 'yields the given block and closes the browser' do
395
411
  expect(browser_instance).to receive(:close)
396
- expect { |blk| env.teardown(status, &blk) }.to yield_with_args(browser_instance)
412
+ expect { |blk| env.teardown(status: status, &blk) }.to yield_with_args(browser_instance)
397
413
  end
398
414
 
399
415
  context 'when keep_browser_open is set to "true"' do
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ module MediawikiSelenium
4
+ describe HeadlessHelper do
5
+ let(:env) { Environment.new(config.merge(headless: true)) }
6
+ let(:config) { {} }
7
+
8
+ describe '.create_or_reuse_display' do
9
+ subject { HeadlessHelper.create_or_reuse_display(env) }
10
+
11
+ let(:headless) { double('Headless') }
12
+
13
+ before { allow(headless).to receive(:destroy) }
14
+ after { HeadlessHelper.destroy_display }
15
+
16
+ context 'called for the first time' do
17
+ it 'creates, starts, and returns a new Headless' do
18
+ expect(Headless).to receive(:new).and_return(headless)
19
+ expect(headless).to receive(:start)
20
+ expect(subject).to be(headless)
21
+ end
22
+ end
23
+
24
+ context 'called a second time' do
25
+ it 'only creates one Headless' do
26
+ expect(Headless).to receive(:new).once.and_return(headless)
27
+ expect(headless).to receive(:start).once
28
+
29
+ 2.times { HeadlessHelper.create_or_reuse_display(env) }
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -47,8 +47,6 @@ module MediawikiSelenium
47
47
 
48
48
  context 'when told to visit a page' do
49
49
  let(:visit) { true }
50
- let(:config) { { mediawiki_url: 'http://an.example/wiki/' } }
51
-
52
50
  let(:page_object_platform) { double('PageObject::WatirPageObject') }
53
51
 
54
52
  before do
@@ -57,6 +55,8 @@ module MediawikiSelenium
57
55
  end
58
56
 
59
57
  context 'where the page URL is defined' do
58
+ let(:config) { { mediawiki_url: 'http://an.example/wiki/' } }
59
+
60
60
  let(:page_class) do
61
61
  Class.new do
62
62
  include ::PageObject
@@ -64,15 +64,35 @@ module MediawikiSelenium
64
64
  end
65
65
  end
66
66
 
67
- it 'qualifies the path with the configured :mediawiki_url' do
67
+ before do
68
68
  expect_any_instance_of(page_class).to receive(:platform).
69
69
  and_return(page_object_platform)
70
+ end
70
71
 
72
+ it 'qualifies the path with the configured :mediawiki_url' do
71
73
  expect(page_object_platform).to receive(:navigate_to).
72
74
  with('http://an.example/wiki/Special:RandomPage')
73
75
 
74
76
  subject
75
77
  end
78
+
79
+ context 'and it contains ERb that references `env`' do
80
+ let(:config) { { mediawiki_url: 'http://an.example/wiki/', mediawiki_user: 'user1' } }
81
+
82
+ let(:page_class) do
83
+ Class.new do
84
+ include ::PageObject
85
+ page_url 'User:<%= env.user %>'
86
+ end
87
+ end
88
+
89
+ it 'successfully calls the `env` method that was added to the page object' do
90
+ expect(page_object_platform).to receive(:navigate_to).
91
+ with('http://an.example/wiki/User:user1')
92
+
93
+ subject
94
+ end
95
+ end
76
96
  end
77
97
 
78
98
  context 'where the page URL is undefined' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mediawiki_selenium
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris McMahon
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2015-06-26 00:00:00.000000000 Z
16
+ date: 2015-07-28 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: cucumber
@@ -41,20 +41,20 @@ dependencies:
41
41
  requirements:
42
42
  - - "~>"
43
43
  - !ruby/object:Gem::Version
44
- version: '1.0'
44
+ version: '2.0'
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.1
47
+ version: 2.1.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.0'
54
+ version: '2.0'
55
55
  - - ">="
56
56
  - !ruby/object:Gem::Version
57
- version: 1.0.1
57
+ version: 2.1.0
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: json
60
60
  requirement: !ruby/object:Gem::Requirement
@@ -332,6 +332,7 @@ files:
332
332
  - bin/mediawiki-selenium-init
333
333
  - features/api.feature
334
334
  - features/basic_usage.feature
335
+ - features/recording.feature
335
336
  - features/saucelabs.feature
336
337
  - features/step_definitions/api_helper_steps.rb
337
338
  - features/step_definitions/browser_steps.rb
@@ -364,6 +365,7 @@ files:
364
365
  - lib/mediawiki_selenium/support/env.rb
365
366
  - lib/mediawiki_selenium/support/hooks.rb
366
367
  - lib/mediawiki_selenium/support/modules/api_helper.rb
368
+ - lib/mediawiki_selenium/support/modules/headless_helper.rb
367
369
  - lib/mediawiki_selenium/support/modules/strict_pending.rb
368
370
  - lib/mediawiki_selenium/support/modules/user_factory_helper.rb
369
371
  - lib/mediawiki_selenium/support/pages.rb
@@ -381,6 +383,7 @@ files:
381
383
  - spec/browser_factory/firefox_spec.rb
382
384
  - spec/browser_factory/phantomjs_spec.rb
383
385
  - spec/environment_spec.rb
386
+ - spec/headless_helper_spec.rb
384
387
  - spec/page_factory_spec.rb
385
388
  - spec/remote_browser_factory_spec.rb
386
389
  - spec/spec_helper.rb