celerity 0.0.2 → 0.0.3

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 (127) hide show
  1. data/History.txt +15 -1
  2. data/Manifest.txt +174 -0
  3. data/README.txt +19 -10
  4. data/config/hoe.rb +68 -0
  5. data/config/requirements.rb +15 -0
  6. data/lib/celerity.rb +14 -11
  7. data/lib/celerity/collections.rb +37 -8
  8. data/lib/celerity/container.rb +100 -3
  9. data/lib/celerity/disabled_element.rb +4 -2
  10. data/lib/celerity/element.rb +21 -8
  11. data/lib/celerity/element_collections.rb +4 -7
  12. data/lib/celerity/element_locator.rb +1 -0
  13. data/lib/celerity/elements/button.rb +6 -2
  14. data/lib/celerity/elements/file_field.rb +1 -1
  15. data/lib/celerity/elements/form.rb +1 -2
  16. data/lib/celerity/elements/frame.rb +0 -3
  17. data/lib/celerity/elements/image.rb +1 -4
  18. data/lib/celerity/elements/label.rb +1 -0
  19. data/lib/celerity/elements/link.rb +2 -0
  20. data/lib/celerity/elements/option.rb +1 -0
  21. data/lib/celerity/elements/radio_check.rb +3 -5
  22. data/lib/celerity/elements/select_list.rb +3 -10
  23. data/lib/celerity/elements/table.rb +8 -22
  24. data/lib/celerity/elements/table_body.rb +5 -11
  25. data/lib/celerity/elements/table_cell.rb +1 -0
  26. data/lib/celerity/elements/table_footer.rb +30 -0
  27. data/lib/celerity/elements/table_header.rb +30 -0
  28. data/lib/celerity/elements/table_row.rb +5 -3
  29. data/lib/celerity/elements/text_field.rb +18 -13
  30. data/lib/celerity/exception.rb +8 -8
  31. data/lib/celerity/extra/method_generator.rb +5 -2
  32. data/lib/celerity/htmlunit/htmlunit-2.2-SNAPSHOT.jar +0 -0
  33. data/lib/celerity/ie.rb +195 -141
  34. data/lib/celerity/non_control_elements.rb +30 -4
  35. data/lib/celerity/version.rb +1 -1
  36. data/lib/celerity/watir_compatibility.rb +62 -0
  37. data/setup.rb +0 -2
  38. data/spec/area_spec.rb +4 -1
  39. data/spec/areas_spec.rb +1 -1
  40. data/spec/button_spec.rb +35 -17
  41. data/spec/buttons_spec.rb +1 -1
  42. data/spec/checkbox_spec.rb +6 -4
  43. data/spec/checkboxes_spec.rb +1 -1
  44. data/spec/div_spec.rb +20 -19
  45. data/spec/divs_spec.rb +2 -2
  46. data/spec/element_spec.rb +13 -2
  47. data/spec/filefield_spec.rb +6 -3
  48. data/spec/filefields_spec.rb +1 -1
  49. data/spec/form_spec.rb +4 -1
  50. data/spec/forms_spec.rb +1 -1
  51. data/spec/frame_spec.rb +6 -2
  52. data/spec/hidden_spec.rb +8 -4
  53. data/spec/hiddens_spec.rb +1 -1
  54. data/spec/hn_spec.rb +86 -0
  55. data/spec/hns_spec.rb +41 -0
  56. data/spec/html/bug_duplicate_attributes.html +14 -0
  57. data/spec/html/bug_javascript_001.html +11 -0
  58. data/spec/html/forms_with_input_elements.html +11 -11
  59. data/spec/html/images.html +18 -15
  60. data/spec/html/latin1_text.html +16 -0
  61. data/spec/html/non_control_elements.html +28 -4
  62. data/spec/html/tables.html +3 -3
  63. data/spec/html/utf8_text.html +15 -0
  64. data/spec/htmlunit_spec.rb +27 -0
  65. data/spec/ie_spec.rb +47 -12
  66. data/spec/image_spec.rb +4 -7
  67. data/spec/images_spec.rb +3 -2
  68. data/spec/label_spec.rb +4 -3
  69. data/spec/labels_spec.rb +1 -1
  70. data/spec/li_spec.rb +11 -8
  71. data/spec/link_spec.rb +5 -1
  72. data/spec/links_spec.rb +2 -1
  73. data/spec/lis_spec.rb +3 -2
  74. data/spec/map_spec.rb +4 -1
  75. data/spec/maps_spec.rb +1 -1
  76. data/spec/meta_spec.rb +6 -0
  77. data/spec/ol_spec.rb +73 -0
  78. data/spec/ols_spec.rb +41 -0
  79. data/spec/option_spec.rb +129 -0
  80. data/spec/p_spec.rb +4 -1
  81. data/spec/pre_spec.rb +4 -1
  82. data/spec/pres_spec.rb +1 -1
  83. data/spec/ps_spec.rb +2 -1
  84. data/spec/radio_spec.rb +7 -19
  85. data/spec/radios_spec.rb +1 -1
  86. data/spec/select_list_spec.rb +19 -57
  87. data/spec/select_lists_spec.rb +3 -2
  88. data/spec/span_spec.rb +8 -5
  89. data/spec/spans_spec.rb +2 -1
  90. data/spec/spec_helper.rb +8 -43
  91. data/spec/table_bodies_spec.rb +17 -4
  92. data/spec/table_body_spec.rb +47 -16
  93. data/spec/table_cell_spec.rb +5 -3
  94. data/spec/table_cells_spec.rb +1 -1
  95. data/spec/table_footer_spec.rb +94 -0
  96. data/spec/table_footers_spec.rb +53 -0
  97. data/spec/table_header_spec.rb +94 -0
  98. data/spec/table_headers_spec.rb +53 -0
  99. data/spec/table_row_spec.rb +25 -4
  100. data/spec/table_rows_spec.rb +1 -1
  101. data/spec/table_spec.rb +22 -2
  102. data/spec/tables_spec.rb +2 -1
  103. data/spec/text_field_spec.rb +52 -20
  104. data/spec/text_fields_spec.rb +1 -1
  105. data/spec/ul_spec.rb +73 -0
  106. data/spec/uls_spec.rb +41 -0
  107. data/spec/watir_compatability_spec.rb +253 -0
  108. data/support/celerity_viewer/rubycocoa/CelerityViewer.icns +0 -0
  109. data/support/celerity_viewer/rubycocoa/English.lproj/Main.nib/classes.nib +37 -0
  110. data/support/celerity_viewer/rubycocoa/English.lproj/Main.nib/info.nib +19 -0
  111. data/support/celerity_viewer/rubycocoa/English.lproj/Main.nib/keyedobjects.nib +0 -0
  112. data/support/celerity_viewer/rubycocoa/Info.plist.erb +28 -0
  113. data/support/celerity_viewer/rubycocoa/MainController.rb +23 -0
  114. data/support/celerity_viewer/rubycocoa/README +94 -0
  115. data/support/celerity_viewer/rubycocoa/Rakefile +100 -0
  116. data/support/celerity_viewer/rubycocoa/distributed_viewer.rb +86 -0
  117. data/support/celerity_viewer/rubycocoa/main.m +7 -0
  118. data/support/celerity_viewer/rubycocoa/main.rb +27 -0
  119. data/support/spec_server.rb +64 -0
  120. data/tasks/benchmark.rake +1 -0
  121. data/tasks/rdoc.rake +4 -0
  122. data/tasks/rspec.rake +10 -3
  123. data/tasks/simple_ci.rake +94 -0
  124. data/tasks/specserver.rake +21 -0
  125. metadata +160 -114
  126. data/spec/table_bodies.rb +0 -40
  127. data/tasks/testserver.rake +0 -32
