celerity 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/History.txt +10 -0
  2. data/README.txt +8 -11
  3. data/Rakefile +5 -3
  4. data/benchmark/bm_2000_spans.rb +48 -0
  5. data/benchmark/bm_digg.rb +26 -0
  6. data/benchmark/bm_google_images.rb +36 -0
  7. data/benchmark/bm_input_locator.rb +69 -0
  8. data/benchmark/loader.rb +9 -0
  9. data/lib/celerity.rb +3 -1
  10. data/lib/celerity/container.rb +23 -171
  11. data/lib/celerity/disabled_element.rb +1 -1
  12. data/lib/celerity/element.rb +78 -47
  13. data/lib/celerity/element_collections.rb +16 -32
  14. data/lib/celerity/element_locator.rb +135 -0
  15. data/lib/celerity/elements/button.rb +15 -0
  16. data/lib/celerity/elements/file_field.rb +1 -1
  17. data/lib/celerity/elements/form.rb +2 -1
  18. data/lib/celerity/elements/frame.rb +18 -21
  19. data/lib/celerity/elements/image.rb +2 -8
  20. data/lib/celerity/elements/label.rb +1 -3
  21. data/lib/celerity/elements/link.rb +1 -1
  22. data/lib/celerity/elements/option.rb +16 -0
  23. data/lib/celerity/elements/radio_check.rb +18 -7
  24. data/lib/celerity/elements/select_list.rb +1 -17
  25. data/lib/celerity/elements/table.rb +4 -4
  26. data/lib/celerity/elements/table_body.rb +6 -8
  27. data/lib/celerity/elements/table_cell.rb +3 -14
  28. data/lib/celerity/elements/table_row.rb +4 -10
  29. data/lib/celerity/elements/text_field.rb +16 -4
  30. data/lib/celerity/extra/method_generator.rb +144 -0
  31. data/lib/celerity/identifier.rb +10 -0
  32. data/lib/celerity/ie.rb +28 -13
  33. data/lib/celerity/input_element.rb +0 -4
  34. data/lib/celerity/non_control_elements.rb +12 -12
  35. data/lib/celerity/version.rb +1 -1
  36. data/spec/area_spec.rb +41 -41
  37. data/spec/areas_spec.rb +11 -11
  38. data/spec/button_spec.rb +73 -68
  39. data/spec/buttons_spec.rb +10 -10
  40. data/spec/checkbox_spec.rb +102 -96
  41. data/spec/checkboxes_spec.rb +10 -10
  42. data/spec/div_spec.rb +78 -73
  43. data/spec/divs_spec.rb +10 -10
  44. data/spec/element_spec.rb +20 -11
  45. data/spec/filefield_spec.rb +36 -41
  46. data/spec/filefields_spec.rb +10 -10
  47. data/spec/form_spec.rb +29 -29
  48. data/spec/forms_spec.rb +11 -11
  49. data/spec/frame_spec.rb +54 -49
  50. data/spec/hidden_spec.rb +43 -43
  51. data/spec/hiddens_spec.rb +10 -10
  52. data/spec/html/2000_spans.html +2009 -0
  53. data/spec/html/forms_with_input_elements.html +15 -9
  54. data/spec/html/non_control_elements.html +4 -2
  55. data/spec/ie_spec.rb +82 -48
  56. data/spec/image_spec.rb +83 -100
  57. data/spec/images_spec.rb +10 -10
  58. data/spec/label_spec.rb +29 -29
  59. data/spec/labels_spec.rb +10 -10
  60. data/spec/li_spec.rb +41 -41
  61. data/spec/link_spec.rb +65 -59
  62. data/spec/links_spec.rb +11 -11
  63. data/spec/lis_spec.rb +10 -10
  64. data/spec/map_spec.rb +30 -30
  65. data/spec/maps_spec.rb +10 -10
  66. data/spec/p_spec.rb +49 -49
  67. data/spec/pre_spec.rb +41 -41
  68. data/spec/pres_spec.rb +10 -10
  69. data/spec/ps_spec.rb +10 -10
  70. data/spec/radio_spec.rb +104 -97
  71. data/spec/radios_spec.rb +11 -11
  72. data/spec/select_list_spec.rb +118 -106
  73. data/spec/select_lists_spec.rb +15 -15
  74. data/spec/span_spec.rb +54 -54
  75. data/spec/spans_spec.rb +11 -11
  76. data/spec/spec.opts +1 -1
  77. data/spec/spec_helper.rb +23 -3
  78. data/spec/table_bodies.rb +8 -8
  79. data/spec/table_bodies_spec.rb +9 -9
  80. data/spec/table_body_spec.rb +28 -27
  81. data/spec/table_cell_spec.rb +25 -25
  82. data/spec/table_cells_spec.rb +16 -16
  83. data/spec/table_row_spec.rb +16 -16
  84. data/spec/table_rows_spec.rb +12 -12
  85. data/spec/table_spec.rb +36 -36
  86. data/spec/tables_spec.rb +12 -12
  87. data/spec/text_field_spec.rb +111 -92
  88. data/spec/text_fields_spec.rb +13 -13
  89. data/tasks/benchmark.rake +3 -0
  90. data/tasks/rspec.rake +2 -2
  91. data/tasks/testserver.rake +15 -0
  92. metadata +58 -46
  93. data/tasks/simple_ci.rake +0 -94
