unobtainium 0.8.1 → 0.9.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Gemfile.lock +10 -9
- data/lib/unobtainium/driver.rb +6 -1
- data/lib/unobtainium/drivers/appium.rb +8 -6
- data/lib/unobtainium/drivers/phantom.rb +148 -32
- data/lib/unobtainium/drivers/selenium.rb +4 -1
- data/lib/unobtainium/support/identifiers.rb +25 -0
- data/lib/unobtainium/support/port_scanner.rb +15 -3
- data/lib/unobtainium/version.rb +1 -1
- data/lib/unobtainium/world.rb +8 -4
- data/spec/data/driverconfig.yml +9 -2
- data/spec/driver_spec.rb +30 -1
- data/spec/drivers_appium_spec.rb +244 -0
- data/spec/drivers_phantom_spec.rb +247 -0
- data/spec/drivers_selenium_spec.rb +170 -0
- data/spec/mock_driver.rb +23 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/support_identifiers_spec.rb +42 -0
- data/spec/{port_scanner_spec.rb → support_port_scanner_spec.rb} +49 -0
- data/spec/{runner_spec.rb → support_runner_spec.rb} +0 -0
- data/spec/{utility_spec.rb → support_utility_spec.rb} +0 -0
- data/spec/world_spec.rb +39 -1
- data/unobtainium.gemspec +1 -1
- metadata +19 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c48a4bbdaf69ce31be6eb42f8a10bd4af462fafb
|
4
|
+
data.tar.gz: f4f811e06460e1a124769e97dadb0d79de82ba93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2582d432e5fc1c6d35cacee66c8eb71ec87437313f1ab3f8706dd457d4925ccb07cac952e535bba1898eb8e1e6b9cb1becaf3e90f2ab36d78c1a2d33e97ab575
|
7
|
+
data.tar.gz: 9e610ebc5b157cb7828a4be8f7208687b8df5acb2ebd7ee9f023173132dd3a0c4d285d1eaf725ea8f2b13ca6c7c2b0c41c71aec11fca49a41082303081ba8e0b
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
unobtainium (0.
|
5
|
-
collapsium (~> 0.
|
4
|
+
unobtainium (0.9.0)
|
5
|
+
collapsium (~> 0.8)
|
6
6
|
collapsium-config (~> 0.4)
|
7
7
|
ptools (~> 1.3)
|
8
8
|
sys-proctable (~> 1.1)
|
@@ -10,11 +10,11 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
appium_lib (8.0
|
13
|
+
appium_lib (8.1.0)
|
14
14
|
awesome_print (~> 1.6)
|
15
15
|
json (~> 1.8)
|
16
16
|
nokogiri (~> 1.6.6)
|
17
|
-
selenium-webdriver (~> 2.
|
17
|
+
selenium-webdriver (~> 2.50)
|
18
18
|
tomlrb (~> 1.1)
|
19
19
|
archive-zip (0.7.0)
|
20
20
|
io-like (~> 0.3.0)
|
@@ -26,10 +26,11 @@ GEM
|
|
26
26
|
chromedriver-helper (1.0.0)
|
27
27
|
archive-zip (~> 0.7.0)
|
28
28
|
nokogiri (~> 1.6)
|
29
|
-
codeclimate-test-reporter (1.0.
|
30
|
-
|
31
|
-
collapsium
|
32
|
-
|
29
|
+
codeclimate-test-reporter (1.0.3)
|
30
|
+
simplecov
|
31
|
+
collapsium (0.8.0)
|
32
|
+
collapsium-config (0.4.3)
|
33
|
+
collapsium (~> 0.7)
|
33
34
|
cucumber (2.4.0)
|
34
35
|
builder (>= 2.1.2)
|
35
36
|
cucumber-core (~> 1.5.0)
|
@@ -52,7 +53,7 @@ GEM
|
|
52
53
|
multi_test (0.1.2)
|
53
54
|
nokogiri (1.6.8.1)
|
54
55
|
mini_portile2 (~> 2.1.0)
|
55
|
-
parser (2.3.
|
56
|
+
parser (2.3.2.0)
|
56
57
|
ast (~> 2.2)
|
57
58
|
phantomjs (2.1.1.0)
|
58
59
|
powerpack (0.1.1)
|
data/lib/unobtainium/driver.rb
CHANGED
@@ -243,7 +243,12 @@ module Unobtainium
|
|
243
243
|
driver_klass.ensure_preconditions(@label, @options)
|
244
244
|
|
245
245
|
# Great, instanciate!
|
246
|
-
|
246
|
+
opts = nil
|
247
|
+
if not @options.nil?
|
248
|
+
opts = @options.dup
|
249
|
+
opts.delete('unobtainium_instance_id')
|
250
|
+
end
|
251
|
+
@impl = driver_klass.create(@label, opts)
|
247
252
|
|
248
253
|
# Now also extend this implementation with all the modues that match
|
249
254
|
@@modules.each do |klass, _|
|
@@ -68,9 +68,7 @@ module Unobtainium
|
|
68
68
|
return driver.send(meth.to_s, *args, &block)
|
69
69
|
end
|
70
70
|
end
|
71
|
-
# :nocov:
|
72
71
|
return super
|
73
|
-
# :nocov:
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
@@ -119,13 +117,14 @@ module Unobtainium
|
|
119
117
|
|
120
118
|
# Merge 'caps' and 'desired_capabilities', letting the former win
|
121
119
|
options[:caps] =
|
122
|
-
::Collapsium::UberHash.new(options[
|
120
|
+
::Collapsium::UberHash.new(options['desired_capabilities'])
|
121
|
+
.recursive_merge(options[:desired_capabilities])
|
123
122
|
.recursive_merge(options[:caps])
|
124
123
|
options.delete(:desired_capabilities)
|
125
124
|
options.delete('desired_capabilities')
|
126
125
|
|
127
126
|
# The label specifies the platform, if no other platform is given.
|
128
|
-
if options['caps.platformName']
|
127
|
+
if not options['caps.platformName']
|
129
128
|
options['caps.platformName'] = normalized.to_s
|
130
129
|
end
|
131
130
|
|
@@ -144,12 +143,14 @@ module Unobtainium
|
|
144
143
|
# some information
|
145
144
|
options = supplement_browser(options)
|
146
145
|
|
147
|
-
return
|
146
|
+
return normalized, options
|
148
147
|
end
|
149
148
|
|
150
149
|
##
|
151
150
|
# Create and return a driver instance
|
152
151
|
def create(_, options)
|
152
|
+
# :nocov:
|
153
|
+
|
153
154
|
# Determine compatibility option
|
154
155
|
compat = options.fetch(:webdriver_compatibility, true)
|
155
156
|
options.delete(:webdriver_compatibility)
|
@@ -158,6 +159,7 @@ module Unobtainium
|
|
158
159
|
driver = ::Appium::Driver.new(options)
|
159
160
|
result = DriverProxy.new(driver, compat)
|
160
161
|
return result
|
162
|
+
# :nocov:
|
161
163
|
end
|
162
164
|
|
163
165
|
private
|
@@ -176,7 +178,7 @@ module Unobtainium
|
|
176
178
|
platform = options['caps.platformName'].to_s.downcase.to_sym
|
177
179
|
|
178
180
|
# If we have supplement data matching the platform and browser, great!
|
179
|
-
data = BROWSER_MATCHES[platform][browser]
|
181
|
+
data = (BROWSER_MATCHES[platform] || {})[browser]
|
180
182
|
if data.nil?
|
181
183
|
return options
|
182
184
|
end
|
@@ -7,10 +7,13 @@
|
|
7
7
|
# All rights reserved.
|
8
8
|
#
|
9
9
|
|
10
|
+
require 'collapsium'
|
11
|
+
|
10
12
|
require_relative './selenium'
|
11
13
|
require_relative '../support/util'
|
12
14
|
require_relative '../support/port_scanner'
|
13
15
|
require_relative '../support/runner'
|
16
|
+
require_relative '../support/identifiers'
|
14
17
|
require_relative '../runtime'
|
15
18
|
|
16
19
|
module Unobtainium
|
@@ -24,7 +27,7 @@ module Unobtainium
|
|
24
27
|
class Phantom < Selenium
|
25
28
|
# Recognized labels for matching the driver
|
26
29
|
LABELS = {
|
27
|
-
phantomjs: [:headless,],
|
30
|
+
phantomjs: [:headless, :phantom],
|
28
31
|
}.freeze
|
29
32
|
|
30
33
|
# Port scanning ranges (can also be arrays or single port numbers.
|
@@ -43,6 +46,7 @@ module Unobtainium
|
|
43
46
|
class << self
|
44
47
|
include ::Unobtainium::Support::Utility
|
45
48
|
include ::Unobtainium::Support::PortScanner
|
49
|
+
include ::Unobtainium::Support::Identifiers
|
46
50
|
|
47
51
|
##
|
48
52
|
# Ensure that the driver's preconditions are fulfilled.
|
@@ -62,40 +66,56 @@ module Unobtainium
|
|
62
66
|
def resolve_options(label, options)
|
63
67
|
label, options = super
|
64
68
|
|
65
|
-
|
66
|
-
raise ArgumentError, "Use either of 'phantomjs' or :phantomjs as "\
|
67
|
-
"option keys, not both!"
|
68
|
-
end
|
69
|
-
if not options[:phantomjs].nil?
|
70
|
-
options['phantomjs'] = options[:phantomjs]
|
71
|
-
options.delete(:phantomjs)
|
72
|
-
end
|
69
|
+
options = ::Collapsium::UberHash.new(options)
|
73
70
|
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
options
|
71
|
+
# If a URL is already provided, we should respect this.
|
72
|
+
merge_url(options)
|
73
|
+
|
74
|
+
# Provide defaults for webdriver host and port.
|
75
|
+
merge_defaults(options)
|
76
|
+
|
77
|
+
# At this point, the :phantomjs field is canonical in that it will
|
78
|
+
# be used to generate a :port and :url if necessary. That means we
|
79
|
+
# can use it to create a stable ID, too.
|
80
|
+
# This also implies that the :url field is pointless and should not
|
81
|
+
# be part of the ID; it will be generated again later on.
|
82
|
+
options.delete(:url)
|
83
|
+
|
84
|
+
# We need to figure out what we have to do based on detecting whether
|
85
|
+
# a port or some other option changed (or nothing did!)
|
86
|
+
fix_ports(label, options)
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
88
|
+
# We find a free port here, so there's a possibility it'll get used
|
89
|
+
# before we run the server in #create. However, for the purpose of
|
90
|
+
# resolving options that's necessary. So we'll just live with this
|
91
|
+
# until it becomes a problem.
|
92
|
+
if options['phantomjs.generated_port'].nil?
|
93
|
+
if options['phantomjs.port'].nil?
|
94
|
+
ports = scan(options['phantomjs.host'], *PORT_RANGES,
|
95
|
+
for: :available, amount: :first)
|
96
|
+
if ports.empty?
|
97
|
+
raise "Could not find an available port for the PhantomJS server!"
|
98
|
+
end
|
99
|
+
options['phantomjs.generated_port'] = ports[0]
|
100
|
+
else
|
101
|
+
options['phantomjs.generated_port'] = options['phantomjs.port']
|
92
102
|
end
|
93
|
-
options['phantomjs']['port'] = ports[0]
|
94
103
|
end
|
95
104
|
|
96
|
-
# Now
|
97
|
-
|
98
|
-
|
105
|
+
# Now we can't just use new_id because we might have found a new
|
106
|
+
# port in the meantime. We'll have to generate yet another ID, and
|
107
|
+
# use that.
|
108
|
+
# Now before calculating this new ID, we'll run the options through
|
109
|
+
# the super method again. This is to ensure that all keys have the
|
110
|
+
# expected class *before* we perform this calculation.
|
111
|
+
new_id = identifier('driver', label, options)
|
112
|
+
options['unobtainium_instance_id'] = new_id
|
113
|
+
|
114
|
+
# Now we can generate the :url field for Selenium's benefit; it's
|
115
|
+
# just a copy of the canonical options.
|
116
|
+
options[:url] = "#{options['phantomjs.scheme']}://"\
|
117
|
+
"#{options['phantomjs.host']}:"\
|
118
|
+
"#{options['phantomjs.generated_port']}"
|
99
119
|
|
100
120
|
return label, options
|
101
121
|
end
|
@@ -103,9 +123,11 @@ module Unobtainium
|
|
103
123
|
##
|
104
124
|
# Create and return a driver instance
|
105
125
|
def create(_, options)
|
126
|
+
# :nocov:
|
127
|
+
|
106
128
|
# Extract PhantomJS options
|
107
|
-
host = options['phantomjs
|
108
|
-
port = options['phantomjs']['
|
129
|
+
host = options['phantomjs.host']
|
130
|
+
port = options['phantomjs.port'] || options['phantomjs.generated_port']
|
109
131
|
opts = options.dup
|
110
132
|
opts.delete('phantomjs')
|
111
133
|
|
@@ -138,6 +160,100 @@ module Unobtainium
|
|
138
160
|
# Run Selenium against server
|
139
161
|
driver = ::Selenium::WebDriver.for(:remote, opts)
|
140
162
|
return driver
|
163
|
+
|
164
|
+
# :nocov:
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def merge_url(options)
|
170
|
+
if not options[:url]
|
171
|
+
return
|
172
|
+
end
|
173
|
+
|
174
|
+
require 'uri'
|
175
|
+
parsed = URI.parse(options[:url])
|
176
|
+
parsed_port = parsed.port.to_i
|
177
|
+
from_parsed = {
|
178
|
+
phantomjs: {
|
179
|
+
scheme: parsed.scheme,
|
180
|
+
host: parsed.host,
|
181
|
+
port: nil,
|
182
|
+
},
|
183
|
+
}
|
184
|
+
|
185
|
+
# Very special case: if the parsed port matches the generated port,
|
186
|
+
# and the port is nil, we want to keep it that way for deduplication
|
187
|
+
# purposes. See `#fix_ports` for how this interacts.
|
188
|
+
port = options['phantomjs.port']
|
189
|
+
generated_port = options['phantomjs.generated_port']
|
190
|
+
if not (parsed_port == generated_port and port.nil?)
|
191
|
+
from_parsed[:phantomjs][:port] = parsed_port
|
192
|
+
end
|
193
|
+
|
194
|
+
options.recursive_merge!(from_parsed, false)
|
195
|
+
end
|
196
|
+
|
197
|
+
def merge_defaults(options)
|
198
|
+
defaults = {
|
199
|
+
phantomjs: {
|
200
|
+
scheme: 'http',
|
201
|
+
host: 'localhost',
|
202
|
+
port: nil,
|
203
|
+
generated_port: nil,
|
204
|
+
},
|
205
|
+
}
|
206
|
+
options.recursive_merge!(defaults, false)
|
207
|
+
end
|
208
|
+
|
209
|
+
def fix_ports(label, options)
|
210
|
+
# Let's keep the old ID around and generate a new one, largely as
|
211
|
+
# a checksum of the options.
|
212
|
+
old_id = options.delete('unobtainium_instance_id')
|
213
|
+
new_id = identifier('driver', label, options)
|
214
|
+
|
215
|
+
# If the IDs don't match, it means some options changed. This may be
|
216
|
+
# the port or another option:
|
217
|
+
# #1 If IDs are the same and port is the same as generated port, we
|
218
|
+
# need not do anything.
|
219
|
+
# #2 If IDs are the same and the ports differ, we have reached an
|
220
|
+
# undefined state. This should be impossible.
|
221
|
+
# #3 If IDs differ and the ports are the same, some other option was
|
222
|
+
# changed. We need to generate a new port and new ID (and warn about
|
223
|
+
# this).
|
224
|
+
# #4 If IDs differ and ports differ, a new port was set. We need to
|
225
|
+
# proceed with the new port and generate a new ID.
|
226
|
+
port = options['phantomjs.port']
|
227
|
+
generated_port = options['phantomjs.generated_port']
|
228
|
+
|
229
|
+
if old_id == new_id and port == generated_port
|
230
|
+
# #1 above, nothing to do.
|
231
|
+
elsif old_id == new_id and port != generated_port
|
232
|
+
# :nocov:
|
233
|
+
# #2 above, raise hell
|
234
|
+
if not port.nil?
|
235
|
+
raise "This can't happen; the instance ID (checksum) is the same, "\
|
236
|
+
"but the input differed: #{port} <-> #{generated_port}"
|
237
|
+
end
|
238
|
+
# :nocov:
|
239
|
+
elsif old_id != new_id and port == generated_port
|
240
|
+
# #3 above; nuke the ports and warn.
|
241
|
+
if not port.nil? and not generated_port.nil?
|
242
|
+
warn "Rejecting port #{port} and generating new port because "\
|
243
|
+
"options changed."
|
244
|
+
end
|
245
|
+
options['phantomjs.port'] = nil
|
246
|
+
options['phantomjs.generated_port'] = nil
|
247
|
+
elsif old_id != new_id and port != generated_port
|
248
|
+
# #4 above
|
249
|
+
options['phantomjs.generated_port'] = nil
|
250
|
+
else
|
251
|
+
# :nocov:
|
252
|
+
# Unreachable
|
253
|
+
raise "This can't happen; we have four cases and handle each of "\
|
254
|
+
"them. This line is unreachable. Please check the logic."
|
255
|
+
# :nocov:
|
256
|
+
end
|
141
257
|
end
|
142
258
|
end # class << self
|
143
259
|
end # class PhantomJS
|
@@ -64,7 +64,8 @@ module Unobtainium
|
|
64
64
|
|
65
65
|
# Merge 'caps' and 'desired_capabilities', letting the latter win
|
66
66
|
options[:desired_capabilities] =
|
67
|
-
::Collapsium::UberHash.new(options[
|
67
|
+
::Collapsium::UberHash.new(options['caps'])
|
68
|
+
.recursive_merge(options[:caps])
|
68
69
|
.recursive_merge(options[:desired_capabilities])
|
69
70
|
options.delete(:caps)
|
70
71
|
options.delete('caps')
|
@@ -82,8 +83,10 @@ module Unobtainium
|
|
82
83
|
##
|
83
84
|
# Create and return a driver instance
|
84
85
|
def create(label, options)
|
86
|
+
# :nocov:
|
85
87
|
driver = ::Selenium::WebDriver.for(normalize_label(label), options)
|
86
88
|
return driver
|
89
|
+
# :nocov:
|
87
90
|
end
|
88
91
|
|
89
92
|
private
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
#
|
3
|
+
# unobtainium
|
4
|
+
# https://github.com/jfinkhaeuser/unobtainium
|
5
|
+
#
|
6
|
+
# Copyright (c) 2016 Jens Finkhaeuser and other unobtainium contributors.
|
7
|
+
# All rights reserved.
|
8
|
+
#
|
9
|
+
module Unobtainium
|
10
|
+
# @api private
|
11
|
+
# Contains support code
|
12
|
+
module Support
|
13
|
+
# Contains code for dealing with instance identifiers.
|
14
|
+
module Identifiers
|
15
|
+
# Given a label and a set of options, generate a unique identifier
|
16
|
+
# string.
|
17
|
+
def identifier(scope, label, options = nil)
|
18
|
+
digest = { label: label, options: options }
|
19
|
+
require 'digest/sha1'
|
20
|
+
digest = Digest::SHA1.hexdigest(digest.to_s)
|
21
|
+
return "#{scope}-#{digest}"
|
22
|
+
end
|
23
|
+
end # module Identifiers
|
24
|
+
end # module Support
|
25
|
+
end # module Unobtainium
|
@@ -30,6 +30,12 @@ module Unobtainium
|
|
30
30
|
# A port scanner for finding a free port for running e.g. a selenium
|
31
31
|
# or appium server.
|
32
32
|
module PortScanner
|
33
|
+
# Retry a port this many times before failing
|
34
|
+
MAX_RETRIES = 5
|
35
|
+
|
36
|
+
# Delay each retry by this many seconds before trying again
|
37
|
+
RETRY_DELAY = 0.5
|
38
|
+
|
33
39
|
##
|
34
40
|
# Returns true if the port is open on the host, false otherwise.
|
35
41
|
# @param host [String] host name or IP address
|
@@ -175,14 +181,20 @@ module Unobtainium
|
|
175
181
|
sock = Socket.new(domain, :STREAM)
|
176
182
|
|
177
183
|
connected = false
|
184
|
+
tries = MAX_RETRIES
|
178
185
|
loop do
|
179
186
|
begin
|
180
187
|
sock.connect_nonblock(addr)
|
181
188
|
rescue Errno::EINPROGRESS
|
182
|
-
|
183
|
-
|
184
|
-
|
189
|
+
tries -= 1
|
190
|
+
if tries <= 0
|
191
|
+
# That's it, we've got enough.
|
192
|
+
break
|
185
193
|
end
|
194
|
+
|
195
|
+
# The result of select doesn't matter. What matters is that we wait
|
196
|
+
# for sock to become usable, or for the timeout to occur.
|
197
|
+
IO.select([sock], [sock], nil, RETRY_DELAY)
|
186
198
|
rescue Errno::EISCONN
|
187
199
|
connected = true
|
188
200
|
break
|
data/lib/unobtainium/version.rb
CHANGED
data/lib/unobtainium/world.rb
CHANGED
@@ -12,6 +12,7 @@ require 'collapsium-config'
|
|
12
12
|
|
13
13
|
require 'unobtainium/driver'
|
14
14
|
require 'unobtainium/runtime'
|
15
|
+
require 'unobtainium/support/identifiers'
|
15
16
|
|
16
17
|
module Unobtainium
|
17
18
|
##
|
@@ -63,6 +64,8 @@ module Unobtainium
|
|
63
64
|
end # module ClassMethods
|
64
65
|
extend ClassMethods
|
65
66
|
|
67
|
+
include ::Unobtainium::Support::Identifiers
|
68
|
+
|
66
69
|
##
|
67
70
|
# (see Driver#create)
|
68
71
|
#
|
@@ -93,6 +96,7 @@ module Unobtainium
|
|
93
96
|
next
|
94
97
|
end
|
95
98
|
label = base.gsub(/^\.drivers\./, '')
|
99
|
+
break
|
96
100
|
end
|
97
101
|
|
98
102
|
# Unfortunately, the "base" key may not be recognized by the drivers,
|
@@ -108,10 +112,10 @@ module Unobtainium
|
|
108
112
|
|
109
113
|
# Create a key for the label and options. This should always
|
110
114
|
# return the same key for the same label and options.
|
111
|
-
key =
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
+
key = options['unobtainum_instance_id']
|
116
|
+
if key.nil?
|
117
|
+
key = identifier('driver', label, options)
|
118
|
+
end
|
115
119
|
|
116
120
|
# Only create a driver with this exact configuration once. Unfortunately
|
117
121
|
# We'll have to bind the destructor to whatever configuration exists at
|
data/spec/data/driverconfig.yml
CHANGED
@@ -7,6 +7,11 @@
|
|
7
7
|
#
|
8
8
|
# so the order in this file has to be mock -> branch2 -> branch1 -> leaf
|
9
9
|
---
|
10
|
+
global:
|
11
|
+
global_opt: 'set'
|
12
|
+
|
13
|
+
driver: leaf
|
14
|
+
|
10
15
|
drivers:
|
11
16
|
mock:
|
12
17
|
mockoption: 42
|
@@ -16,11 +21,13 @@ drivers:
|
|
16
21
|
branch1:
|
17
22
|
extends: mock
|
18
23
|
branch1option: foo
|
24
|
+
branch3:
|
25
|
+
extends: .global
|
26
|
+
branch3option: baz
|
19
27
|
leaf:
|
20
|
-
extends: branch2
|
28
|
+
extends: .global, branch2
|
21
29
|
leafoption: baz
|
22
30
|
branch1option: override
|
23
31
|
base_does_not_exist:
|
24
32
|
extends: nonexistent_base
|
25
33
|
some: value
|
26
|
-
driver: leaf
|
data/spec/driver_spec.rb
CHANGED
@@ -34,7 +34,10 @@ end # module FakeModule
|
|
34
34
|
|
35
35
|
describe ::Unobtainium::Driver do
|
36
36
|
before :each do
|
37
|
-
::Unobtainium::Driver.register_implementation(MockDriver,
|
37
|
+
::Unobtainium::Driver.register_implementation(MockDriver,
|
38
|
+
"mock_driver.rb")
|
39
|
+
::Unobtainium::Driver.register_implementation(OptionResolvingMockDriver,
|
40
|
+
"mock_driver.rb")
|
38
41
|
end
|
39
42
|
|
40
43
|
describe "driver registration" do
|
@@ -101,6 +104,32 @@ describe ::Unobtainium::Driver do
|
|
101
104
|
drv = ::Unobtainium::Driver.create(:mock, foo: 42)
|
102
105
|
expect(drv.passed_options).to eql foo: 42
|
103
106
|
end
|
107
|
+
|
108
|
+
context "option resolution" do
|
109
|
+
it "provides defaults" do
|
110
|
+
drv = ::Unobtainium::Driver.create(:option_resolving)
|
111
|
+
expect(drv.options).to include(:foo)
|
112
|
+
expect(drv.options[:foo]).to eql 42
|
113
|
+
end
|
114
|
+
|
115
|
+
it "overrides when appropriate" do
|
116
|
+
drv = ::Unobtainium::Driver.create(:option_resolving, foo: 123)
|
117
|
+
expect(drv.options).to include(:foo)
|
118
|
+
expect(drv.options[:foo]).to eql 42
|
119
|
+
end
|
120
|
+
|
121
|
+
it "does not override always" do
|
122
|
+
drv = ::Unobtainium::Driver.create(:option_resolving, foo: 456)
|
123
|
+
expect(drv.options).to include(:foo)
|
124
|
+
expect(drv.options[:foo]).to eql 456
|
125
|
+
end
|
126
|
+
|
127
|
+
it "sets an instance ID" do
|
128
|
+
drv = ::Unobtainium::Driver.create(:option_resolving)
|
129
|
+
expect(drv.options).to include('unobtainium_instance_id')
|
130
|
+
expect(drv.options['unobtainium_instance_id']).to eql 'FIXED'
|
131
|
+
end
|
132
|
+
end
|
104
133
|
end
|
105
134
|
|
106
135
|
describe 'modules' do
|