@@ -1,10 +1,12 @@
1
1
  module Celerity
2
2
 
3
3
  class Table < Element
4
+ include Enumerable # specs for this?
4
5
  include Container
6
+
5
7
  TAGS = [ Identifier.new('table') ]
6
8
  ATTRIBUTES = BASE_ATTRIBUTES | [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding, :align, :bgcolor]
7
- DEFAULT_HOW = :name
9
+ DEFAULT_HOW = :id
8
10
 
9
11
  def locate
10
12
  super
@@ -31,7 +33,7 @@ module Celerity
31
33
 
32
34
  def each
33
35
  assert_exists
34
- 0.upto(@object.getRowCount-1) { |index| yield TableRow.new(self, :object, @rows[index]) }
36
+ @rows.each { |row| yield TableRow.new(self, :object, row) }
35
37
  end
36
38
 
37
39
  def [](index)
@@ -49,9 +51,8 @@ module Celerity
49
51
  @object.getRow(index-1).getCells.length
50
52
  end
51
53
 
52
- # This method returns the table as a 2 dimensional array. Dont expect too much if there are nested tables, colspan etc.
54
+ # This method returns the table as a 2 dimensional array.
53
55
  # Raises an UnknownObjectException if the table doesn't exist.
54
- # http://www.w3.org/TR/html4/struct/tables.html
55
56
  def to_a