@@ -2,41 +2,38 @@ module Celerity
2
2
  class Frame < Element
3
3
  include Container
4
4
  attr_accessor :page
5
- TAGS = {'frame' => nil, 'iframe' => nil}
5
+
6
+ TAGS = [Identifier.new('frame'), Identifier.new('iframe')]
7
+
6
8
  ATTRIBUTES = BASE_ATTRIBUTES | [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :noresize, :scrolling]
7
9
  DEFAULT_HOW = :name
8
10
 
9
11
  def locate
10
- # Log.debug(@container.object.inspect)
11
- frame_elements = @container.object.getByXPath(".//iframe | .//frame").collect { |frame| frame.getEnclosedWindow.getFrameElement }
12
- unless frame_elements.empty?
13
- case @how
14
- when :id, :name, :src, :class
15
- matching_frame_elements = frame_elements.select { |frame_element| matches?(frame_element.getAttribute(@how.to_s), @what) }
16
- if @frame_element = matching_frame_elements.first
17
- @object = @frame_element.getEnclosedPage.getDocumentElement
18
- end
19
- when :index
20
- if @frame_element = frame_elements[@what-1]
21
- @object = @frame_element.getEnclosedPage.getDocumentElement
22
- end
23
- when :xpath
24
- raise NotImplementedError
25
- else
26
- raise MissingWayOfFindingObjectException
12
+ super
13
+ if @object
14
+ @inline_frame_object = @object.getEnclosedWindow.getFrameElement
15
+ if (frame = @object.getEnclosedPage.getDocumentElement)
16
+ @object = frame
17
+ else
18
+ @object = nil
27
19
  end
28
20
  end
29
- raise UnknownFrameException unless @object
21
+ end
22
+
23
+ def assert_exists
24
+ locate unless @object
25
+ unless @object
26
+ raise UnknownFrameException, "unable to locate frame, using #{identifier_string}"
27
+ end
30
28
  end
31
29
 
32
30
  def update_page(value)
33
- # Log.debug(value.asXml)
34
31
  @page_container.set_page(value.getEnclosingWindow.getTopWindow.getEnclosedPage)
35
32
  end
36
33
 
37
34
  def to_s
38
35
  assert_exists
39
- create_string(@frame_element)
36
+ create_string(@inline_frame_object)
40
37
  end
41
38
 
42
39
  end
@@ -9,7 +9,7 @@ module Celerity
9
9
  include ClickableElement
10
10
  include DisabledElement
11
11
 
12
- TAGS = ['img']
12
+ TAGS = [ Identifier.new('img') ]
13
13
  ATTRIBUTES = BASE_ATTRIBUTES | [:src, :alt, :longdesc, :name, :height, :width, :usemap, :ismap, :align, :border, :hspace, :vspace]
14
14
 
15
15
  # this method returns the file created date of the image
@@ -39,13 +39,7 @@ module Celerity
39
39
  assert_exists
40
40
  @object.getHeight
41
41
  end
