akephalos2-stable 2.1.1.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.
- data/MIT_LICENSE +20 -0
- data/README.md +365 -0
- data/bin/akephalos +110 -0
- data/lib/akephalos.rb +16 -0
- data/lib/akephalos/capybara.rb +348 -0
- data/lib/akephalos/client.rb +192 -0
- data/lib/akephalos/client/cookies.rb +73 -0
- data/lib/akephalos/client/filter.rb +120 -0
- data/lib/akephalos/configuration.rb +49 -0
- data/lib/akephalos/console.rb +32 -0
- data/lib/akephalos/cucumber.rb +6 -0
- data/lib/akephalos/htmlunit.rb +31 -0
- data/lib/akephalos/htmlunit/ext/confirm_handler.rb +18 -0
- data/lib/akephalos/htmlunit/ext/http_method.rb +30 -0
- data/lib/akephalos/htmlunit_downloader.rb +38 -0
- data/lib/akephalos/node.rb +187 -0
- data/lib/akephalos/page.rb +118 -0
- data/lib/akephalos/remote_client.rb +93 -0
- data/lib/akephalos/server.rb +79 -0
- data/lib/akephalos/version.rb +3 -0
- metadata +158 -0
data/lib/akephalos.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# **Akephalos** is a cross-platform Ruby interface for *HtmlUnit*, a headless
|
2
|
+
# browser for the Java platform.
|
3
|
+
#
|
4
|
+
# The only requirement is that a Java runtime is available.
|
5
|
+
#
|
6
|
+
require 'java' if RUBY_PLATFORM == 'java'
|
7
|
+
require 'pathname'
|
8
|
+
|
9
|
+
module Akephalos
|
10
|
+
BIN_DIR = Pathname(__FILE__).expand_path.dirname.parent + 'bin'
|
11
|
+
ENV['htmlunit_version'] ||= "2.9"
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'akephalos/client'
|
15
|
+
require 'capybara'
|
16
|
+
require 'akephalos/capybara'
|
@@ -0,0 +1,348 @@
|
|
1
|
+
# Driver class exposed to Capybara. It implements Capybara's full driver API,
|
2
|
+
# and is the entry point for interaction between the test suites and HtmlUnit.
|
3
|
+
#
|
4
|
+
# This class and +Capybara::Driver::Akephalos::Node+ are written to run on both
|
5
|
+
# MRI and JRuby, and is agnostic whether the Akephalos::Client instance is used
|
6
|
+
# directly or over DRb.
|
7
|
+
class Capybara::Driver::Akephalos < Capybara::Driver::Base
|
8
|
+
|
9
|
+
# Akephalos-specific implementation for Capybara's Driver::Node class.
|
10
|
+
class Node < Capybara::Driver::Node
|
11
|
+
|
12
|
+
# @api capybara
|
13
|
+
# @return [String] the inner text of the node
|
14
|
+
def text
|
15
|
+
native.text
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api capybara
|
19
|
+
# @param [String] name attribute name
|
20
|
+
# @return [String] the attribute value
|
21
|
+
def [](name)
|
22
|
+
name = name.to_s
|
23
|
+
case name
|
24
|
+
when 'checked'
|
25
|
+
native.checked?
|
26
|
+
else
|
27
|
+
native[name.to_s]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @api capybara
|
32
|
+
# @return [String, Array<String>] the form element's value
|
33
|
+
def value
|
34
|
+
native.value
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set the form element's value.
|
38
|
+
#
|
39
|
+
# @api capybara
|
40
|
+
# @param [String] value the form element's new value
|
41
|
+
def set(value)
|
42
|
+
if tag_name == 'textarea'
|
43
|
+
native.value = value.to_s
|
44
|
+
elsif tag_name == 'input' and type == 'radio'
|
45
|
+
click
|
46
|
+
elsif tag_name == 'input' and type == 'checkbox'
|
47
|
+
if value != self['checked']
|
48
|
+
click
|
49
|
+
end
|
50
|
+
elsif tag_name == 'input'
|
51
|
+
native.value = value.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# @api capybara
|
56
|
+
def select_option
|
57
|
+
#if it is already selected: do nothing
|
58
|
+
#if it isn't selected: click on it
|
59
|
+
native.click unless selected?
|
60
|
+
end
|
61
|
+
|
62
|
+
# Unselect an option from a select box.
|
63
|
+
#
|
64
|
+
# @api capybara
|
65
|
+
def unselect_option
|
66
|
+
unless select_node.multiple_select?
|
67
|
+
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
|
68
|
+
end
|
69
|
+
|
70
|
+
native.unselect
|
71
|
+
end
|
72
|
+
|
73
|
+
# Click the element.
|
74
|
+
def click
|
75
|
+
native.click
|
76
|
+
end
|
77
|
+
|
78
|
+
# Drag the element on top of the target element.
|
79
|
+
#
|
80
|
+
# @api capybara
|
81
|
+
# @param [Node] element the target element
|
82
|
+
def drag_to(element)
|
83
|
+
trigger('mousedown')
|
84
|
+
element.trigger('mousemove')
|
85
|
+
element.trigger('mouseup')
|
86
|
+
end
|
87
|
+
|
88
|
+
# @api capybara
|
89
|
+
# @return [String] the element's tag name
|
90
|
+
def tag_name
|
91
|
+
native.tag_name
|
92
|
+
end
|
93
|
+
|
94
|
+
# @api capybara
|
95
|
+
# @return [true, false] the element's visiblity
|
96
|
+
def visible?
|
97
|
+
native.visible?
|
98
|
+
end
|
99
|
+
|
100
|
+
# @api capybara
|
101
|
+
# @return [true, false] the element's visiblity
|
102
|
+
def checked?
|
103
|
+
native.checked?
|
104
|
+
end
|
105
|
+
|
106
|
+
# @api capybara
|
107
|
+
# @return [true, false] the element's visiblity
|
108
|
+
def selected?
|
109
|
+
native.selected?
|
110
|
+
end
|
111
|
+
|
112
|
+
# @api capybara
|
113
|
+
# @return [String] the XPath to locate the node
|
114
|
+
def path
|
115
|
+
native.xpath
|
116
|
+
end
|
117
|
+
|
118
|
+
# Trigger an event on the element.
|
119
|
+
#
|
120
|
+
# @api capybara
|
121
|
+
# @param [String] event the event to trigger
|
122
|
+
def trigger(event)
|
123
|
+
native.fire_event(event.to_s)
|
124
|
+
end
|
125
|
+
|
126
|
+
# @api capybara
|
127
|
+
# @param [String] selector XPath query
|
128
|
+
# @return [Array<Node>] the matched nodes
|
129
|
+
def find(selector)
|
130
|
+
nodes = []
|
131
|
+
native.find(selector).each { |node| nodes << self.class.new(self, node) }
|
132
|
+
nodes
|
133
|
+
end
|
134
|
+
|
135
|
+
protected
|
136
|
+
|
137
|
+
# @return [true, false] whether the node allows multiple-option selection (if the node is a select).
|
138
|
+
def multiple_select?
|
139
|
+
tag_name == "select" && native.multiple_select?
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# Return all child nodes which match the selector criteria.
|
145
|
+
#
|
146
|
+
# @api capybara
|
147
|
+
# @return [Array<Node>] the matched nodes
|
148
|
+
def all_unfiltered(selector)
|
149
|
+
nodes = []
|
150
|
+
native.find(selector).each { |node| nodes << self.class.new(driver, node) }
|
151
|
+
nodes
|
152
|
+
end
|
153
|
+
|
154
|
+
# @return [String] the node's type attribute
|
155
|
+
def type
|
156
|
+
native[:type]
|
157
|
+
end
|
158
|
+
|
159
|
+
# @return [Node] the select node, if this is an option node
|
160
|
+
def select_node
|
161
|
+
find('./ancestor::select').first
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
attr_reader :app, :rack_server, :options
|
166
|
+
|
167
|
+
# Creates a new instance of the Akephalos Driver for Capybara. The driver is
|
168
|
+
# registered with Capybara by a name, so that it can be chosen when
|
169
|
+
# Capybara's javascript_driver is changed. By default, Akephalos is
|
170
|
+
# registered like this:
|
171
|
+
#
|
172
|
+
# Capybara.register_driver :akephalos do |app|
|
173
|
+
# Capybara::Akephalos::Driver.new(
|
174
|
+
# app,
|
175
|
+
# :browser => :firefox_3_6,
|
176
|
+
# :validate_scripts => true
|
177
|
+
# )
|
178
|
+
# end
|
179
|
+
#
|
180
|
+
# @param app the Rack application to run
|
181
|
+
# @param [Hash] options the Akephalos configuration options
|
182
|
+
# @option options [Symbol] :browser (:firefox_3_6) the browser
|
183
|
+
# compatibility mode to run in. Available options:
|
184
|
+
# :firefox_3_6
|
185
|
+
# :firefox_3
|
186
|
+
# :ie6
|
187
|
+
# :ie7
|
188
|
+
# :ie8
|
189
|
+
#
|
190
|
+
# @option options [true, false] :validate_scripts (true) whether to raise
|
191
|
+
# exceptions on script errors
|
192
|
+
#
|
193
|
+
def initialize(app, options = {})
|
194
|
+
@app = app
|
195
|
+
@options = options
|
196
|
+
@rack_server = Capybara::Server.new(@app)
|
197
|
+
@rack_server.boot if Capybara.run_server
|
198
|
+
end
|
199
|
+
|
200
|
+
# Visit the given path in the browser.
|
201
|
+
#
|
202
|
+
# @param [String] path relative path to visit
|
203
|
+
def visit(path)
|
204
|
+
browser.visit(url(path))
|
205
|
+
end
|
206
|
+
|
207
|
+
# @return [String] the page's original source
|
208
|
+
def source
|
209
|
+
page.source
|
210
|
+
end
|
211
|
+
|
212
|
+
# @return [String] the page's modified source
|
213
|
+
# page.modified_source will return a string with
|
214
|
+
# html entities converted into the unicode equivalent
|
215
|
+
# but the string will be marked as ASCII-8BIT
|
216
|
+
# which causes conversion issues so we force the encoding
|
217
|
+
# to UTF-8 (ruby 1.9 only)
|
218
|
+
def body
|
219
|
+
body_source = page.modified_source
|
220
|
+
|
221
|
+
if body_source.respond_to?(:force_encoding)
|
222
|
+
body_source.force_encoding("UTF-8")
|
223
|
+
else
|
224
|
+
body_source
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# @return [Hash{String => String}] the page's response headers
|
229
|
+
def response_headers
|
230
|
+
page.response_headers
|
231
|
+
end
|
232
|
+
|
233
|
+
# @return [Integer] the response's status code
|
234
|
+
def status_code
|
235
|
+
page.status_code
|
236
|
+
end
|
237
|
+
|
238
|
+
# Execute the given block within the context of a specified frame.
|
239
|
+
#
|
240
|
+
# @param [String] frame_id the frame's id or index
|
241
|
+
# @raise [Capybara::ElementNotFound] if the frame is not found
|
242
|
+
def within_frame(frame_id_or_index, &block)
|
243
|
+
result = page.within_frame(frame_id_or_index, &block)
|
244
|
+
unless page.within_frame(frame_id_or_index, &block)
|
245
|
+
raise Capybara::ElementNotFound, "Unable to find frame with id '#{frame_id_or_index}'"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Clear all cookie session data.
|
250
|
+
# @deprecated This method is deprecated in Capybara's master branch. Use
|
251
|
+
# {#reset!} instead.
|
252
|
+
def cleanup!
|
253
|
+
reset!
|
254
|
+
end
|
255
|
+
|
256
|
+
# Reset session
|
257
|
+
def reset!
|
258
|
+
cookies.clear
|
259
|
+
browser.close_all_windows()
|
260
|
+
browser.visit('about:blank')
|
261
|
+
end
|
262
|
+
|
263
|
+
# Confirm or cancel the dialog, returning the text of the dialog
|
264
|
+
def confirm_dialog(confirm = true, &block)
|
265
|
+
browser.confirm_dialog(confirm, &block)
|
266
|
+
end
|
267
|
+
|
268
|
+
# @return [String] the page's current URL
|
269
|
+
def current_url
|
270
|
+
page.current_url
|
271
|
+
end
|
272
|
+
|
273
|
+
# Search for nodes which match the given XPath selector.
|
274
|
+
#
|
275
|
+
# @param [String] selector XPath query
|
276
|
+
# @return [Array<Node>] the matched nodes
|
277
|
+
def find(selector)
|
278
|
+
nodes = []
|
279
|
+
page.find(selector).each { |node| nodes << Node.new(self, node) }
|
280
|
+
nodes
|
281
|
+
end
|
282
|
+
|
283
|
+
# Execute JavaScript against the current page, discarding any return value.
|
284
|
+
#
|
285
|
+
# @param [String] script the JavaScript to be executed
|
286
|
+
# @return [nil]
|
287
|
+
def execute_script(script)
|
288
|
+
page.execute_script script
|
289
|
+
end
|
290
|
+
|
291
|
+
# Execute JavaScript against the current page and return the results.
|
292
|
+
#
|
293
|
+
# @param [String] script the JavaScript to be executed
|
294
|
+
# @return the result of the JavaScript
|
295
|
+
def evaluate_script(script)
|
296
|
+
page.evaluate_script script
|
297
|
+
end
|
298
|
+
|
299
|
+
# @return the current page
|
300
|
+
def page
|
301
|
+
browser.page
|
302
|
+
end
|
303
|
+
|
304
|
+
# @return the browser
|
305
|
+
def browser
|
306
|
+
@browser ||= Akephalos::Client.new(@options)
|
307
|
+
end
|
308
|
+
|
309
|
+
# @return the session cookies
|
310
|
+
def cookies
|
311
|
+
browser.cookies
|
312
|
+
end
|
313
|
+
|
314
|
+
# @return [String] the current user agent string
|
315
|
+
def user_agent
|
316
|
+
browser.user_agent
|
317
|
+
end
|
318
|
+
|
319
|
+
# Set the User-Agent header for this session. If :default is given, the
|
320
|
+
# User-Agent header will be reset to the default browser's user agent.
|
321
|
+
#
|
322
|
+
# @param [:default] user_agent the default user agent
|
323
|
+
# @param [String] user_agent the user agent string to use
|
324
|
+
def user_agent=(user_agent)
|
325
|
+
browser.user_agent = user_agent
|
326
|
+
end
|
327
|
+
|
328
|
+
# Disable waiting in Capybara, since waiting is handled directly by
|
329
|
+
# Akephalos.
|
330
|
+
#
|
331
|
+
# @return [false]
|
332
|
+
def wait
|
333
|
+
false
|
334
|
+
end
|
335
|
+
|
336
|
+
private
|
337
|
+
|
338
|
+
# @param [String] path
|
339
|
+
# @return [String] the absolute URL for the given path
|
340
|
+
def url(path)
|
341
|
+
rack_server.url(path)
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
346
|
+
Capybara.register_driver :akephalos do |app|
|
347
|
+
Capybara::Driver::Akephalos.new(app)
|
348
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'akephalos/configuration'
|
2
|
+
|
3
|
+
if RUBY_PLATFORM != "java"
|
4
|
+
require 'akephalos/remote_client'
|
5
|
+
Akephalos::Client = Akephalos::RemoteClient
|
6
|
+
else
|
7
|
+
require 'akephalos/htmlunit'
|
8
|
+
require 'akephalos/htmlunit/ext/http_method'
|
9
|
+
require 'akephalos/htmlunit/ext/confirm_handler'
|
10
|
+
|
11
|
+
require 'akephalos/page'
|
12
|
+
require 'akephalos/node'
|
13
|
+
|
14
|
+
require 'akephalos/client/cookies'
|
15
|
+
require 'akephalos/client/filter'
|
16
|
+
|
17
|
+
module Akephalos
|
18
|
+
|
19
|
+
# Akephalos::Client wraps HtmlUnit's WebClient class. It is the main entry
|
20
|
+
# point for all interaction with the browser, exposing its current page and
|
21
|
+
# allowing navigation.
|
22
|
+
class Client
|
23
|
+
|
24
|
+
# @return [Akephalos::Page] the current page
|
25
|
+
attr_reader :page
|
26
|
+
|
27
|
+
# @return [HtmlUnit::BrowserVersion] the configured browser version
|
28
|
+
attr_reader :browser_version
|
29
|
+
|
30
|
+
# @return [true/false] whether to raise errors on javascript failures
|
31
|
+
attr_reader :validate_scripts
|
32
|
+
|
33
|
+
# @return [true/false] whether to ignore insecure ssl certificates
|
34
|
+
attr_reader :use_insecure_ssl
|
35
|
+
|
36
|
+
# @return ["trace" / "debug" / "info" / "warn" / "error" or "fatal"] which points the htmlunit log level
|
37
|
+
attr_reader :htmlunit_log_level
|
38
|
+
|
39
|
+
# The default configuration options for a new Client.
|
40
|
+
DEFAULT_OPTIONS = {
|
41
|
+
:browser => :firefox_3_6,
|
42
|
+
:validate_scripts => true,
|
43
|
+
:use_insecure_ssl => false,
|
44
|
+
:htmlunit_log_level => 'fatal'
|
45
|
+
}
|
46
|
+
|
47
|
+
# Map of browser version symbols to their HtmlUnit::BrowserVersion
|
48
|
+
# instances.
|
49
|
+
BROWSER_VERSIONS = {
|
50
|
+
:ie6 => HtmlUnit::BrowserVersion::INTERNET_EXPLORER_6,
|
51
|
+
:ie7 => HtmlUnit::BrowserVersion::INTERNET_EXPLORER_7,
|
52
|
+
:ie8 => HtmlUnit::BrowserVersion::INTERNET_EXPLORER_8,
|
53
|
+
:firefox_3_6 => HtmlUnit::BrowserVersion::FIREFOX_3_6
|
54
|
+
}
|
55
|
+
|
56
|
+
# @param [Hash] options the configuration options for this client
|
57
|
+
#
|
58
|
+
# @option options [Symbol] :browser (:firefox_3_6) the browser version (
|
59
|
+
# see BROWSER_VERSIONS)
|
60
|
+
#
|
61
|
+
# @option options [true, false] :validate_scripts (true) whether to raise
|
62
|
+
# errors on javascript errors
|
63
|
+
def initialize(options = {})
|
64
|
+
process_options!(options)
|
65
|
+
|
66
|
+
@_client = java.util.concurrent.FutureTask.new do
|
67
|
+
|
68
|
+
if @http_proxy.nil? or @http_proxy_port.nil?
|
69
|
+
client = HtmlUnit::WebClient.new(browser_version)
|
70
|
+
else
|
71
|
+
client = HtmlUnit::WebClient.new(browser_version, @http_proxy, @http_proxy_port)
|
72
|
+
end
|
73
|
+
|
74
|
+
client.setThrowExceptionOnFailingStatusCode(false)
|
75
|
+
client.setAjaxController(HtmlUnit::NicelyResynchronizingAjaxController.new)
|
76
|
+
client.setCssErrorHandler(HtmlUnit::SilentCssErrorHandler.new)
|
77
|
+
client.setThrowExceptionOnScriptError(validate_scripts)
|
78
|
+
client.setUseInsecureSSL(use_insecure_ssl)
|
79
|
+
client.setRefreshHandler(HtmlUnit::WaitingRefreshHandler.new)
|
80
|
+
|
81
|
+
Filter.new(client)
|
82
|
+
client
|
83
|
+
end
|
84
|
+
Thread.new { @_client.run }
|
85
|
+
end
|
86
|
+
|
87
|
+
# Visit the requested URL and return the page.
|
88
|
+
#
|
89
|
+
# @param [String] url the URL to load
|
90
|
+
# @return [Page] the loaded page
|
91
|
+
def visit(url)
|
92
|
+
client.getPage(url)
|
93
|
+
page
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [Cookies] the cookies for this session
|
97
|
+
def cookies
|
98
|
+
@cookies ||= Cookies.new(client.getCookieManager)
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [String] the current user agent string
|
102
|
+
def user_agent
|
103
|
+
@user_agent || client.getBrowserVersion.getUserAgent
|
104
|
+
end
|
105
|
+
|
106
|
+
# Set the User-Agent header for this session. If :default is given, the
|
107
|
+
# User-Agent header will be reset to the default browser's user agent.
|
108
|
+
#
|
109
|
+
# @param [:default] user_agent the default user agent
|
110
|
+
# @param [String] user_agent the user agent string to use
|
111
|
+
def user_agent=(user_agent)
|
112
|
+
if user_agent == :default
|
113
|
+
@user_agent = nil
|
114
|
+
client.removeRequestHeader("User-Agent")
|
115
|
+
else
|
116
|
+
@user_agent = user_agent
|
117
|
+
client.addRequestHeader("User-Agent", user_agent)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Page] the current page
|
122
|
+
def page
|
123
|
+
self.page = client.getCurrentWindow.getTopWindow.getEnclosedPage
|
124
|
+
@page
|
125
|
+
end
|
126
|
+
|
127
|
+
# Update the current page.
|
128
|
+
#
|
129
|
+
# @param [HtmlUnit::HtmlPage] _page the new page
|
130
|
+
# @return [Page] the new page
|
131
|
+
def page=(_page)
|
132
|
+
if @page != _page
|
133
|
+
@page = Page.new(_page)
|
134
|
+
end
|
135
|
+
@page
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [true, false] whether javascript errors will raise exceptions
|
139
|
+
def validate_scripts?
|
140
|
+
!!validate_scripts
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [true, false] whether to ignore insecure ssl certificates
|
144
|
+
def use_insecure_ssl?
|
145
|
+
!!use_insecure_ssl
|
146
|
+
end
|
147
|
+
|
148
|
+
# Merges the DEFAULT_OPTIONS with those provided to initialize the Client
|
149
|
+
# state, namely, its browser version, whether it should
|
150
|
+
# validate scripts, and htmlunit log level.
|
151
|
+
#
|
152
|
+
# @param [Hash] options the options to process
|
153
|
+
def process_options!(options)
|
154
|
+
options = DEFAULT_OPTIONS.merge(options)
|
155
|
+
|
156
|
+
@browser_version = BROWSER_VERSIONS.fetch(options.delete(:browser))
|
157
|
+
@validate_scripts = options.delete(:validate_scripts)
|
158
|
+
@use_insecure_ssl = options.delete(:use_insecure_ssl)
|
159
|
+
@htmlunit_log_level = options.delete(:htmlunit_log_level)
|
160
|
+
@http_proxy = options.delete(:http_proxy)
|
161
|
+
@http_proxy_port = options.delete(:http_proxy_port)
|
162
|
+
|
163
|
+
java.lang.System.setProperty("org.apache.commons.logging.simplelog.defaultlog", @htmlunit_log_level)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Confirm or cancel the dialog, returning the text of the dialog
|
167
|
+
def confirm_dialog(confirm = true, &block)
|
168
|
+
handler = HtmlUnit::ConfirmHandler.new
|
169
|
+
handler.handleConfirmValue = confirm
|
170
|
+
client.setConfirmHandler(handler)
|
171
|
+
yield if block_given?
|
172
|
+
return handler.text
|
173
|
+
end
|
174
|
+
|
175
|
+
def close_all_windows()
|
176
|
+
@client.closeAllWindows()
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
# Call the future set up in #initialize and return the WebCLient
|
182
|
+
# instance.
|
183
|
+
#
|
184
|
+
# @return [HtmlUnit::WebClient] the WebClient instance
|
185
|
+
def client
|
186
|
+
@client ||= @_client.get.tap do |client|
|
187
|
+
client.getCurrentWindow.getHistory.ignoreNewPages_.set(true)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|