56
57
  assert_exists
57
58
  y = []
@@ -66,29 +67,14 @@ module Celerity
66
67
  return y
67
68
  end
68
69
 
69
- def table_body(index = 1)
70
- return @object.getBodies.get(index)
71
- end
72
- private :table_body
73
-
74
- def body(how, what)
75
- assert_exists
76
- return TableBody.new(@container, how, what)
77
- end
78
-
79
- def bodies
80
- assert_exists
81
- return TableBodies.new(self)
82
- end
83
-
84
70
  def column_values(columnnumber)
85
- return (1..row_count).collect { |index| self[index][columnnumber].text }
71
+ (1..row_count).collect { |index| self[index][columnnumber].text }
86
72
  end
87
73
 
88
74
  def row_values(rownumber)
89
- return (1..column_count(rownumber)).collect { |index| self[rownumber][index].text }
75
+ (1..column_count(rownumber)).collect { |index| self[rownumber][index].text }
90
76
  end
91
-
77
+
92
78
  end
93
79
 
94
80
  end
@@ -1,20 +1,14 @@
1
1
  module Celerity
2
-
3
2
  class TableBody < Element
3
+ include Enumerable # specs for this?
4
+
4
5
  TAGS = [ Identifier.new('tbody') ]
6
+ ATTRIBUTES = BASE_ATTRIBUTES | CELLHALIGN_ATTRIBUTES | CELLVALIGN_ATTRIBUTES
7
+ DEFAULT_HOW = :id
5
8
 
6
9
  def locate
7
10
  super
8
- # can't call the assert_exists here, as an exists? method call will fail
9
- if @object
10
- @rows = @object.getRows
11
- @cells = []
12
- @rows.each do |row|
13
- row.getCells.each do |c|
14
- @cells << c
15
- end
16
- end
17
- end
11
+ @rows = @object.getRows if @object
18
12
  end
19
13
 
20
14
  def [](index)
@@ -6,6 +6,7 @@ module Celerity
6
6
 
7
7
  TAGS = [ Identifier.new('td') ]
8
8
  ATTRIBUTES = BASE_ATTRIBUTES | [:abbr, :axis, :headers, :scope, :rowspan, :colspan] | CELLHALIGN_ATTRIBUTES | CELLVALIGN_ATTRIBUTES
9
+ DEFAULT_HOW = :id
9
10
 
10
11
  alias_method :to_s, :text
11
12
 
