webrat 0.3.4 → 0.4.0

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 (63) hide show
  1. data/History.txt +140 -30
  2. data/README.rdoc +85 -0
  3. data/Rakefile +72 -22
  4. data/install.rb +1 -1
  5. data/lib/webrat.rb +12 -17
  6. data/lib/webrat/core.rb +9 -7
  7. data/lib/webrat/core/configuration.rb +87 -0
  8. data/lib/webrat/core/{area.rb → elements/area.rb} +7 -20
  9. data/lib/webrat/core/elements/element.rb +33 -0
  10. data/lib/webrat/core/elements/field.rb +394 -0
  11. data/lib/webrat/core/elements/form.rb +103 -0
  12. data/lib/webrat/core/elements/label.rb +31 -0
  13. data/lib/webrat/core/{link.rb → elements/link.rb} +15 -26
  14. data/lib/webrat/core/elements/select_option.rb +35 -0
  15. data/lib/webrat/core/locators.rb +13 -85
  16. data/lib/webrat/core/locators/area_locator.rb +38 -0
  17. data/lib/webrat/core/locators/button_locator.rb +54 -0
  18. data/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  19. data/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
  20. data/lib/webrat/core/locators/field_locator.rb +25 -0
  21. data/lib/webrat/core/locators/field_named_locator.rb +41 -0
  22. data/lib/webrat/core/locators/form_locator.rb +19 -0
  23. data/lib/webrat/core/locators/label_locator.rb +34 -0
  24. data/lib/webrat/core/locators/link_locator.rb +66 -0
  25. data/lib/webrat/core/locators/locator.rb +20 -0
  26. data/lib/webrat/core/locators/select_option_locator.rb +59 -0
  27. data/lib/webrat/core/logging.rb +5 -9
  28. data/lib/webrat/core/matchers/have_content.rb +19 -44
  29. data/lib/webrat/core/matchers/have_selector.rb +15 -2
  30. data/lib/webrat/core/matchers/have_tag.rb +15 -2
  31. data/lib/webrat/core/matchers/have_xpath.rb +21 -28
  32. data/lib/webrat/core/methods.rb +32 -15
  33. data/lib/webrat/core/mime.rb +3 -3
  34. data/lib/webrat/core/save_and_open_page.rb +50 -0
  35. data/lib/webrat/core/scope.rb +183 -41
  36. data/lib/webrat/core/session.rb +125 -63
  37. data/lib/webrat/core/xml.rb +115 -0
  38. data/lib/webrat/core/xml/hpricot.rb +19 -0
  39. data/lib/webrat/core/xml/nokogiri.rb +76 -0
  40. data/lib/webrat/core/xml/rexml.rb +24 -0
  41. data/lib/webrat/core_extensions/deprecate.rb +1 -1
  42. data/lib/webrat/mechanize.rb +58 -12
  43. data/lib/webrat/merb.rb +7 -73
  44. data/lib/webrat/merb_session.rb +65 -0
  45. data/lib/webrat/rack.rb +1 -1
  46. data/lib/webrat/rails.rb +56 -55
  47. data/lib/webrat/rspec-rails.rb +13 -0
  48. data/lib/webrat/selenium.rb +92 -1
  49. data/lib/webrat/selenium/matchers.rb +146 -0
  50. data/lib/webrat/selenium/selenium_session.rb +179 -80
  51. data/lib/webrat/sinatra.rb +14 -4
  52. data/vendor/selenium-server.jar +0 -0
  53. metadata +36 -17
  54. data/README.txt +0 -90
  55. data/TODO.txt +0 -10
  56. data/init.rb +0 -3
  57. data/lib/webrat/core/field.rb +0 -332
  58. data/lib/webrat/core/flunk.rb +0 -7
  59. data/lib/webrat/core/form.rb +0 -130
  60. data/lib/webrat/core/label.rb +0 -18
  61. data/lib/webrat/core/nokogiri.rb +0 -44
  62. data/lib/webrat/core/select_option.rb +0 -29
  63. data/lib/webrat/rails/redirect_actions.rb +0 -18
data/install.rb CHANGED
@@ -1 +1 @@
1
- puts IO.read(File.join(File.dirname(__FILE__), 'README'))
1
+ puts IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
@@ -3,37 +3,32 @@ require "rubygems"
3
3
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
4
4
 
5
5
  module Webrat
6
- VERSION = '0.3.4'
7
-
8
- def self.root #:nodoc:
9
- defined?(RAILS_ROOT) ? RAILS_ROOT : Merb.root
6
+ # The common base class for all exceptions raised by Webrat.
7
+ class WebratError < StandardError
10
8
  end