42
-
43
- def disabled?
44
- assert_exists
45
- raise NotImplementedError
46
- end
47
- alias_method :disabled, :disabled?
48
-
42
+
49
43
  def loaded?
50
44
  assert_exists
51
45
  begin
@@ -1,10 +1,8 @@
1
1
  module Celerity
2
2
 
3
3
  class Label < Element
4
- TAGS = ['label']
4
+ TAGS = [ Identifier.new('label') ]
5
5
  ATTRIBUTES = BASE_ATTRIBUTES | [:for, :accesskey, :onfocus, :onblur]
6
-
7
-
8
6
  end
9
7
 
10
8
  end
@@ -1,6 +1,6 @@
1
1
  module Celerity
2
2
  class Link < Element
3
- TAGS = ['a']
3
+ TAGS = [ Identifier.new('a') ]
4
4
  ATTRIBUTES = BASE_ATTRIBUTES | [:charset, :type, :name, :href, :hreflang, :target, :rel, :rev, :accesskey, :shape, :coords, :tabindex, :onfocus, :onblur]
5
5
 
6
6
  def click
@@ -0,0 +1,16 @@
1
+ module Celerity
2
+ class Option < Element
3
+ include ClickableElement
4
+ include DisabledElement
5
+
6
+ TAGS = [ Identifier.new('option')]
7
+ ATTRIBUTES = BASE_ATTRIBUTES | [:selected, :disabled, :label, :value]
8
+
9
+ alias_method :select, :click
10
+
11
+ def selected?
12
+ assert_exists
13
+ @object.isSelected
14
+ end
15
+ end
16
+ end
@@ -6,14 +6,17 @@ module Celerity
6
6
  # most of the methods available to this element are inherited from the Element class
7
7
  #
8
8
  class RadioCheckCommon < InputElement
9
- def locate
10
- @object = @container.locate_input_element(self, @how, @what, @value)
11
- end
12
-
13
- def initialize(container, how, what, type, value = nil)
9
+ def initialize(container, type, *args)
14
10
  @type = type
15
- @value = value
16
- super(container, how, what)
11
+
12
+ case args.size
13
+ when 2
14
+ super(container, args[0] => args[1])
15
+ when 3
16
+ super(container, args[0] => args[1], :value => args[2])
17
+ else
18
+ super(container, *args)
19
+ end
17
20
  end
18
21
 
19
22
  def set?
@@ -35,6 +38,10 @@ module Celerity
35
38
  class Radio < RadioCheckCommon
36
39
  TAGS = [Identifier.new('input', :type => %w(radio))]
37
40
 
41
+ def initialize(container, *args)
42
+ super(container, ['radio'], *args)
43
+ end
44
+
38
45
  def set(value = true)
39
46
  assert_exists
40
47
  assert_enabled
@@ -47,6 +54,10 @@ module Celerity
47
54
  class CheckBox < RadioCheckCommon
48
55
  TAGS = [Identifier.new('input', :type => %w(checkbox))]
49
56
 
57
+ def initialize(container, *args)
58
+ super(container, ['checkbox'], *args)
59
+ end
60
+
50
61
  def set(value = true)
51
62
  assert_exists
52
63
  assert_enabled
@@ -43,7 +43,7 @@ module Celerity
43
43
 
44
44
  def selected?(value)
45
45
  assert_exists
46
- # This should probably raise NoValueFoundException as well?
46
+ # This should probably raise NoValueFoundException?
47
47
  raise UnknownObjectException, "unknown option with value #{value.inspect}" unless include?(value)
48
48
  !!@object.getOptions.find { |e| matches?(e.asText, value) && e.isSelected }
49
49
  end
@@ -65,20 +65,4 @@ module Celerity
65
65
  Option.new(self, attribute, value)
66
66
  end
67
67
  end
68
-
69
- class Option < Element
70
- TAGS = ['option']
71
- ATTRIBUTES = BASE_ATTRIBUTES | [:selected, :disabled, :label, :value]
72
-
73
- def select
74
- assert_exists
75
- # click?
76
- @object.setSelected(true)
77
- end
78
-
79
- def selected?
80
- assert_exists
81
- @object.isSelected
82
- end
83
- end
84
68
  end