@@ -0,0 +1,30 @@
1
+ module Celerity
2
+ class TableFooter < Element
3
+ include Enumerable # specs for this?
4
+
5
+ TAGS = [ Identifier.new('tfoot') ]
6
+ ATTRIBUTES = BASE_ATTRIBUTES | CELLHALIGN_ATTRIBUTES | CELLVALIGN_ATTRIBUTES
7
+ DEFAULT_HOW = :id
8
+
9
+ def locate
10
+ super
11
+ @rows = @object.getRows if @object
12
+ end
13
+
14
+ def [](index)
15
+ assert_exists
16
+ return TableRow.new(self, :object, @rows[index-1])
17
+ end
18
+
19
+ def length
20
+ assert_exists
21
+ return @object.getRows.length
22
+ end
23
+
24
+ def each
25
+ assert_exists
26
+ @rows.each { |row| yield TableRow.new(self, :object, row) }
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ module Celerity
2
+ class TableHeader < Element
3
+ include Enumerable # specs for this?
4
+
5
+ TAGS = [ Identifier.new('thead') ]
6
+ ATTRIBUTES = BASE_ATTRIBUTES | CELLHALIGN_ATTRIBUTES | CELLVALIGN_ATTRIBUTES
7
+ DEFAULT_HOW = :id
8
+
9
+ def locate
10
+ super
11
+ @rows = @object.getRows if @object
12
+ end
13
+
14
+ def [](index)
15
+ assert_exists
16
+ return TableRow.new(self, :object, @rows[index-1])
17
+ end
18
+
19
+ def length
20
+ assert_exists
21
+ return @object.getRows.length
22
+ end
23
+
24
+ def each
25
+ assert_exists
26
+ @rows.each { |row| yield TableRow.new(self, :object, row) }
27
+ end
28
+
29
+ end
30
+ end
@@ -1,7 +1,9 @@
1
1
  module Celerity
2
-
3
2
  class TableRow < Element
3
+ include Enumerable # specs for this?
4
+
4
5
  TAGS = [ Identifier.new('tr') ]
6
+ DEFAULT_HOW = :id
5
7
 
6
8
  def locate
7
9
  super
@@ -9,7 +11,7 @@ module Celerity
9
11
  end
10
12
 
11
13
  def each
12
- locate
14
+ assert_exists
13
15
  @cells.each { |cell| yield TableCell.new(self, :object, cell) }
14
16
  end
15
17
 
@@ -20,7 +22,7 @@ module Celerity
20
22
  end
21
23
 
22
24
  def column_count
23
- locate
25
+ assert_exists
24
26
  @cells.length
25
27
  end
26
28
 
@@ -7,6 +7,7 @@ module Celerity
7
7
  class TextField < InputElement
8
8
  TAGS = [ Identifier.new('textarea'),
9
9
  Identifier.new('input', :type => ["text", "password", /^(?!(file|radio|checkbox|submit|reset|image|button|hidden)$)/]) ]
10
+ DEFAULT_HOW = :name
10
11
 
11
12
  def clear
12
13
  assert_exists
@@ -22,14 +23,7 @@ module Celerity
22
23
  assert_enabled
23
24
  assert_not_readonly
24
25
  clear
25
- # workaround for bug in HtmlPasswordInput - should be fixed soon (Jari - 2008-05-14)
26
- if @object.class == com.gargoylesoftware.htmlunit.html.HtmlPasswordInput
27
- @object.setValueAttribute(value.to_s)
28
- else
29
- java.lang.String.new(value.to_s).toCharArray.each do |char|
30
- @container.update_page @object.type(char)
31
- end
32
- end
26
+ type_string(value.to_s)
33
27
  end
34
28
 
35
29
  def value=(value)
@@ -57,9 +51,13 @@ module Celerity
57
51
  def append(value)
58
52
  assert_enabled
59
53
  assert_not_readonly
60
- java.lang.String.new(value.to_s).toCharArray.each do |char|
61
- @container.update_page @object.type(char)
62
- end
54
+ type_string(value)
55
+ end
56
+
57
+ def type
58
+ assert_exists
59
+ type = @object.getAttributeValue('type')
60
+ return ['file', 'radio', 'checkbox', 'submit', 'reset', 'image', 'button', 'hidden'].include?(type) ? type : 'text'
63
61
  end
64
62
 
65
63
  # This bascially just moves the text to the other text field using TextField#append
@@ -70,23 +68,30 @@ module Celerity
70
68
  self.value = ''
71
69
  @container.text_field(how, what).append(val)
72
70
  end
73
- alias_method :dragContentsTo, :drag_contents_to
74
71
 
75
72
  def get_contents
76
73
  self.value
77
74
  end
78
- alias_method :getContents, :get_contents
79
75
 
80
76
  def verify_contains(expected)
81
77
  assert_exists
82
78
  !!contains_text(expected)
83
79
  end
80
+
81
+
82
+ private
83
+ def type_string(value)
84
+ JavaString.new(value.to_java_bytes, @container.page.getPageEncoding).toCharArray.each do |char|
85
+ @container.update_page @object.type(char)
86
+ end
87
+ end
84
88
  end