11
-
9
+
10
+ VERSION = '0.4.0'
11
+
12
12
  def self.require_xml
13
- gem "nokogiri", ">= 1.1.0"
14
-
15
- # We need Nokogiri's CSS to XPath support, even if using
16
- # REXML and Hpricot for parsing and searching
17
- require "nokogiri"
13
+ gem "nokogiri", ">= 1.0.6"
18
14
 
19
15
  if on_java?
16
+ # We need Nokogiri's CSS to XPath support, even if using REXML and Hpricot for parsing and searching
17
+ require "nokogiri/css"
20
18
  require "hpricot"
21
19
  require "rexml/document"
22
20
  else
23
- require "webrat/core/nokogiri"
21
+ require "nokogiri"
22
+ require "webrat/core/xml/nokogiri"
24
23
  end
25
24
  end
26
25
 
27
26
  def self.on_java?
28
27
  RUBY_PLATFORM =~ /java/
29
28
  end
29
+
30
30
  end
31
31
 
32
32
  Webrat.require_xml
33
- require "webrat/core"
34
33
 
35
- # TODO: This is probably not a good idea.
36
- # Probably better for webrat users to require "webrat/rails" etc. directly
37
- if defined?(RAILS_ENV)
38
- require "webrat/rails"
39
- end
34
+ require "webrat/core"
@@ -1,12 +1,14 @@
1
- require "webrat/core/nokogiri"
1
+ require "webrat/core/configuration"
2
+ require "webrat/core/xml"
3
+ require "webrat/core/xml/nokogiri"
2
4
  require "webrat/core/logging"
3
- require "webrat/core/flunk"
4
- require "webrat/core/form"
5
+ require "webrat/core/elements/form"
5
6
  require "webrat/core/scope"
6
- require "webrat/core/link"
7
- require "webrat/core/area"
8
- require "webrat/core/label"
9
- require "webrat/core/select_option"
7
+ require "webrat/core/elements/link"
8
+ require "webrat/core/elements/area"
9
+ require "webrat/core/elements/label"
10
+ require "webrat/core/elements/select_option"
10
11
  require "webrat/core/session"
11
12
  require "webrat/core/methods"
12
13
  require "webrat/core/matchers"
14
+ require "webrat/core/save_and_open_page"
@@ -0,0 +1,87 @@
1
+ require "webrat/core_extensions/deprecate"
2
+
3
+ module Webrat
4
+
5
+ # Configures Webrat. If this is not done, Webrat will be created
6
+ # with all of the default settings.
7
+ def self.configure(configuration = Webrat.configuration)
8
+ yield configuration if block_given?
9
+ @@configuration = configuration
10
+ end
11
+
12
+ def self.configuration # :nodoc:
13
+ @@configuration ||= Webrat::Configuration.new
14
+ end
15
+
16
+ # Webrat can be configured using the Webrat.configure method. For example:
17
+ #
18
+ # Webrat.configure do |config|
19
+ # config.parse_with_nokogiri = false
20
+ # end
21
+ class Configuration
22
+
23
+ # Should XHTML be parsed with Nokogiri? Defaults to true, except on JRuby. When false, Hpricot and REXML are used
24
+ attr_writer :parse_with_nokogiri
25
+
26
+ # Webrat's mode, set automatically when requiring webrat/rails, webrat/merb, etc.
27
+ attr_reader :mode # :nodoc:
28
+
29
+ # Save and open pages with error status codes (500-599) in a browser? Defualts to true.
30
+ attr_writer :open_error_files
31
+
32
+ # Which rails environment should the selenium tests be run in? Defaults to selenium.
33
+ attr_accessor :application_environment
34
+ webrat_deprecate :selenium_environment, :application_environment
35
+
36
+ # Which port is the application running on for selenium testing? Defaults to 3001.
37
+ attr_accessor :application_port
38
+ webrat_deprecate :selenium_port, :application_port
39
+
40
+ # Which server the application is running on for selenium testing? Defaults to localhost
41
+ attr_accessor :application_address
42
+
43
+ # Which server Selenium server is running on. Defaults to nil(server starts in webrat process and runs locally)
44
+ attr_accessor :selenium_server_address
45
+
46
+ # Which server Selenium port is running on. Defaults to 4444
47
+ attr_accessor :selenium_server_port
48
+
49
+ # Set the key that Selenium uses to determine the browser running. Default *firefox
50
+ attr_accessor :selenium_browser_key
51
+
52
+ def initialize # :nodoc:
53
+ self.open_error_files = true
54
+ self.parse_with_nokogiri = !Webrat.on_java?
55
+ self.application_environment = :selenium
56
+ self.application_port = 3001
57
+ self.application_address = 'localhost'
58
+ self.selenium_server_port = 4444
59
+ self.selenium_browser_key = '*firefox'
60
+ end
61
+
62
+ def parse_with_nokogiri? #:nodoc:
63
+ @parse_with_nokogiri ? true : false
64
+ end
65
+
66
+ def open_error_files? #:nodoc:
67
+ @open_error_files ? true : false
68
+ end
69
+
70
+ # Allows setting of webrat's mode, valid modes are:
71
+ # :rails, :selenium, :rack, :sinatra, :mechanize, :merb
72
+ def mode=(mode)
73
+ @mode = mode.to_sym
74
+
75
+ # This is a temporary hack to support backwards compatibility
76
+ # with Merb 1.0.8 until it's updated to use the new Webrat.configure
77
+ # syntax
78
+ if @mode == :merb
79
+ require("webrat/merb_session")
80
+ else
81
+ require("webrat/#{mode}")
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -1,34 +1,21 @@
1
+ require "webrat/core/elements/element"
2
+
1
3
  module Webrat
