mediawiki_selenium 0.4.3 → 1.0.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitreview +1 -1
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/Gemfile +1 -1
- data/README.md +108 -55
- data/bin/mediawiki-selenium-init +5 -0
- data/lib/mediawiki_selenium.rb +10 -19
- data/lib/mediawiki_selenium/browser_factory.rb +24 -0
- data/lib/mediawiki_selenium/browser_factory/base.rb +212 -0
- data/lib/mediawiki_selenium/browser_factory/chrome.rb +27 -0
- data/lib/mediawiki_selenium/browser_factory/firefox.rb +34 -0
- data/lib/mediawiki_selenium/browser_factory/phantomjs.rb +21 -0
- data/lib/mediawiki_selenium/configuration_error.rb +4 -0
- data/lib/mediawiki_selenium/environment.rb +494 -0
- data/lib/mediawiki_selenium/initializer.rb +19 -0
- data/lib/mediawiki_selenium/page_factory.rb +38 -0
- data/lib/mediawiki_selenium/remote_browser_factory.rb +87 -0
- data/lib/mediawiki_selenium/step_definitions.rb +5 -0
- data/lib/mediawiki_selenium/support.rb +3 -0
- data/lib/mediawiki_selenium/support/env.rb +3 -127
- data/lib/mediawiki_selenium/support/hooks.rb +23 -34
- data/lib/mediawiki_selenium/support/modules/api_helper.rb +44 -5
- data/lib/mediawiki_selenium/support/pages.rb +4 -0
- data/lib/mediawiki_selenium/support/pages/api_page.rb +1 -0
- data/lib/mediawiki_selenium/support/pages/login_page.rb +3 -12
- data/lib/mediawiki_selenium/support/pages/random_page.rb +2 -12
- data/lib/mediawiki_selenium/support/pages/reset_preferences_page.rb +3 -12
- data/lib/mediawiki_selenium/version.rb +1 -1
- data/mediawiki_selenium.gemspec +9 -3
- data/spec/api_helper_spec.rb +84 -0
- data/spec/browser_factory/base_spec.rb +211 -0
- data/spec/browser_factory/chrome_spec.rb +36 -0
- data/spec/browser_factory/firefox_spec.rb +60 -0
- data/spec/browser_factory/phantomjs_spec.rb +38 -0
- data/spec/environment_spec.rb +474 -0
- data/spec/page_factory_spec.rb +61 -0
- data/spec/remote_browser_factory_spec.rb +50 -0
- data/spec/spec_helper.rb +4 -0
- data/templates/tests/browser/environments.yml +35 -0
- data/templates/tests/browser/features/support/env.rb +6 -0
- metadata +122 -20
- data/lib/mediawiki_selenium/support/modules/sauce_helper.rb +0 -13
- data/lib/mediawiki_selenium/support/modules/url_module.rb +0 -21
- data/spec/README +0 -2
@@ -0,0 +1,27 @@
|
|
1
|
+
module MediawikiSelenium
|
2
|
+
module BrowserFactory
|
3
|
+
# Constructs new Chrome browser instances. The following configuration is
|
4
|
+
# supported.
|
5
|
+
#
|
6
|
+
# - browser_language
|
7
|
+
# - browser_user_agent
|
8
|
+
#
|
9
|
+
# @see Base
|
10
|
+
#
|
11
|
+
class Chrome < Base
|
12
|
+
bind(:browser_language) do |language, options|
|
13
|
+
options[:prefs]["intl.accept_languages"] = language
|
14
|
+
end
|
15
|
+
|
16
|
+
bind(:browser_user_agent) do |user_agent, options|
|
17
|
+
options[:args] << "--user-agent=#{user_agent}"
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def default_browser_options
|
23
|
+
super.merge(args: [], prefs: {})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module MediawikiSelenium
|
2
|
+
module BrowserFactory
|
3
|
+
# Constructs new Firefox browser instances. The following configuration is
|
4
|
+
# supported.
|
5
|
+
#
|
6
|
+
# - browser_language
|
7
|
+
# - browser_timeout
|
8
|
+
# - browser_user_agent
|
9
|
+
#
|
10
|
+
# @see Base
|
11
|
+
#
|
12
|
+
class Firefox < Base
|
13
|
+
bind(:browser_timeout) do |timeout, options|
|
14
|
+
timeout = timeout.to_i
|
15
|
+
options[:profile]["dom.max_script_run_time"] = timeout
|
16
|
+
options[:profile]["dom.max_chrome_script_run_time"] = timeout
|
17
|
+
end
|
18
|
+
|
19
|
+
bind(:browser_language) do |language, options|
|
20
|
+
options[:profile]["intl.accept_languages"] = language
|
21
|
+
end
|
22
|
+
|
23
|
+
bind(:browser_user_agent) do |user_agent, options|
|
24
|
+
options[:profile]["general.useragent.override"] = user_agent
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def default_browser_options
|
30
|
+
super.merge(profile: Selenium::WebDriver::Firefox::Profile.new)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MediawikiSelenium
|
2
|
+
module BrowserFactory
|
3
|
+
# Constructs new Phantomjs browser instances. The following configuration is
|
4
|
+
# supported.
|
5
|
+
#
|
6
|
+
# - browser_language
|
7
|
+
# - browser_user_agent
|
8
|
+
#
|
9
|
+
# @see Base
|
10
|
+
#
|
11
|
+
class Phantomjs < Base
|
12
|
+
bind(:browser_language) do |language, options|
|
13
|
+
options[:desired_capabilities]["phantomjs.page.customHeaders.Accept-Language"] = language
|
14
|
+
end
|
15
|
+
|
16
|
+
bind(:browser_user_agent) do |user_agent, options|
|
17
|
+
options[:desired_capabilities]["phantomjs.page.settings.userAgent"] = user_agent
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,494 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module MediawikiSelenium
|
4
|
+
# Provides an interface that unifies environmental configuration, page
|
5
|
+
# objects, and browser setup. Additionally, it provides a DSL for switching
|
6
|
+
# between user/wiki/browser contexts in ways that help to decouple test
|
7
|
+
# implementation from the target wikis.
|
8
|
+
#
|
9
|
+
# Default configuration for various resources (wiki URLs, users, etc.) is
|
10
|
+
# typically loaded from an `environments.yml` YAML file in the current
|
11
|
+
# working directory. It should contain defaults for each environment in
|
12
|
+
# which the tests are expected to run, indexed by environment name.
|
13
|
+
#
|
14
|
+
# beta:
|
15
|
+
# mediawiki_url: http://en.wikipedia.beta.wmflabs.org/wiki/
|
16
|
+
# mediawiki_user: Selenium_user
|
17
|
+
# test2:
|
18
|
+
# mediawiki_url: http://test2.wikipedia.org/wiki/
|
19
|
+
# mediawiki_user: Selenium_user
|
20
|
+
#
|
21
|
+
# Which default set to use is determined by the value of the
|
22
|
+
# `MEDIAWIKI_ENVIRONMENT` environment variable. (See {load} and
|
23
|
+
# {load_default}.)
|
24
|
+
#
|
25
|
+
# Any additional configuration specified via environment variables overrides
|
26
|
+
# what is specified in the YAML file. For example, the following would use
|
27
|
+
# the default configuration as specified under `beta` in the YAML file but
|
28
|
+
# define `mediawiki_user` as `Other_user` instead of `Selenium_user`.
|
29
|
+
#
|
30
|
+
# export MEDIAWIKI_ENVIRONMENT=beta MEDIAWIKI_USER=Other_user
|
31
|
+
# bundle exec cucumber ...
|
32
|
+
#
|
33
|
+
# There are various methods that allow you to perform actions in the context
|
34
|
+
# of some alternative resource, for example as a different user using
|
35
|
+
# {#as_user}, or on different wiki using {#on_wiki}. Instead of referencing
|
36
|
+
# the exact user names or URLs for these resources, you reference them by an
|
37
|
+
# ID which corresponds to configuration made in `environments.yml`.
|
38
|
+
#
|
39
|
+
# # environments.yml:
|
40
|
+
# beta:
|
41
|
+
# # ...
|
42
|
+
# mediawiki_user_b: Selenium_user2
|
43
|
+
#
|
44
|
+
# # step definition:
|
45
|
+
# Given(/^user B has linked to a page I created$/) do
|
46
|
+
# as_user(:b) { api.create_page(...) }
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# This level of abstraction is intended to reduce coupling between tests
|
50
|
+
# and test environments, and should promote step definitions that are more
|
51
|
+
# readable and congruent with the natural-language steps they implement.
|
52
|
+
#
|
53
|
+
class Environment
|
54
|
+
include Comparable
|
55
|
+
|
56
|
+
class << self
|
57
|
+
attr_accessor :default_configuration
|
58
|
+
|
59
|
+
# Instantiates a new environment using the given set of default
|
60
|
+
# configuration from `environments.yml` in the current working
|
61
|
+
# directory, and the additional hash of environment variables.
|
62
|
+
#
|
63
|
+
# @param name [String] Name of the environment.
|
64
|
+
# @param extra [Hash] Additional configuration to use.
|
65
|
+
#
|
66
|
+
def load(name, extra = {})
|
67
|
+
name = name.to_s
|
68
|
+
configs = []
|
69
|
+
|
70
|
+
unless name.empty?
|
71
|
+
envs = YAML.load_file(default_configuration)
|
72
|
+
raise ConfigurationError, "unknown environment `#{name}`" unless envs.include?(name)
|
73
|
+
configs << envs[name]
|
74
|
+
end
|
75
|
+
|
76
|
+
configs << extra
|
77
|
+
|
78
|
+
new(*configs)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Instantiates a new environment from the values of `ENV` and the
|
82
|
+
# default configuration corresponding to `ENV["MEDIAWIKI_ENVIRONMENT"]`,
|
83
|
+
# if one is defined.
|
84
|
+
#
|
85
|
+
# @see load
|
86
|
+
#
|
87
|
+
def load_default
|
88
|
+
load(ENV["MEDIAWIKI_ENVIRONMENT"], ENV)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
self.default_configuration = "environments.yml"
|
93
|
+
|
94
|
+
def initialize(*configs)
|
95
|
+
@_config = configs.map { |config| normalize_config(config) }.reduce(:merge)
|
96
|
+
@_factory_cache = {}
|
97
|
+
end
|
98
|
+
|
99
|
+
# Whether the given environment is equal to this one. Two environments are
|
100
|
+
# considered equal if they have identical configuration.
|
101
|
+
#
|
102
|
+
# @param other [Environment]
|
103
|
+
#
|
104
|
+
# @return [Boolean]
|
105
|
+
#
|
106
|
+
def ==(other)
|
107
|
+
config == other.config
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns the configured value for the given env variable name.
|
111
|
+
#
|
112
|
+
# @see #lookup
|
113
|
+
#
|
114
|
+
# @param key [Symbol] Environment variable name.
|
115
|
+
#
|
116
|
+
# @return [String]
|
117
|
+
#
|
118
|
+
def [](key)
|
119
|
+
lookup(key)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Executes the given block within the context of an environment that's
|
123
|
+
# using the given alternative user and its password.
|
124
|
+
#
|
125
|
+
# @example
|
126
|
+
# Given(/^user B has linked to a page I created$/) do
|
127
|
+
# as_user(:b) { api.create_page(...) }
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# @param id [Symbol] Alternative user ID.
|
131
|
+
#
|
132
|
+
# @yield [user, password]
|
133
|
+
# @yieldparam user [String] Alternative MediaWiki user.
|
134
|
+
# @yieldparam password [String] Alternative MediaWiki password.
|
135
|
+
#
|
136
|
+
def as_user(id, &blk)
|
137
|
+
user = lookup(:mediawiki_user, id: id)
|
138
|
+
password = lookup(:mediawiki_password, id: id, default: -> { lookup(:mediawiki_password) })
|
139
|
+
|
140
|
+
with(mediawiki_user: user, mediawiki_password: password, &blk)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Browser with which to drive tests.
|
144
|
+
#
|
145
|
+
# @return [Watir::Browser]
|
146
|
+
#
|
147
|
+
def browser
|
148
|
+
browser_factory.browser_for(browser_config)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Factory used to instantiate and open new browsers.
|
152
|
+
#
|
153
|
+
# @param browser [Symbol] Browser name.
|
154
|
+
#
|
155
|
+
# @return [BrowserFactory::Base]
|
156
|
+
#
|
157
|
+
def browser_factory(browser = browser_name)
|
158
|
+
browser = browser.to_s.downcase.to_sym
|
159
|
+
|
160
|
+
@_factory_cache[[remote?, browser]] ||= BrowserFactory.new(browser).tap do |factory|
|
161
|
+
factory.bind(:_browser_session)
|
162
|
+
factory.extend(RemoteBrowserFactory) if remote?
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Name of the browser we're using.
|
167
|
+
#
|
168
|
+
# @return [Symbol]
|
169
|
+
#
|
170
|
+
def browser_name
|
171
|
+
lookup(:browser, default: "firefox").downcase.to_sym
|
172
|
+
end
|
173
|
+
|
174
|
+
# A reference to this environment. Can be used in conjunction with {#[]}
|
175
|
+
# for syntactic sugar in looking up environment configuration where `self`
|
176
|
+
# would otherwise seem ambiguous.
|
177
|
+
#
|
178
|
+
# @example
|
179
|
+
# Then(/^I see my username on the page$/) do
|
180
|
+
# expect(on(SomePage).html).to include(env[:mediawiki_user])
|
181
|
+
# end
|
182
|
+
#
|
183
|
+
# @return [self]
|
184
|
+
#
|
185
|
+
def env
|
186
|
+
self
|
187
|
+
end
|
188
|
+
|
189
|
+
# Executes the given block within the context of an environment that uses
|
190
|
+
# a unique browser session and possibly different configuration. Note that
|
191
|
+
# any given configuration overrides are scoped with a `:browser_` prefix.
|
192
|
+
#
|
193
|
+
# @example Implement a "logged out" step following some authenticated one
|
194
|
+
# When(/^I do something while logged in$/) do
|
195
|
+
# in_browser(:a) do
|
196
|
+
# # perform action in logged in session
|
197
|
+
# end
|
198
|
+
# end
|
199
|
+
#
|
200
|
+
# When(/^I do something else after logging out$/) do
|
201
|
+
# in_browser(:b) do
|
202
|
+
# # perform action in logged out session without actually logging
|
203
|
+
# # out since that would affect all auth sessions for the user
|
204
|
+
# end
|
205
|
+
# end
|
206
|
+
#
|
207
|
+
# @example Perform a subsequent step requiring a different browser language
|
208
|
+
# When(/^I visit the same page with my browser in Spanish$/) do |scenario, block|
|
209
|
+
# in_browser(:a, language: "es") do
|
210
|
+
# # test that it now serves up Spanish text
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
#
|
214
|
+
# @param id [Symbol] Browser session ID.
|
215
|
+
# @param overrides [Hash] Browser configuration overrides.
|
216
|
+
#
|
217
|
+
# @yield [*args] Overridden browser configuration.
|
218
|
+
#
|
219
|
+
def in_browser(id, overrides = {}, &blk)
|
220
|
+
overrides = overrides.each.with_object({}) do |(name, value), hash|
|
221
|
+
hash["browser_#{name}".to_sym] = value
|
222
|
+
end
|
223
|
+
|
224
|
+
with(overrides.merge(_browser_session: id), &blk)
|
225
|
+
end
|
226
|
+
|
227
|
+
# Whether browsers should be left open after each scenario completes.
|
228
|
+
#
|
229
|
+
def keep_browser_open?
|
230
|
+
lookup(:keep_browser_open, default: "false") == "true"
|
231
|
+
end
|
232
|
+
|
233
|
+
# Returns the configured value for the given env variable name.
|
234
|
+
#
|
235
|
+
# @example Value of `:browser_language` and fail if it wasn't provided
|
236
|
+
# env.lookup(:browser_language)
|
237
|
+
#
|
238
|
+
# @example Value of `:browser_language` alternative `:b`
|
239
|
+
# env.lookup(:browser_language, id: :b)
|
240
|
+
#
|
241
|
+
# @example Value of `:browser_language` or try `:browser_lang`
|
242
|
+
# env.lookup(:browser_language, default: -> { env.lookup(:browser_lang) })
|
243
|
+
#
|
244
|
+
# @param key [Symbol] Environment variable name.
|
245
|
+
# @param options [Hash] Options.
|
246
|
+
# @option options [Symbol] :id Alternative ID.
|
247
|
+
# @option options [Object, Proc] :default Default value or promise of a value.
|
248
|
+
#
|
249
|
+
# @return [String]
|
250
|
+
#
|
251
|
+
def lookup(key, options = {})
|
252
|
+
key = "#{key}_#{options[:id]}" if options.fetch(:id, nil)
|
253
|
+
key = normalize_key(key)
|
254
|
+
|
255
|
+
value = config[key]
|
256
|
+
|
257
|
+
if value.nil? || value.to_s.empty?
|
258
|
+
if options.include?(:default)
|
259
|
+
options[:default].is_a?(Proc) ? options[:default].call : options[:default]
|
260
|
+
else
|
261
|
+
raise ConfigurationError, "missing configuration for `#{key}`"
|
262
|
+
end
|
263
|
+
else
|
264
|
+
value
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# Returns the configured values for the given env variable names.
|
269
|
+
#
|
270
|
+
# @param keys [Array<Symbol>] Environment variable names.
|
271
|
+
# @param options [Hash] Options.
|
272
|
+
# @option options [Symbol] :id Alternative ID.
|
273
|
+
# @option options [Object] :default Default if no configuration is found.
|
274
|
+
#
|
275
|
+
# @return [Array<String>]
|
276
|
+
#
|
277
|
+
# @see #lookup
|
278
|
+
#
|
279
|
+
def lookup_all(keys, options = {})
|
280
|
+
keys.each.with_object({}) do |key, hash|
|
281
|
+
hash[key] = lookup(key, options)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Executes the given block within the context of an environment that's
|
286
|
+
# using the given alternative wiki URL and its corresponding API endpoint.
|
287
|
+
#
|
288
|
+
# If no API URL is explicitly defined for the given alternative, one is
|
289
|
+
# constructed relative to the wiki URL.
|
290
|
+
#
|
291
|
+
# @example Visit a random page on wiki B
|
292
|
+
# on_wiki(:b) { visit(RandomPage) }
|
293
|
+
#
|
294
|
+
# @param id [Symbol] Alternative wiki ID.
|
295
|
+
#
|
296
|
+
# @yield [wiki_url]
|
297
|
+
# @yieldparam wiki_url [String] Alternative wiki URL.
|
298
|
+
#
|
299
|
+
def on_wiki(id, &blk)
|
300
|
+
with_alternative(:mediawiki_url, id, &blk)
|
301
|
+
end
|
302
|
+
|
303
|
+
# Returns the current value for `:mediawiki_password` or the value for the
|
304
|
+
# given alternative.
|
305
|
+
#
|
306
|
+
# @param id [Symbol] Alternative user ID.
|
307
|
+
#
|
308
|
+
# @return [String]
|
309
|
+
#
|
310
|
+
def password(id = nil)
|
311
|
+
lookup(password_variable, id: id)
|
312
|
+
end
|
313
|
+
|
314
|
+
# Whether this environment has been configured to use remote browser
|
315
|
+
# sessions.
|
316
|
+
#
|
317
|
+
# @return [Boolean]
|
318
|
+
#
|
319
|
+
def remote?
|
320
|
+
RemoteBrowserFactory::REQUIRED_CONFIG.all? { |name| lookup(name, default: false) }
|
321
|
+
end
|
322
|
+
|
323
|
+
# Executes teardown tasks including instructing all browser factories to
|
324
|
+
# close any open browsers and perform their own teardown tasks.
|
325
|
+
#
|
326
|
+
# @example Teardown environment resources after each scenario completes
|
327
|
+
# After do
|
328
|
+
# teardown(scenario.status)
|
329
|
+
# end
|
330
|
+
#
|
331
|
+
# @param status [Symbol] Status of the executed scenario.
|
332
|
+
#
|
333
|
+
# @yield [browser]
|
334
|
+
# @yieldparam browser [Watir::Browser] Browser object, before it's closed.
|
335
|
+
#
|
336
|
+
def teardown(status = :passed)
|
337
|
+
@_factory_cache.each do |_, factory|
|
338
|
+
factory.each do |browser|
|
339
|
+
yield browser if block_given?
|
340
|
+
browser.close unless keep_browser_open?
|
341
|
+
end
|
342
|
+
|
343
|
+
factory.teardown(self, status)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
# Returns a name from the given scenario.
|
348
|
+
#
|
349
|
+
# @param scenario [Cucumber::Ast::Scenario]
|
350
|
+
#
|
351
|
+
# @return [String]
|
352
|
+
#
|
353
|
+
def test_name(scenario)
|
354
|
+
if scenario.respond_to? :feature
|
355
|
+
"#{scenario.feature.title}: #{scenario.title}"
|
356
|
+
elsif scenario.respond_to? :scenario_outline
|
357
|
+
"#{scenario.scenario_outline.feature.title}: #{scenario.scenario_outline.title}: #{scenario.name}"
|
358
|
+
else
|
359
|
+
scenario.name
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# Returns the current value for `:mediawiki_user` or the value for the
|
364
|
+
# given alternative.
|
365
|
+
#
|
366
|
+
# @param id [Symbol] Alternative user ID.
|
367
|
+
#
|
368
|
+
# @return [String]
|
369
|
+
#
|
370
|
+
def user(id = nil)
|
371
|
+
lookup(:mediawiki_user, id: id)
|
372
|
+
end
|
373
|
+
|
374
|
+
# Returns the current user, or the one for the given alternative, with all
|
375
|
+
# "_" replaced with " ".
|
376
|
+
#
|
377
|
+
# @param id [Symbol] Alternative user ID.
|
378
|
+
#
|
379
|
+
# @return [String]
|
380
|
+
#
|
381
|
+
def user_label(id = nil)
|
382
|
+
user(id).gsub("_", " ")
|
383
|
+
end
|
384
|
+
|
385
|
+
# Navigates the current browser to the given wiki.
|
386
|
+
#
|
387
|
+
# @param id [Symbol] Alternative wiki ID.
|
388
|
+
#
|
389
|
+
# @yield [url]
|
390
|
+
# @yieldparam url [String] Wiki URL.
|
391
|
+
#
|
392
|
+
def visit_wiki(id)
|
393
|
+
on_wiki(id) do |url|
|
394
|
+
browser.goto url
|
395
|
+
yield url if block_given?
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
# Qualifies any given relative path using the configured `:mediawiki_url`.
|
400
|
+
# Absolute URLs are left untouched.
|
401
|
+
#
|
402
|
+
# @example
|
403
|
+
# env = Environment.new(mediawiki_url: "http://an.example/wiki/")
|
404
|
+
#
|
405
|
+
# env.wiki_url # => "http://an.example/wiki/"
|
406
|
+
# env.wiki_url("page") # => "http://an.example/wiki/page"
|
407
|
+
# env.wiki_url("/page") # => "http://an.example/page"
|
408
|
+
# env.wiki_url("http://other.example") # => "http://other.example"
|
409
|
+
#
|
410
|
+
def wiki_url(path = nil)
|
411
|
+
url = lookup(:mediawiki_url)
|
412
|
+
|
413
|
+
if path
|
414
|
+
# Prefixing relative paths with an explicit "./" guarantees proper
|
415
|
+
# parsing of paths like "Special:Page" that would otherwise be
|
416
|
+
# confused for URI schemes.
|
417
|
+
if path.include?(":")
|
418
|
+
path_uri = URI.parse(path)
|
419
|
+
path = "./#{path}" if path_uri.class == URI::Generic && !path.start_with?("/")
|
420
|
+
end
|
421
|
+
|
422
|
+
url = URI.parse(url).merge(path).to_s
|
423
|
+
end
|
424
|
+
|
425
|
+
url
|
426
|
+
end
|
427
|
+
|
428
|
+
# Executes the given block within the context of a new environment
|
429
|
+
# configured using the alternative versions of the given options. The
|
430
|
+
# alternative configuration values are resolved using the given ID and
|
431
|
+
# passed to the block as arguments.
|
432
|
+
#
|
433
|
+
# @example Overwrite :foo with the :b alternative
|
434
|
+
# # given an environment with config { foo: "x", foo_b: "y", ... }
|
435
|
+
# with_alternative(:foo, :b) do |foo|
|
436
|
+
# self # => #<Environment @config = { foo: "y", ... }>
|
437
|
+
# foo # => "y"
|
438
|
+
# end
|
439
|
+
#
|
440
|
+
# @example Overwrite both :foo and :bar with the :b alternatives
|
441
|
+
# # given an environment with config { foo: "x", foo_b: "y", bar: "w", bar_b: "z" }
|
442
|
+
# with_alternative([:foo, :bar], :b) do |foo, bar|
|
443
|
+
# self # => #<Environment @config = { foo: "y", bar: "z", ... }>
|
444
|
+
# foo # => "y"
|
445
|
+
# bar # => "z"
|
446
|
+
# end
|
447
|
+
#
|
448
|
+
# @param names [Symbol|Array<Symbol>] Configuration option or options.
|
449
|
+
# @param id [Symbol] Alternative user ID.
|
450
|
+
#
|
451
|
+
# @yield [*args] Values of the overridden configuration.
|
452
|
+
#
|
453
|
+
def with_alternative(names, id, &blk)
|
454
|
+
with(lookup_all(Array(names), id: id), &blk)
|
455
|
+
end
|
456
|
+
|
457
|
+
protected
|
458
|
+
|
459
|
+
def config
|
460
|
+
@_config
|
461
|
+
end
|
462
|
+
|
463
|
+
private
|
464
|
+
|
465
|
+
def browser_config
|
466
|
+
lookup_all(browser_factory.all_binding_keys, default: nil).reject { |k, v| v.nil? }
|
467
|
+
end
|
468
|
+
|
469
|
+
def password_variable
|
470
|
+
name = lookup(:mediawiki_password_variable, default: "")
|
471
|
+
name.empty? ? :mediawiki_password : normalize_key(name)
|
472
|
+
end
|
473
|
+
|
474
|
+
def normalize_config(hash)
|
475
|
+
hash.each.with_object({}) { |(k, v), acc| acc[normalize_key(k)] = v }
|
476
|
+
end
|
477
|
+
|
478
|
+
def normalize_key(key)
|
479
|
+
key.to_s.downcase.to_sym
|
480
|
+
end
|
481
|
+
|
482
|
+
def with(overrides = {})
|
483
|
+
overrides = normalize_config(overrides)
|
484
|
+
original_config = @_config.dup
|
485
|
+
|
486
|
+
begin
|
487
|
+
@_config = @_config.merge(overrides)
|
488
|
+
yield *overrides.values if block_given?
|
489
|
+
ensure
|
490
|
+
@_config = original_config
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|