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
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../lib/unobtainium/drivers/appium'
|
3
|
+
|
4
|
+
class SeleniumMock
|
5
|
+
def test
|
6
|
+
return "selenium"
|
7
|
+
end
|
8
|
+
|
9
|
+
def selenium_only
|
10
|
+
return "selenium"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class AppiumMock
|
15
|
+
def test
|
16
|
+
return "appium"
|
17
|
+
end
|
18
|
+
|
19
|
+
def appium_only
|
20
|
+
return "appium"
|
21
|
+
end
|
22
|
+
|
23
|
+
def start_driver
|
24
|
+
return SeleniumMock.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ::Unobtainium::Drivers::Appium do
|
29
|
+
let(:tester) { ::Unobtainium::Drivers::Appium }
|
30
|
+
|
31
|
+
context "#matches?" do
|
32
|
+
it "matches all known aliases" do
|
33
|
+
aliases = [:ios, :iphone, :ipad, :android]
|
34
|
+
aliases.each do |name|
|
35
|
+
expect(tester.matches?(name)).to be_truthy
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does not match unknown names" do
|
40
|
+
unknown = [:foo, :bar, :appium, :phantomjs, :headless]
|
41
|
+
unknown.each do |name|
|
42
|
+
expect(tester.matches?(name)).to be_falsey
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context ::Unobtainium::Drivers::Appium::DriverProxy do
|
48
|
+
let(:appium_driver) { AppiumMock.new }
|
49
|
+
|
50
|
+
it "prefers appium if compatibility is not desired" do
|
51
|
+
proxy = ::Unobtainium::Drivers::Appium::DriverProxy.new(appium_driver, false)
|
52
|
+
|
53
|
+
expect(proxy.respond_to?(:test)).to be_truthy
|
54
|
+
expect(proxy.respond_to?(:selenium_only)).to be_truthy
|
55
|
+
expect(proxy.respond_to?(:appium_only)).to be_truthy
|
56
|
+
|
57
|
+
expect(proxy.test).to eql "appium"
|
58
|
+
expect(proxy.selenium_only).to eql "selenium"
|
59
|
+
expect(proxy.appium_only).to eql "appium"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "prefers selenium if compatibility is desired" do
|
63
|
+
proxy = ::Unobtainium::Drivers::Appium::DriverProxy.new(appium_driver, true)
|
64
|
+
|
65
|
+
expect(proxy.respond_to?(:test)).to be_truthy
|
66
|
+
expect(proxy.respond_to?(:selenium_only)).to be_truthy
|
67
|
+
expect(proxy.respond_to?(:appium_only)).to be_truthy
|
68
|
+
|
69
|
+
expect(proxy.test).to eql "selenium"
|
70
|
+
expect(proxy.selenium_only).to eql "selenium"
|
71
|
+
expect(proxy.appium_only).to eql "appium"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "fails if an undefined method is called" do
|
75
|
+
proxy = ::Unobtainium::Drivers::Appium::DriverProxy.new(appium_driver, true)
|
76
|
+
expect(proxy.respond_to?(:undefined_method)).to be_falsy
|
77
|
+
expect { proxy.undefined_method }.to raise_error(NoMethodError)
|
78
|
+
|
79
|
+
proxy = ::Unobtainium::Drivers::Appium::DriverProxy.new(appium_driver, false)
|
80
|
+
expect(proxy.respond_to?(:undefined_method)).to be_falsy
|
81
|
+
expect { proxy.undefined_method }.to raise_error(NoMethodError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "#ensure_preconditions" do
|
86
|
+
it "will succeed because development dependencies include requirements" do
|
87
|
+
expect { tester.ensure_preconditions(:label, nil) }.not_to raise_error
|
88
|
+
end
|
89
|
+
|
90
|
+
it "would fail if requirements were not met" do
|
91
|
+
allow_any_instance_of(Object).to receive(:require).and_raise(LoadError)
|
92
|
+
expect { tester.ensure_preconditions(:label, nil) }.to raise_error(LoadError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "#resolve_options" do
|
97
|
+
it "normalizes labels" do
|
98
|
+
::Unobtainium::Drivers::Appium::LABELS.each do |normalized, aliases|
|
99
|
+
([normalized] + aliases).each do |label|
|
100
|
+
returned_label, _ = tester.resolve_options(label, nil)
|
101
|
+
expect(returned_label).to eql normalized
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "capabilities merging" do
|
107
|
+
let(:caps1) { { foo: 42 } }
|
108
|
+
let(:caps2) { { foo: 123 } }
|
109
|
+
let(:caps3) { { foo: "bar" } }
|
110
|
+
|
111
|
+
it "creates :caps from :desired_capabilities" do
|
112
|
+
_, resolved = tester.resolve_options(:ios, desired_capabilities: caps1)
|
113
|
+
|
114
|
+
expect(resolved[:caps]).not_to be_nil
|
115
|
+
expect(resolved[:caps][:foo]).to eql 42
|
116
|
+
expect(resolved[:desired_capabilites]).to be_nil
|
117
|
+
end
|
118
|
+
|
119
|
+
it "creates :caps from 'desired_capabilities'" do
|
120
|
+
_, resolved = tester.resolve_options(:ios, 'desired_capabilities' => caps1)
|
121
|
+
|
122
|
+
expect(resolved[:caps]).not_to be_nil
|
123
|
+
expect(resolved[:caps][:foo]).to eql 42
|
124
|
+
expect(resolved['desired_capabilities']).to be_nil
|
125
|
+
end
|
126
|
+
|
127
|
+
it "merges :caps with :desired_capabilities" do
|
128
|
+
opts = {
|
129
|
+
desired_capabilities: caps1,
|
130
|
+
caps: caps2
|
131
|
+
}
|
132
|
+
_, resolved = tester.resolve_options(:ios, opts)
|
133
|
+
|
134
|
+
expect(resolved[:caps]).not_to be_nil
|
135
|
+
expect(resolved[:caps][:foo]).to eql 123
|
136
|
+
expect(resolved[:desired_capabilities]).to be_nil
|
137
|
+
end
|
138
|
+
|
139
|
+
it "merges :caps with 'desired_capabilities'" do
|
140
|
+
opts = {
|
141
|
+
'desired_capabilities' => caps1,
|
142
|
+
caps: caps2,
|
143
|
+
}
|
144
|
+
_, resolved = tester.resolve_options(:ios, opts)
|
145
|
+
|
146
|
+
expect(resolved[:caps]).not_to be_nil
|
147
|
+
expect(resolved[:caps][:foo]).to eql 123
|
148
|
+
expect(resolved['desired_capabilities']).to be_nil
|
149
|
+
end
|
150
|
+
|
151
|
+
it "merges :caps with :desired_capabilities and 'desired_capabilities'" do
|
152
|
+
opts = {
|
153
|
+
'desired_capabilities' => caps1,
|
154
|
+
desired_capabilites: caps2,
|
155
|
+
caps: caps3,
|
156
|
+
}
|
157
|
+
_, resolved = tester.resolve_options(:ios, opts)
|
158
|
+
|
159
|
+
expect(resolved[:caps]).not_to be_nil
|
160
|
+
expect(resolved[:caps][:foo]).to eql 'bar'
|
161
|
+
expect(resolved[:desired_capabilities]).to be_nil
|
162
|
+
expect(resolved['desired_capabilities']).to be_nil
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it "adds a normalized platform name" do
|
167
|
+
_, resolved = tester.resolve_options(:iphone, nil)
|
168
|
+
|
169
|
+
expect(resolved['caps.platformName']).to eql 'ios'
|
170
|
+
end
|
171
|
+
|
172
|
+
context "appium URL" do
|
173
|
+
it "uses 'url' when nothing else is given" do
|
174
|
+
_, resolved = tester.resolve_options(:iphone, url: 'test')
|
175
|
+
expect(resolved['url']).to eql 'test'
|
176
|
+
expect(resolved['appium_lib.server_url']).to eql 'test'
|
177
|
+
end
|
178
|
+
|
179
|
+
it "prefers 'appium_lib.server_url' to 'url'" do
|
180
|
+
opts = {
|
181
|
+
url: 'test1',
|
182
|
+
appium_lib: {
|
183
|
+
server_url: 'test2',
|
184
|
+
},
|
185
|
+
}
|
186
|
+
_, resolved = tester.resolve_options(:iphone, opts)
|
187
|
+
expect(resolved['url']).to eql 'test1'
|
188
|
+
expect(resolved['appium_lib.server_url']).to eql 'test2'
|
189
|
+
end
|
190
|
+
|
191
|
+
it "does not set anything if nothing is given" do
|
192
|
+
_, resolved = tester.resolve_options(:iphone, nil)
|
193
|
+
expect(resolved['url']).to be_nil
|
194
|
+
expect(resolved['appium_lib.server_url']).to be_nil
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "browser matching" do
|
199
|
+
it "does nothing if no browser is requested" do
|
200
|
+
_, resolved = tester.resolve_options(:iphone, nil)
|
201
|
+
expect(resolved['caps.browserName']).to be_nil
|
202
|
+
end
|
203
|
+
|
204
|
+
it "does nothing if no browser match is found" do
|
205
|
+
_, resolved = tester.resolve_options(:iphone, browser: :chrome)
|
206
|
+
expect(resolved['caps.browserName']).to be_nil
|
207
|
+
|
208
|
+
_, resolved = tester.resolve_options(:iphone, browser: :safari)
|
209
|
+
expect(resolved['caps.browserName']).to be_nil
|
210
|
+
end
|
211
|
+
|
212
|
+
it "supplements browserName for chrome on android" do
|
213
|
+
_, resolved = tester.resolve_options(:android, browser: :chrome)
|
214
|
+
expect(resolved['caps.browserName']).to eql 'Chrome'
|
215
|
+
end
|
216
|
+
|
217
|
+
it "raises instead of overwriting explicit options" do
|
218
|
+
opts = {
|
219
|
+
browser: :chrome,
|
220
|
+
caps: {
|
221
|
+
platformName: :android,
|
222
|
+
browserName: 'Something Else',
|
223
|
+
}
|
224
|
+
}
|
225
|
+
expect { tester.resolve_options(:android, opts) }.to \
|
226
|
+
raise_error(ArgumentError)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "silently ignores identical options" do
|
230
|
+
opts = {
|
231
|
+
browser: :chrome,
|
232
|
+
caps: {
|
233
|
+
platformName: :android,
|
234
|
+
browserName: 'Chrome',
|
235
|
+
}
|
236
|
+
}
|
237
|
+
resolved = nil
|
238
|
+
expect { _, resolved = tester.resolve_options(:android, opts) }.not_to \
|
239
|
+
raise_error
|
240
|
+
expect(resolved['caps.browserName']).to eql 'Chrome'
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../lib/unobtainium/drivers/phantom'
|
3
|
+
|
4
|
+
class SeleniumMock
|
5
|
+
def test
|
6
|
+
return "selenium"
|
7
|
+
end
|
8
|
+
|
9
|
+
def selenium_only
|
10
|
+
return "selenium"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class AppiumMock
|
15
|
+
def test
|
16
|
+
return "appium"
|
17
|
+
end
|
18
|
+
|
19
|
+
def appium_only
|
20
|
+
return "appium"
|
21
|
+
end
|
22
|
+
|
23
|
+
def start_driver
|
24
|
+
return SeleniumMock.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ::Unobtainium::Drivers::Phantom do
|
29
|
+
let(:tester) { ::Unobtainium::Drivers::Phantom }
|
30
|
+
|
31
|
+
context "#matches?" do
|
32
|
+
it "matches all known aliases" do
|
33
|
+
aliases = [:phantomjs, :headless, :phantom]
|
34
|
+
aliases.each do |name|
|
35
|
+
expect(tester.matches?(name)).to be_truthy
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does not match unknown names" do
|
40
|
+
unknown = [:foo, :bar, :appium, :selenium, :ios]
|
41
|
+
unknown.each do |name|
|
42
|
+
expect(tester.matches?(name)).to be_falsey
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "#ensure_preconditions" do
|
48
|
+
it "will succeed because development dependencies include requirements" do
|
49
|
+
expect { tester.ensure_preconditions(:label, nil) }.not_to raise_error
|
50
|
+
end
|
51
|
+
|
52
|
+
it "would fail if requirements were not met" do
|
53
|
+
allow_any_instance_of(Object).to receive(:require) do |_, name|
|
54
|
+
if name == 'phantomjs'
|
55
|
+
raise LoadError
|
56
|
+
end
|
57
|
+
end
|
58
|
+
expect { tester.ensure_preconditions(:label, nil) }.to raise_error(LoadError)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "#resolve_options" do
|
63
|
+
it "normalizes labels" do
|
64
|
+
::Unobtainium::Drivers::Phantom::LABELS.each do |normalized, aliases|
|
65
|
+
([normalized] + aliases).each do |label|
|
66
|
+
returned_label, _ = tester.resolve_options(label, nil)
|
67
|
+
expect(returned_label).to eql normalized
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "phantomjs options" do
|
73
|
+
it "prefers the string if both :phantomjs and 'phantomjs' are given" do
|
74
|
+
opts = {
|
75
|
+
phantomjs: { scheme: 123 },
|
76
|
+
'phantomjs' => { scheme: 42 },
|
77
|
+
}
|
78
|
+
|
79
|
+
resolved = nil
|
80
|
+
expect { _, resolved = tester.resolve_options(:phantomjs, opts) }.not_to \
|
81
|
+
raise_error
|
82
|
+
expect(resolved['phantomjs.scheme']).to eql 42
|
83
|
+
end
|
84
|
+
|
85
|
+
it "uses :url if that is given" do
|
86
|
+
opts = {
|
87
|
+
url: 'http://localhost:1234',
|
88
|
+
}
|
89
|
+
|
90
|
+
_, resolved = tester.resolve_options(:phantomjs, opts)
|
91
|
+
expect(resolved[:phantomjs]).not_to be_nil
|
92
|
+
expect(resolved['phantomjs.scheme']).to eql 'http'
|
93
|
+
expect(resolved['phantomjs.host']).to eql 'localhost'
|
94
|
+
expect(resolved['phantomjs.port']).to eql 1234
|
95
|
+
expect(resolved['url']).to eql 'http://localhost:1234'
|
96
|
+
end
|
97
|
+
|
98
|
+
it "prefers :phantomjs over :url" do
|
99
|
+
opts = {
|
100
|
+
url: 'http://localhost:1234',
|
101
|
+
phantomjs: {
|
102
|
+
port: 8888
|
103
|
+
},
|
104
|
+
}
|
105
|
+
|
106
|
+
_, resolved = tester.resolve_options(:phantomjs, opts)
|
107
|
+
expect(resolved[:phantomjs]).not_to be_nil
|
108
|
+
expect(resolved['phantomjs.scheme']).to eql 'http'
|
109
|
+
expect(resolved['phantomjs.host']).to eql 'localhost'
|
110
|
+
expect(resolved['phantomjs.port']).to eql 8888
|
111
|
+
expect(resolved['url']).to eql 'http://localhost:8888'
|
112
|
+
end
|
113
|
+
|
114
|
+
it "defaults to 'http' and 'localhost' and a free port" do
|
115
|
+
allow(tester).to receive(:scan) { |*_| [9134] }
|
116
|
+
_, resolved = tester.resolve_options(:phantomjs, nil)
|
117
|
+
expect(resolved[:phantomjs]).not_to be_nil
|
118
|
+
expect(resolved['phantomjs.scheme']).to eql 'http'
|
119
|
+
expect(resolved['phantomjs.host']).to eql 'localhost'
|
120
|
+
expect(resolved['phantomjs.port']).to be_nil
|
121
|
+
expect(resolved['phantomjs.generated_port']).to eql 9134
|
122
|
+
expect(resolved['url']).to eql 'http://localhost:9134'
|
123
|
+
end
|
124
|
+
|
125
|
+
it "raises an error when no free port could be found" do
|
126
|
+
allow(tester).to receive(:scan) { |*_| [] }
|
127
|
+
expect { tester.resolve_options(:phantomjs, nil) }.to \
|
128
|
+
raise_error(RuntimeError)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "driver ID and port" do
|
133
|
+
it "sets a driver ID" do
|
134
|
+
allow(tester).to receive(:scan) { |*_| [9134] }
|
135
|
+
_, resolved = tester.resolve_options(:phantomjs, nil)
|
136
|
+
|
137
|
+
expect(resolved['unobtainium_instance_id']).not_to be_nil
|
138
|
+
end
|
139
|
+
|
140
|
+
it "generates new IDs for new options" do
|
141
|
+
opts = ::Collapsium::UberHash.new(
|
142
|
+
phantomjs: {
|
143
|
+
scheme: 'noodle',
|
144
|
+
port: 1234,
|
145
|
+
}
|
146
|
+
)
|
147
|
+
_, resolved1 = tester.resolve_options(:phantomjs, opts)
|
148
|
+
expect(resolved1['phantomjs.port']).to eql 1234
|
149
|
+
|
150
|
+
opts = opts.deep_dup
|
151
|
+
opts[:phantomjs][:port] = 8888
|
152
|
+
_, resolved2 = tester.resolve_options(:phantomjs, opts)
|
153
|
+
|
154
|
+
# resolved1 must remain untouched by the change
|
155
|
+
expect(resolved1['phantomjs.port']).to eql 1234
|
156
|
+
|
157
|
+
# resolved2 must have the new ID, and the new port
|
158
|
+
expect(resolved1['unobtainium_instance_id']).not_to eql \
|
159
|
+
resolved2['unobtainium_instance_id']
|
160
|
+
expect(resolved2['phantomjs.port']).to eql 8888
|
161
|
+
|
162
|
+
# Urls must differ as well.
|
163
|
+
expect(resolved1[:url]).not_to eql resolved2[:url]
|
164
|
+
end
|
165
|
+
|
166
|
+
it "generates new IDs for changed connection options" do
|
167
|
+
opts = {
|
168
|
+
phantomjs: {
|
169
|
+
scheme: 'noodle',
|
170
|
+
port: 1234,
|
171
|
+
},
|
172
|
+
}
|
173
|
+
_, resolved1 = tester.resolve_options(:phantomjs, opts)
|
174
|
+
expect(resolved1['phantomjs.port']).to eql 1234
|
175
|
+
|
176
|
+
opts = resolved1.deep_dup
|
177
|
+
opts[:phantomjs][:port] = 8888
|
178
|
+
_, resolved2 = tester.resolve_options(:phantomjs, opts)
|
179
|
+
|
180
|
+
# resolved1 must remain untouched by the change
|
181
|
+
expect(resolved1['phantomjs.port']).to eql 1234
|
182
|
+
|
183
|
+
# resolved2 must have the new ID, and the new port
|
184
|
+
expect(resolved1['unobtainium_instance_id']).not_to eql \
|
185
|
+
resolved2['unobtainium_instance_id']
|
186
|
+
expect(resolved2['phantomjs.port']).to eql 8888
|
187
|
+
|
188
|
+
# Urls must differ as well.
|
189
|
+
expect(resolved1[:url]).not_to eql resolved2[:url]
|
190
|
+
end
|
191
|
+
|
192
|
+
it "generates new IDs and port when other options change" do
|
193
|
+
opts = {
|
194
|
+
phantomjs: {
|
195
|
+
scheme: 'noodle',
|
196
|
+
port: 1234,
|
197
|
+
},
|
198
|
+
}
|
199
|
+
_, resolved1 = tester.resolve_options(:phantomjs, opts)
|
200
|
+
expect(resolved1['phantomjs.port']).to eql 1234
|
201
|
+
|
202
|
+
opts = resolved1.deep_dup
|
203
|
+
opts[:foo] = 'something'
|
204
|
+
_, resolved2 = tester.resolve_options(:phantomjs, opts)
|
205
|
+
|
206
|
+
# resolved1 must remain untouched by the change
|
207
|
+
expect(resolved1['phantomjs.port']).to eql 1234
|
208
|
+
|
209
|
+
# resolved2 must have the new ID, and a new port, and also the
|
210
|
+
# extra value.
|
211
|
+
expect(resolved1['unobtainium_instance_id']).not_to eql \
|
212
|
+
resolved2['unobtainium_instance_id']
|
213
|
+
expect(resolved2['phantomjs.port']).not_to eql 1234
|
214
|
+
expect(resolved2[:foo]).to eql 'something'
|
215
|
+
|
216
|
+
# Urls must differ as well.
|
217
|
+
expect(resolved1[:url]).not_to eql resolved2[:url]
|
218
|
+
end
|
219
|
+
|
220
|
+
it "leaves IDs untouched when the port is left undefined" do
|
221
|
+
opts = {
|
222
|
+
phantomjs: {
|
223
|
+
scheme: 'noodle',
|
224
|
+
port: nil,
|
225
|
+
},
|
226
|
+
}
|
227
|
+
_, resolved1 = tester.resolve_options(:phantomjs, opts)
|
228
|
+
expect(resolved1['phantomjs.port']).to be_nil
|
229
|
+
|
230
|
+
opts = resolved1.deep_dup
|
231
|
+
opts[:phantomjs][:port] = nil
|
232
|
+
_, resolved2 = tester.resolve_options(:phantomjs, opts)
|
233
|
+
|
234
|
+
# resolved1 must remain untouched by the change
|
235
|
+
expect(resolved1['phantomjs.port']).to be_nil
|
236
|
+
|
237
|
+
# resolved2 must have the same ID and port
|
238
|
+
expect(resolved1['unobtainium_instance_id']).to eql \
|
239
|
+
resolved2['unobtainium_instance_id']
|
240
|
+
expect(resolved2['phantomjs.port']).to eql resolved1['phantomjs.port']
|
241
|
+
|
242
|
+
# Urls must be the same, too!
|
243
|
+
expect(resolved1[:url]).to eql resolved2[:url]
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../lib/unobtainium/drivers/selenium'
|
3
|
+
|
4
|
+
describe ::Unobtainium::Drivers::Selenium do
|
5
|
+
let(:tester) { ::Unobtainium::Drivers::Selenium }
|
6
|
+
|
7
|
+
context "#matches?" do
|
8
|
+
it "matches all known aliases" do
|
9
|
+
aliases = [
|
10
|
+
:firefox, :ff, :internet_explorer, :internetexplorer, :explorer,
|
11
|
+
:ie, :safari, :chrome, :chromium
|
12
|
+
]
|
13
|
+
aliases.each do |name|
|
14
|
+
expect(tester.matches?(name)).to be_truthy
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "does not match unknown names" do
|
19
|
+
unknown = [:foo, :bar, :appium, :phantomjs, :headless]
|
20
|
+
unknown.each do |name|
|
21
|
+
expect(tester.matches?(name)).to be_falsey
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "#ensure_preconditions" do
|
27
|
+
it "will succeed because development dependencies include requirements" do
|
28
|
+
expect { tester.ensure_preconditions(:label, nil) }.not_to raise_error
|
29
|
+
end
|
30
|
+
|
31
|
+
it "would fail if requirements were not met" do
|
32
|
+
allow_any_instance_of(Object).to receive(:require).and_raise(LoadError)
|
33
|
+
expect { tester.ensure_preconditions(:label, nil) }.to raise_error(LoadError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "#resolve_options" do
|
38
|
+
it "normalizes labels" do
|
39
|
+
::Unobtainium::Drivers::Selenium::LABELS.each do |normalized, aliases|
|
40
|
+
([normalized] + aliases).each do |label|
|
41
|
+
returned_label, _ = tester.resolve_options(label, nil)
|
42
|
+
if normalized == :chromium
|
43
|
+
expect(returned_label).to eql :chrome # chromedriver
|
44
|
+
else
|
45
|
+
expect(returned_label).to eql normalized
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "capabilities merging" do
|
52
|
+
let(:caps1) { { foo: 42 } }
|
53
|
+
let(:caps2) { { foo: 123 } }
|
54
|
+
let(:caps3) { { foo: "bar" } }
|
55
|
+
|
56
|
+
it "creates :desired_capabilites from :caps" do
|
57
|
+
_, resolved = tester.resolve_options(:chrome, caps: caps1)
|
58
|
+
|
59
|
+
expect(resolved[:desired_capabilities]).not_to be_nil
|
60
|
+
expect(resolved[:desired_capabilities][:foo]).to eql 42
|
61
|
+
expect(resolved[:caps]).to be_nil
|
62
|
+
end
|
63
|
+
|
64
|
+
it "creates :desired_capabilites from 'caps'" do
|
65
|
+
_, resolved = tester.resolve_options(:chrome, 'caps' => caps1)
|
66
|
+
|
67
|
+
expect(resolved[:desired_capabilities]).not_to be_nil
|
68
|
+
expect(resolved[:desired_capabilities][:foo]).to eql 42
|
69
|
+
expect(resolved['caps']).to be_nil
|
70
|
+
end
|
71
|
+
|
72
|
+
it "merges :desired_capabilites with :caps" do
|
73
|
+
opts = {
|
74
|
+
caps: caps1,
|
75
|
+
desired_capabilities: caps2,
|
76
|
+
}
|
77
|
+
_, resolved = tester.resolve_options(:chrome, opts)
|
78
|
+
|
79
|
+
expect(resolved[:desired_capabilities]).not_to be_nil
|
80
|
+
expect(resolved[:desired_capabilities][:foo]).to eql 123
|
81
|
+
expect(resolved[:caps]).to be_nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "merges :desired_capabilites with 'caps'" do
|
85
|
+
opts = {
|
86
|
+
'caps' => caps1,
|
87
|
+
desired_capabilities: caps2,
|
88
|
+
}
|
89
|
+
_, resolved = tester.resolve_options(:chrome, opts)
|
90
|
+
|
91
|
+
expect(resolved[:desired_capabilities]).not_to be_nil
|
92
|
+
expect(resolved[:desired_capabilities][:foo]).to eql 123
|
93
|
+
expect(resolved['caps']).to be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
it "merges :desired_capabilites with :caps and 'caps'" do
|
97
|
+
opts = {
|
98
|
+
'caps' => caps1,
|
99
|
+
caps: caps2,
|
100
|
+
desired_capabilities: caps3,
|
101
|
+
}
|
102
|
+
_, resolved = tester.resolve_options(:chrome, opts)
|
103
|
+
|
104
|
+
expect(resolved[:desired_capabilities]).not_to be_nil
|
105
|
+
expect(resolved[:desired_capabilities][:foo]).to eql 'bar'
|
106
|
+
expect(resolved[:caps]).to be_nil
|
107
|
+
expect(resolved['caps']).to be_nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context ":chromium" do
|
112
|
+
it "supplements a binary when one is found" do
|
113
|
+
# Ensure a test result
|
114
|
+
allow_any_instance_of(Object).to receive(:require) {}
|
115
|
+
allow(File).to receive(:which) { '/path/to/binary' }
|
116
|
+
|
117
|
+
label, resolved = tester.resolve_options(:chromium, nil)
|
118
|
+
|
119
|
+
expect(resolved[:desired_capabilities]["chromeOptions"]["binary"]).to \
|
120
|
+
eql '/path/to/binary'
|
121
|
+
expect(label).to eql :chrome
|
122
|
+
end
|
123
|
+
|
124
|
+
it "returns the label and options unaltered when no binary is found" do
|
125
|
+
# Ensure a test result
|
126
|
+
allow_any_instance_of(Object).to receive(:require) {}
|
127
|
+
allow(File).to receive(:which) { nil }
|
128
|
+
|
129
|
+
label, resolved = tester.resolve_options(:chromium, nil)
|
130
|
+
|
131
|
+
expect(resolved[:desired_capabilities]["chromeOptions"]).to be_nil
|
132
|
+
expect(label).to eql :chromium
|
133
|
+
end
|
134
|
+
|
135
|
+
it "does not overwrite binaries if they are set" do
|
136
|
+
# Ensure a test result
|
137
|
+
allow_any_instance_of(Object).to receive(:require) {}
|
138
|
+
allow(File).to receive(:which) { '/path/to/binary' }
|
139
|
+
|
140
|
+
opts = {
|
141
|
+
desired_capabilities: {
|
142
|
+
chromeOptions: {
|
143
|
+
binary: 'test',
|
144
|
+
},
|
145
|
+
},
|
146
|
+
}
|
147
|
+
label, resolved = tester.resolve_options(:chromium, opts)
|
148
|
+
|
149
|
+
expect(resolved[:desired_capabilities]["chromeOptions"]["binary"]).to \
|
150
|
+
eql 'test'
|
151
|
+
expect(label).to eql :chrome
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "fixing options" do
|
156
|
+
it "symbolies option keys" do
|
157
|
+
opts = {
|
158
|
+
"foo" => "bar",
|
159
|
+
baz: 42,
|
160
|
+
}
|
161
|
+
_, resolved = tester.resolve_options(:chromium, opts)
|
162
|
+
|
163
|
+
expect(resolved["foo"]).to be_nil
|
164
|
+
expect(resolved[:foo]).to eql "bar"
|
165
|
+
expect(resolved["baz"]).to be_nil
|
166
|
+
expect(resolved[:baz]).to eql 42
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/spec/mock_driver.rb
CHANGED
@@ -24,4 +24,27 @@ class MockDriver
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end # class MockDriver
|
27
|
+
|
28
|
+
class OptionResolvingMockDriver < MockDriver
|
29
|
+
class << self
|
30
|
+
def matches?(label)
|
31
|
+
label == :option_resolving
|
32
|
+
end
|
33
|
+
|
34
|
+
def resolve_options(label, options)
|
35
|
+
if options
|
36
|
+
opts = options.dup
|
37
|
+
end
|
38
|
+
opts ||= {}
|
39
|
+
|
40
|
+
if opts[:foo] == 123 or opts[:foo].nil?
|
41
|
+
opts[:foo] = 42
|
42
|
+
end
|
43
|
+
|
44
|
+
opts["unobtainium_instance_id"] = 'FIXED'
|
45
|
+
|
46
|
+
return label, opts
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # class OptionResolvingMockDriver
|
27
50
|
# rubocop:enable Style/GuardClause
|