jarib-celerity 0.0.5

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.
Files changed (69) hide show
  1. data/History.txt +42 -0
  2. data/License.txt +621 -0
  3. data/README.txt +64 -0
  4. data/Rakefile +12 -0
  5. data/lib/celerity.rb +59 -0
  6. data/lib/celerity/browser.rb +410 -0
  7. data/lib/celerity/clickable_element.rb +26 -0
  8. data/lib/celerity/collections.rb +148 -0
  9. data/lib/celerity/container.rb +488 -0
  10. data/lib/celerity/default_viewer.rb +10 -0
  11. data/lib/celerity/disabled_element.rb +27 -0
  12. data/lib/celerity/element.rb +241 -0
  13. data/lib/celerity/element_collections.rb +68 -0
  14. data/lib/celerity/element_locator.rb +167 -0
  15. data/lib/celerity/elements/button.rb +34 -0
  16. data/lib/celerity/elements/file_field.rb +17 -0
  17. data/lib/celerity/elements/form.rb +16 -0
  18. data/lib/celerity/elements/frame.rb +53 -0
  19. data/lib/celerity/elements/image.rb +57 -0
  20. data/lib/celerity/elements/label.rb +9 -0
  21. data/lib/celerity/elements/link.rb +12 -0
  22. data/lib/celerity/elements/meta.rb +6 -0
  23. data/lib/celerity/elements/non_control_elements.rb +93 -0
  24. data/lib/celerity/elements/option.rb +18 -0
  25. data/lib/celerity/elements/radio_check.rb +85 -0
  26. data/lib/celerity/elements/select_list.rb +81 -0
  27. data/lib/celerity/elements/table.rb +117 -0
  28. data/lib/celerity/elements/table_cell.rb +28 -0
  29. data/lib/celerity/elements/table_elements.rb +41 -0
  30. data/lib/celerity/elements/table_row.rb +36 -0
  31. data/lib/celerity/elements/text_field.rb +127 -0
  32. data/lib/celerity/exception.rb +40 -0
  33. data/lib/celerity/extra/method_generator.rb +158 -0
  34. data/lib/celerity/htmlunit.rb +41 -0
  35. data/lib/celerity/htmlunit/commons-codec-1.3.jar +0 -0
  36. data/lib/celerity/htmlunit/commons-collections-3.2.1.jar +0 -0
  37. data/lib/celerity/htmlunit/commons-httpclient-3.1.jar +0 -0
  38. data/lib/celerity/htmlunit/commons-io-1.4.jar +0 -0
  39. data/lib/celerity/htmlunit/commons-lang-2.4.jar +0 -0
  40. data/lib/celerity/htmlunit/commons-logging-1.1.1.jar +0 -0
  41. data/lib/celerity/htmlunit/cssparser-0.9.5.jar +0 -0
  42. data/lib/celerity/htmlunit/htmlunit-2.4-SNAPSHOT.jar +0 -0
  43. data/lib/celerity/htmlunit/htmlunit-core-js-2.4-SNAPSHOT.jar +0 -0
  44. data/lib/celerity/htmlunit/nekohtml-1.9.10-20081209.100757-4.jar +0 -0
  45. data/lib/celerity/htmlunit/sac-1.3.jar +0 -0
  46. data/lib/celerity/htmlunit/serializer-2.7.1.jar +0 -0
  47. data/lib/celerity/htmlunit/xalan-2.7.1.jar +0 -0
  48. data/lib/celerity/htmlunit/xercesImpl-2.8.1.jar +0 -0
  49. data/lib/celerity/htmlunit/xml-apis-1.3.04.jar +0 -0
  50. data/lib/celerity/identifier.rb +11 -0
  51. data/lib/celerity/input_element.rb +25 -0
  52. data/lib/celerity/listener.rb +106 -0
  53. data/lib/celerity/resources/no_viewer.png +0 -0
  54. data/lib/celerity/util.rb +79 -0
  55. data/lib/celerity/version.rb +9 -0
  56. data/lib/celerity/watir_compatibility.rb +85 -0
  57. data/tasks/benchmark.rake +4 -0
  58. data/tasks/deployment.rake +43 -0
  59. data/tasks/environment.rake +7 -0
  60. data/tasks/fix.rake +25 -0
  61. data/tasks/jar.rake +57 -0
  62. data/tasks/rdoc.rake +4 -0
  63. data/tasks/rspec.rake +30 -0
  64. data/tasks/simple_ci.rake +94 -0
  65. data/tasks/snapshot.rake +26 -0
  66. data/tasks/specserver.rake +21 -0
  67. data/tasks/website.rake +17 -0
  68. data/tasks/yard.rake +5 -0
  69. metadata +129 -0