@@ -2,13 +2,13 @@ module Celerity
2
2
 
3
3
  class Table < Element
4
4
  include Container
5
- TAGS = ['table']
5
+ TAGS = [ Identifier.new('table') ]
6
6
  ATTRIBUTES = BASE_ATTRIBUTES | [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding, :align, :bgcolor]
7
7
  DEFAULT_HOW = :name
8
8
 
9
9
  def locate
10
- @object = @container.locate_tagged_element(self, @how, @what)
11
- if @object # cant call the assert_exists here, as an exists? method call will fail
10
+ super
11
+ if @object # cant call assert_exists here, as an exists? method call will fail
12
12
  @rows = @object.getRows
13
13
  @cells = []
14
14
  @rows.each do |row|
@@ -73,7 +73,7 @@ module Celerity
73
73
 
74
74
  def body(how, what)
75
75
  assert_exists
76
- return TableBody.new(@container, how, what, self)
76
+ return TableBody.new(@container, how, what)
77
77
  end
78
78
 
79
79
  def bodies
@@ -1,15 +1,12 @@
1
1
  module Celerity
2
2
 
3
3
  class TableBody < Element
4
- TAGS = ['tbody']
4
+ TAGS = [ Identifier.new('tbody') ]
5
5
 
6
6
  def locate
7
- if @how == :object
8
- @object = @what
9
- else
10
- @object = @container.locate_tagged_element(self, @how, @what)
11
- end
12
- if @object # cant call the assert_exists here, as an exists? method call will fail
7
+ super
8
+ # can't call the assert_exists here, as an exists? method call will fail
9
+ if @object
13
10
  @rows = @object.getRows
14
11
  @cells = []
15
12
  @rows.each do |row|
@@ -31,7 +28,8 @@ module Celerity
31
28
  end
32
29
 
33
30
  def each
34
- 0.upto(length-1) { |index| yield TableRow.new(self, :object, @rows[index]) }
31
+ assert_exists
32
+ @rows.each { |row| yield TableRow.new(self, :object, row) }
35
33
  end
36
34
 
37
35
  end
@@ -4,27 +4,16 @@ module Celerity
4
4
  include Celerity::Exception
5
5
  include Container
6
6
 
7
- TAGS = ['td']
7
+ TAGS = [ Identifier.new('td') ]
8
8
  ATTRIBUTES = BASE_ATTRIBUTES | [:abbr, :axis, :headers, :scope, :rowspan, :colspan] | CELLHALIGN_ATTRIBUTES | CELLVALIGN_ATTRIBUTES
9
9
 
10
- def locate
11
- if @how == :object
12
- @object = @what
13
- else
14
- @object = @container.locate_tagged_element(self, @how, @what)
15
- end
16
- end
10
+ alias_method :to_s, :text
17
11
 
18
12
  def colspan
19
13
  assert_exists
20
14
  attribute_value = @object.getAttributeValue('colspan').to_i
21
- if attribute_value > 0
22
- attribute_value
23
- else
24
- 1
25
- end
15
+ attribute_value > 0 ? attribute_value : 1
26
16
  end
27
17
 
28
- alias_method :to_s, :text
29
18
  end
30
19
  end
@@ -1,22 +1,16 @@
1
1
  module Celerity
2
2
 
3
3
  class TableRow < Element
4
- TAGS = ['tr']
4
+ TAGS = [ Identifier.new('tr') ]
5
5
 
6
6
  def locate
7
- if @how == :object
8
- @object = @what
9
- else
10
- @object = @container.locate_tagged_element(self, @how, @what)
11
- end
12
- if @object # cant call the assert_exists here, as an exists? method call will fail
13
- @cells = @object.getCells
14
- end
7
+ super
8
+ @cells = @object.getCells if @object
15
9
  end
16
10
 
17
11
  def each
18
12
  locate
19
- 0.upto(@cells.length-1) { |index| yield TableCell.new(self, :object, @cells[index]) }
13
+ @cells.each { |cell| yield TableCell.new(self, :object, cell) }
20
14
  end
21
15
 
22
16
  def [](index)
