mediawiki_selenium 0.4.3 → 1.0.0.pre.1
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/.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
|