data/README.txt ADDED
@@ -0,0 +1,64 @@
1
+ = Celerity
2
+
3
+ * http://celerity.rubyforge.org/
4
+
5
+ == TUTORIAL:
6
+
7
+ * http://celerity.rubyforge.org/wiki/wiki.pl?GettingStarted
8
+
9
+ == DESCRIPTION:
10
+
11
+ Celerity is a JRuby library for easy and fast functional test automation for web applications.
12
+ It is a wrapper around the HtmlUnit Java library and is currently aimed at providing the same API and functionality as Watir.
13
+
14
+ == FEATURES:
15
+
16
+ * Fast: No time-consuming GUI rendering or unessential downloads
17
+ * Scalable: Java threads lets you run tests in parallel
18
+ * Easy to use: Simple API
19
+ * Portable: Cross-platform
20
+ * Unintrusive: No browser window interrupting your workflow (runs in background)
21
+
22
+ == REQUIREMENTS:
23
+
24
+ * JRuby 1.1.5 or higher
25
+ * Java 6
26
+
27
+ == INSTALL:
28
+
29
+ `jruby -S gem install celerity`
30
+
31
+
32
+ == EXAMPLE:
33
+
34
+ require "rubygems"
35
+ require "celerity"
36
+
37
+ browser = Celerity::Browser.new
38
+ browser.goto('http://www.google.com')
39
+ browser.text_field(:name, 'q').value = 'Celerity'
40
+ browser.button(:name, 'btnG').click
41
+
42
+ puts "yay" if browser.text.include? 'celerity.rubyforge.org'
43
+
44
+ == GIT
45
+
46
+ The project is manually mirrored @ http://github.com/jarib/celerity/tree/master
47
+
48
+ == LICENSE:
49
+
50
+ Celerity - JRuby wrapper for HtmlUnit
51
+ Copyright (c) 2008 FINN.no AS
52
+
53
+ This program is free software: you can redistribute it and/or modify
54
+ it under the terms of the GNU General Public License as published by
55
+ the Free Software Foundation, either version 3 of the License, or
56
+ (at your option) any later version.
57
+
58
+ This program is distributed in the hope that it will be useful,
59
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
60
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61
+ GNU General Public License for more details.
62
+
63
+ You should have received a copy of the GNU General Public License
64
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ $:.unshift("#{File.dirname(__FILE__)}/lib")
2
+
3
+ if File.exist?('config') # are we in a git clone
4
+ require 'config/requirements'
5
+ require 'config/hoe' # setup Hoe + all gem configuration
6
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
7
+ else # in gem dir
8
+ load 'tasks/jar.rake'
9
+ load 'tasks/rdoc.rake'
10
+ end
11
+
12
+
data/lib/celerity.rb ADDED
@@ -0,0 +1,59 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ raise "Celerity only works on JRuby at the moment." unless RUBY_PLATFORM =~ /java/
4
+
5
+ require 'java'
6
+ require "logger"
7
+ require "uri"
8
+ require "pp"
9
+ require "timeout"
10
+ require "time"
11
+ require 'drb'
12
+ require "fileutils"
13
+
14
+ module Celerity
15
+ Log = Logger.new($DEBUG ? $stderr : nil)
16
+ Log.level = Logger::DEBUG
17
+
18
+ INDEX_OFFSET = 1
19
+ DIR = File.expand_path(File.dirname(__FILE__) + "/celerity")
20
+ end
21
+
22
+ require "celerity/htmlunit"
23
+ require "celerity/version"
24
+ require "celerity/exception"
25
+ require "celerity/clickable_element"
26
+ require "celerity/disabled_element"
27
+ require "celerity/element_collections"
28
+ require "celerity/collections"
29
+ require "celerity/element_locator"
30
+ require "celerity/identifier"
31
+ require "celerity/container"
32
+ require "celerity/element"
33
+ require "celerity/input_element"
34
+ require "celerity/elements/non_control_elements"
35
+ require "celerity/elements/button.rb"
36
+ require "celerity/elements/file_field.rb"
37
+ require "celerity/elements/form.rb"
38
+ require "celerity/elements/frame.rb"
39
+ require "celerity/elements/image.rb"
40
+ require "celerity/elements/label.rb"
41
+ require "celerity/elements/link.rb"
42
+ require "celerity/elements/meta.rb"
43
+ require "celerity/elements/option.rb"
44
+ require "celerity/elements/radio_check.rb"
45
+ require "celerity/elements/select_list.rb"
46
+ require "celerity/elements/table.rb"
47
+ require "celerity/elements/table_elements.rb"
48
+ require "celerity/elements/table_cell.rb"
49
+ require "celerity/elements/table_row.rb"
50
+ require "celerity/elements/text_field.rb"
51
+ require "celerity/util"
52
+ require "celerity/default_viewer"
53
+ require "celerity/listener"
54
+ require "celerity/browser"
55
+ require "celerity/watir_compatibility"
56
+
57
+ # undefine deprecated methods to use them for Element attributes
58
+ Object.send :undef_method, :id if Object.method_defined? "id"
59
+ Object.send :undef_method, :type if Object.method_defined? "type"
@@ -0,0 +1,410 @@
1
+ module Celerity
2
+ class Browser
3
+ include Container
4
+
5
+ attr_accessor :page, :object
6
+ attr_reader :webclient, :viewer
7
+
8
+ # Initialize a browser and goto the given URL
9
+ # @param uri The URL to go to.
10
+ # @return Instance of Celerity::Browser.
11
+ def self.start(uri)
12
+ browser = new
13
+ browser.goto(uri)
14
+ browser
15
+ end
16
+
17
+ def self.attach(*args)
18
+ raise NotImplementedError, "use ClickableElement#click_and_attach instead"
19
+ end
20
+
21
+ # Creates a browser object.
22
+ #
23
+ # @option opts :log_level [Symbol] (:warning) @see log_level=
24
+ # @option opts :browser [:firefox, :internet_explorer] (:internet_explorer) Set the BrowserVersion used by HtmlUnit. Defaults to Internet Explorer.
25
+ # @option opts :css [Boolean] (false) Enable CSS. Disabled by default.
26
+ # @option opts :secure_ssl [Boolean] (true) Disable secure SSL. Enabled by default.
27
+ # @option opts :resynchronize [Boolean] (false) Use HtmlUnit::NicelyResynchronizingAjaxController to resynchronize Ajax calls.
28
+ # @option opts :javascript_exceptions [Boolean] (false) Raise exceptions on script errors. Disabled by default.
29
+ # @option opts :status_code_exceptions [Boolean] (false) Raise exceptions on failing status codes (404 etc.). Disabled by default.
30
+ # @option opts :render [:html, :xml](:html) What DOM representation to send to connected viewers.
31
+ #
32
+ # @return [Celerity::Browser] An instance of the browser.
33
+ # @see Celerity::Container for a small introduction to the API.
34
+ # @api public
35
+ def initialize(opts = {})
36
+ raise TypeError, "bad argument: #{opts.inspect}" unless opts.is_a? Hash
37
+ unless [:html, :xml, nil].include?(opts[:render])
38
+ raise ArgumentError, "bad argument :render => #{opts[:render].inspect}"
39
+ end
40
+
41
+ opts[:render] = opts[:render] || :html
42
+
43
+ @opts = opts
44
+ @last_url, @page = nil
45
+ @error_checkers = []
46
+ @browser = self # for Container#browser
47
+
48
+ self.log_level = @opts[:log_level] || :warning
49
+
50
+ browser = @opts[:browser] == :firefox ?
51
+ ::HtmlUnit::BrowserVersion::FIREFOX_2 : ::HtmlUnit::BrowserVersion::INTERNET_EXPLORER_7_0
52
+
53
+ @webclient = ::HtmlUnit::WebClient.new(browser)
54
+
55
+ configure_webclient
56
+ find_viewer
57
+ end
58
+
59
+ # Goto the given URL
60
+ #
61
+ # @param [String] uri The url.
62
+ # @return [String] The url.
63
+ def goto(uri)
64
+ uri = "http://#{uri}" unless uri =~ %r{://}
65
+ self.page = @webclient.getPage(uri)
66
+
67
+ url()
68
+ end
69
+
70
+ # Unsets the current page / closes all windows
71
+ def close
72
+ @page = nil
73
+ @webclient.closeAllWindows
74
+ end
75
+
76
+ # @return [String] the URL of the current page
77
+ def url
78
+ assert_exists
79
+ # will be renamed getUrl => getRequestUrl
80
+ @page.getWebResponse.getUrl.toString
81
+ end
82
+
83
+ # @return [String] the title of the current page
84
+ def title
85
+ @page ? @page.getTitleText : ''
86
+ end
87
+
88
+ # @return [String] the HTML content of the current page
89
+ def html
90
+ @page ? @page.getWebResponse.getContentAsString : ''
91
+ end
92
+
93
+ # @return [String] the XML representation of the DOM
94
+ def xml
95
+ return '' unless @page
96
+ return @page.asXml if @page.respond_to?(:asXml)
97
+ return text # fallback to text (for exampel for "plain/text" pages)
98
+ end
99
+
100
+ # @return [String] a text representation of the current page
101
+ def text
102
+ return '' unless @page
103
+
104
+ if @page.respond_to?("getContent")
105
+ string = @page.getContent.strip
106
+ else
107
+ string = @page.documentElement.asText.strip
108
+ end
109
+
110
+ # Celerity::Util.normalize_text(string)
111
+ string
112
+ end
113
+
114
+ # Check if the current page contains the given text.
115
+ #
116
+ # @param [String, Regexp] expected_text The text to look for.
117
+ # @raise [TypeError]
118
+ # @return [Numeric, nil] The index of the matched text, or nil if it doesn't match.
119
+ def contains_text(expected_text)
120
+ return nil unless exist?
121
+ super
122
+ end
123
+
124
+ #
125
+ # write me!
126
+ #
127
+ def element_by_xpath(xpath)
128
+ assert_exists
129
+ obj = @page.getFirstByXPath(xpath)
130
+ element_from_dom_node(obj)
131
+ end
132
+
133
+ #
134
+ # write me!
135
+ #
136
+ def elements_by_xpath(xpath)
137
+ assert_exists
138
+ objects = @page.getByXPath(xpath)
139
+ # should use an ElementCollection here?
140
+ objects.map { |o| element_from_dom_node(o) }.compact
141
+ end
142
+
143
+ # @return [HtmlUnit::HtmlHtml] the underlying HtmlUnit object.
144
+ def document
145
+ @object
146
+ end
147
+
148
+ # Goto the last url - HtmlUnit doesn't have a 'back' functionality, so we only have 1 history item :)
149
+ # @return [String, nil] The url of the resulting page, or nil if none was stored.
150
+ def back
151
+ # TODO: this is naive, need capability from HtmlUnit
152
+ goto(@last_url) if @last_url
153
+ end
154
+
155
+ # Refresh the current page
156
+ def refresh
157
+ assert_exists
158
+ self.page = @page.refresh
159
+ end
160
+
161
+ # Clears all cookies. (Celerity-specific API)
162
+ def clear_cookies
163
+ @webclient.getCookieManager.clearCookies
164
+ end
165
+
166
+ # Execute the given JavaScript on the current page. (Celerity-specific API)
167
+ # @return [Object] The resulting Object
168
+ def execute_script(source)
169
+ assert_exists
170
+ @page.executeJavaScript(source.to_s).getJavaScriptResult
171
+ end
172
+
173
+ # experimental
174
+ def send_keys(keys)
175
+ keys = keys.gsub(/\s*/, '').scan(/((?:\{[A-Z]+?\})|.)/u).flatten
176
+ keys.each do |key|
177
+ element = @page.getFocusedElement
178
+ case key
179
+ when "{TAB}"
180
+ @page.tabToNextElement
181
+ when /\w/
182
+ element.type(key)
183
+ else
184
+ raise NotImplementedError
185
+ end
186
+ end
187
+ end
188
+
189
+ # Wait until the given block evaluates to true (Celerity-specific API)
190
+ #
191
+ # @param [Fixnum] timeout Number of seconds to wait before timing out (default: 30).
192
+ # @yieldparam [Celerity::Browser] browser The browser instance.
193
+ # @see Celerity::Browser#resynchronized
194
+ def wait_until(timeout = 30, &block)
195
+ Timeout.timeout(timeout) do
196
+ until yield(self)
197
+ refresh_page_from_window
198
+ sleep 0.1
199
+ end
200
+ end
201
+ end
202
+
203
+ # Wait while the given block evaluates to true (Celerity-specific API)
204
+ #
205
+ # @param [Fixnum] timeout Number of seconds to wait before timing out (default: 30).
206
+ # @yieldparam [Celerity::Browser] browser The browser instance.
207
+ # @see Celerity::Browser#resynchronized
208
+ def wait_while(timeout = 30, &block)
209
+ Timeout.timeout(timeout) do
210
+ while yield(self)
211
+ refresh_page_from_window
212
+ sleep 0.1
213
+ end
214
+ end
215
+ end
216
+
217
+ # Add a 'checker' proc that will be run on every page load
218
+ #
219
+ # @param [Proc] checker The proc to be run (can also be given as a block)
220
+ # @yieldparam [Celerity::Browser] browser The current browser object.
221
+ # @raise [ArgumentError] if no Proc or block was given.
222
+ def add_checker(checker = nil, &block)
223
+ if block_given?
224
+ @error_checkers << block
225
+ elsif Proc === checker
226
+ @error_checkers << checker
227
+ else
228
+ raise ArgumentError, "argument must be a Proc or block"
229
+ end
230
+ end
231
+
232
+ # Remove the given checker from the list of checkers
233
+ # @param [Proc] checker The Proc to disable.
234
+ def disable_checker(checker)
235
+ @error_checkers.delete(checker)
236
+ end
237
+
238
+ # @return [Symbol] the current log level
239
+ def log_level
240
+ java.util.logging.Logger.getLogger('com.gargoylesoftware.htmlunit').level.to_s.downcase.to_sym
241
+ end
242
+
243
+ # Set Java log level (default is :warning)
244
+ #
245
+ # @param [Symbol] level :finest, :finer, :fine, :config, :info, :warning, :severe, or :off, :all
246
+ def log_level=(level)
247
+ java.util.logging.Logger.getLogger('com.gargoylesoftware.htmlunit').level = java.util.logging.Level.const_get(level.to_s.upcase)
248
+ end
249
+
250
+ # Checks if we have a page currently loaded.
251
+ # @return [true, false]
252
+ def exist?
253
+ !!@page
254
+ end
255
+ alias_method :exists?, :exist?
256
+
257
+ # Allows you to temporarily switch to HtmlUnit's NicelyResynchronizingAjaxController to resynchronize ajax calls.
258
+ #
259
+ # @browser.resynchroniced do |b|
260
+ # b.link(:id, 'load_fancy_ajax_stuff').click
261
+ # end
262
+ #
263
+ # @yieldparam [Celerity::Browser] browser The current browser object.
264
+ # @see Celerity::Browser#new for options on how to always use this.
265
+ def resynchronized(&block)
266
+ old_controller = @webclient.ajaxController
267
+ @webclient.setAjaxController(::HtmlUnit::NicelyResynchronizingAjaxController.new)
268
+
269
+ yield(self)
270
+
271
+ @webclient.setAjaxController(old_controller)
272
+ end
273
+
274
+ #--
275
+ # TODO: could be private?
276
+ #++
277
+ #
278
+ # Check that we have a @page object.
279
+ #
280
+ # @raise [Celerity::Exception::UnknownObjectException] if no page is loaded.
281
+ # @api private
282
+ def assert_exists
283
+ raise UnknownObjectException, "no page loaded" unless exist?
284
+ end
285
+
286
+ #--
287
+ # TODO: could be private?
288
+ #++
289
+ # Runs the all the checker procs added by +add_checker+
290
+ #
291
+ # @see add_checker
292
+ # @api private
293
+ def run_error_checks
294
+ @error_checkers.each { |e| e[self] }
295
+ end
296
+
297
+ # Set the current page object for the browser
298
+ #
299
+ # @param [HtmlUnit::HtmlPage] value The page to set.
300
+ # @api private
301
+ def page=(value)
302
+ @last_url = url() if exist?
303
+ @page = value
304
+
305
+ if @page.respond_to?("getDocumentElement")
306
+ @object = @page.getDocumentElement
307
+ elsif @page.is_a? HtmlUnit::UnexpectedPage
308
+ raise UnexpectedPageException, @page.getWebResponse.getContentType
309
+ end
310
+
311
+ render unless @viewer == DefaultViewer
312
+ run_error_checks
313
+
314
+ value
315
+ end
316
+
317
+ # Start or stop HtmlUnit's DebuggingWebConnection.
318
+ # The output will go to /tmp/«name»
319
+ #
320
+ # @param [Boolean] bool start or stop
321
+ # @param [String] name required if bool is true
322
+ def debug_web_connection(bool, name = nil)
323
+ if bool
324
+ raise "no name given" unless name
325
+ @old_webconnection = @webclient.getWebConnection
326
+ dwc = HtmlUnit::Util::DebuggingWebConnection.new(@old_webconnection, name)
327
+ @webclient.setWebConnection(dwc)
328
+ $stderr.puts "debug-webconnection on"
329
+ else
330
+ @webclient.setWebConnection(@old_webconnection) if @old_webconnection
331
+ $stderr.puts "debug-webconnection off"
332
+ end
333
+ end
334
+
335
+ # Add a listener block for one of the available types.
336
+ # Types map to HtmlUnit interfaces like this:
337
+ #
338
+ # :status => StatusHandler
339
+ # :alert => AlertHandler ( window.alert() )
340
+ # :web_window_event => WebWindowListener
341
+ # :html_parser => HTMLParserListener
342
+ # :incorrectness => IncorrectnessListener
343
+ # :confirm => ConfirmHandler ( window.confirm() )
344
+ # :prompt => PromptHandler ( window.prompt() )
345
+ #
346
+ #
347
+ # @param [Symbol] type One of the above symbols.
348
+ # @param [Proc] block A block to be executed for events of this type.
349
+ def add_listener(type, &block)
350
+ @listener ||= Celerity::Listener.new(@webclient)
351
+ @listener.add_listener(type, &block)
352
+ end
353
+
354
+ private
355
+
356
+ # Configure the webclient according to the options given to #new.
357
+ # @see initialize
358
+ def configure_webclient
359
+ @webclient.throwExceptionOnScriptError = false unless @opts[:javascript_exceptions]
360
+ @webclient.throwExceptionOnFailingStatusCode = false unless @opts[:status_code_exceptions]
361
+ @webclient.cssEnabled = false unless @opts[:css]
362
+ @webclient.useInsecureSSL = @opts[:secure_ssl] == false
363
+ @webclient.setAjaxController(::HtmlUnit::NicelyResynchronizingAjaxController.new) if @opts[:resynchronize]
364
+
365
+ end
366
+
367
+ # This *should* be unneccessary, but sometimes the page we get from the
368
+ # window is different (ie. a different object) from our current @page
369
+ # (Used by #wait_while and #wait_until)
370
+ def refresh_page_from_window
371
+ new_page = @page.getEnclosingWindow.getEnclosedPage
372
+
373
+ if new_page && (new_page != @page)
374
+ self.page = new_page
375
+ else
376
+ Log.debug "unneccessary refresh"
377
+ end
378
+ end
379
+
380
+ # Render the current page on the viewer.
381
+ # @api private
382
+ def render
383
+ @viewer.render_html(self.send(@opts[:render]), url)
384
+ rescue DRb::DRbConnError, Errno::ECONNREFUSED => e
385
+ @viewer = DefaultViewer
386
+ end
387
+
388
+ # Check if we have a viewer available on druby://127.0.0.1:6429
389
+ # @api private
390
+ def find_viewer
391
+ viewer = DRbObject.new_with_uri("druby://127.0.0.1:6429")
392
+ if viewer.respond_to?(:render_html)
393
+ @viewer = viewer
394
+ else
395
+ @viewer = DefaultViewer
396
+ end
397
+ rescue DRb::DRbConnError, Errno::ECONNREFUSED
398
+ @viewer = DefaultViewer
399
+ end
400
+
401
+ def element_from_dom_node(obj)
402
+ if element_class = Celerity::Util.htmlunit2celerity(obj.class)
403
+ element_class.new(self, :object, obj)
404
+ else
405
+ Element.new(self, :object, nil)
406
+ end
407
+ end
408
+
409
+ end # Browser
410
+ end # Celerity