@@ -6,7 +6,7 @@ module Celerity
6
6
  # Normally a user would not need to create this object as it is returned by the Watir::Container#text_field method
7
7
  class TextField < InputElement
8
8
  TAGS = [ Identifier.new('textarea'),
9
- Identifier.new('input', :type => %w(text password)) ]
9
+ Identifier.new('input', :type => ["text", "password", /^(?!(file|radio|checkbox|submit|reset|image|button|hidden)$)/]) ]
10
10
 
11
11
  def clear
12
12
  assert_exists
@@ -22,11 +22,11 @@ module Celerity
22
22
  assert_enabled
23
23
  assert_not_readonly
24
24
  clear
25
- # not sure what else to do here
25
+ # workaround for bug in HtmlPasswordInput - should be fixed soon (Jari - 2008-05-14)
26
26
  if @object.class == com.gargoylesoftware.htmlunit.html.HtmlPasswordInput
27
27
  @object.setValueAttribute(value.to_s)
28
28
  else
29
- value.to_s.to_java_bytes.each do |char|
29
+ java.lang.String.new(value.to_s).toCharArray.each do |char|
30
30
  @container.update_page @object.type(char)
31
31
  end
32
32
  end
@@ -43,11 +43,23 @@ module Celerity
43
43
  @object.setValueAttribute(value.to_s)
44
44
  end
45
45
  end
46
+
47
+ def value
48
+ assert_exists
49
+ case @object.getTagName
50
+ when 'textarea'
51
+ @object.getText
52
+ when 'input'
53
+ @object.getValueAttribute
54
+ end
55
+ end
46
56
 
47
57
  def append(value)
48
58
  assert_enabled
49
59
  assert_not_readonly
50
- value.to_s.to_java_bytes.each { |char| @container.update_page @object.type(char) }
60
+ java.lang.String.new(value.to_s).toCharArray.each do |char|
61
+ @container.update_page @object.type(char)
62
+ end
51
63
  end
52
64
 
53
65
  # This bascially just moves the text to the other text field using TextField#append