85
89
 
86
90
  # this class can be used to access hidden field objects
87
91
  # Normally a user would not need to create this object as it is returned by the Watir::Container#hidden method
88
92
  class Hidden < TextField
89
93
  TAGS = [ Identifier.new('input', :type => %w(hidden)) ]
94
+ DEFAULT_HOW = :name
90
95
  end
91
96
 
92
97
  end
@@ -35,14 +35,14 @@ module Celerity
35
35
  # This exception is thrown if an http error, such as a 404, 500 etc is encountered while navigating
36
36
  class NavigationException < CelerityException; end
37
37
 
38
- # This exception is raised if a timeout is exceeded
39
- class TimeOutException < CelerityException
40
- def initialize(duration, timeout)
41
- @duration, @timeout = duration, timeout
42
- super
43
- end
44
- attr_reader :duration, :timeout
45
- end
38
+ # # This exception is raised if a timeout is exceeded
39
+ # class TimeOutException < CelerityException
40
+ # def initialize(duration, timeout)
41
+ # @duration, @timeout = duration, timeout
42
+ # super
43
+ # end
44
+ # attr_reader :duration, :timeout
45
+ # end
46
46
 
47
47
  end
48
48
  end
@@ -2,7 +2,10 @@ require "rubygems"
2
2
  require "uri"
3
3
  require "active_support"
4
4
 
5
+ #--
5
6
  # http://api.rubyonrails.com/classes/Inflector.html#M001621
7
+ #++
8
+
6
9
  class String
7
10
  def underscore
8
11
  gsub(/::/, '/').
@@ -123,8 +126,8 @@ module Celerity
123
126
  end # MethodGenerator
124
127
 
125
128
  class IE
126
- def generate_method
127
- MethodGenerator.new(self).parse
129
+ def generate_method(opts = {})
130
+ MethodGenerator.new(self, opts).parse
128
131
  end
129
132
  end
130
133
 