2
- class Area #:nodoc:
4
+ class Area < Element #:nodoc:
3
5
 
4
- def initialize(session, element)
5
- @session = session
6
- @element = element
6
+ def self.xpath_search
7
+ ".//area"
7
8
  end
8
9
 
9
10
  def click(method = nil, options = {})
10
11
  @session.request_page(absolute_href, :get, {})
11
12
  end
12
13
 
13
- def matches_text?(id_or_title)
14
- matcher = /#{Regexp.escape(id_or_title.to_s)}/i
15
- title =~ matcher || id =~ matcher
16
- end
17
-
18
- protected
14
+ protected
19
15
 
20
16
  def href
21
- @element["href"]
22
- end
23
-
24
- def title
25
- @element["title"]
17
+ Webrat::XML.attribute(@element, "href")
26
18
  end
27
-
28
- def id
29
- @element["id"]
30
- end
31
-
32
19
 
33
20
  def absolute_href
34
21
  if href =~ /^\?/
@@ -0,0 +1,33 @@
1
+ module Webrat
2
+
3
+ class Element # :nodoc:
4
+
5
+ def self.load_all(session, dom)
6
+ Webrat::XML.xpath_search(dom, xpath_search).map do |element|
7
+ load(session, element)
8
+ end
9
+ end
10
+
11
+ def self.load(session, element)
12
+ return nil if element.nil?
13
+ session.elements[Webrat::XML.xpath_to(element)] ||= self.new(session, element)
14
+ end
15
+
16
+ attr_reader :element
17
+
18
+ def initialize(session, element)
19
+ @session = session
20
+ @element = element
21
+ end
22
+
23
+ def path
24
+ Webrat::XML.xpath_to(@element)
25
+ end
26
+
27
+ def inspect
28
+ "#<#{self.class} @element=#{element.inspect}>"
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,394 @@
1
+ require "cgi"
2
+ require "webrat/core_extensions/blank"
3
+ require "webrat/core_extensions/nil_to_param"
4
+
5
+ require "webrat/core/elements/element"
6
+
7
+ module Webrat
8
+ # Raised when Webrat is asked to manipulate a disabled form field
9
+ class DisabledFieldError < WebratError
10
+ end
11
+
12
+ class Field < Element #:nodoc:
13
+ attr_reader :value
14
+
15
+ def self.xpath_search
16
+ [".//button", ".//input", ".//textarea", ".//select"]
17
+ end
18
+
19
+ def self.field_classes
20
+ @field_classes || []
21
+ end
22
+
23
+ def self.inherited(klass)
24
+ @field_classes ||= []
25
+ @field_classes << klass
26
+ # raise args.inspect
27
+ end
28
+
29
+ def self.load(session, element)
30
+ return nil if element.nil?
31
+ session.elements[Webrat::XML.xpath_to(element)] ||= field_class(element).new(session, element)
32
+ end
33
+
34
+ def self.field_class(element)
35
+ case element.name
36
+ when "button" then ButtonField
37
+ when "select" then SelectField
38
+ when "textarea" then TextareaField
39
+ else
40
+ case Webrat::XML.attribute(element, "type")
41
+ when "checkbox" then CheckboxField
42
+ when "hidden" then HiddenField
43
+ when "radio" then RadioField
44
+ when "password" then PasswordField
45
+ when "file" then FileField
46
+ when "reset" then ResetField
47
+ when "submit" then ButtonField
48
+ when "image" then ButtonField
49
+ else TextField
50
+ end
51
+ end
52
+ end
53
+
54
+ def initialize(*args)
55
+ super
56
+ @value = default_value
57
+ end
58
+
59
+ def label_text
60
+ return nil if labels.empty?
61
+ labels.first.text
62
+ end
63
+
64
+ def id
65
+ Webrat::XML.attribute(@element, "id")
66
+ end
67
+
68
+ def disabled?
69
+ @element.attributes.has_key?("disabled") && Webrat::XML.attribute(@element, "disabled") != 'false'
70
+ end
71
+
72
+ def raise_error_if_disabled
73
+ return unless disabled?
74
+ raise DisabledFieldError.new("Cannot interact with disabled form element (#{self})")
75
+ end
76
+
77
+ def to_param
78
+ return nil if disabled?
79
+
80
+ case Webrat.configuration.mode
81
+ when :rails
82
+ rails_request_parser.parse_query_parameters("#{name}=#{escaped_value}")
83
+ when :merb
84
+ ::Merb::Parse.query("#{name}=#{escaped_value}")
85
+ else
86
+ { name => escaped_value }
87
+ end
88
+ end
89
+
90
+ def set(value)
91
+ @value = value
92
+ end
93
+
94
+ def unset
95
+ @value = default_value
96
+ end
97
+
98
+ protected
99
+
100
+ def rails_request_parser
101
+ if defined?(ActionController::RequestParser) # For Rails > 2.2
102
+ ActionController::RequestParser
103
+ else
104
+ ActionController::AbstractRequest
105
+ end
106
+ end
107
+
108
+ def form
109
+ Form.load(@session, form_element)
110
+ end
111
+
112
+ def form_element
113
+ parent = @element.parent
114
+
115
+ while parent.respond_to?(:parent)
116
+ return parent if parent.name == 'form'
117
+ parent = parent.parent
118
+ end
119
+ end
120
+
121
+ def name
122
+ Webrat::XML.attribute(@element, "name")
123
+ end
124
+
125
+ def escaped_value
126
+ CGI.escape(@value.to_s)
127
+ end
128
+
129
+ def labels
130
+ @labels ||= label_elements.map do |element|
131
+ Label.load(@session, element)
132
+ end
133
+ end
134
+
135
+ def label_elements
136
+ return @label_elements unless @label_elements.nil?
137
+ @label_elements = []
138
+
139
+ parent = @element.parent
140
+ while parent.respond_to?(:parent)
141
+ if parent.name == 'label'
142
+ @label_elements.push parent
143
+ break
144
+ end
145
+ parent = parent.parent
146
+ end
147
+
148
+ unless id.blank?
149
+ @label_elements += Webrat::XML.xpath_search(form.element, ".//label[@for = '#{id}']")
150
+ end
151
+
152
+ @label_elements
153
+ end
154
+
155
+ def default_value
156
+ Webrat::XML.attribute(@element, "value")
157
+ end
158
+
159
+ def replace_param_value(params, oval, nval)
160
+ output = Hash.new
161
+ params.each do |key, value|
162
+ case value
163
+ when Hash
164
+ value = replace_param_value(value, oval, nval)
165
+ when Array
166
+ value = value.map { |o| o == oval ? nval : oval }
167
+ when oval
168
+ value = nval
169
+ end
170
+ output[key] = value
171
+ end
172
+ output
173
+ end
174
+ end
175
+
176
+ class ButtonField < Field #:nodoc:
177
+
178
+ def self.xpath_search
179
+ [".//button", ".//input[@type = 'submit']", ".//input[@type = 'image']"]
180
+ end
181
+
182
+ def to_param
183
+ return nil if @value.nil?
184
+ super
185
+ end
186
+
187
+ def default_value
188
+ nil
189
+ end
190
+
191
+ def click
192
+ raise_error_if_disabled
193
+ set(Webrat::XML.attribute(@element, "value")) unless Webrat::XML.attribute(@element, "name").blank?
194
+ form.submit
195
+ end
196
+
197
+ end
198
+
199
+ class HiddenField < Field #:nodoc:
200
+
201
+ def self.xpath_search
202
+ ".//input[@type = 'hidden']"
203
+ end
204
+
205
+ def to_param
206
+ if collection_name?
207
+ super
208
+ else
209
+ checkbox_with_same_name = form.field_named(name, CheckboxField)
210
+
211
+ if checkbox_with_same_name.to_param.blank?
212
+ super
213
+ else
214
+ nil
215
+ end
216
+ end
217
+ end
218
+
219
+ protected
220
+
221
+ def collection_name?
222
+ name =~ /\[\]/
223
+ end
224
+
225
+ end
226
+
227
+ class CheckboxField < Field #:nodoc:
228
+
229
+ def self.xpath_search
230
+ ".//input[@type = 'checkbox']"
231
+ end
232
+
233
+ def to_param
234
+ return nil if @value.nil?
235
+ super
236
+ end
237
+
238
+ def check
239
+ raise_error_if_disabled
240
+ set(Webrat::XML.attribute(@element, "value") || "on")
241
+ end
242
+
243
+ def checked?
244
+ Webrat::XML.attribute(@element, "checked") == "checked"
245
+ end
246
+
247
+ def uncheck
248
+ raise_error_if_disabled
249
+ set(nil)
250
+ end
251
+
252
+ protected
253
+
254
+ def default_value
255
+ if Webrat::XML.attribute(@element, "checked") == "checked"
256
+ Webrat::XML.attribute(@element, "value") || "on"
257
+ else
258
+ nil
259
+ end
260
+ end
261
+
262
+ end
263
+
264
+ class PasswordField < Field #:nodoc:
265
+
266
+ def self.xpath_search
267
+ ".//input[@type = 'password']"
268
+ end
269
+
270
+ end
271
+
272
+ class RadioField < Field #:nodoc:
273
+
274
+ def self.xpath_search
275
+ ".//input[@type = 'radio']"
276
+ end
277
+
278
+ def to_param
279
+ return nil if @value.nil?
280
+ super
281
+ end
282
+
283
+ def choose
284
+ raise_error_if_disabled
285
+ other_options.each do |option|
286
+ option.set(nil)
287
+ end
288
+
289
+ set(Webrat::XML.attribute(@element, "value") || "on")
290
+ end
291
+
292
+ def checked?
293
+ Webrat::XML.attribute(@element, "checked") == "checked"
294
+ end
295
+
296
+ protected
297
+
298
+ def other_options
299
+ form.fields.select { |f| f.name == name }
300
+ end
301
+
302
+ def default_value
303
+ if Webrat::XML.attribute(@element, "checked") == "checked"
304
+ Webrat::XML.attribute(@element, "value") || "on"
305
+ else
306
+ nil
307
+ end
308
+ end
309
+
310
+ end
311
+
312
+ class TextareaField < Field #:nodoc:
313
+
314
+ def self.xpath_search
315
+ ".//textarea"
316
+ end
317
+
318
+ protected
319
+
320
+ def default_value
321
+ Webrat::XML.inner_html(@element)
322
+ end
323
+
324
+ end
325
+
326
+ class FileField < Field #:nodoc:
327
+
328
+ def self.xpath_search
329
+ ".//input[@type = 'file']"
330
+ end
331
+
332
+ attr_accessor :content_type
333
+
334
+ def set(value, content_type = nil)
335
+ super(value)
336
+ @content_type = content_type
337
+ end
338
+
339
+ def to_param
340
+ if @value.nil?
341
+ super
342
+ else
343
+ replace_param_value(super, @value, test_uploaded_file)
344
+ end
345
+ end
346
+
347
+ protected
348
+
349
+ def test_uploaded_file
350
+ if content_type
351
+ ActionController::TestUploadedFile.new(@value, content_type)
352
+ else
353
+ ActionController::TestUploadedFile.new(@value)
354
+ end
355
+ end
356
+
357
+ end
358
+
359
+ class TextField < Field #:nodoc:
360
+ def self.xpath_search
361
+ [".//input[@type = 'text']", ".//input[not(@type)]"]
362
+ end
363
+ end
364
+
365
+ class ResetField < Field #:nodoc:
366
+ def self.xpath_search
367
+ ".//input[@type = 'reset']"
368
+ end
369
+ end
370
+
371
+ class SelectField < Field #:nodoc:
372
+
373
+ def self.xpath_search
374
+ ".//select"
375
+ end
376
+
377
+ def options
378
+ @options ||= SelectOption.load_all(@session, @element)
379
+ end
380
+
381
+ protected
382
+
383
+ def default_value
384
+ selected_options = Webrat::XML.xpath_search(@element, ".//option[@selected = 'selected']")
385
+ selected_options = Webrat::XML.xpath_search(@element, ".//option[position() = 1]") if selected_options.empty?
386
+
387
+ selected_options.map do |option|
388
+ return "" if option.nil?
389
+ Webrat::XML.attribute(option, "value") || Webrat::XML.inner_html(option)
390
+ end
391
+ end
392
+
393
+ end
394
+ end