@@ -0,0 +1,144 @@
1
+ require "rubygems"
2
+ require "uri"
3
+ require "active_support"
4
+
5
+ # http://api.rubyonrails.com/classes/Inflector.html#M001621
6
+ class String
7
+ def underscore
8
+ gsub(/::/, '/').
9
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
10
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
11
+ tr("-", "_").
12
+ downcase
13
+ end
14
+ end
15
+
16
+ module Celerity
17
+ class MethodGenerator
18
+
19
+ ELEMENTS = %w(text_field select_list radio checkbox button).map { |e| e.to_sym }
20
+ BUGGY_ELEMENTS = %w(radio checkbox).map { |e| e.to_sym }
21
+
22
+ def initialize(ie, opts = {})
23
+ @ie = ie
24
+ @opts = opts
25
+ @browser = @opts[:browser] || '@ie'
26
+
27
+ @docs = " # Fills in the page at #{@ie.url}\n #\n"
28
+ @docs << " # Parameters:\n #\n"
29
+ @doc_elements = []
30
+
31
+ @method = " def #{@opts[:method_name] || 'generated_method'}(opts = {})\n\n"
32
+ end
33
+
34
+ def parse
35
+ ELEMENTS.each do |elem|
36
+ @method << " # buggy!\n" if BUGGY_ELEMENTS.include?(elem)
37
+ add_elements(elem)
38
+ end
39
+ add_elements(:link) if @opts[:include_links]
40
+ @method << " end\n\n"
41
+
42
+ # fix docs
43
+ max = @doc_elements.map { |symbol, _| symbol.to_s.size }.max
44
+ @doc_elements.each do |sym, desc|
45
+ @docs << " # #{sym.to_s.ljust(max)} => #{desc}\n"
46
+ end
47
+ @docs << " #\n"*2
48
+ @docs + @method
49
+ end
50
+
51
+ private
52
+
53
+ def add_elements(symbol)
54
+ symbol = symbol.to_sym
55
+ symbol_pluralized = symbol.to_s.pluralize.to_sym
56
+ @ie.send(symbol_pluralized).each_with_index do |elem, idx|
57
+ self.send("add_#{symbol}".to_sym, elem, idx)
58
+ end
59
+ @method << "\n"
60
+ end
61
+
62
+ def add_text_field(elem, idx)
63
+ how, what = find_identifier(elem) || [:index, (idx + 1).to_s]
64
+ @method << " #{@browser}.text_field(#{how.inspect}, #{what.inspect}).value = "
65
+ symbol = (how == :index) ? ":text_field_#{what.underscore}" : ":#{what.underscore}"
66
+ @method << "opts[#{symbol}]\n"
67
+ @doc_elements << [symbol, "value for text field #{what.inspect}"]
68
+ end
69
+
70
+ def add_select_list(elem, idx)
71
+ how, what = find_identifier(elem) || [:index, (idx + 1).to_s]
72
+ @method << " #{@browser}.select_list(#{how.inspect}, #{what.inspect}).select("
73
+ symbol = (how == :index) ? ":select_list_#{what.underscore}" : ":#{what.underscore}"
74
+ @method << "opts[#{symbol}])\n"
75
+ @doc_elements << [symbol, "option to select for select list #{what.inspect}"]
76
+ end
77
+
78
+ def add_radio(elem, idx)
79
+ how, what = find_identifier(elem) || [:index, (idx + 1).to_s]
80
+ @method << " #{@browser}.radio(#{how.inspect}, #{what.inspect}, "
81
+ if (value = elem.value).empty?
82
+ symbol = (how == :index) ? ":radio_#{what.underscore}" : ":#{what.underscore}"
83
+ else
84
+ symbol = ":#{what.underscore}_#{value.underscore}"
85
+ @method << "#{value.inspect}).set if opts[#{symbol}]\n"
86
+ end
87
+ @doc_elements << [symbol, "set the radio with id/value #{what.inspect}"]
88
+ end
89
+
90
+ def add_checkbox(elem, idx)
91
+ how, what = find_identifier(elem) || [:index, (idx + 1).to_s]
92
+ @method << " #{@browser}.checkbox(#{how.inspect}, #{what.inspect}, "
93
+ symbol = (how == :index) ? ":checkbox_#{what.underscore}" : ":#{what.underscore}"
94
+ @method << "#{elem.value.inspect}).set if opts[#{symbol}]\n"
95
+ @doc_elements << [symbol, "set the checkbox with id/value #{what.inspect}"]
96
+ end
97
+
98
+ def add_button(elem, idx)
99
+ how, what = find_identifier(elem) || [:index, (idx + 1).to_s]
100
+ @method << " #{@browser}.button(#{how.inspect}, #{what.inspect}).click\n"
101
+ end
102
+
103
+ def add_link(elem, idx)
104
+ if (href = elem.href) =~ /javascript/
105
+ how, what = :index, (idx + 1).to_s
106
+ else
107
+ how = :url
108
+ uri = URI.parse(href)
109
+ what = Regexp.new(Regexp.escape(uri.to_s.sub(/.*#{uri.host}\//, '')))
110
+ end
111
+ @method << " #{@browser}.link(#{how.inspect}, #{what.inspect}).click\n"
112
+ end
113
+
114
+ def find_identifier(element)
115
+ # could use these if they were 'weighted' ?
116
+ attrs = element.class::ATTRIBUTES
117
+ [:id, :name].each do |attribute|
118
+ return [attribute, element.send(attribute)] if attrs.include?(attribute) && !element.send(attribute).empty?
119
+ end
120
+ nil
121
+ end
122
+
123
+ end # MethodGenerator
124
+
125
+ class IE
126
+ def generate_method
127
+ MethodGenerator.new(self).parse
128
+ end
129
+ end
130
+
131
+ end # Celerity
132
+
133
+
134
+
135
+ # if __FILE__ == $0
136
+ # require File.dirname(__FILE__) + "/../spec/spec_helper"
137
+ # $stdout.sync = true
138
+ # @ie = IE.new
139
+ # @ie.goto(TEST_HOST + "/forms_with_input_elements.html")
140
+ #
141
+ # puts MethodGenerator.new(@ie).parse
142
+ # @ie.goto(TEST_HOST + "/forms3.html")
143
+ # puts MethodGenerator.new(@ie).parse
144
+ # end