@@ -1,141 +1,195 @@
1
- module Celerity
2
- class IE
3
- include Container
4
- attr_accessor :page, :object, :webclient
5
-
6
- def self.start(uri)
7
- browser = new
8
- browser.goto(uri)
9
- browser
10
- end
11
-
12
- def initialize(opts = {})
13
- @page_container = self
14
- @error_checkers = []
15
- @last_url, @page = nil
16
-
17
- browser = RUBY_PLATFORM =~ /java/ ? ::HtmlUnit::BrowserVersion::FIREFOX_2 : ::HtmlUnit::BrowserVersion.FIREFOX_2
18
- @webclient = ::HtmlUnit::WebClient.new(browser)
19
- @webclient.setThrowExceptionOnScriptError(false) unless $DEBUG || opts[:enable_javascript_exceptions]
20
- @webclient.setCssEnabled(false) if opts[:disable_css]
21
- end
22
-
23
- def goto(uri)
24
- uri = "http://#{uri}" unless uri =~ %r{^http://}
25
- set_page @webclient.getPage(uri)
26
- uri
27
- end
28
-
29
- def close
30
- @page = nil
31
- end
32
-
33
- def set_page(value)
34
- @last_url = url() if exist?
35
- @page = value
36
- @object = @page.getDocumentElement
37
- run_error_checks
38
- end
39
-
40
- def url
41
- assert_exists
42
- @page.getWebResponse.getUrl.toString
43
- end
44
-
45
- def base_url
46
- # FIXME: base_url HTTPS
47
- "http://" + URI.parse( url() ).host
48
- end
49
-
50
- def title
51
- @page ? @page.getTitleText : ''
52
- end
53
-
54
- def html
55
- @page ? @page.getWebResponse.getContentAsString : ''
56
- end
57
-
58
- def text
59
- # nicer way to do this?
60
- @page ? @page.getFirstByXPath("//body").asText : ''
61
- end
62
-
63
- def document
64
- @object
65
- end
66
-
67
- def back
68
- # FIXME: this is naive, need capability from HtmlUnit
69
- goto(@last_url) if @last_url
70
- end
71
-
72
- def refresh
73
- assert_exists
74
- set_page(@page.refresh)
75
- end
76
-
77
- def exist?
78
- !!@page
79
- end
80
- alias_method :exists?, :exist?
81
-
82
- # check that we have a @page object
83
- # need to find a better way to handle this
84
- def assert_exists
85
- raise UnknownObjectException, "no page loaded" unless exist?
86
- end
87
-
88
- def contains_text(expected_text)
89
- return nil unless exist?
90
- case expected_text
91
- when Regexp
92
- text().match(expected_text)
93
- when String
94
- text().index(expected_text)
95
- else
96
- raise ArgumentError, "Argument #{expected_text.inspect} should be a String or Regexp."
97
- end
98
- end
99
-
100
- def execute_script(source)
101
- assert_exists
102
- @page.executeJavaScript(source.to_s)
103
- end
104
-
105
- def run_error_checks
106
- @error_checkers.each { |e| e.call(self) }
107
- end
108
-
109
- def add_checker(checker = nil, &block)
110
- if block_given?
111
- @error_checkers << block
112
- elsif Proc === checker
113
- @error_checkers << checker
114
- else
115
- raise ArgumentError, "argument must be a Proc or block"
116
- end
117
- end
118
-
119
- def disable_checker(checker)
120
- @error_checkers.delete(checker)
121
- end
122
-
123
- # these are just for Watir compatability - should we keep them?
124
- class << self
125
- attr_accessor :speed, :attach_timeout, :visible
126
- alias_method :start_window, :start
127
- def reset_attach_timeout; @attach_timeout = 2.0; end
128
- def each; end
129
- def quit; end
130
- def set_fast_speed; @speed = :fast; end
131
- def set_slow_speed; @speed = :slow; end
132
- end
133
-
134
- attr_accessor :visible
135
- def bring_to_front; true; end
136
- def speed=(s); end
137
-
138
- end # IE
139
- end # Celerity
140
-
141
- Celerity::Browser = Celerity::IE
1
+ module Celerity
2
+ class IE
3
+ include Container
4
+ attr_accessor :page, :object
5
+ attr_reader :charset, :webclient
6
+
7
+ def self.start(uri)
8
+ browser = new
9
+ browser.goto(uri)
10
+ browser
11
+ end
12
+
13
+
14
+ # Creates a browser object.
15
+ #
16
+ # ==== Options (opts)
17
+ # :javascript_exceptions<true, false, nil>::
18
+ # Throw exceptions on script errors. Disabled by default.
19
+ # :status_code_exceptions<true, false, nil>::
20
+ # Throw exceptions on failing status codes (404++). Disabled by default.
21
+ # :css<true, false, nil>::
22
+ # Enable CSS. Disabled by default.
23
+ # :secure_ssl<true, false, nil>::
24
+ # Disable secure SSL. Enabled by default.
25
+ # :log_level<:trace, :debug, :info, :warn, :error, or :fatal>::
26
+ # Set the log level for Apache Jakarta commons logging system (used by HtmlUnit)
27
+ # Defaults to :warn. (not working..)
28
+ # ==== Returns
29
+ # An instance of Celerity::IE
30
+ #
31
+ #--
32
+ # @public
33
+ def initialize(opts = {})
34
+ java.lang.System.getProperties.put("org.apache.commons.logging.simplelog.defaultlog", opts[:log_level] ? opts[:log_level].to_s : "warn")
35
+
36
+ browser = RUBY_PLATFORM =~ /java/ ? ::HtmlUnit::BrowserVersion::FIREFOX_2 : ::HtmlUnit::BrowserVersion.FIREFOX_2
37
+ @webclient = ::HtmlUnit::WebClient.new(browser)
38
+ @webclient.setThrowExceptionOnScriptError(false) unless opts[:javascript_exceptions]
39
+ @webclient.setThrowExceptionOnFailingStatusCode(false) unless opts[:status_code_exceptions]
40
+ @webclient.setCssEnabled(false) unless opts[:css]
41
+ @webclient.setUseInsecureSSL(true) if opts[:secure_ssl]
42
+
43
+ @last_url, @page = nil
44
+ @page_container = self
45
+ @error_checkers = []
46
+ find_viewer
47
+ end
48
+
49
+ def goto(uri)
50
+ uri = "http://#{uri}" unless uri =~ %r{^https?://}
51
+ set_page @webclient.getPage(uri)
52
+ uri
53
+ end
54
+
55
+ def close
56
+ @page = nil
57
+ end
58
+
59
+ def set_page(value)
60
+ @last_url = url() if exist?
61
+ @page = value
62
+ if @page.respond_to?("getDocumentElement")
63
+ @object = @page.getDocumentElement
64
+ end
65
+ render if @viewer
66
+ run_error_checks
67
+ end
68
+
69
+ def url
70
+ assert_exists
71
+ @page.getWebResponse.getUrl.toString
72
+ end
73
+
74
+ def title
75
+ @page ? @page.getTitleText : ''
76
+ end
77
+
78
+ def html
79
+ @page ? @page.getWebResponse.getContentAsString : ''
80
+ end
81
+
82
+ def text
83
+ if @page.respond_to?("getContent")
84
+ @page.getContent
85
+ else
86
+ @page ? @page.getFirstByXPath("//body").asText : ''
87
+ end
88
+ end
89
+
90
+ def document
91
+ @object
92
+ end
93
+
94
+ def collection_string(collection_method)
95
+ collection = self.send collection_method
96
+ buffer = "Found #{collection.size} divs\n"
97
+ collection.each_with_index do |div, index|
98
+ buffer += "#{index+1}: #{div.attribute_string}\n"
99
+ end
100
+ return buffer
101
+ end
102
+
103
+ def back
104
+ # FIXME: this is naive, need capability from HtmlUnit
105
+ goto(@last_url) if @last_url
106
+ end
107
+
108
+ def refresh
109
+ assert_exists
110
+ set_page(@page.refresh)
111
+ end
112
+
113
+ def exist?
114
+ !!@page
115
+ end
116
+ alias_method :exists?, :exist?
117
+
118
+ # check that we have a @page object
119
+ # need to find a better way to handle this
120
+ def assert_exists
121
+ raise UnknownObjectException, "no page loaded" unless exist?
122
+ end
123
+
124
+ def contains_text(expected_text)
125
+ return nil unless exist?
126
+ case expected_text
127
+ when Regexp
128
+ text().match(expected_text)
129
+ when String
130
+ text().index(expected_text)
131
+ else
132
+ raise ArgumentError, "Argument #{expected_text.inspect} should be a String or Regexp."
133
+ end
134
+ end
135
+
136
+ def execute_script(source)
137
+ assert_exists
138
+ @page.executeJavaScript(source.to_s)
139
+ end
140
+
141
+ def run_error_checks
142
+ @error_checkers.each { |e| e.call(self) }
143
+ end
144
+
145
+ def add_checker(checker = nil, &block)
146
+ if block_given?
147
+ @error_checkers << block
148
+ elsif Proc === checker
149
+ @error_checkers << checker
150
+ else
151
+ raise ArgumentError, "argument must be a Proc or block"
152
+ end
153
+ end
154
+
155
+ def disable_checker(checker)
156
+ @error_checkers.delete(checker)
157
+ end
158
+
159
+ def method_missing(meth, *args)
160
+ match_data = /^show_(.*)$/.match(meth.to_s)
161
+ if match_data
162
+ begin
163
+ puts collection_string(match_data[1])
164
+ rescue NoMethodError
165
+ super
166
+ end
167
+ else
168
+ super
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ def render
175
+ begin
176
+ @viewer.render_html(html, url)
177
+ rescue Errno::ECONNREFUSED => e
178
+ puts e.message
179
+ end
180
+ end
181
+
182
+ def find_viewer
183
+ begin
184
+ if `uname`.chomp == "Darwin" && `ps ax`[/CelerityViewer/]
185
+ require "drb"
186
+ @viewer = DRbObject.new_with_uri("druby://127.0.0.1:1337")
187
+ end
188
+ rescue IOError, Errno::ENOENT
189
+ end
190
+ end
191
+
192
+ end # IE
193
+ end # Celerity
194
+
195
+ Celerity::Browser = Celerity::IE