jarib-celerity 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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